diff options
Diffstat (limited to 'mesonbuild/build.py')
-rw-r--r-- | mesonbuild/build.py | 125 |
1 files changed, 89 insertions, 36 deletions
diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 2b4b1b9..4fb977e 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1413,8 +1413,15 @@ class Generator: relpath = pathlib.PurePath(trial).relative_to(parent) return relpath.parts[0] != '..' # For subdirs we can only go "down". - def process_files(self, name, files, state, preserve_path_from=None, extra_args=None): - output = GeneratedList(self, state.subdir, preserve_path_from, extra_args=extra_args if extra_args is not None else []) + def process_files(self, name, files, state, *, + preserve_path_from=None, + extra_args=None, + owning_gentarget=None): + output = GeneratedList(self, + state.subdir, + preserve_path_from=preserve_path_from, + extra_args=extra_args if extra_args is not None else [], + owning_gentarget=owning_gentarget) for f in files: if isinstance(f, str): f = File.from_source_file(state.environment.source_dir, state.subdir, f) @@ -1429,7 +1436,7 @@ class Generator: class GeneratedList: - def __init__(self, generator, subdir, preserve_path_from=None, extra_args=None): + def __init__(self, generator, subdir, *, preserve_path_from=None, extra_args=None, owning_gentarget=None): self.generator = unholder(generator) self.name = self.generator.exe self.subdir = subdir @@ -1448,6 +1455,11 @@ class GeneratedList: # Can only add a dependency on an external program which we # know the absolute path of self.depend_files.append(File.from_absolute_file(path)) + # If None, this generated list is of the old freestanding type. + # Its output goes in the target private directory. Otherwise it is + # the outcome of a generator_target and the output goes in its + # output dir. + self.owning_gentarget = owning_gentarget def add_preserved_path_segment(self, infile, outfiles, state): result = [] @@ -1993,8 +2005,41 @@ class SharedModule(SharedLibrary): def get_default_install_dir(self, environment): return environment.get_shared_module_dir() +class CustomMixin: + def __init__(self, *args, **kwargs): + self.dependencies = [] + self.extra_depends = [] + self.depend_files = [] # Files that this target depends on but are not on the command line. + self.depfile = None -class CustomTarget(Target): + def flatten_command(self, cmd): + cmd = unholder(listify(cmd)) + final_cmd = [] + for c in cmd: + if isinstance(c, str): + final_cmd.append(c) + elif isinstance(c, File): + self.depend_files.append(c) + final_cmd.append(c) + elif isinstance(c, dependencies.ExternalProgram): + if not c.found(): + raise InvalidArguments('Tried to use not-found external program in "command"') + path = c.get_path() + if os.path.isabs(path): + # Can only add a dependency on an external program which we + # know the absolute path of + self.depend_files.append(File.from_absolute_file(path)) + final_cmd += c.get_command() + elif isinstance(c, (BuildTarget, CustomTarget)): + self.dependencies.append(c) + final_cmd.append(c) + elif isinstance(c, list): + final_cmd += self.flatten_command(c) + else: + raise InvalidArguments('Argument {!r} in "command" is invalid'.format(c)) + return final_cmd + +class CustomTarget(Target, CustomMixin): known_kwargs = set([ 'input', 'output', @@ -2016,11 +2061,8 @@ class CustomTarget(Target): def __init__(self, name, subdir, subproject, kwargs, absolute_paths=False, backend=None): self.typename = 'custom' # TODO expose keyword arg to make MachineChoice.HOST configurable - super().__init__(name, subdir, subproject, False, MachineChoice.HOST) - self.dependencies = [] - self.extra_depends = [] - self.depend_files = [] # Files that this target depends on but are not on the command line. - self.depfile = None + Target.__init__(self, name, subdir, subproject, False, MachineChoice.HOST) + CustomMixin.__init__(self) self.process_kwargs(kwargs, backend) self.extra_files = [] # Whether to use absolute paths for all files on the commandline @@ -2065,33 +2107,6 @@ class CustomTarget(Target): bdeps.update(d.get_transitive_build_target_deps()) return bdeps - def flatten_command(self, cmd): - cmd = unholder(listify(cmd)) - final_cmd = [] - for c in cmd: - if isinstance(c, str): - final_cmd.append(c) - elif isinstance(c, File): - self.depend_files.append(c) - final_cmd.append(c) - elif isinstance(c, dependencies.ExternalProgram): - if not c.found(): - raise InvalidArguments('Tried to use not-found external program in "command"') - path = c.get_path() - if os.path.isabs(path): - # Can only add a dependency on an external program which we - # know the absolute path of - self.depend_files.append(File.from_absolute_file(path)) - final_cmd += c.get_command() - elif isinstance(c, (BuildTarget, CustomTarget)): - self.dependencies.append(c) - final_cmd.append(c) - elif isinstance(c, list): - final_cmd += self.flatten_command(c) - else: - raise InvalidArguments('Argument {!r} in "command" is invalid'.format(c)) - return final_cmd - def process_kwargs(self, kwargs, backend): self.process_kwargs_base(kwargs) self.sources = unholder(extract_as_list(kwargs, 'input')) @@ -2261,6 +2276,44 @@ class CustomTarget(Target): for i in self.outputs: yield CustomTargetIndex(self, i) +class GeneratorTarget(Target, CustomMixin): + + def __init__(self, name, state, kwargs, backend=None): + self.typename = 'gent' + Target.__init__(self, name, state.subdir, state.subproject, False, MachineChoice.HOST) + CustomMixin.__init__(self) + self.sources = unholder(extract_as_list(kwargs, 'input')) + self.process_kwargs(kwargs, backend) + self.extra_files = [] + self.output = self.generator.process_files('GeneratorTarget', + self.sources, + state, + owning_gentarget=self) + assert(isinstance(self.output, GeneratedList)) + + def __repr__(self): + repr_str = "<{0} {1}: {2}>" + return repr_str.format(self.__class__.__name__, self.get_id(), self.command) + + def type_suffix(self): + return "@gta" + + def get_dependencies(self): + return self.dependencies + + def process_kwargs(self, kwargs, backend): + if 'generator' not in kwargs: + raise InvalidArguments('Missing keyword argument "command".') + self.generator = unholder(kwargs['generator']) + if not isinstance(self.generator, Generator): + raise InvalidArguments("Generator argument is not a generator object.") + + def should_install(self): + return False + + def get_outputs(self): + return [] + class RunTarget(Target): def __init__(self, name, command, args, dependencies, subdir, subproject): self.typename = 'run' |