diff options
Diffstat (limited to 'mesonbuild/backend/backends.py')
-rw-r--r-- | mesonbuild/backend/backends.py | 95 |
1 files changed, 53 insertions, 42 deletions
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 982b0ee..8c2752a 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -69,17 +69,13 @@ class TargetInstallData: self.optional = optional class ExecutableSerialisation: - def __init__(self, name, fname, cmd_args, env, is_cross, exe_wrapper, - workdir, extra_paths, capture, needs_exe_wrapper: bool): - self.name = name - self.fname = fname + def __init__(self, cmd_args, env=None, exe_wrapper=None, + workdir=None, extra_paths=None, capture=None): self.cmd_args = cmd_args - self.env = env - self.is_cross = is_cross + self.env = env or {} if exe_wrapper is not None: assert(isinstance(exe_wrapper, dependencies.ExternalProgram)) self.exe_runner = exe_wrapper - self.needs_exe_wrapper = needs_exe_wrapper self.workdir = workdir self.extra_paths = extra_paths self.capture = capture @@ -323,26 +319,61 @@ class Backend: raise MesonException('Unknown data type in object list.') return obj_list - def serialize_executable(self, tname, exe, cmd_args, workdir, env=None, - extra_paths=None, capture=None): + def as_meson_exe_cmdline(self, tname, exe, cmd_args, workdir=None, + for_machine=MachineChoice.BUILD, + extra_bdeps=None, capture=None, force_serialize=False): ''' Serialize an executable for running with a generator or a custom target ''' import hashlib - if env is None: - env = {} - if extra_paths is None: - # The callee didn't check if we needed extra paths, so check it here - if mesonlib.is_windows() or mesonlib.is_cygwin(): - extra_paths = self.determine_windows_extra_paths(exe, []) - else: - extra_paths = [] - # Can't just use exe.name here; it will likely be run more than once + machine = self.environment.machines[for_machine] + if machine.is_windows() or machine.is_cygwin(): + extra_paths = self.determine_windows_extra_paths(exe, extra_bdeps or []) + else: + extra_paths = [] + + if isinstance(exe, dependencies.ExternalProgram): + exe_cmd = exe.get_command() + exe_for_machine = exe.for_machine + elif isinstance(exe, (build.BuildTarget, build.CustomTarget)): + exe_cmd = [self.get_target_filename_abs(exe)] + exe_for_machine = exe.for_machine + else: + exe_cmd = [exe] + exe_for_machine = MachineChoice.BUILD + + is_cross_built = not self.environment.machines.matches_build_machine(exe_for_machine) + if is_cross_built and self.environment.need_exe_wrapper(): + exe_wrapper = self.environment.get_exe_wrapper() + if not exe_wrapper.found(): + msg = 'The exe_wrapper {!r} defined in the cross file is ' \ + 'needed by target {!r}, but was not found. Please ' \ + 'check the command and/or add it to PATH.' + raise MesonException(msg.format(exe_wrapper.name, tname)) + else: + if exe_cmd[0].endswith('.jar'): + exe_cmd = ['java', '-jar'] + exe_cmd + elif exe_cmd[0].endswith('.exe') and not (mesonlib.is_windows() or mesonlib.is_cygwin()): + exe_cmd = ['mono'] + exe_cmd + exe_wrapper = None + + force_serialize = force_serialize or extra_paths or workdir or \ + exe_wrapper or any('\n' in c for c in cmd_args) + if not force_serialize: + if not capture: + return None + return (self.environment.get_build_command() + + ['--internal', 'exe', '--capture', capture, '--'] + exe_cmd + cmd_args) + + workdir = workdir or self.environment.get_build_dir() + env = {} if isinstance(exe, (dependencies.ExternalProgram, build.BuildTarget, build.CustomTarget)): basename = exe.name else: 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. @@ -352,31 +383,11 @@ class Backend: scratch_file = 'meson_exe_{0}_{1}.dat'.format(basename, digest) exe_data = os.path.join(self.environment.get_scratch_dir(), scratch_file) with open(exe_data, 'wb') as f: - if isinstance(exe, dependencies.ExternalProgram): - exe_cmd = exe.get_command() - exe_for_machine = exe.for_machine - elif isinstance(exe, (build.BuildTarget, build.CustomTarget)): - exe_cmd = [self.get_target_filename_abs(exe)] - exe_for_machine = exe.for_machine - else: - exe_cmd = [exe] - exe_for_machine = MachineChoice.BUILD - is_cross_built = not self.environment.machines.matches_build_machine(exe_for_machine) - if is_cross_built and self.environment.need_exe_wrapper(): - exe_wrapper = self.environment.get_exe_wrapper() - if not exe_wrapper.found(): - msg = 'The exe_wrapper {!r} defined in the cross file is ' \ - 'needed by target {!r}, but was not found. Please ' \ - 'check the command and/or add it to PATH.' - raise MesonException(msg.format(exe_wrapper.name, tname)) - else: - exe_wrapper = None - es = ExecutableSerialisation(basename, exe_cmd, cmd_args, env, - is_cross_built, exe_wrapper, workdir, - extra_paths, capture, - self.environment.need_exe_wrapper()) + es = ExecutableSerialisation(exe_cmd + cmd_args, env, + exe_wrapper, workdir, + extra_paths, capture) pickle.dump(es, f) - return exe_data + return self.environment.get_build_command() + ['--internal', 'exe', '--unpickle', exe_data] def serialize_tests(self): test_data = os.path.join(self.environment.get_scratch_dir(), 'meson_test_setup.dat') |