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.
pull/1171/head
Nirbheek Chauhan 8 years ago
parent 0fc4ad2a0b
commit 82a77609e8
  1. 38
      mesonbuild/backend/backends.py
  2. 22
      mesonbuild/backend/ninjabackend.py
  3. 14
      mesonbuild/build.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):

@ -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)

@ -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):

Loading…
Cancel
Save