diff options
-rw-r--r-- | mesonbuild/backend/backends.py | 8 | ||||
-rw-r--r-- | mesonbuild/backend/ninjabackend.py | 10 | ||||
-rw-r--r-- | mesonbuild/build.py | 5 | ||||
-rw-r--r-- | mesonbuild/scripts/meson_exe.py | 7 | ||||
-rw-r--r-- | test cases/common/117 custom target capture/data_source.txt | 1 | ||||
-rw-r--r-- | test cases/common/117 custom target capture/installed_files.txt | 1 | ||||
-rw-r--r-- | test cases/common/117 custom target capture/meson.build | 16 | ||||
-rwxr-xr-x | test cases/common/117 custom target capture/my_compiler.py | 13 |
8 files changed, 54 insertions, 7 deletions
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index bdba44f..fbc5079 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -37,7 +37,7 @@ class InstallData(): class ExecutableSerialisation(): def __init__(self, name, fname, cmd_args, env, is_cross, exe_wrapper, - workdir, extra_paths): + workdir, extra_paths, capture): self.name = name self.fname = fname self.cmd_args = cmd_args @@ -46,6 +46,7 @@ class ExecutableSerialisation(): self.exe_runner = exe_wrapper self.workdir = workdir self.extra_paths = extra_paths + self.capture = capture class TestSerialisation: def __init__(self, name, suite, fname, is_cross, exe_wrapper, is_parallel, cmd_args, env, @@ -176,7 +177,8 @@ class Backend(): raise MesonException('Unknown data type in object list.') return obj_list - def serialise_executable(self, exe, cmd_args, workdir, env={}): + def serialise_executable(self, exe, cmd_args, workdir, env={}, + capture=None): import uuid # Can't just use exe.name here; it will likely be run more than once if isinstance(exe, (dependencies.ExternalProgram, @@ -207,7 +209,7 @@ class Backend(): extra_paths = [] es = ExecutableSerialisation(basename, exe_fullpath, cmd_args, env, is_cross, exe_wrapper, workdir, - extra_paths) + extra_paths, capture) pickle.dump(es, f) return exe_data diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 15f298b..7855729 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -379,15 +379,19 @@ int dummy; tmp = [tmp] for fname in tmp: elem.add_dep(os.path.join(self.get_target_dir(d), fname)) + # If the target requires capturing stdout, then use the serialized + # executable wrapper to capture that output and save it to a file. + # # Windows doesn't have -rpath, so for EXEs that need DLLs built within # the project, we need to set PATH so the DLLs are found. We use # a serialized executable wrapper for that and check if the # CustomTarget command needs extra paths first. - if mesonlib.is_windows() and \ - self.determine_windows_extra_paths(target.command[0]): + if target.capture or (mesonlib.is_windows() and + self.determine_windows_extra_paths(target.command[0])): exe_data = self.serialise_executable(target.command[0], cmd[1:], # All targets are built from the build dir - self.environment.get_build_dir()) + self.environment.get_build_dir(), + capture=ofilenames[0] if target.capture else None) cmd = [sys.executable, self.environment.get_build_command(), '--internal', 'exe', exe_data] cmd_type = 'meson_exe.py custom' diff --git a/mesonbuild/build.py b/mesonbuild/build.py index dd03d81..48d7843 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -927,6 +927,7 @@ class CustomTarget: known_kwargs = {'input' : True, 'output' : True, 'command' : True, + 'capture' : False, 'install' : True, 'install_dir' : True, 'build_always' : True, @@ -982,6 +983,10 @@ class CustomTarget: raise InvalidArguments('Output argument not a string.') if '/' in i: raise InvalidArguments('Output must not contain a path segment.') + self.capture = kwargs.get('capture', False) + if self.capture and len(self.output) != 1: + raise InvalidArguments( + 'Capturing can only output to a single file.') if 'command' not in kwargs: raise InvalidArguments('Missing keyword argument "command".') cmd = kwargs['command'] diff --git a/mesonbuild/scripts/meson_exe.py b/mesonbuild/scripts/meson_exe.py index f075fa0..cdfed09 100644 --- a/mesonbuild/scripts/meson_exe.py +++ b/mesonbuild/scripts/meson_exe.py @@ -59,6 +59,11 @@ def run_exe(exe): stderr=subprocess.PIPE, env=child_env, cwd=exe.workdir) + stdout, stderr = p.communicate() + if exe.capture and p.returncode == 0: + with open(exe.capture, 'wb') as output: + output.write(stdout) + return p.returncode def run(args): global options @@ -68,7 +73,7 @@ def run(args): print(sys.argv[0] + ' [data file]') exe_data_file = options.args[0] exe = pickle.load(open(exe_data_file, 'rb')) - run_exe(exe) + return run_exe(exe) if __name__ == '__main__': sys.exit(run(sys.argv[1:])) diff --git a/test cases/common/117 custom target capture/data_source.txt b/test cases/common/117 custom target capture/data_source.txt new file mode 100644 index 0000000..0c23cc0 --- /dev/null +++ b/test cases/common/117 custom target capture/data_source.txt @@ -0,0 +1 @@ +This is a text only input file. diff --git a/test cases/common/117 custom target capture/installed_files.txt b/test cases/common/117 custom target capture/installed_files.txt new file mode 100644 index 0000000..d90a6b0 --- /dev/null +++ b/test cases/common/117 custom target capture/installed_files.txt @@ -0,0 +1 @@ +usr/subdir/data.dat diff --git a/test cases/common/117 custom target capture/meson.build b/test cases/common/117 custom target capture/meson.build new file mode 100644 index 0000000..6c19752 --- /dev/null +++ b/test cases/common/117 custom target capture/meson.build @@ -0,0 +1,16 @@ +project('custom target', 'c') + +python = find_program('python3') + +# Note that this will not add a dependency to the compiler executable. +# Code will not be rebuilt if it changes. +comp = '@0@/@1@'.format(meson.current_source_dir(), 'my_compiler.py') + +mytarget = custom_target('bindat', +output : 'data.dat', +input : 'data_source.txt', +capture : true, +command : [python, comp, '@INPUT@'], +install : true, +install_dir : 'subdir' +) diff --git a/test cases/common/117 custom target capture/my_compiler.py b/test cases/common/117 custom target capture/my_compiler.py new file mode 100755 index 0000000..3e9ec23 --- /dev/null +++ b/test cases/common/117 custom target capture/my_compiler.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 + +import sys + +if __name__ == '__main__': + if len(sys.argv) != 2: + print(sys.argv[0], 'input_file') + sys.exit(1) + ifile = open(sys.argv[1]).read() + if ifile != 'This is a text only input file.\n': + print('Malformed input') + sys.exit(1) + print('This is a binary output file.') |