Allow meson build file to exit early. (#2808)

pull/3347/head
behlec 7 years ago committed by Jussi Pakkanen
parent 6146353f45
commit 37d379ebe5
  1. 27
      docs/markdown/Reference-manual.md
  2. 7
      docs/markdown/Release-notes-for-0.46.0.md
  3. 11
      mesonbuild/interpreter.py
  4. 5
      mesonbuild/interpreterbase.py
  5. 10
      test cases/common/188 subdir_done/meson.build
  6. 8
      test cases/failing/71 skip only subdir/meson.build
  7. 3
      test cases/failing/71 skip only subdir/subdir/meson.build

@ -1129,6 +1129,33 @@ This function has one keyword argument.
recurse in the subdir if they all return `true` when queried with
`.found()`
### subdir_done()
``` meson
subdir_done()
```
Stops further interpretation of the meson script file from the point of
the invocation. All steps executed up to this point are valid and will
be executed by meson. This means that all targets defined before the call
of `subdir_done` will be build.
If the current script was called by `subdir` the execution returns to the
calling directory and continues as if the script had reached the end.
If the current script is the top level script meson configures the project
as defined up to this point.
Example:
```meson
project('example exit', 'cpp')
executable('exe1', 'exe1.cpp')
subdir_done()
executable('exe2', 'exe2.cpp')
```
The executable `exe1` will be build, while the executable `exe2` is not
build.
### subproject()
``` meson

@ -14,3 +14,10 @@ whose contents should look like this:
## Feature name
A short description explaining the new feature and how it should be used.
## Allow early return from a script
Added the function `subdir_done()`. Its invocation exits the current script at
the point of invocation. All previously invoked build targets and commands are
build/executed. All following ones are ignored. If the current script was
invoked via `subdir()` the parent script continues normally.

@ -26,7 +26,7 @@ from .dependencies import ExternalProgram
from .dependencies import InternalDependency, Dependency, DependencyException
from .interpreterbase import InterpreterBase
from .interpreterbase import check_stringlist, noPosargs, noKwargs, stringArgs, permittedKwargs, permittedMethodKwargs
from .interpreterbase import InterpreterException, InvalidArguments, InvalidCode
from .interpreterbase import InterpreterException, InvalidArguments, InvalidCode, SubdirDoneRequest
from .interpreterbase import InterpreterObject, MutableInterpreterObject, Disabler
from .modules import ModuleReturnValue
@ -1612,6 +1612,7 @@ class Interpreter(InterpreterBase):
'static_library': self.func_static_lib,
'test': self.func_test,
'vcs_tag': self.func_vcs_tag,
'subdir_done': self.func_subdir_done,
})
if 'MESON_UNIT_TEST' in os.environ:
self.funcs.update({'exception': self.func_exception})
@ -2606,6 +2607,14 @@ root and issuing %s.
kwargs.setdefault('build_always', True)
return self.func_custom_target(node, [kwargs['output']], kwargs)
@stringArgs
def func_subdir_done(self, node, args, kwargs):
if len(kwargs) > 0:
raise InterpreterException('exit does not take named arguments')
if len(args) > 0:
raise InterpreterException('exit does not take any arguments')
raise SubdirDoneRequest()
@stringArgs
@permittedKwargs(permitted_kwargs['custom_target'])
def func_custom_target(self, node, args, kwargs):

@ -105,6 +105,9 @@ class InvalidCode(InterpreterException):
class InvalidArguments(InterpreterException):
pass
class SubdirDoneRequest(BaseException):
pass
class InterpreterObject:
def __init__(self):
self.methods = {}
@ -203,6 +206,8 @@ class InterpreterBase:
try:
self.current_lineno = cur.lineno
self.evaluate_statement(cur)
except SubdirDoneRequest:
break
except Exception as e:
if not(hasattr(e, 'lineno')):
e.lineno = cur.lineno

@ -0,0 +1,10 @@
# Should run, even though main.cpp does not exist and we call error in the last line.
# subdir_done jumps to end, so both lines are not executed.
project('example exit', 'cpp')
subdir_done()
executable('main', 'main.cpp')
error('Unreachable')

@ -0,0 +1,8 @@
# Check that skip_rest only exits subdir, not the whole script.
# Should create an error because main.cpp does not exists.
project('example exit', 'cpp')
subdir('subdir')
message('Good')
executable('main', 'main.cpp')

@ -0,0 +1,3 @@
subdir_done()
error('Unreachable')
Loading…
Cancel
Save