diff options
author | Jussi Pakkanen <jpakkane@gmail.com> | 2021-02-07 11:46:41 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-07 11:46:41 +0000 |
commit | 8b82ffa9e423558d7644c7135db4114f59537829 (patch) | |
tree | 90a326f8e796d4a81e98e0639fe67b6a0459ed08 /mesonbuild/backend | |
parent | 8e73e5fe1c4fcd5a875cb4777c7938f9069e0102 (diff) | |
parent | f63e168685c22a749502161355a7ea98a6c5344a (diff) | |
download | meson-8b82ffa9e423558d7644c7135db4114f59537829.zip meson-8b82ffa9e423558d7644c7135db4114f59537829.tar.gz meson-8b82ffa9e423558d7644c7135db4114f59537829.tar.bz2 |
Merge pull request #8305 from xclaesse/run-target-env
run_target: Add env kwarg
Diffstat (limited to 'mesonbuild/backend')
-rw-r--r-- | mesonbuild/backend/backends.py | 45 | ||||
-rw-r--r-- | mesonbuild/backend/ninjabackend.py | 79 | ||||
-rw-r--r-- | mesonbuild/backend/vs2010backend.py | 38 |
3 files changed, 54 insertions, 108 deletions
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 233173f..e19afca 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -21,8 +21,6 @@ import json import os import pickle import re -import shlex -import textwrap import typing as T import hashlib import copy @@ -34,7 +32,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 +136,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], @@ -432,12 +431,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') @@ -987,18 +988,8 @@ class Backend: if delta > 0.001: raise MesonException('Clock skew detected. File {} has a time stamp {:.4f}s in the future.'.format(absf, delta)) - def build_target_to_cmd_array(self, bt, check_cross): + def build_target_to_cmd_array(self, bt): if isinstance(bt, build.BuildTarget): - if check_cross and isinstance(bt, build.Executable) and bt.for_machine is not MachineChoice.BUILD: - if (self.environment.is_cross_build() and - self.environment.exe_wrapper is None and - self.environment.need_exe_wrapper()): - s = textwrap.dedent(''' - Cannot use target {} as a generator because it is built for the - host machine and no exe wrapper is defined or needs_exe_wrapper is - true. You might want to set `native: true` instead to build it for - the build machine.'''.format(bt.name)) - raise MesonException(s) arr = [os.path.join(self.environment.get_build_dir(), self.get_target_filename(bt))] else: arr = bt.get_command() @@ -1129,11 +1120,9 @@ class Backend: inputs = self.get_custom_target_sources(target) # Evaluate the command list cmd = [] - index = -1 for i in target.command: - index += 1 if isinstance(i, build.BuildTarget): - cmd += self.build_target_to_cmd_array(i, (index == 0)) + cmd += self.build_target_to_cmd_array(i) continue elif isinstance(i, build.CustomTarget): # GIR scanner will attempt to execute this binary but @@ -1146,10 +1135,7 @@ class Backend: i = os.path.join(self.environment.get_build_dir(), i) # FIXME: str types are blindly added ignoring 'target.absolute_paths' # because we can't know if they refer to a file or just a string - elif not isinstance(i, str): - err_msg = 'Argument {0} is of unknown type {1}' - raise RuntimeError(err_msg.format(str(i), str(type(i)))) - else: + elif isinstance(i, str): if '@SOURCE_ROOT@' in i: i = i.replace('@SOURCE_ROOT@', source_root) if '@BUILD_ROOT@' in i: @@ -1179,6 +1165,9 @@ class Backend: else: lead_dir = self.environment.get_build_dir() i = i.replace(source, os.path.join(lead_dir, outdir)) + else: + err_msg = 'Argument {0} is of unknown type {1}' + raise RuntimeError(err_msg.format(str(i), str(type(i)))) cmd.append(i) # Substitute the rest of the template strings values = mesonlib.get_filenames_templates_dict(inputs, outputs) @@ -1204,11 +1193,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 ca17f19..3eca3c0 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 ( @@ -974,7 +973,6 @@ int dummy; elem.add_item('DEPFILE', rel_dfile) if target.console: elem.add_item('pool', 'console') - cmd = self.replace_paths(target, cmd) elem.add_item('COMMAND', cmd) elem.add_item('description', desc.format(target.name, cmd_type)) self.add_build(elem) @@ -988,65 +986,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 @@ -2105,7 +2066,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) generator = genlist.get_generator() subdir = genlist.subdir exe = generator.get_exe() - exe_arr = self.build_target_to_cmd_array(exe, True) + exe_arr = self.build_target_to_cmd_array(exe) infilelist = genlist.get_inputs() outfilelist = genlist.get_outputs() extra_dependencies = self.get_custom_target_depend_files(genlist) diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index c47fb4a..e94ab49 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 @@ -121,7 +121,7 @@ class Vs2010Backend(backends.Backend): infilelist = genlist.get_inputs() outfilelist = genlist.get_outputs() source_dir = os.path.join(down, self.build_to_src, genlist.subdir) - exe_arr = self.build_target_to_cmd_array(exe, True) + exe_arr = self.build_target_to_cmd_array(exe) idgroup = ET.SubElement(parent_node, 'ItemGroup') for i in range(len(infilelist)): if len(infilelist) == len(outfilelist): @@ -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) |