diff options
author | Xavier Claessens <xavier.claessens@collabora.com> | 2021-02-04 16:02:03 -0500 |
---|---|---|
committer | Xavier Claessens <xavier.claessens@collabora.com> | 2021-02-05 17:53:09 -0500 |
commit | 522392e7553823e6b3ac38cadc4fbee72eae9540 (patch) | |
tree | 0a86dd0524aa3456b6a52443db54f7c5b84102e0 /mesonbuild/backend | |
parent | 5d94d161ff0abf72ed7c771ab3bb86e34560762e (diff) | |
download | meson-522392e7553823e6b3ac38cadc4fbee72eae9540.zip meson-522392e7553823e6b3ac38cadc4fbee72eae9540.tar.gz meson-522392e7553823e6b3ac38cadc4fbee72eae9540.tar.bz2 |
run_target: Add env kwarg
Re-implement it in backend using the same code path as for
custom_target(). This for example handle setting PATH on Windows when
command is an executable.
Diffstat (limited to 'mesonbuild/backend')
-rw-r--r-- | mesonbuild/backend/backends.py | 20 | ||||
-rw-r--r-- | mesonbuild/backend/ninjabackend.py | 76 | ||||
-rw-r--r-- | mesonbuild/backend/vs2010backend.py | 36 |
3 files changed, 46 insertions, 86 deletions
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index badc2d0..0ab5061 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -21,7 +21,6 @@ import json import os import pickle import re -import shlex import textwrap import typing as T import hashlib @@ -34,7 +33,7 @@ from .. import mlog from ..compilers import LANGUAGES_USING_LDFLAGS from ..mesonlib import ( File, MachineChoice, MesonException, OptionType, OrderedSet, OptionOverrideProxy, - classify_unity_sources, unholder, OptionKey + classify_unity_sources, unholder, OptionKey, join_args ) if T.TYPE_CHECKING: @@ -138,6 +137,7 @@ class ExecutableSerialisation: self.capture = capture self.pickled = False self.skip_if_destdir = False + self.verbose = False class TestSerialisation: def __init__(self, name: str, project: str, suite: str, fname: T.List[str], @@ -421,12 +421,14 @@ class Backend: def as_meson_exe_cmdline(self, tname, exe, cmd_args, workdir=None, extra_bdeps=None, capture=None, force_serialize=False, - env: T.Optional[build.EnvironmentVariables] = None): + 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.verbose = verbose reasons = [] if es.extra_paths: reasons.append('to set PATH') @@ -1193,11 +1195,21 @@ class Backend: cmd = [i.replace('\\', '/') for i in cmd] return inputs, outputs, cmd + def get_run_target_env(self, target: build.RunTarget) -> build.EnvironmentVariables: + env = target.env if target.env else build.EnvironmentVariables() + introspect_cmd = join_args(self.environment.get_build_command() + ['introspect']) + env.add_var(env.set, 'MESON_SOURCE_ROOT', [self.environment.get_source_dir()], {}) + env.add_var(env.set, 'MESON_BUILD_ROOT', [self.environment.get_build_dir()], {}) + env.add_var(env.set, 'MESON_SUBDIR', [target.subdir], {}) + env.add_var(env.set, 'MESONINTROSPECT', [introspect_cmd], {}) + return env + def run_postconf_scripts(self) -> None: from ..scripts.meson_exe import run_exe + introspect_cmd = join_args(self.environment.get_build_command() + ['introspect']) env = {'MESON_SOURCE_ROOT': self.environment.get_source_dir(), 'MESON_BUILD_ROOT': self.environment.get_build_dir(), - 'MESONINTROSPECT': ' '.join([shlex.quote(x) for x in self.environment.get_build_command() + ['introspect']]), + 'MESONINTROSPECT': introspect_cmd, } for s in self.build.postconf_scripts: diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 36f1fd2..2bd22bf 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -28,7 +28,6 @@ from .. import modules from .. import environment, mesonlib from .. import build from .. import mlog -from .. import dependencies from .. import compilers from ..arglist import CompilerArgs from ..compilers import ( @@ -989,65 +988,28 @@ int dummy; 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) - arg_strings = [] - for i in target.args: - if isinstance(i, str): - arg_strings.append(i) - elif isinstance(i, (build.BuildTarget, build.CustomTarget)): - relfname = self.get_target_filename(i) - arg_strings.append(os.path.join(self.environment.get_build_dir(), relfname)) - deps.append(relfname) - elif isinstance(i, mesonlib.File): - relfname = i.rel_to_builddir(self.build_to_src) - arg_strings.append(os.path.join(self.environment.get_build_dir(), relfname)) - else: - raise AssertionError('Unreachable code in generate_run_target: ' + str(i)) - cmd += [self.environment.get_source_dir(), - self.environment.get_build_dir(), - target.subdir] + self.environment.get_build_command() - texe = target.command - try: - texe = texe.held_object - except AttributeError: - pass - if isinstance(texe, build.Executable): - abs_exe = os.path.join(self.environment.get_build_dir(), self.get_target_filename(texe)) - deps.append(self.get_target_filename(texe)) - if self.environment.is_cross_build(): - exe_wrap = self.environment.get_exe_wrapper() - if exe_wrap: - if not exe_wrap.found(): - msg = 'The exe_wrapper {!r} defined in the cross file is ' \ - 'needed by run target {!r}, but was not found. ' \ - 'Please check the command and/or add it to PATH.' - raise MesonException(msg.format(exe_wrap.name, target.name)) - cmd += exe_wrap.get_command() - cmd.append(abs_exe) - elif isinstance(texe, dependencies.ExternalProgram): - cmd += texe.get_command() - elif isinstance(texe, build.CustomTarget): - deps.append(self.get_target_filename(texe)) - cmd += [os.path.join(self.environment.get_build_dir(), self.get_target_filename(texe))] - elif isinstance(texe, mesonlib.File): - cmd.append(texe.absolute_path(self.environment.get_source_dir(), self.environment.get_build_dir())) + target_name = self.build_run_target_name(target) + if not target.command: + # This is an alias target, it has no command, it just depends on + # other targets. + elem = NinjaBuildElement(self.all_outputs, target_name, 'phony', []) else: - 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 {}'.format(target.name)) + target_env = self.get_run_target_env(target) + _, _, cmd = self.eval_custom_target_command(target) + desc = 'Running external command {}{}' + meson_exe_cmd, reason = self.as_meson_exe_cmdline(target_name, cmd[0], cmd[1:], + force_serialize=True, env=target_env, + verbose=True) + cmd_type = ' (wrapped by meson {})'.format(reason) + internal_target_name = 'meson-{}'.format(target_name) + elem = NinjaBuildElement(self.all_outputs, internal_target_name, 'CUSTOM_COMMAND', []) + elem.add_item('COMMAND', meson_exe_cmd) + elem.add_item('description', desc.format(target.name, cmd_type)) 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', []) - + self.create_target_alias(internal_target_name) + deps = self.unwrap_dep_list(target) + deps += self.get_custom_target_depend_files(target) elem.add_dep(deps) self.add_build(elem) self.processed_targets[target.get_id()] = True diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index c47fb4a..f4e2bd0 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -28,7 +28,7 @@ from .. import mlog from .. import compilers from ..interpreter import Interpreter from ..mesonlib import ( - MesonException, File, python_command, replace_if_different, OptionKey, + MesonException, python_command, replace_if_different, OptionKey, ) from ..environment import Environment, build_filename @@ -257,9 +257,8 @@ class Vs2010Backend(backends.Backend): for d in target.get_target_dependencies(): all_deps[d.get_id()] = d elif isinstance(target, build.RunTarget): - for d in [target.command] + target.args: - if isinstance(d, (build.BuildTarget, build.CustomTarget)): - all_deps[d.get_id()] = d + for d in target.get_dependencies(): + all_deps[d.get_id()] = d elif isinstance(target, build.BuildTarget): for ldep in target.link_targets: if isinstance(ldep, build.CustomTargetIndex): @@ -534,27 +533,14 @@ class Vs2010Backend(backends.Backend): # 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_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): - cmd.append(os.path.join(self.environment.get_build_dir(), self.get_target_filename(i))) - elif isinstance(i, dependencies.ExternalProgram): - cmd += i.get_command() - elif isinstance(i, File): - relfname = i.rel_to_builddir(self.build_to_src) - cmd.append(os.path.join(self.environment.get_build_dir(), relfname)) - elif isinstance(i, str): - # Escape embedded quotes, because we quote the entire argument below. - cmd.append(i.replace('"', '\\"')) - else: - cmd.append(i) - cmd_templ = '''"%s" ''' * len(cmd) - self.add_custom_build(root, 'run_target', cmd_templ % tuple(cmd)) + _, _, cmd_raw = self.eval_custom_target_command(target) + depend_files = self.get_custom_target_depend_files(target) + target_env = self.get_run_target_env(target) + wrapper_cmd, _ = self.as_meson_exe_cmdline(target.name, cmd_raw[0], cmd_raw[1:], + force_serialize=True, env=target_env, + verbose=True) + self.add_custom_build(root, 'run_target', ' '.join(self.quote_arguments(wrapper_cmd)), + deps=depend_files) ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.targets') self.add_regen_dependency(root) self.add_target_deps(root, target) |