summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mesonbuild/backend/backends.py20
-rw-r--r--mesonbuild/backend/ninjabackend.py116
2 files changed, 81 insertions, 55 deletions
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index a83d95f27..4988f2820 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -692,23 +692,3 @@ class Backend:
for s in self.build.postconf_scripts:
cmd = s['exe'] + s['args']
subprocess.check_call(cmd, env=child_env)
-
- # Subprojects of subprojects may cause the same dep args to be used
- # multiple times. Remove duplicates here. Note that we can't dedup
- # libraries based on name alone, because "-lfoo -lbar -lfoo" is
- # a completely valid (though pathological) sequence and removing the
- # latter may fail. Usually only applies to static libs, though.
- def dedup_arguments(self, commands):
- includes = {}
- final_commands = []
- previous = '-fsuch_arguments=woof'
- for c in commands:
- if c.startswith(('-I', '-L', '/LIBPATH')):
- if c in includes:
- continue
- includes[c] = True
- if previous == c:
- continue
- previous = c
- final_commands.append(c)
- return final_commands
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 98740a4d0..9444087de 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -2043,47 +2043,23 @@ rule FORTRAN_DEP_HACK
return []
return linker.get_no_stdlib_link_args()
- def generate_link(self, target, outfile, outname, obj_list, linker, extra_args=[]):
- if isinstance(target, build.StaticLibrary):
- linker_base = 'STATIC'
- else:
- linker_base = linker.get_language() # Fixme.
- if isinstance(target, build.SharedLibrary):
- self.generate_shsym(outfile, target)
- crstr = ''
- if target.is_cross:
- crstr = '_CROSS'
- linker_rule = linker_base + crstr + '_LINKER'
+ def get_target_type_link_args(self, target, linker):
abspath = os.path.join(self.environment.get_build_dir(), target.subdir)
commands = []
- if not isinstance(target, build.StaticLibrary):
- commands += self.build.get_project_link_args(linker, target.subproject)
- commands += self.build.get_global_link_args(linker)
- commands += self.get_cross_stdlib_link_args(target, linker)
- commands += linker.get_linker_always_args()
- if not isinstance(target, build.StaticLibrary):
- commands += compilers.get_base_link_args(self.environment.coredata.base_options,
- linker,
- isinstance(target, build.SharedModule))
- commands += linker.get_buildtype_linker_args(self.environment.coredata.get_builtin_option('buildtype'))
- commands += linker.get_option_link_args(self.environment.coredata.compiler_options)
- commands += self.get_link_debugfile_args(linker, target, outname)
- if not(isinstance(target, build.StaticLibrary)):
- commands += self.environment.coredata.external_link_args[linker.get_language()]
if isinstance(target, build.Executable):
+ # Currently only used with the Swift compiler to add '-emit-executable'
commands += linker.get_std_exe_link_args()
elif isinstance(target, build.SharedLibrary):
if isinstance(target, build.SharedModule):
commands += linker.get_std_shared_module_link_args()
else:
commands += linker.get_std_shared_lib_link_args()
+ # All shared libraries are PIC
commands += linker.get_pic_args()
- if hasattr(target, 'soversion'):
- soversion = target.soversion
- else:
- soversion = None
+ # Add -Wl,-soname arguments on Linux, -install_name on OS X
commands += linker.get_soname_args(target.prefix, target.name, target.suffix,
- abspath, soversion, isinstance(target, build.SharedModule))
+ abspath, target.soversion,
+ isinstance(target, build.SharedModule))
# This is only visited when using the Visual Studio toolchain
if target.vs_module_defs and hasattr(linker, 'gen_vs_module_defs_args'):
commands += linker.gen_vs_module_defs_args(target.vs_module_defs.rel_to_builddir(self.build_to_src))
@@ -2094,17 +2070,75 @@ rule FORTRAN_DEP_HACK
commands += linker.get_std_link_args()
else:
raise RuntimeError('Unknown build target type.')
- # Link arguments of static libraries are not put in the command line of
- # the library. They are instead appended to the command line where
- # the static library is used.
+ return commands
+
+ def generate_link(self, target, outfile, outname, obj_list, linker, extra_args=[]):
+ if isinstance(target, build.StaticLibrary):
+ linker_base = 'STATIC'
+ else:
+ linker_base = linker.get_language() # Fixme.
+ if isinstance(target, build.SharedLibrary):
+ self.generate_shsym(outfile, target)
+ crstr = ''
+ if target.is_cross:
+ crstr = '_CROSS'
+ linker_rule = linker_base + crstr + '_LINKER'
+
+ # Create an empty commands list, and start adding link arguments from
+ # various sources in the order in which they must override each other
+ # starting from hard-coded defaults followed by build options and so on.
+ #
+ # Once all the linker options have been passed, we will start passing
+ # libraries and library paths from internal and external sources.
+ commands = CompilerArgs(linker)
+ # First, the trivial ones that are impossible to override.
+ #
+ # Add linker args for linking this target derived from 'base' build
+ # options passed on the command-line, in default_options, etc.
+ # These have the lowest priority.
+ if not isinstance(target, build.StaticLibrary):
+ commands += compilers.get_base_link_args(self.environment.coredata.base_options,
+ linker,
+ isinstance(target, build.SharedModule))
+ # Add -nostdlib if needed; can't be overriden
+ commands += self.get_cross_stdlib_link_args(target, linker)
+ # Add things like /NOLOGO; usually can't be overriden
+ commands += linker.get_linker_always_args()
+ # Add buildtype linker args: optimization level, etc.
+ commands += linker.get_buildtype_linker_args(self.environment.coredata.get_builtin_option('buildtype'))
+ # Add /DEBUG and the pdb filename when using MSVC
+ commands += self.get_link_debugfile_args(linker, target, outname)
+ # Add link args specific to this BuildTarget type, such as soname args,
+ # PIC, import library generation, etc.
+ commands += self.get_target_type_link_args(target, linker)
+ if not isinstance(target, build.StaticLibrary):
+ # Add link args added using add_project_link_arguments()
+ commands += self.build.get_project_link_args(linker, target.subproject)
+ # Add link args added using add_global_link_arguments()
+ # These override per-project link arguments
+ commands += self.build.get_global_link_args(linker)
+ # Link args added from the env: LDFLAGS. We want these to
+ # override all the defaults but not the per-target link args.
+ commands += self.environment.coredata.external_link_args[linker.get_language()]
+
+ # Now we will add libraries and library paths from various sources
+
+ # Add link args to link to all internal libraries (link_with:) and
+ # internal dependencies needed by this target.
if linker_base == 'STATIC':
+ # Link arguments of static libraries are not put in the command
+ # line of the library. They are instead appended to the command
+ # line where the static library is used.
dependencies = []
else:
dependencies = target.get_dependencies()
commands += self.build_target_link_arguments(linker, dependencies)
+ # For 'automagic' deps: Boost and GTest. Also dependency('threads').
+ # pkg-config puts the thread flags itself via `Cflags:`
for d in target.external_deps:
if d.need_threads():
commands += linker.thread_link_flags()
+ # Only non-static built targets need link args and link dependencies
if not isinstance(target, build.StaticLibrary):
commands += target.link_args
# External deps must be last because target link libraries may depend on them.
@@ -2114,12 +2148,24 @@ rule FORTRAN_DEP_HACK
if isinstance(d, build.StaticLibrary):
for dep in d.get_external_deps():
commands += dep.get_link_args()
+ # Add link args for c_* or cpp_* build options. Currently this only
+ # adds c_winlibs and cpp_winlibs when building for Windows. This needs
+ # to be after all internal and external libraries so that unresolved
+ # symbols from those can be found here. This is needed when the
+ # *_winlibs that we want to link to are static mingw64 libraries.
+ commands += linker.get_option_link_args(self.environment.coredata.compiler_options)
+ # Set runtime-paths so we can run executables without needing to set
+ # LD_LIBRARY_PATH, etc in the environment. Doesn't work on Windows.
commands += linker.build_rpath_args(self.environment.get_build_dir(),
- self.determine_rpath_dirs(target), target.install_rpath)
+ self.determine_rpath_dirs(target),
+ target.install_rpath)
+ # Add libraries generated by custom targets
custom_target_libraries = self.get_custom_target_provided_libraries(target)
commands += extra_args
commands += custom_target_libraries
- commands = linker.unix_args_to_native(self.dedup_arguments(commands))
+ # Convert from GCC-style link argument naming to the naming used by the
+ # current compiler.
+ commands = commands.to_native()
dep_targets = [self.get_dependency_filename(t) for t in dependencies]
dep_targets += [os.path.join(self.environment.source_dir,
target.subdir, t) for t in target.link_depends]