aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElliott Sales de Andrade <quantum.analyst@gmail.com>2016-08-24 04:35:15 -0400
committerElliott Sales de Andrade <quantum.analyst@gmail.com>2016-08-26 20:46:42 -0400
commit70d94a555004563178878b73274e345adff5b4e8 (patch)
treea5944eecebc2992e322e42364148d63ba73acda8
parentdcaf2d7b3d010526eb5035fec788f1b9a854262c (diff)
downloadmeson-70d94a555004563178878b73274e345adff5b4e8.zip
meson-70d94a555004563178878b73274e345adff5b4e8.tar.gz
meson-70d94a555004563178878b73274e345adff5b4e8.tar.bz2
Allow capturing command output of a custom target.
For commands that always output to stdout and don't have a "-o" or "--output" or some other similar option, this 'capture' setting allows the build to capture the result and place it in the output file.
-rw-r--r--mesonbuild/backend/backends.py8
-rw-r--r--mesonbuild/backend/ninjabackend.py10
-rw-r--r--mesonbuild/build.py5
-rw-r--r--mesonbuild/scripts/meson_exe.py7
-rw-r--r--test cases/common/117 custom target capture/data_source.txt1
-rw-r--r--test cases/common/117 custom target capture/installed_files.txt1
-rw-r--r--test cases/common/117 custom target capture/meson.build16
-rwxr-xr-xtest cases/common/117 custom target capture/my_compiler.py13
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.')