aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNirbheek Chauhan <nirbheek@centricular.com>2016-12-09 12:53:10 +0530
committerNirbheek Chauhan <nirbheek@centricular.com>2016-12-13 09:37:47 +0530
commit82a77609e81a513e04fd08a43f0921743a4b1617 (patch)
tree88f59ebe9c39c46d5dcba4a835b81d03feb32f80
parent0fc4ad2a0bc8f60f0c9336a39cf71746d1dab9b9 (diff)
downloadmeson-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.py38
-rw-r--r--mesonbuild/backend/ninjabackend.py22
-rw-r--r--mesonbuild/build.py14
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):