diff options
author | Nirbheek Chauhan <nirbheek@centricular.com> | 2016-12-09 12:53:10 +0530 |
---|---|---|
committer | Nirbheek Chauhan <nirbheek@centricular.com> | 2016-12-13 09:37:47 +0530 |
commit | 82a77609e81a513e04fd08a43f0921743a4b1617 (patch) | |
tree | 88f59ebe9c39c46d5dcba4a835b81d03feb32f80 | |
parent | 0fc4ad2a0bc8f60f0c9336a39cf71746d1dab9b9 (diff) | |
download | meson-82a77609e81a513e04fd08a43f0921743a4b1617.zip meson-82a77609e81a513e04fd08a43f0921743a4b1617.tar.gz meson-82a77609e81a513e04fd08a43f0921743a4b1617.tar.bz2 |
Query the target itself for the dynamic linker
This greatly improves the logic for determining the linker. Previously,
we would completely break if a target contained only extracted objects
and we were using more than one compiler in our project.
This also fixes determination of the linker if our target only contains
generated objc++ sources, and other funky combinations.
-rw-r--r-- | mesonbuild/backend/backends.py | 38 | ||||
-rw-r--r-- | mesonbuild/backend/ninjabackend.py | 22 | ||||
-rw-r--r-- | mesonbuild/build.py | 14 |
3 files changed, 33 insertions, 41 deletions
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 91c5b0f..48dfb11 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -235,39 +235,21 @@ class Backend(): self.write_benchmark_file(datafile) return (test_data, benchmark_data) - def determine_linker(self, target, src): + def determine_linker(self, target): + ''' + If we're building a static library, there is only one static linker. + Otherwise, we query the target for the dynamic linker. + ''' if isinstance(target, build.StaticLibrary): if target.is_cross: return self.build.static_cross_linker else: return self.build.static_linker - if target.is_cross: - compilers = self.build.cross_compilers - else: - compilers = self.build.compilers - if len(compilers) == 1: - return compilers[0] - # Currently a bit naive. C++ must - # be linked with a C++ compiler, but - # otherwise we don't care. This will - # become trickier if and when Fortran - # and the like become supported. - cpp = None - for c in compilers: - if c.get_language() == 'cpp': - cpp = c - break - if cpp is not None: - for s in src: - if c.can_compile(s): - return cpp - for c in compilers: - if c.get_language() == 'vala': - continue - for s in src: - if c.can_compile(s): - return c - raise AssertionError("BUG: Couldn't determine linker for sources {!r}".format(src)) + l = target.get_clike_dynamic_linker() + if not l: + m = "Couldn't determine linker for target {!r}" + raise MesonException(m.format(target.name)) + return l def object_filename_from_source(self, target, source): if isinstance(source, mesonlib.File): diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index f39f361..39e0e79 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -299,6 +299,9 @@ int dummy; self.generate_swift_target(target, outfile) return + # Now we handle the following languages: + # ObjC++, ObjC, C++, C, D, Fortran, Vala + # Pre-existing target C/C++ sources to be built; dict of full path to # source relative to build root and the original File object. target_sources = OrderedDict() @@ -332,7 +335,6 @@ int dummy; unity_src = [] unity_deps = [] # Generated sources that must be built before compiling a Unity target. header_deps += self.get_generated_headers(target) - src_list = [] if is_unity: # Warn about incompatible sources if a unity build is enabled @@ -346,16 +348,12 @@ int dummy; ''.format(langs_are, langs, target.name) mlog.log(mlog.red('FIXME'), msg) - # Get a list of all generated *sources* (sources files, headers, - # objects, etc). Needed to determine the linker. - generated_output_sources = [] # Get a list of all generated headers that will be needed while building # this target's sources (generated sources and pre-existing sources). # This will be set as dependencies of all the target's sources. At the # same time, also deal with generated sources that need to be compiled. generated_source_files = [] for rel_src, gensrc in generated_sources.items(): - generated_output_sources.append(rel_src) raw_src = RawFilename(rel_src) if self.environment.is_source(rel_src) and not self.environment.is_header(rel_src): if is_unity and self.get_target_source_can_unity(target, rel_src): @@ -377,12 +375,12 @@ int dummy; # this target. We create the Ninja build file elements for this here # because we need `header_deps` to be fully generated in the above loop. for src in generated_source_files: - src_list.append(src) if self.environment.is_llvm_ir(src): - obj_list.append(self.generate_llvm_ir_compile(target, outfile, src)) - continue - obj_list.append(self.generate_single_compile(target, outfile, src, True, - header_deps=header_deps)) + o = self.generate_llvm_ir_compile(target, outfile, src) + else: + o = self.generate_single_compile(target, outfile, src, True, + header_deps=header_deps) + obj_list.append(o) # Generate compilation targets for C sources generated from Vala # sources. This can be extended to other $LANG->C compilers later if @@ -390,7 +388,6 @@ int dummy; vala_generated_source_files = [] for src in vala_generated_sources: raw_src = RawFilename(src) - src_list.append(src) if is_unity: unity_src.append(os.path.join(self.environment.get_build_dir(), src)) header_deps.append(raw_src) @@ -415,7 +412,6 @@ int dummy; # Generate compile targets for all the pre-existing sources for this target for f, src in target_sources.items(): if not self.environment.is_header(src): - src_list.append(src) if self.environment.is_llvm_ir(src): obj_list.append(self.generate_llvm_ir_compile(target, outfile, src)) elif is_unity and self.get_target_source_can_unity(target, src): @@ -428,7 +424,7 @@ int dummy; if is_unity: for src in self.generate_unity_files(target, unity_src): obj_list.append(self.generate_single_compile(target, outfile, RawFilename(src), True, unity_deps + header_deps)) - linker = self.determine_linker(target, src_list + generated_output_sources) + linker = self.determine_linker(target) elem = self.generate_link(target, outfile, outname, obj_list, linker, pch_objects) self.generate_shlib_aliases(target, self.get_target_dir(target)) elem.write(outfile) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index cc34d57..bfb094e 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -804,6 +804,20 @@ class BuildTarget(): def get_aliaslist(self): return [] + def get_clike_dynamic_linker(self): + ''' + We use the order of languages in `clike_langs` to determine which + linker to use in case the target has sources compiled with multiple + compilers. All languages other than those in this list have their own + linker. + Note that Vala outputs C code, so Vala sources can use any linker + that can link compiled C. We don't actually need to add an exception + for Vala here because of that. + ''' + for l in clike_langs: + if l in self.compilers: + return self.compilers[l] + class Generator(): def __init__(self, args, kwargs): |