diff --git a/mesonbuild/cmake/data/run_ctgt.py b/mesonbuild/cmake/data/run_ctgt.py index d4e325922..4e9428335 100755 --- a/mesonbuild/cmake/data/run_ctgt.py +++ b/mesonbuild/cmake/data/run_ctgt.py @@ -13,13 +13,16 @@ SEPARATOR = ';;;' parser = argparse.ArgumentParser(description='Wrapper for add_custom_command') parser.add_argument('-d', '--directory', type=str, metavar='D', required=True, help='Working directory to cwd to') parser.add_argument('-o', '--outputs', nargs='+', metavar='O', required=True, help='Expected output files') -parser.add_argument('-O', '--original-outputs', nargs='+', metavar='O', required=True, help='Output files expected by CMake') -parser.add_argument('commands', nargs=argparse.REMAINDER, help='A "{}" separated list of commands'.format(SEPARATOR)) +parser.add_argument('-O', '--original-outputs', nargs='*', metavar='O', default=[], help='Output files expected by CMake') +parser.add_argument('commands', nargs=argparse.REMAINDER, help='A "{}" seperated list of commands'.format(SEPERATOR)) # Parse args = parser.parse_args() -if len(args.outputs) != len(args.original_outputs): +dummy_target = None +if len(args.outputs) == 1 and len(args.original_outputs) == 0: + dummy_target = args.outputs[0] +elif len(args.outputs) != len(args.original_outputs): print('Length of output list and original output list differ') sys.exit(1) @@ -39,6 +42,11 @@ for i in commands: subprocess.run(i, cwd=args.directory) +if dummy_target: + with open(dummy_target, 'a'): + os.utime(dummy_target, None) + exit(0) + # Copy outputs zipped_outputs = zip(args.outputs, args.original_outputs) for expected, generated in zipped_outputs: diff --git a/mesonbuild/cmake/interpreter.py b/mesonbuild/cmake/interpreter.py index 718e70acc..5fd8ce0ed 100644 --- a/mesonbuild/cmake/interpreter.py +++ b/mesonbuild/cmake/interpreter.py @@ -408,7 +408,10 @@ class ConverterCustomTarget: out_counter = 0 # type: int def __init__(self, target: CMakeGeneratorTarget): - self.name = 'custom_tgt_{}'.format(ConverterCustomTarget.tgt_counter) + self.name = target.name + if not self.name: + self.name = 'custom_tgt_{}'.format(ConverterCustomTarget.tgt_counter) + ConverterCustomTarget.tgt_counter += 1 self.original_outputs = list(target.outputs) self.outputs = [os.path.basename(x) for x in self.original_outputs] self.conflict_map = {} @@ -418,8 +421,6 @@ class ConverterCustomTarget: self.inputs = [] self.depends = [] - ConverterCustomTarget.tgt_counter += 1 - def __repr__(self) -> str: return '<{}: {}>'.format(self.__class__.__name__, self.outputs) @@ -729,6 +730,7 @@ class CMakeInterpreter: for j in i.artifacts: output_target_map[os.path.basename(j)] = i for i in self.custom_targets: + output_target_map[_target_key(i.name)] = i for j in i.original_outputs: output_target_map[_generated_file_key(j)] = i object_libs = [] @@ -971,6 +973,11 @@ class CMakeInterpreter: tgt_var = tgt.name # type: str + # If the custom target does not declare any output, create a dummy + # one that can be used as dependency. + if not tgt.outputs: + tgt.outputs = [tgt.name + '.h'] + def resolve_source(x: Any) -> Any: if isinstance(x, ConverterTarget): if x.name not in processed: @@ -991,7 +998,8 @@ class CMakeInterpreter: command = [] command += [id_node(run_script_var)] command += ['-o', '@OUTPUT@'] - command += ['-O'] + tgt.original_outputs + if tgt.original_outputs: + command += ['-O'] + tgt.original_outputs command += ['-d', tgt.working_dir] # Generate the commands. Subcommands are separated by ';;;' diff --git a/mesonbuild/cmake/traceparser.py b/mesonbuild/cmake/traceparser.py index c5e0d93a9..50cabab7c 100644 --- a/mesonbuild/cmake/traceparser.py +++ b/mesonbuild/cmake/traceparser.py @@ -52,12 +52,12 @@ class CMakeTarget: propSTR += " '{}': {}\n".format(i, self.properties[i]) return s.format(self.name, self.type, self.imported, propSTR, self.tline) -class CMakeGeneratorTarget: - def __init__(self): +class CMakeGeneratorTarget(CMakeTarget): + def __init__(self, name): + super().__init__(name, 'CUSTOM', {}) self.outputs = [] # type: List[str] self.command = [] # type: List[List[str]] self.working_dir = None # type: Optional[str] - self.depends = [] # type: List[str] class CMakeTraceParser: def __init__(self, permissive: bool = False): @@ -237,7 +237,7 @@ class CMakeTraceParser: else: self.targets[args[0]] = CMakeTarget(args[0], 'NORMAL', {}, tline=tline) - def _cmake_add_custom_command(self, tline: CMakeTraceLine): + def _cmake_add_custom_command(self, tline: CMakeTraceLine, name=None): # DOC: https://cmake.org/cmake/help/latest/command/add_custom_command.html args = list(tline.args) # Make a working copy @@ -252,7 +252,7 @@ class CMakeTraceParser: 'IMPLICIT_DEPENDS', 'WORKING_DIRECTORY', 'COMMENT', 'DEPFILE', 'JOB_POOL', 'VERBATIM', 'APPEND', 'USES_TERMINAL', 'COMMAND_EXPAND_LISTS'] - target = CMakeGeneratorTarget() + target = CMakeGeneratorTarget(name) def handle_output(key: str, target: CMakeGeneratorTarget) -> None: target.outputs += [key] @@ -297,6 +297,8 @@ class CMakeTraceParser: target.command = [self._guess_files(x) for x in target.command] self.custom_targets += [target] + if name: + self.targets[name] = target def _cmake_add_custom_target(self, tline: CMakeTraceLine): # DOC: https://cmake.org/cmake/help/latest/command/add_custom_target.html @@ -304,7 +306,8 @@ class CMakeTraceParser: if len(tline.args) < 1: return self._gen_exception('add_custom_target', 'requires at least one argument', tline) - self.targets[tline.args[0]] = CMakeTarget(tline.args[0], 'CUSTOM', {}, tline=tline) + # It's pretty much the same as a custom command + self._cmake_add_custom_command(tline, tline.args[0]) def _cmake_set_property(self, tline: CMakeTraceLine) -> None: # DOC: https://cmake.org/cmake/help/latest/command/set_property.html