diff options
author | Dylan Baker <dylan@pnwbakers.com> | 2017-09-25 13:46:07 -0700 |
---|---|---|
committer | Jussi Pakkanen <jpakkane@gmail.com> | 2017-09-27 22:01:24 +0300 |
commit | dda5e8cadbfdeee3267b1a0943c014e06bcd0100 (patch) | |
tree | 049a70c550729d722e23c67d8312c2eaa820da6f /mesonbuild | |
parent | dfc2b75ee2dba3245ac23bb3d7f0156e47773ed5 (diff) | |
download | meson-dda5e8cadbfdeee3267b1a0943c014e06bcd0100.zip meson-dda5e8cadbfdeee3267b1a0943c014e06bcd0100.tar.gz meson-dda5e8cadbfdeee3267b1a0943c014e06bcd0100.tar.bz2 |
Allow CustomTarget's to be indexed
This allows a CustomTarget to be indexed, and the resulting indexed
value (a CustomTargetIndex type), to be used as a source in other
targets. This will confer a dependency on the original target, but only
inserts the source file returning by index the original target's
outputs. This can allow a CustomTarget that creates both a header and a
code file to have it's outputs split, for example.
Fixes #1470
Diffstat (limited to 'mesonbuild')
-rw-r--r-- | mesonbuild/backend/backends.py | 2 | ||||
-rw-r--r-- | mesonbuild/backend/ninjabackend.py | 11 | ||||
-rw-r--r-- | mesonbuild/backend/vs2010backend.py | 4 | ||||
-rw-r--r-- | mesonbuild/build.py | 34 | ||||
-rw-r--r-- | mesonbuild/interpreter.py | 16 | ||||
-rw-r--r-- | mesonbuild/interpreterbase.py | 10 | ||||
-rw-r--r-- | mesonbuild/modules/gnome.py | 9 |
7 files changed, 69 insertions, 17 deletions
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 97959b6..12fb3eb 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -174,7 +174,7 @@ class Backend: Returns the full path of the generated source relative to the build root """ # CustomTarget generators output to the build dir of the CustomTarget - if isinstance(gensrc, build.CustomTarget): + if isinstance(gensrc, (build.CustomTarget, build.CustomTargetIndex)): return os.path.join(self.get_target_dir(gensrc), src) # GeneratedList generators output to the private build directory of the # target that the GeneratedList is used in diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 41b93cb..d2ba49f 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -245,7 +245,7 @@ int dummy; header_deps = [] # XXX: Why don't we add deps to CustomTarget headers here? for genlist in target.get_generated_sources(): - if isinstance(genlist, build.CustomTarget): + if isinstance(genlist, (build.CustomTarget, build.CustomTargetIndex)): continue for src in genlist.get_outputs(): if self.environment.is_header(src): @@ -1761,10 +1761,11 @@ rule FORTRAN_DEP_HACK outfile.write('\n') def generate_generator_list_rules(self, target, outfile): - # CustomTargets have already written their rules, - # so write rules for GeneratedLists here + # CustomTargets have already written their rules and + # CustomTargetIndexes don't actually get generated, so write rules for + # GeneratedLists here for genlist in target.get_generated_sources(): - if isinstance(genlist, build.CustomTarget): + if isinstance(genlist, (build.CustomTarget, build.CustomTargetIndex)): continue self.generate_genlist_for_target(genlist, target, outfile) @@ -2013,7 +2014,7 @@ rule FORTRAN_DEP_HACK # Generator output goes into the target private dir which is # already in the include paths list. Only custom targets have their # own target build dir. - if not isinstance(i, build.CustomTarget): + if not isinstance(i, (build.CustomTarget, build.CustomTargetIndex)): continue idir = self.get_target_dir(i) if idir not in custom_target_include_dirs: diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index 22c1779..cb8dad6 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -91,7 +91,7 @@ class Vs2010Backend(backends.Backend): source_target_dir = self.get_target_source_dir(target) down = self.target_to_build_root(target) for genlist in target.get_generated_sources(): - if isinstance(genlist, build.CustomTarget): + if isinstance(genlist, (build.CustomTarget, build.CustomTargetIndex)): for i in genlist.get_outputs(): # Path to the generated source from the current vcxproj dir via the build root ipath = os.path.join(down, self.get_target_dir(genlist), i) @@ -201,6 +201,8 @@ class Vs2010Backend(backends.Backend): for gendep in target.get_generated_sources(): if isinstance(gendep, build.CustomTarget): all_deps[gendep.get_id()] = gendep + elif isinstance(gendep, build.CustomTargetIndex): + all_deps[gendep.target.get_id()] = gendep.target else: gen_exe = gendep.generator.get_exe() if isinstance(gen_exe, build.Executable): diff --git a/mesonbuild/build.py b/mesonbuild/build.py index c54abbd..d3c0b54 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -425,7 +425,7 @@ class BuildTarget(Target): if s not in added_sources: self.sources.append(s) added_sources[s] = True - elif isinstance(s, (GeneratedList, CustomTarget)): + elif isinstance(s, (GeneratedList, CustomTarget, CustomTargetIndex)): self.generated.append(s) else: msg = 'Bad source of type {!r} in target {!r}.'.format(type(s).__name__, self.name) @@ -1676,6 +1676,15 @@ class CustomTarget(Target): def type_suffix(self): return "@cus" + def __getitem__(self, index): + return CustomTargetIndex(self, self.outputs[index]) + + def __setitem__(self, index, value): + raise NotImplementedError + + def __delitem__(self, index): + raise NotImplementedError + class RunTarget(Target): def __init__(self, name, command, args, dependencies, subdir): super().__init__(name, subdir, False) @@ -1735,6 +1744,29 @@ class Jar(BuildTarget): pass +class CustomTargetIndex: + + """A special opaque object returned by indexing a CustomTaget. This object + exists in meson, but acts as a proxy in the backends, making targets depend + on the CustomTarget it's derived from, but only adding one source file to + the sources. + """ + + def __init__(self, target, output): + self.target = target + self.output = output + + def __repr__(self): + return '<CustomTargetIndex: {!r}[{}]>'.format( + self.target, self.target.output.index(self.output)) + + def get_outputs(self): + return [self.output] + + def get_subdir(self): + return self.target.get_subdir() + + class ConfigureFile: def __init__(self, subdir, sourcename, targetname, configuration_data): diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 2148bed..012370d 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -566,6 +566,11 @@ class JarHolder(BuildTargetHolder): def __init__(self, target, interp): super().__init__(target, interp) +class CustomTargetIndexHolder(InterpreterObject): + def __init__(self, object_to_hold): + super().__init__() + self.held_object = object_to_hold + class CustomTargetHolder(TargetHolder): def __init__(self, object_to_hold, interp): super().__init__() @@ -582,6 +587,15 @@ class CustomTargetHolder(TargetHolder): def full_path_method(self, args, kwargs): return self.interpreter.backend.get_target_filename_abs(self.held_object) + def __getitem__(self, index): + return CustomTargetIndexHolder(self.held_object[index]) + + def __setitem__(self, index, value): + raise InterpreterException('Cannot set a member of a CustomTarget') + + def __delitem__(self, index): + raise InterpreterException('Cannot delete a member of a CustomTarget') + class RunTargetHolder(InterpreterObject): def __init__(self, name, command, args, dependencies, subdir): super().__init__() @@ -2774,7 +2788,7 @@ different subdirectory. results = [] for s in sources: if isinstance(s, (mesonlib.File, GeneratedListHolder, - CustomTargetHolder)): + CustomTargetHolder, CustomTargetIndexHolder)): pass elif isinstance(s, str): s = mesonlib.File.from_source_file(self.environment.source_dir, self.subdir, s) diff --git a/mesonbuild/interpreterbase.py b/mesonbuild/interpreterbase.py index 1dd2f02..cb82e56 100644 --- a/mesonbuild/interpreterbase.py +++ b/mesonbuild/interpreterbase.py @@ -369,14 +369,16 @@ class InterpreterBase: def evaluate_indexing(self, node): assert(isinstance(node, mparser.IndexNode)) iobject = self.evaluate_statement(node.iobject) - if not isinstance(iobject, list): - raise InterpreterException('Tried to index a non-array object.') + if not hasattr(iobject, '__getitem__'): + raise InterpreterException( + 'Tried to index an object that doesn\'t support indexing.') index = self.evaluate_statement(node.index) if not isinstance(index, int): raise InterpreterException('Index value is not an integer.') - if index < -len(iobject) or index >= len(iobject): + try: + return iobject[index] + except IndexError: raise InterpreterException('Index %d out of bounds of array of size %d.' % (index, len(iobject))) - return iobject[index] def function_call(self, node): func_name = node.func_name diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index 1ab075b..d1d7013 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -107,12 +107,12 @@ class GnomeModule(ExtensionModule): for (ii, dep) in enumerate(dependencies): if hasattr(dep, 'held_object'): dependencies[ii] = dep = dep.held_object - if not isinstance(dep, (mesonlib.File, build.CustomTarget)): + if not isinstance(dep, (mesonlib.File, build.CustomTarget, build.CustomTargetIndex)): m = 'Unexpected dependency type {!r} for gnome.compile_resources() ' \ '"dependencies" argument.\nPlease pass the return value of ' \ 'custom_target() or configure_file()' raise MesonException(m.format(dep)) - if isinstance(dep, build.CustomTarget): + if isinstance(dep, (build.CustomTarget, build.CustomTargetIndex)): if not mesonlib.version_compare(glib_version, gresource_dep_needed_version): m = 'The "dependencies" argument of gnome.compile_resources() can not\n' \ 'be used with the current version of glib-compile-resources due to\n' \ @@ -131,6 +131,7 @@ class GnomeModule(ExtensionModule): elif isinstance(ifile, str): ifile = os.path.join(state.subdir, ifile) elif isinstance(ifile, (interpreter.CustomTargetHolder, + interpreter.CustomTargetIndexHolder, interpreter.GeneratedObjectsHolder)): m = 'Resource xml files generated at build-time cannot be used ' \ 'with gnome.compile_resources() because we need to scan ' \ @@ -261,7 +262,7 @@ class GnomeModule(ExtensionModule): dep_files.append(dep) subdirs.append(dep.subdir) break - elif isinstance(dep, build.CustomTarget): + elif isinstance(dep, (build.CustomTarget, build.CustomTargetIndex)): fname = None outputs = {(o, os.path.basename(o)) for o in dep.get_outputs()} for o, baseo in outputs: @@ -443,7 +444,7 @@ class GnomeModule(ExtensionModule): for s in libsources: if hasattr(s, 'held_object'): s = s.held_object - if isinstance(s, build.CustomTarget): + if isinstance(s, (build.CustomTarget, build.CustomTargetIndex)): gir_filelist.write(os.path.join(state.environment.get_build_dir(), state.backend.get_target_dir(s), s.get_outputs()[0]) + '\n') |