summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2019-07-11 00:34:40 +0300
committerGitHub <noreply@github.com>2019-07-11 00:34:40 +0300
commit19cda6b7c96cc3a63796549764261306e1db94b4 (patch)
tree6d47683818b05b2eee6a9f9dfb92c92463ac26cc
parent30e42009c03cbb53e3462e1c4ee29af666474742 (diff)
parentd8b3af00aca3a2825d199367d588a4b24e5ab779 (diff)
downloadmeson-19cda6b7c96cc3a63796549764261306e1db94b4.tar.gz
Merge pull request #5606 from xclaesse/alias_target
Add alias_target() function
-rw-r--r--data/syntax-highlighting/vim/syntax/meson.vim1
-rw-r--r--docs/markdown/Reference-manual.md14
-rw-r--r--docs/markdown/snippets/alias_target.md12
-rw-r--r--mesonbuild/ast/interpreter.py1
-rw-r--r--mesonbuild/backend/ninjabackend.py30
-rw-r--r--mesonbuild/backend/vs2010backend.py9
-rw-r--r--mesonbuild/build.py4
-rw-r--r--mesonbuild/interpreter.py26
-rwxr-xr-xrun_unittests.py13
-rw-r--r--test cases/unit/62 alias target/main.c3
-rw-r--r--test cases/unit/62 alias target/meson.build15
11 files changed, 110 insertions, 18 deletions
diff --git a/data/syntax-highlighting/vim/syntax/meson.vim b/data/syntax-highlighting/vim/syntax/meson.vim
index 85acf4301..94936c80b 100644
--- a/data/syntax-highlighting/vim/syntax/meson.vim
+++ b/data/syntax-highlighting/vim/syntax/meson.vim
@@ -69,6 +69,7 @@ syn keyword mesonBuiltin
\ add_project_arguments
\ add_project_link_arguments
\ add_test_setup
+ \ alias_target
\ assert
\ benchmark
\ both_libraries
diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md
index 3793ce358..195c451d5 100644
--- a/docs/markdown/Reference-manual.md
+++ b/docs/markdown/Reference-manual.md
@@ -119,6 +119,20 @@ Note that all these options are also available while running the
`meson test` script for running tests instead of `ninja test` or
`msbuild RUN_TESTS.vcxproj`, etc depending on the backend.
+### alias_target
+
+``` meson
+runtarget alias_target(target_name, dep1, ...)
+```
+
+Since *0.52.0*
+
+This function creates a new top-level target. Like all top-level targets, this
+integrates with the selected backend. For instance, with Ninja you can
+run it as `ninja target_name`. This is a dummy target that does not execute any
+command, but ensures that all dependencies are built. Dependencies can be any
+build target (e.g. return value of executable(), custom_target(), etc)
+
### assert()
``` meson
diff --git a/docs/markdown/snippets/alias_target.md b/docs/markdown/snippets/alias_target.md
new file mode 100644
index 000000000..129730d03
--- /dev/null
+++ b/docs/markdown/snippets/alias_target.md
@@ -0,0 +1,12 @@
+## alias_target
+
+``` meson
+runtarget alias_target(target_name, dep1, ...)
+```
+
+This function creates a new top-level target. Like all top-level targets, this
+integrates with the selected backend. For instance, with Ninja you can
+run it as `ninja target_name`. This is a dummy target that does not execute any
+command, but ensures that all dependencies are built. Dependencies can be any
+build target (e.g. return value of executable(), custom_target(), etc)
+
diff --git a/mesonbuild/ast/interpreter.py b/mesonbuild/ast/interpreter.py
index 535471066..0e490abdf 100644
--- a/mesonbuild/ast/interpreter.py
+++ b/mesonbuild/ast/interpreter.py
@@ -117,6 +117,7 @@ class AstInterpreter(interpreterbase.InterpreterBase):
'add_test_setup': self.func_do_nothing,
'find_library': self.func_do_nothing,
'subdir_done': self.func_do_nothing,
+ 'alias_target': self.func_do_nothing,
})
def func_do_nothing(self, node, args, kwargs):
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index b830e377e..b57a783ce 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -702,6 +702,13 @@ int dummy;
self.add_build(elem)
self.processed_targets[target.get_id()] = True
+ def build_run_target_name(self, target):
+ if target.subproject != '':
+ subproject_prefix = '{}@@'.format(target.subproject)
+ else:
+ subproject_prefix = ''
+ return '{}{}'.format(subproject_prefix, target.name)
+
def generate_run_target(self, target):
cmd = self.environment.get_build_command() + ['--internal', 'commandrunner']
deps = self.unwrap_dep_list(target)
@@ -718,12 +725,6 @@ int dummy;
arg_strings.append(os.path.join(self.environment.get_build_dir(), relfname))
else:
raise AssertionError('Unreachable code in generate_run_target: ' + str(i))
- if target.subproject != '':
- subproject_prefix = '{}@@'.format(target.subproject)
- else:
- subproject_prefix = ''
- target_name = 'meson-{}{}'.format(subproject_prefix, target.name)
- elem = NinjaBuildElement(self.all_outputs, target_name, 'CUSTOM_COMMAND', [])
cmd += [self.environment.get_source_dir(),
self.environment.get_build_dir(),
target.subdir] + self.environment.get_build_command()
@@ -756,14 +757,21 @@ int dummy;
cmd.append(target.command)
cmd += arg_strings
+ if texe:
+ target_name = 'meson-{}'.format(self.build_run_target_name(target))
+ elem = NinjaBuildElement(self.all_outputs, target_name, 'CUSTOM_COMMAND', [])
+ elem.add_item('COMMAND', cmd)
+ elem.add_item('description', 'Running external command %s.' % target.name)
+ elem.add_item('pool', 'console')
+ # Alias that runs the target defined above with the name the user specified
+ self.create_target_alias(target_name)
+ else:
+ target_name = self.build_run_target_name(target)
+ elem = NinjaBuildElement(self.all_outputs, target_name, 'phony', [])
+
elem.add_dep(deps)
cmd = self.replace_paths(target, cmd)
- elem.add_item('COMMAND', cmd)
- elem.add_item('description', 'Running external command %s.' % target.name)
- elem.add_item('pool', 'console')
self.add_build(elem)
- # Alias that runs the target defined above with the name the user specified
- self.create_target_alias(target_name)
self.processed_targets[target.get_id()] = True
def generate_coverage_command(self, elem, outputs):
diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py
index 86a7f8307..82fc0cf40 100644
--- a/mesonbuild/backend/vs2010backend.py
+++ b/mesonbuild/backend/vs2010backend.py
@@ -516,11 +516,16 @@ class Vs2010Backend(backends.Backend):
def gen_run_target_vcxproj(self, target, ofname, guid):
root = self.create_basic_crap(target, guid)
- cmd_raw = [target.command] + target.args
+ if not target.command:
+ # FIXME: This is an alias target that doesn't run any command, there
+ # is probably a better way than running a this dummy command.
+ cmd_raw = python_command + ['-c', 'exit']
+ else:
+ cmd_raw = [target.command] + target.args
cmd = python_command + \
[os.path.join(self.environment.get_script_dir(), 'commandrunner.py'),
- self.environment.get_build_dir(),
self.environment.get_source_dir(),
+ self.environment.get_build_dir(),
self.get_target_dir(target)] + self.environment.get_build_command()
for i in cmd_raw:
if isinstance(i, build.BuildTarget):
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 55b162974..2e23a59bc 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -2205,6 +2205,10 @@ class RunTarget(Target):
def type_suffix(self):
return "@run"
+class AliasTarget(RunTarget):
+ def __init__(self, name, dependencies, subdir, subproject):
+ super().__init__(name, '', [], dependencies, subdir, subproject)
+
class Jar(BuildTarget):
known_kwargs = known_jar_kwargs
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index a20dcd5cd..fd9425156 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -863,10 +863,9 @@ class CustomTargetHolder(TargetHolder):
return IncludeDirsHolder(build.IncludeDirs('', [], False,
[os.path.join('@BUILD_ROOT@', self.interpreter.backend.get_target_dir(self.held_object))]))
-class RunTargetHolder(InterpreterObject, ObjectHolder):
- def __init__(self, name, command, args, dependencies, subdir, subproject):
- InterpreterObject.__init__(self)
- ObjectHolder.__init__(self, build.RunTarget(name, command, args, dependencies, subdir, subproject))
+class RunTargetHolder(TargetHolder):
+ def __init__(self, target, interp):
+ super().__init__(target, interp)
def __repr__(self):
r = '<{} {}: {}>'
@@ -2103,6 +2102,7 @@ class Interpreter(InterpreterBase):
'add_project_link_arguments': self.func_add_project_link_arguments,
'add_test_setup': self.func_add_test_setup,
'add_languages': self.func_add_languages,
+ 'alias_target': self.func_alias_target,
'assert': self.func_assert,
'benchmark': self.func_benchmark,
'build_target': self.func_build_target,
@@ -3300,7 +3300,23 @@ This will become a hard error in the future.''' % kwargs['input'], location=self
raise InterpreterException('Depends items must be build targets.')
cleaned_deps.append(d)
command, *cmd_args = cleaned_args
- tg = RunTargetHolder(name, command, cmd_args, cleaned_deps, self.subdir, self.subproject)
+ tg = RunTargetHolder(build.RunTarget(name, command, cmd_args, cleaned_deps, self.subdir, self.subproject), self)
+ self.add_target(name, tg.held_object)
+ return tg
+
+ @FeatureNew('alias_target', '0.52.0')
+ @noKwargs
+ def func_alias_target(self, node, args, kwargs):
+ if len(args) < 2:
+ raise InvalidCode('alias_target takes at least 2 arguments.')
+ name = args[0]
+ if not isinstance(name, str):
+ raise InterpreterException('First argument must be a string.')
+ deps = listify(args[1:], unholder=True)
+ for d in deps:
+ if not isinstance(d, (build.BuildTarget, build.CustomTarget)):
+ raise InterpreterException('Depends items must be build targets.')
+ tg = RunTargetHolder(build.AliasTarget(name, deps, self.subdir, self.subproject), self)
self.add_target(name, tg.held_object)
return tg
diff --git a/run_unittests.py b/run_unittests.py
index 33174b191..56f2683bd 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -3747,6 +3747,19 @@ recommended as it is not supported on some platforms''')
testdir = os.path.join(self.unit_test_dir, '61 cmake parser')
self.init(testdir, extra_args=['-Dcmake_prefix_path=' + os.path.join(testdir, 'prefix')])
+ def test_alias_target(self):
+ if self.backend is Backend.vs:
+ # FIXME: This unit test is broken with vs backend, needs investigation
+ raise unittest.SkipTest('Skipping alias_target test with {} backend'.format(self.backend.name))
+ testdir = os.path.join(self.unit_test_dir, '62 alias target')
+ self.init(testdir)
+ self.build()
+ self.assertPathDoesNotExist(os.path.join(self.builddir, 'prog' + exe_suffix))
+ self.assertPathDoesNotExist(os.path.join(self.builddir, 'hello.txt'))
+ self.run_target('build-all')
+ self.assertPathExists(os.path.join(self.builddir, 'prog' + exe_suffix))
+ self.assertPathExists(os.path.join(self.builddir, 'hello.txt'))
+
class FailureTests(BasePlatformTests):
'''
Tests that test failure conditions. Build files here should be dynamically
diff --git a/test cases/unit/62 alias target/main.c b/test cases/unit/62 alias target/main.c
new file mode 100644
index 000000000..0fb4389f7
--- /dev/null
+++ b/test cases/unit/62 alias target/main.c
@@ -0,0 +1,3 @@
+int main(int argc, char *argv[]) {
+ return 0;
+}
diff --git a/test cases/unit/62 alias target/meson.build b/test cases/unit/62 alias target/meson.build
new file mode 100644
index 000000000..6934cc79b
--- /dev/null
+++ b/test cases/unit/62 alias target/meson.build
@@ -0,0 +1,15 @@
+project('alias target', 'c')
+
+python3 = import('python').find_installation()
+
+exe_target = executable('prog', 'main.c',
+ build_by_default : false)
+
+custom_target = custom_target('custom-target',
+ output : 'hello.txt',
+ command : [python3, '-c', 'print("hello")'],
+ capture : true,
+ build_by_default : false
+)
+
+alias_target('build-all', [exe_target, custom_target])