diff options
author | Simon Ser <contact@emersion.fr> | 2021-06-23 10:58:26 +0200 |
---|---|---|
committer | Jussi Pakkanen <jpakkane@gmail.com> | 2021-06-29 20:54:13 +0300 |
commit | 1f3adc4dbe20196eb45b7c0cfe502ce108618ada (patch) | |
tree | 60771f94cfca0c0761a95eafa584c83f478edeaa /mesonbuild | |
parent | 4bfee181c5a166e3d429bd265e06d299dce50f30 (diff) | |
download | meson-1f3adc4dbe20196eb45b7c0cfe502ce108618ada.zip meson-1f3adc4dbe20196eb45b7c0cfe502ce108618ada.tar.gz meson-1f3adc4dbe20196eb45b7c0cfe502ce108618ada.tar.bz2 |
Add feed arg to custom_target()
Diffstat (limited to 'mesonbuild')
-rw-r--r-- | mesonbuild/backend/backends.py | 32 | ||||
-rw-r--r-- | mesonbuild/backend/ninjabackend.py | 1 | ||||
-rw-r--r-- | mesonbuild/backend/vs2010backend.py | 1 | ||||
-rw-r--r-- | mesonbuild/build.py | 13 | ||||
-rw-r--r-- | mesonbuild/interpreter/interpreter.py | 4 | ||||
-rw-r--r-- | mesonbuild/scripts/meson_exe.py | 11 |
6 files changed, 43 insertions, 19 deletions
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 21a6c83..aa8e844 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -141,7 +141,7 @@ class SubdirInstallData(InstallDataBase): class ExecutableSerialisation: def __init__(self, cmd_args, env: T.Optional[build.EnvironmentVariables] = None, exe_wrapper=None, - workdir=None, extra_paths=None, capture=None) -> None: + workdir=None, extra_paths=None, capture=None, feed=None) -> None: self.cmd_args = cmd_args self.env = env if exe_wrapper is not None: @@ -150,6 +150,7 @@ class ExecutableSerialisation: self.workdir = workdir self.extra_paths = extra_paths self.capture = capture + self.feed = feed self.pickled = False self.skip_if_destdir = False self.verbose = False @@ -441,7 +442,7 @@ class Backend: return result def get_executable_serialisation(self, cmd, workdir=None, - extra_bdeps=None, capture=None, + extra_bdeps=None, capture=None, feed=None, env: T.Optional[build.EnvironmentVariables] = None): exe = cmd[0] cmd_args = cmd[1:] @@ -489,17 +490,18 @@ class Backend: workdir = workdir or self.environment.get_build_dir() return ExecutableSerialisation(exe_cmd + cmd_args, env, exe_wrapper, workdir, - extra_paths, capture) + extra_paths, capture, feed) def as_meson_exe_cmdline(self, tname, exe, cmd_args, workdir=None, - extra_bdeps=None, capture=None, force_serialize=False, + extra_bdeps=None, capture=None, feed=None, + force_serialize=False, env: T.Optional[build.EnvironmentVariables] = None, verbose: bool = False): ''' Serialize an executable for running with a generator or a custom target ''' cmd = [exe] + cmd_args - es = self.get_executable_serialisation(cmd, workdir, extra_bdeps, capture, env) + es = self.get_executable_serialisation(cmd, workdir, extra_bdeps, capture, feed, env) es.verbose = verbose reasons = [] if es.extra_paths: @@ -521,12 +523,19 @@ class Backend: if capture: reasons.append('to capture output') + if feed: + reasons.append('to feed input') if not force_serialize: - if not capture: + if not capture and not feed: return es.cmd_args, '' + args = [] + if capture: + args += ['--capture', capture] + if feed: + args += ['--feed', feed] return ((self.environment.get_build_command() + - ['--internal', 'exe', '--capture', capture, '--'] + es.cmd_args), + ['--internal', 'exe'] + args + ['--'] + es.cmd_args), ', '.join(reasons)) if isinstance(exe, (programs.ExternalProgram, @@ -538,10 +547,11 @@ class Backend: basename = os.path.basename(exe) # Can't just use exe.name here; it will likely be run more than once - # Take a digest of the cmd args, env, workdir, and capture. This avoids - # collisions and also makes the name deterministic over regenerations - # which avoids a rebuild by Ninja because the cmdline stays the same. - data = bytes(str(es.env) + str(es.cmd_args) + str(es.workdir) + str(capture), + # Take a digest of the cmd args, env, workdir, capture, and feed. This + # avoids collisions and also makes the name deterministic over + # regenerations which avoids a rebuild by Ninja because the cmdline + # stays the same. + data = bytes(str(es.env) + str(es.cmd_args) + str(es.workdir) + str(capture) + str(feed), encoding='utf-8') digest = hashlib.sha1(data).hexdigest() scratch_file = f'meson_exe_{basename}_{digest}.dat' diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 597789b..d6b535b 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -975,6 +975,7 @@ class NinjaBackend(backends.Backend): cmd, reason = self.as_meson_exe_cmdline(target.name, target.command[0], cmd[1:], extra_bdeps=target.get_transitive_build_target_deps(), capture=ofilenames[0] if target.capture else None, + feed=srcs[0] if target.feed else None, env=target.env) if reason: cmd_type = f' (wrapped by meson {reason})' diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index 7fcc324..6e6e47f 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -563,6 +563,7 @@ class Vs2010Backend(backends.Backend): workdir=tdir_abs, extra_bdeps=extra_bdeps, capture=ofilenames[0] if target.capture else None, + feed=srcs[0] if target.feed else None, force_serialize=True, env=target.env) if target.build_always_stale: diff --git a/mesonbuild/build.py b/mesonbuild/build.py index f9de5c4..d72aab8 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -2198,6 +2198,7 @@ class CustomTarget(Target, CommandBase): 'output', 'command', 'capture', + 'feed', 'install', 'install_dir', 'install_mode', @@ -2296,6 +2297,9 @@ class CustomTarget(Target, CommandBase): self.capture = kwargs.get('capture', False) if self.capture and len(self.outputs) != 1: raise InvalidArguments('Capturing can only output to a single file.') + self.feed = kwargs.get('feed', False) + if self.feed and len(self.sources) != 1: + raise InvalidArguments('Feeding can only input from a single file.') self.console = kwargs.get('console', False) if not isinstance(self.console, bool): raise InvalidArguments('"console" kwarg only accepts booleans') @@ -2311,10 +2315,11 @@ class CustomTarget(Target, CommandBase): raise InvalidArguments('Depfile must be a plain filename without a subdirectory.') self.depfile = depfile self.command = self.flatten_command(kwargs['command']) - if self.capture: - for c in self.command: - if isinstance(c, str) and '@OUTPUT@' in c: - raise InvalidArguments('@OUTPUT@ is not allowed when capturing output.') + for c in self.command: + if self.capture and isinstance(c, str) and '@OUTPUT@' in c: + raise InvalidArguments('@OUTPUT@ is not allowed when capturing output.') + if self.feed and isinstance(c, str) and '@INPUT@' in c: + raise InvalidArguments('@INPUT@ is not allowed when feeding input.') if 'install' in kwargs: self.install = kwargs['install'] if not isinstance(self.install, bool): diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 1a9872d..693924f 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -1694,9 +1694,11 @@ external dependencies (including libraries) must go to "dependencies".''') @FeatureNewKwargs('custom_target', '0.48.0', ['console']) @FeatureNewKwargs('custom_target', '0.47.0', ['install_mode', 'build_always_stale']) @FeatureNewKwargs('custom_target', '0.40.0', ['build_by_default']) + @FeatureNewKwargs('custom_target', '0.59.0', ['feed']) @permittedKwargs({'input', 'output', 'command', 'install', 'install_dir', 'install_mode', 'build_always', 'capture', 'depends', 'depend_files', 'depfile', - 'build_by_default', 'build_always_stale', 'console', 'env'}) + 'build_by_default', 'build_always_stale', 'console', 'env', + 'feed'}) def func_custom_target(self, node, args, kwargs): if len(args) != 1: raise InterpreterException('custom_target: Only one positional argument is allowed, and it must be a string name') diff --git a/mesonbuild/scripts/meson_exe.py b/mesonbuild/scripts/meson_exe.py index ea0fef6..9c1ae59 100644 --- a/mesonbuild/scripts/meson_exe.py +++ b/mesonbuild/scripts/meson_exe.py @@ -29,6 +29,7 @@ def buildparser() -> argparse.ArgumentParser: parser = argparse.ArgumentParser(description='Custom executable wrapper for Meson. Do not run on your own, mmm\'kay?') parser.add_argument('--unpickle') parser.add_argument('--capture') + parser.add_argument('--feed') return parser def run_exe(exe: ExecutableSerialisation, extra_env: T.Optional[dict] = None) -> int: @@ -53,13 +54,17 @@ def run_exe(exe: ExecutableSerialisation, extra_env: T.Optional[dict] = None) -> ['Z:' + p for p in exe.extra_paths] + child_env.get('WINEPATH', '').split(';') ) + stdin = None + if exe.feed: + stdin = open(exe.feed, 'rb') + pipe = subprocess.PIPE if exe.verbose: assert not exe.capture, 'Cannot capture and print to console at the same time' pipe = None p = subprocess.Popen(cmd_args, env=child_env, cwd=exe.workdir, - close_fds=False, stdout=pipe, stderr=pipe) + close_fds=False, stdin=stdin, stdout=pipe, stderr=pipe) stdout, stderr = p.communicate() if p.returncode == 0xc0000135: @@ -103,13 +108,13 @@ def run(args: T.List[str]) -> int: if not options.unpickle and not cmd_args: parser.error('either --unpickle or executable and arguments are required') if options.unpickle: - if cmd_args or options.capture: + if cmd_args or options.capture or options.feed: parser.error('no other arguments can be used with --unpickle') with open(options.unpickle, 'rb') as f: exe = pickle.load(f) exe.pickled = True else: - exe = ExecutableSerialisation(cmd_args, capture=options.capture) + exe = ExecutableSerialisation(cmd_args, capture=options.capture, feed=options.feed) return run_exe(exe) |