From 79d530e32509b8ccdc50a6769e8c786b3eccebd3 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Mon, 20 May 2019 00:59:20 +0300 Subject: [PATCH] Generators can have extra target dependencies. Closes #4131. --- docs/markdown/Reference-manual.md | 3 +++ docs/markdown/snippets/gendeps.md | 16 ++++++++++++++ mesonbuild/backend/ninjabackend.py | 1 + mesonbuild/build.py | 7 ++++++ mesonbuild/interpreter.py | 7 +++++- .../common/27 pipeline/depends/copyrunner.py | 7 ++++++ .../common/27 pipeline/depends/filecopier.c | 22 +++++++++++++++++++ .../common/27 pipeline/depends/libsrc.c.in | 3 +++ .../common/27 pipeline/depends/meson.build | 11 ++++++++++ test cases/common/27 pipeline/depends/prog.c | 5 +++++ test cases/common/27 pipeline/meson.build | 2 ++ 11 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 docs/markdown/snippets/gendeps.md create mode 100755 test cases/common/27 pipeline/depends/copyrunner.py create mode 100644 test cases/common/27 pipeline/depends/filecopier.c create mode 100644 test cases/common/27 pipeline/depends/libsrc.c.in create mode 100644 test cases/common/27 pipeline/depends/meson.build create mode 100644 test cases/common/27 pipeline/depends/prog.c diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md index 01fa3c38d..2fc3d6ab0 100644 --- a/docs/markdown/Reference-manual.md +++ b/docs/markdown/Reference-manual.md @@ -714,6 +714,9 @@ following: - `arguments` a list of template strings that will be the command line arguments passed to the executable +- `depends` is an array of build targets that must be built before this + generator can be run. This is used if you have a generator that calls + a second executable that is built in this project. Available since 0.51.0 - `depfile` is a template string pointing to a dependency file that a generator can write listing all the additional files this target depends on, for example a C compiler would list all the header files diff --git a/docs/markdown/snippets/gendeps.md b/docs/markdown/snippets/gendeps.md new file mode 100644 index 000000000..e72499479 --- /dev/null +++ b/docs/markdown/snippets/gendeps.md @@ -0,0 +1,16 @@ +## Generators have a new `depends` keyword argument + +Generators can now specify extra dependencies with the `depends` +keyword argument. It matches the behaviour of the same argument in +other functions and specifies that the given targets must be built +before the generator can be run. This is used in cases such as this +one where you need to tell a generator to indirectly invoke a +different program. + +```meson +exe = executable(...) +cg = generator(program_runner, + output: ['@BASENAME@.c'], + arguments: ['--use-tool=' + exe.full_path(), '@INPUT@', '@OUTPUT@'], + depends: exe) +``` diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index b8971804f..591b2f49d 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1800,6 +1800,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) cmd = cmdlist elem = NinjaBuildElement(self.all_outputs, outfiles, rulename, infilename) + elem.add_dep([self.get_target_filename(x) for x in generator.depends]) if generator.depfile is not None: elem.add_item('DEPFILE', depfile) if len(extra_dependencies) > 0: diff --git a/mesonbuild/build.py b/mesonbuild/build.py index d51e2e318..65b2c20fc 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1273,6 +1273,7 @@ class Generator: self.exe = exe self.depfile = None self.capture = False + self.depends = [] self.process_kwargs(kwargs) def __repr__(self): @@ -1321,6 +1322,12 @@ class Generator: if not isinstance(capture, bool): raise InvalidArguments('Capture must be boolean.') self.capture = capture + if 'depends' in kwargs: + depends = listify(kwargs['depends'], unholder=True) + for d in depends: + if not isinstance(d, BuildTarget): + raise InvalidArguments('Depends entries must be build targets.') + self.depends.append(d) def get_base_outnames(self, inname): plainname = os.path.basename(inname) diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 678560f0d..cb3aa8aad 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -1983,7 +1983,12 @@ permitted_kwargs = {'add_global_arguments': {'language', 'native'}, }, 'executable': build.known_exe_kwargs, 'find_program': {'required', 'native'}, - 'generator': {'arguments', 'output', 'depfile', 'capture', 'preserve_path_from'}, + 'generator': {'arguments', + 'output', + 'depends', + 'depfile', + 'capture', + 'preserve_path_from'}, 'include_directories': {'is_system'}, 'install_data': {'install_dir', 'install_mode', 'rename', 'sources'}, 'install_headers': {'install_dir', 'install_mode', 'subdir'}, diff --git a/test cases/common/27 pipeline/depends/copyrunner.py b/test cases/common/27 pipeline/depends/copyrunner.py new file mode 100755 index 000000000..0ef6a6d68 --- /dev/null +++ b/test cases/common/27 pipeline/depends/copyrunner.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python3 + +import sys, subprocess + +prog, infile, outfile = sys.argv[1:] + +subprocess.check_call([prog, infile, outfile]) diff --git a/test cases/common/27 pipeline/depends/filecopier.c b/test cases/common/27 pipeline/depends/filecopier.c new file mode 100644 index 000000000..9001cf327 --- /dev/null +++ b/test cases/common/27 pipeline/depends/filecopier.c @@ -0,0 +1,22 @@ +#include +#include + +#define BUFSIZE 1024 + +int main(int argc, char **argv) { + char buffer[BUFSIZE]; + size_t num_read; + size_t num_written; + FILE *fin = fopen(argv[1], "rb"); + FILE *fout; + assert(fin); + num_read = fread(buffer, 1, BUFSIZE, fin); + assert(num_read > 0); + fclose(fin); + fout = fopen(argv[2], "wb"); + assert(fout); + num_written = fwrite(buffer, 1, num_read, fout); + assert(num_written == num_read); + fclose(fout); + return 0; +} diff --git a/test cases/common/27 pipeline/depends/libsrc.c.in b/test cases/common/27 pipeline/depends/libsrc.c.in new file mode 100644 index 000000000..652f4eb13 --- /dev/null +++ b/test cases/common/27 pipeline/depends/libsrc.c.in @@ -0,0 +1,3 @@ +int func() { + return 42; +} diff --git a/test cases/common/27 pipeline/depends/meson.build b/test cases/common/27 pipeline/depends/meson.build new file mode 100644 index 000000000..5111fee7a --- /dev/null +++ b/test cases/common/27 pipeline/depends/meson.build @@ -0,0 +1,11 @@ +runner = find_program('copyrunner.py') + +copier = executable('copier', 'filecopier.c', native: true) + +cg = generator(runner, + output: ['@BASENAME@.c'], + arguments: [copier.full_path(), '@INPUT@', '@OUTPUT@'], + depends: copier) + +test('generatordep', + executable('gd', 'prog.c', cg.process('libsrc.c.in'))) diff --git a/test cases/common/27 pipeline/depends/prog.c b/test cases/common/27 pipeline/depends/prog.c new file mode 100644 index 000000000..f4a7dd3bc --- /dev/null +++ b/test cases/common/27 pipeline/depends/prog.c @@ -0,0 +1,5 @@ +int func(); + +int main(int argc, char **argv) { + return func() != 42; +} diff --git a/test cases/common/27 pipeline/meson.build b/test cases/common/27 pipeline/meson.build index bbb49d627..e12cb7b58 100644 --- a/test cases/common/27 pipeline/meson.build +++ b/test cases/common/27 pipeline/meson.build @@ -19,3 +19,5 @@ test('pipelined', e2) # This is in a subdirectory to make sure # we write proper subdir paths to output. subdir('src') + +subdir('depends')