diff options
-rw-r--r-- | mesonbuild/backend/backends.py | 29 | ||||
-rw-r--r-- | mesonbuild/backend/ninjabackend.py | 54 | ||||
-rw-r--r-- | mesonbuild/backend/vs2010backend.py | 13 |
3 files changed, 40 insertions, 56 deletions
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 71d5e20..b016fe5 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -323,26 +323,33 @@ class Backend: raise MesonException('Unknown data type in object list.') return obj_list - def as_meson_exe_cmdline(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 = [] + + force_serialize = force_serialize or extra_paths or capture or workdir or \ + any('\n' in c for c in cmd_args) + if not force_serialize: + return None + + 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. diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 3dfb2ae..b0bbbf5 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -658,32 +658,13 @@ int dummy; # Add a dependency on all the outputs of this target for output in d.get_outputs(): elem.add_dep(os.path.join(self.get_target_dir(d), output)) - serialize = False - extra_paths = [] - # If the target requires capturing stdout, then use the serialized - # executable wrapper to capture that output and save it to a file. - if target.capture: - serialize = True - # If the command line requires a newline, also use the wrapper, as - # ninja does not support them in its build rule syntax. - if any('\n' in c for c in cmd): - serialize = True - # 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. - machine = self.environment.machines[target.for_machine] - if machine.is_windows() or machine.is_cygwin(): - extra_bdeps = target.get_transitive_build_target_deps() - extra_paths = self.determine_windows_extra_paths(target.command[0], extra_bdeps) - if extra_paths: - serialize = True - if serialize: - cmd = self.as_meson_exe_cmdline(target.name, target.command[0], cmd[1:], - # All targets are built from the build dir - self.environment.get_build_dir(), - extra_paths=extra_paths, - capture=ofilenames[0] if target.capture else None) + + meson_exe_cmd = self.as_meson_exe_cmdline(target.name, target.command[0], cmd[1:], + for_machine=target.for_machine, + extra_bdeps=target.get_transitive_build_target_deps(), + capture=ofilenames[0] if target.capture else None) + if meson_exe_cmd: + cmd = meson_exe_cmd cmd_type = 'meson_exe.py custom' else: cmd_type = 'custom' @@ -1785,18 +1766,13 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) outfilelist = outfilelist[len(generator.outputs):] args = self.replace_paths(target, args, override_subdir=subdir) cmdlist = exe_arr + self.replace_extra_args(args, genlist) - if generator.capture: - cmd = self.as_meson_exe_cmdline( - 'generator ' + cmdlist[0], - cmdlist[0], - cmdlist[1:], - self.environment.get_build_dir(), - capture=outfiles[0] - ) - abs_pdir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target)) - os.makedirs(abs_pdir, exist_ok=True) - else: - cmd = cmdlist + meson_exe_cmd = self.as_meson_exe_cmdline('generator ' + cmdlist[0], + cmdlist[0], cmdlist[1:], + capture=outfiles[0] if generator.capture else None) + if meson_exe_cmd: + cmdlist = meson_exe_cmd + abs_pdir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target)) + os.makedirs(abs_pdir, exist_ok=True) elem = NinjaBuildElement(self.all_outputs, outfiles, rulename, infilename) elem.add_dep([self.get_target_filename(x) for x in generator.depends]) @@ -1811,7 +1787,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) elem.add_item('DESC', 'Generating source from {!r}.'.format(sole_output)) if isinstance(exe, build.BuildTarget): elem.add_dep(self.get_target_filename(exe)) - elem.add_item('COMMAND', cmd) + elem.add_item('COMMAND', cmdlist) self.add_build(elem) def scan_fortran_module_outputs(self, target): diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index 054fae0..a0f6a95 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -150,8 +150,9 @@ class Vs2010Backend(backends.Backend): 'generator ' + cmd[0], cmd[0], cmd[1:], - tdir_abs, - capture=outfiles[0] if generator.capture else None + workdir=tdir_abs, + capture=outfiles[0] if generator.capture else None, + force_serialize=True ) deps = cmd[-1:] + deps abs_pdir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target)) @@ -559,12 +560,12 @@ class Vs2010Backend(backends.Backend): # there are many arguments. tdir_abs = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target)) extra_bdeps = target.get_transitive_build_target_deps() - extra_paths = self.determine_windows_extra_paths(target.command[0], extra_bdeps) wrapper_cmd = self.as_meson_exe_cmdline(target.name, target.command[0], cmd[1:], # All targets run from the target dir - tdir_abs, - extra_paths=extra_paths, - capture=ofilenames[0] if target.capture else None) + workdir=tdir_abs, + extra_bdeps=extra_bdeps, + capture=ofilenames[0] if target.capture else None, + force_serialize=True) if target.build_always_stale: # Use a nonexistent file to always consider the target out-of-date. ofilenames += [self.nonexistent_file(os.path.join(self.environment.get_scratch_dir(), |