diff options
-rw-r--r-- | mesonbuild/backend/backends.py | 31 | ||||
-rw-r--r-- | mesonbuild/backend/ninjabackend.py | 27 | ||||
-rw-r--r-- | mesonbuild/backend/vs2010backend.py | 14 | ||||
-rw-r--r-- | mesonbuild/scripts/meson_exe.py | 6 | ||||
-rw-r--r-- | test cases/failing build/5 failed pickled/meson.build | 7 |
5 files changed, 60 insertions, 25 deletions
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index a8b6df9..65a8932 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -114,6 +114,7 @@ class ExecutableSerialisation: self.workdir = workdir self.extra_paths = extra_paths self.capture = capture + self.pickled = False class TestSerialisation: def __init__(self, name: str, project: str, suite: str, fname: T.List[str], @@ -395,13 +396,30 @@ class Backend: 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) + reasons = [] + if extra_paths: + reasons.append('to set PATH') + + if exe_wrapper: + reasons.append('to use exe_wrapper') + + if workdir: + reasons.append('to set workdir') + + if any('\n' in c for c in cmd_args): + reasons.append('because command contains newlines') + + force_serialize = force_serialize or bool(reasons) + + if capture: + reasons.append('to capture output') + if not force_serialize: if not capture: - return None - return (self.environment.get_build_command() + - ['--internal', 'exe', '--capture', capture, '--'] + exe_cmd + cmd_args) + return None, '' + return ((self.environment.get_build_command() + + ['--internal', 'exe', '--capture', capture, '--'] + exe_cmd + cmd_args), + ', '.join(reasons)) workdir = workdir or self.environment.get_build_dir() env = {} @@ -425,7 +443,8 @@ class Backend: exe_wrapper, workdir, extra_paths, capture) pickle.dump(es, f) - return self.environment.get_build_command() + ['--internal', 'exe', '--unpickle', exe_data] + return (self.environment.get_build_command() + ['--internal', 'exe', '--unpickle', exe_data], + ', '.join(reasons)) def serialize_tests(self): test_data = os.path.join(self.environment.get_scratch_dir(), 'meson_test_setup.dat') diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index f89b917..a086d37 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -870,7 +870,7 @@ int dummy; (srcs, ofilenames, cmd) = self.eval_custom_target_command(target) deps = self.unwrap_dep_list(target) deps += self.get_custom_target_depend_files(target) - desc = 'Generating {0} with a {1} command' + desc = 'Generating {0} with a custom command{1}' if target.build_always_stale: deps.append('PHONY') if target.depfile is None: @@ -884,14 +884,14 @@ int dummy; for output in d.get_outputs(): elem.add_dep(os.path.join(self.get_target_dir(d), output)) - meson_exe_cmd = 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) + meson_exe_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) if meson_exe_cmd: cmd = meson_exe_cmd - cmd_type = 'meson_exe.py custom' + cmd_type = ' (wrapped by meson {})'.format(reason) else: - cmd_type = 'custom' + cmd_type = '' if target.depfile is not None: depfile = target.get_dep_outname(elem.infilenames) rel_dfile = os.path.join(self.get_target_dir(target), depfile) @@ -2012,9 +2012,9 @@ 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) - meson_exe_cmd = self.as_meson_exe_cmdline('generator ' + cmdlist[0], - cmdlist[0], cmdlist[1:], - capture=outfiles[0] if generator.capture else None) + meson_exe_cmd, reason = 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)) @@ -2026,11 +2026,16 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) elem.add_item('DEPFILE', depfile) if len(extra_dependencies) > 0: elem.add_dep(extra_dependencies) + if len(generator.outputs) == 1: - elem.add_item('DESC', 'Generating {!r}.'.format(sole_output)) + what = '{!r}'.format(sole_output) else: # since there are multiple outputs, we log the source that caused the rebuild - elem.add_item('DESC', 'Generating source from {!r}.'.format(sole_output)) + what = 'from {!r}.'.format(sole_output) + if reason: + reason = ' (wrapped by meson {})'.format(reason) + elem.add_item('DESC', 'Generating {}{}.'.format(what, reason)) + if isinstance(exe, build.BuildTarget): elem.add_dep(self.get_target_filename(exe)) elem.add_item('COMMAND', cmdlist) diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index ab2cafd..021a1da 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -150,7 +150,7 @@ class Vs2010Backend(backends.Backend): # Always use a wrapper because MSBuild eats random characters when # there are many arguments. tdir_abs = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target)) - cmd = self.as_meson_exe_cmdline( + cmd, _ = self.as_meson_exe_cmdline( 'generator ' + cmd[0], cmd[0], cmd[1:], @@ -567,12 +567,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() - wrapper_cmd = self.as_meson_exe_cmdline(target.name, target.command[0], cmd[1:], - # All targets run from the target dir - workdir=tdir_abs, - extra_bdeps=extra_bdeps, - capture=ofilenames[0] if target.capture else None, - force_serialize=True) + wrapper_cmd, _ = self.as_meson_exe_cmdline(target.name, target.command[0], cmd[1:], + # All targets run from the target dir + 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(), diff --git a/mesonbuild/scripts/meson_exe.py b/mesonbuild/scripts/meson_exe.py index df54b47..50ad2f5 100644 --- a/mesonbuild/scripts/meson_exe.py +++ b/mesonbuild/scripts/meson_exe.py @@ -55,9 +55,12 @@ def run_exe(exe: ExecutableSerialisation) -> int: stderr=subprocess.PIPE) stdout, stderr = p.communicate() + if exe.pickled and p.returncode != 0: + print('while executing {!r}'.format(cmd_args)) + if p.returncode == 0xc0000135: # STATUS_DLL_NOT_FOUND on Windows indicating a common problem that is otherwise hard to diagnose - raise FileNotFoundError('Missing DLLs on calling {!r}'.format(cmd_args)) + raise FileNotFoundError('due to missing DLLs') if exe.capture and p.returncode == 0: skip_write = False @@ -90,6 +93,7 @@ def run(args: T.List[str]) -> int: 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) diff --git a/test cases/failing build/5 failed pickled/meson.build b/test cases/failing build/5 failed pickled/meson.build new file mode 100644 index 0000000..28115d5 --- /dev/null +++ b/test cases/failing build/5 failed pickled/meson.build @@ -0,0 +1,7 @@ +project('failed pickled command') + +custom_target('failure', + command: ['false', '\n'], + output: 'output.txt', + build_by_default: true, +) |