aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild
diff options
context:
space:
mode:
authorDylan Baker <dylan@pnwbakers.com>2019-08-27 14:50:10 -0700
committerJussi Pakkanen <jpakkane@gmail.com>2019-08-30 00:01:32 +0300
commit0efab591da210418e0d618449be2f9462d5d58e8 (patch)
treeb2fb1641b336c8262b1ec2e4da5d6cec12046241 /mesonbuild
parent3256e7ea63edb8508d1a2aac45da02e5c452df2c (diff)
downloadmeson-0efab591da210418e0d618449be2f9462d5d58e8.zip
meson-0efab591da210418e0d618449be2f9462d5d58e8.tar.gz
meson-0efab591da210418e0d618449be2f9462d5d58e8.tar.bz2
compilers: Move the compiler argument to proxy linker flags to the compiler class
Instead of the DynamicLinker returning a hardcoded value like `-Wl,-foo`, it now is passed a value that could be '-Wl,', or could be something '-Xlinker=' This makes a few things cleaner, and will make it possible to fix using clang (not clang-cl) on windows, where it invokes either link.exe or lld-link.exe instead of a gnu-ld compatible linker.
Diffstat (limited to 'mesonbuild')
-rw-r--r--mesonbuild/compilers/compilers.py2
-rw-r--r--mesonbuild/compilers/cuda.py16
-rw-r--r--mesonbuild/compilers/d.py6
-rw-r--r--mesonbuild/compilers/fortran.py6
-rw-r--r--mesonbuild/compilers/mixins/gnu.py4
-rw-r--r--mesonbuild/compilers/swift.py3
-rw-r--r--mesonbuild/environment.py66
-rw-r--r--mesonbuild/linkers.py122
8 files changed, 137 insertions, 88 deletions
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index f16e447..4218775 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -650,6 +650,8 @@ class Compiler:
# manually searched.
internal_libs = ()
+ LINKER_PREFIX = None # type: typing.Union[None, str, typing.List[str]]
+
def __init__(self, exelist, version, for_machine: MachineChoice,
linker: typing.Optional['DynamicLinker'] = None, **kwargs):
if isinstance(exelist, str):
diff --git a/mesonbuild/compilers/cuda.py b/mesonbuild/compilers/cuda.py
index b6bafe7..3bcabf5 100644
--- a/mesonbuild/compilers/cuda.py
+++ b/mesonbuild/compilers/cuda.py
@@ -25,6 +25,9 @@ if typing.TYPE_CHECKING:
class CudaCompiler(Compiler):
+
+ LINKER_PREFIX = '-Xlinker='
+
def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwargs):
if not hasattr(self, 'language'):
self.language = 'cuda'
@@ -162,17 +165,8 @@ class CudaCompiler(Compiler):
@staticmethod
def _cook_link_args(args: typing.List[str]) -> typing.List[str]:
- """
- Converts GNU-style arguments -Wl,-arg,-arg
- to NVCC-style arguments -Xlinker=-arg,-arg
- """
- cooked = [] # type: typing.List[str]
- for arg in args:
- if arg.startswith('-Wl,'):
- arg = arg.replace('-Wl,', '-Xlinker=', 1)
- arg = arg.replace(' ', '\\')
- cooked.append(arg)
- return cooked
+ """Fixup arguments."""
+ return [a.replace(' ', '\\') for a in args]
def name_string(self):
return ' '.join(self.exelist)
diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py
index 18e3bf9..5e0c173 100644
--- a/mesonbuild/compilers/d.py
+++ b/mesonbuild/compilers/d.py
@@ -67,6 +67,8 @@ dmd_optimization_args = {'0': [],
class DmdLikeCompilerMixin:
+ LINKER_PREFIX = '-L'
+
def get_output_args(self, target):
return ['-of=' + target]
@@ -577,6 +579,10 @@ class DCompiler(Compiler):
class GnuDCompiler(DCompiler, GnuCompiler):
+
+ # we mostly want DCompiler, but that gives us the Compiler.LINKER_PREFIX instead
+ LINKER_PREFIX = GnuCompiler.LINKER_PREFIX
+
def __init__(self, exelist, version, for_machine: MachineChoice, arch, **kwargs):
DCompiler.__init__(self, exelist, version, for_machine, arch, **kwargs)
self.id = 'gcc'
diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py
index 30ec6fe..fd7b91a 100644
--- a/mesonbuild/compilers/fortran.py
+++ b/mesonbuild/compilers/fortran.py
@@ -185,6 +185,9 @@ class ElbrusFortranCompiler(GnuFortranCompiler, ElbrusCompiler):
ElbrusCompiler.__init__(self, compiler_type, defines)
class G95FortranCompiler(FortranCompiler):
+
+ LINKER_PREFIX = '-Wl,'
+
def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwags):
FortranCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper, **kwags)
self.id = 'g95'
@@ -203,6 +206,9 @@ class G95FortranCompiler(FortranCompiler):
class SunFortranCompiler(FortranCompiler):
+
+ LINKER_PREFIX = '-Wl,'
+
def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwags):
FortranCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper, **kwags)
self.id = 'sun'
diff --git a/mesonbuild/compilers/mixins/gnu.py b/mesonbuild/compilers/mixins/gnu.py
index d4318b6..998b86c 100644
--- a/mesonbuild/compilers/mixins/gnu.py
+++ b/mesonbuild/compilers/mixins/gnu.py
@@ -128,6 +128,9 @@ class GnuLikeCompiler(metaclass=abc.ABCMeta):
and ICC. Certain functionality between them is different and requires
that the actual concrete subclass define their own implementation.
"""
+
+ LINKER_PREFIX = '-Wl,'
+
def __init__(self, compiler_type: 'CompilerType'):
self.compiler_type = compiler_type
self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage',
@@ -298,6 +301,7 @@ class GnuCompiler(GnuLikeCompiler):
GnuCompiler represents an actual GCC in its many incarnations.
Compilers imitating GCC (Clang/Intel) should use the GnuLikeCompiler ABC.
"""
+
def __init__(self, compiler_type: 'CompilerType', defines: typing.Dict[str, str]):
super().__init__(compiler_type)
self.id = 'gcc'
diff --git a/mesonbuild/compilers/swift.py b/mesonbuild/compilers/swift.py
index 6c639fd..e429056 100644
--- a/mesonbuild/compilers/swift.py
+++ b/mesonbuild/compilers/swift.py
@@ -27,6 +27,9 @@ swift_optimization_args = {'0': [],
}
class SwiftCompiler(Compiler):
+
+ LINKER_PREFIX = ['-Xlinker']
+
def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, **kwargs):
self.language = 'swift'
super().__init__(exelist, version, for_machine, **kwargs)
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
index 2675bca..71de41e 100644
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -660,8 +660,8 @@ class Environment:
raise EnvironmentException(errmsg)
@staticmethod
- def _guess_nix_linker(compiler: typing.List[str], for_machine: MachineChoice, *,
- prefix: typing.Union[str, typing.List[str]] = '-Wl,',
+ def _guess_nix_linker(compiler: typing.List[str], for_machine: MachineChoice,
+ prefix: typing.Union[str, typing.List[str]], *,
extra_args: typing.Optional[typing.List[str]] = None) -> 'DynamicLinker':
"""Helper for guessing what linker to use on Unix-Like OSes.
@@ -682,7 +682,7 @@ class Environment:
_, o, e = Popen_safe(compiler + check_args)
v = search_version(o)
if o.startswith('LLD'):
- linker = LLVMDynamicLinker(compiler, for_machine, 'lld', version=v) # type: DynamicLinker
+ linker = LLVMDynamicLinker(compiler, for_machine, 'lld', prefix, version=v) # type: DynamicLinker
# first is for apple clang, second is for real gcc
elif e.endswith('(use -v to see invocation)\n') or 'macosx_version' in e:
if isinstance(prefix, str):
@@ -696,15 +696,17 @@ class Environment:
break
else:
v = 'unknown version'
- linker = AppleDynamicLinker(compiler, for_machine, i, version=v)
+ linker = AppleDynamicLinker(compiler, for_machine, i, prefix, version=v)
elif 'GNU' in o:
if 'gold' in 'o':
i = 'GNU ld.gold'
else:
i = 'GNU ld.bfd'
- linker = GnuDynamicLinker(compiler, for_machine, i, version=v)
+ linker = GnuDynamicLinker(compiler, for_machine, i, prefix, version=v)
elif 'Solaris' in e:
- linker = SolarisDynamicLinker(compiler, for_machine, 'solaris', version=search_version(e))
+ linker = SolarisDynamicLinker(
+ compiler, for_machine, 'solaris', prefix,
+ version=search_version(e))
else:
raise MesonException('Unable to determine dynamic linker.')
return linker
@@ -772,14 +774,14 @@ class Environment:
continue
compiler_type = self.get_gnu_compiler_type(defines)
- linker = self._guess_nix_linker(compiler, for_machine)
-
if guess_gcc_or_lcc == 'lcc':
version = self.get_lcc_version_from_defines(defines)
cls = ElbrusCCompiler if lang == 'c' else ElbrusCPPCompiler
else:
version = self.get_gnu_version_from_defines(defines)
cls = GnuCCompiler if lang == 'c' else GnuCPPCompiler
+
+ linker = self._guess_nix_linker(compiler, for_machine, cls.LINKER_PREFIX)
return cls(ccache + compiler, version, compiler_type,
for_machine, is_cross, exe_wrap, defines,
full_version=full_version, linker=linker)
@@ -833,7 +835,7 @@ class Environment:
compiler_type = CompilerType.CLANG_STANDARD
cls = ClangCCompiler if lang == 'c' else ClangCPPCompiler
- linker = self._guess_nix_linker(compiler, for_machine)
+ linker = self._guess_nix_linker(compiler, for_machine, cls.LINKER_PREFIX)
return cls(ccache + compiler, version, compiler_type, for_machine, is_cross, exe_wrap, full_version=full_version, linker=linker)
if 'Intel(R) C++ Intel(R)' in err:
version = search_version(err)
@@ -869,15 +871,15 @@ class Environment:
else:
compiler_type = CompilerType.PGI_STANDARD
cls = PGICCompiler if lang == 'c' else PGICPPCompiler
- linker = PGIDynamicLinker(compiler, for_machine, 'pgi', version=version)
+ linker = PGIDynamicLinker(compiler, for_machine, 'pgi', cls.LINKER_PREFIX, version=version)
return cls(ccache + compiler, version, compiler_type, for_machine, is_cross, exe_wrap, linker=linker)
if '(ICC)' in out:
if self.machines[for_machine].is_darwin():
compiler_type = CompilerType.ICC_OSX
- l = XildAppleDynamicLinker(compiler, for_machine, 'xild', version=version)
+ l = XildAppleDynamicLinker(compiler, for_machine, 'xild', '-Wl,', version=version)
else:
compiler_type = CompilerType.ICC_STANDARD
- l = XildLinuxDynamicLinker(compiler, for_machine, 'xild', version=version)
+ l = XildLinuxDynamicLinker(compiler, for_machine, 'xild', '-Wl,', version=version)
cls = IntelCCompiler if lang == 'c' else IntelCPPCompiler
return cls(ccache + compiler, version, compiler_type, for_machine, is_cross, exe_wrap, full_version=full_version, linker=l)
if 'ARM' in out:
@@ -929,7 +931,7 @@ class Environment:
# Luckily, the "V" also makes it very simple to extract
# the full version:
version = out.strip().split('V')[-1]
- linker = self._guess_nix_linker(compiler, for_machine, prefix='-Xlinker=')
+ linker = self._guess_nix_linker(compiler, for_machine, CudaCompiler.LINKER_PREFIX)
return CudaCompiler(ccache + compiler, version, for_machine, exe_wrap, linker=linker)
raise EnvironmentException('Could not find suitable CUDA compiler: "' + ' '.join(compilers) + '"')
@@ -968,16 +970,16 @@ class Environment:
else:
version = self.get_gnu_version_from_defines(defines)
cls = GnuFortranCompiler
- linker = self._guess_nix_linker(compiler, for_machine)
+ linker = self._guess_nix_linker(compiler, for_machine, cls.LINKER_PREFIX)
return cls(compiler, version, compiler_type, for_machine, is_cross, exe_wrap, defines, full_version=full_version, linker=linker)
if 'G95' in out:
- linker = self._guess_nix_linker(compiler, for_machine)
+ linker = self._guess_nix_linker(compiler, for_machine, G95FortranCompiler.LINKER_PREFIX)
return G95FortranCompiler(compiler, version, for_machine, is_cross, exe_wrap, full_version=full_version, linker=linker)
if 'Sun Fortran' in err:
version = search_version(err)
- linker = self._guess_nix_linker(compiler, for_machine)
+ linker = self._guess_nix_linker(compiler, for_machine, SunFortranCompiler.LINKER_PREFIX)
return SunFortranCompiler(compiler, version, for_machine, is_cross, exe_wrap, full_version=full_version, linker=linker)
if 'Intel(R) Visual Fortran' in err:
@@ -987,7 +989,7 @@ class Environment:
return IntelClFortranCompiler(compiler, version, for_machine, is_cross, target, exe_wrap, linker=linker)
if 'ifort (IFORT)' in out:
- linker = XildLinuxDynamicLinker(compiler, for_machine, 'xild', version=version)
+ linker = XildLinuxDynamicLinker(compiler, for_machine, 'xild', '-Wl,', version=version)
return IntelFortranCompiler(compiler, version, for_machine, is_cross, exe_wrap, full_version=full_version, linker=linker)
if 'PathScale EKOPath(tm)' in err:
@@ -1000,19 +1002,19 @@ class Environment:
compiler_type = CompilerType.PGI_WIN
else:
compiler_type = CompilerType.PGI_STANDARD
- linker = PGIDynamicLinker(compiler, for_machine, 'pgi', version=version)
+ linker = PGIDynamicLinker(compiler, for_machine, 'pgi', PGIFortranCompiler.LINKER_PREFIX, version=version)
return PGIFortranCompiler(compiler, version, compiler_type, for_machine, is_cross, exe_wrap, full_version=full_version, linker=linker)
if 'flang' in out or 'clang' in out:
- linker = self._guess_nix_linker(compiler, for_machine)
+ linker = self._guess_nix_linker(compiler, for_machine, FlangFortranCompiler.LINKER_PREFIX)
return FlangFortranCompiler(compiler, version, for_machine, is_cross, exe_wrap, full_version=full_version, linker=linker)
if 'Open64 Compiler Suite' in err:
- linker = self._guess_nix_linker(compiler, for_machine)
+ linker = self._guess_nix_linker(compiler, for_machine, Open64FortranCompiler.LINKER_PREFIX)
return Open64FortranCompiler(compiler, version, for_machine, is_cross, exe_wrap, full_version=full_version, linker=linker)
if 'NAG Fortran' in err:
- linker = self._guess_nix_linker(compiler, for_machine)
+ linker = self._guess_nix_linker(compiler, for_machine, NAGFortranCompiler.LINKER_PREFIX)
return NAGFortranCompiler(compiler, version, for_machine, is_cross, exe_wrap, full_version=full_version, linker=linker)
self._handle_exceptions(popen_exceptions, compilers)
@@ -1047,7 +1049,7 @@ class Environment:
compiler_type = self.get_gnu_compiler_type(defines)
version = self.get_gnu_version_from_defines(defines)
comp = GnuObjCCompiler if objc else GnuObjCPPCompiler
- linker = self._guess_nix_linker(compiler, for_machine)
+ linker = self._guess_nix_linker(compiler, for_machine, comp.LINKER_PREFIX)
return comp(ccache + compiler, version, compiler_type, for_machine, is_cross, exe_wrap, defines, linker=linker)
if 'clang' in out:
comp = ClangObjCCompiler if objc else ClangObjCPPCompiler
@@ -1057,7 +1059,7 @@ class Environment:
compiler_type = CompilerType.CLANG_MINGW
else:
compiler_type = CompilerType.CLANG_STANDARD
- linker = self._guess_nix_linker(compiler, for_machine)
+ linker = self._guess_nix_linker(compiler, for_machine, comp.LINKER_PREFIX)
return comp(ccache + compiler, version, compiler_type, for_machine, is_cross, exe_wrap, linker=linker)
self._handle_exceptions(popen_exceptions, compilers)
@@ -1141,9 +1143,9 @@ class Environment:
# default, and apple ld is used on mac.
# TODO: find some better way to figure this out.
if self.machines[for_machine].is_darwin():
- linker = AppleDynamicLinker([], for_machine, 'Apple ld')
+ linker = AppleDynamicLinker([], for_machine, 'Apple ld', '-Wl,')
else:
- linker = GnuDynamicLinker([], for_machine, 'GNU ld')
+ linker = GnuDynamicLinker([], for_machine, 'GNU ld', '-Wl,')
return RustCompiler(compiler, version, for_machine, is_cross, exe_wrap, linker=linker)
self._handle_exceptions(popen_exceptions, compilers)
@@ -1196,10 +1198,13 @@ class Environment:
linker = ClangClDynamicLinker(for_machine, version=search_version(o))
else:
with tempfile.NamedTemporaryFile(suffix='.d') as f:
- linker = self._guess_nix_linker(exelist, for_machine, prefix='-L', extra_args=[f.name])
+ linker = self._guess_nix_linker(
+ exelist, for_machine,
+ compilers.LLVMDCompiler.LINKER_PREFIX,
+ extra_args=[f.name])
return compilers.LLVMDCompiler(exelist, version, for_machine, arch, full_version=full_version, linker=linker)
elif 'gdc' in out:
- linker = self._guess_nix_linker(exelist, for_machine)
+ linker = self._guess_nix_linker(exelist, for_machine, compilers.GnuDCompiler.LINKER_PREFIX)
return compilers.GnuDCompiler(exelist, version, for_machine, arch, full_version=full_version, linker=linker)
elif 'The D Language Foundation' in out or 'Digital Mars' in out:
# DMD seems to require a file
@@ -1208,7 +1213,10 @@ class Environment:
linker = OptlinkDynamicLinker(for_machine, version=full_version)
else:
with tempfile.NamedTemporaryFile(suffix='.d') as f:
- linker = self._guess_nix_linker(exelist, for_machine, prefix='-L', extra_args=[f.name])
+ linker = self._guess_nix_linker(
+ exelist, for_machine,
+ compilers.LLVMDCompiler.LINKER_PREFIX,
+ extra_args=[f.name])
return compilers.DmdDCompiler(exelist, version, for_machine, arch, full_version=full_version, linker=linker)
raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')
@@ -1228,7 +1236,7 @@ class Environment:
# As for 5.0.1 swiftc *requires* a file to check the linker:
with tempfile.NamedTemporaryFile(suffix='.swift') as f:
linker = self._guess_nix_linker(
- exelist, for_machine, prefix=['-Xlinker'], extra_args=[f.name])
+ exelist, for_machine, compilers.SwiftCompiler.LINKER_PREFIX, extra_args=[f.name])
return compilers.SwiftCompiler(exelist, version, for_machine, is_cross, linker=linker)
raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')
diff --git a/mesonbuild/linkers.py b/mesonbuild/linkers.py
index caf11f1..272f927 100644
--- a/mesonbuild/linkers.py
+++ b/mesonbuild/linkers.py
@@ -238,12 +238,18 @@ class DynamicLinker(metaclass=abc.ABCMeta):
'custom': [],
} # type: typing.Dict[str, typing.List[str]]
+ def _apply_prefix(self, arg: str) -> typing.List[str]:
+ if isinstance(self.prefix_arg, str):
+ return [self.prefix_arg + arg]
+ return self.prefix_arg + [arg]
+
def __init__(self, exelist: typing.List[str], for_machine: mesonlib.MachineChoice,
- id_: str, *, version: str = 'unknown version'):
+ id_: str, prefix_arg: str, *, version: str = 'unknown version'):
self.exelist = exelist
self.for_machine = for_machine
self.version = version
self.id = id_
+ self.prefix_arg = prefix_arg
def __repr__(self) -> str:
return '<{}: v{} `{}`>'.format(type(self).__name__, self.version, ' '.join(self.exelist))
@@ -413,24 +419,29 @@ class GnuLikeDynamicLinkerMixin:
'plain': [],
'debug': [],
'debugoptimized': [],
- 'release': ['-Wl,-O1'],
+ 'release': ['-O1'],
'minsize': [],
'custom': [],
} # type: typing.Dict[str, typing.List[str]]
+ def get_buildtype_args(self, buildtype: str) -> typing.List[str]:
+ # We can override these in children by just overriding the
+ # _BUILDTYPE_ARGS value.
+ return mesonlib.listify([self._apply_prefix(a) for a in self._BUILDTYPE_ARGS[buildtype]])
+
def get_pie_args(self) -> typing.List[str]:
return ['-pie']
def get_asneeded_args(self) -> typing.List[str]:
- return ['-Wl,--as-needed']
+ return self._apply_prefix('--as-needed')
def get_link_whole_for(self, args: typing.List[str]) -> typing.List[str]:
if not args:
return args
- return ['-Wl,--whole-archive'] + args + ['-Wl,--no-whole-archive']
+ return self._apply_prefix('--whole-archive') + args + self._apply_prefix('--no-whole-archive')
def get_allow_undefined_args(self) -> typing.List[str]:
- return ['-Wl,--allow-shlib-undefined']
+ return self._apply_prefix('--allow-shlib-undefined')
def get_lto_args(self) -> typing.List[str]:
return ['-flto']
@@ -450,11 +461,11 @@ class GnuLikeDynamicLinkerMixin:
def export_dynamic_args(self, env: 'Environment') -> typing.List[str]:
m = env.machines[self.for_machine]
if m.is_windows() or m.is_cygwin():
- return ['-Wl,--export-all-symbols']
- return ['-Wl,-export-dynamic']
+ return self._apply_prefix('--export-all-symbols')
+ return self._apply_prefix('-export-dynamic')
def import_library_args(self, implibname: str) -> typing.List[str]:
- return ['-Wl,--out-implib=' + implibname]
+ return self._apply_prefix('--out-implib=' + implibname)
def thread_flags(self, env: 'Environment') -> typing.List[str]:
if env.machines[self.for_machine].is_haiku():
@@ -462,10 +473,10 @@ class GnuLikeDynamicLinkerMixin:
return ['-pthread']
def no_undefined_args(self) -> typing.List[str]:
- return ['-Wl,--no-undefined']
+ return self._apply_prefix('--no-undefined')
def fatal_warnings(self) -> typing.List[str]:
- return ['-Wl,--fatal-warnings']
+ return self._apply_prefix('--fatal-warnings')
def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
suffix: str, soversion: str, darwin_versions: typing.Tuple[str, str],
@@ -475,7 +486,7 @@ class GnuLikeDynamicLinkerMixin:
# For PE/COFF the soname argument has no effect
return []
sostr = '' if soversion is None else '.' + soversion
- return ['-Wl,-soname,{}{}.{}{}'.format(prefix, shlib_name, suffix, sostr)]
+ return self._apply_prefix('-soname,{}{}.{}{}'.format(prefix, shlib_name, suffix, sostr))
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str,
@@ -503,7 +514,7 @@ class GnuLikeDynamicLinkerMixin:
# by default, but is not on dragonfly/openbsd for some reason. Without this
# $ORIGIN in the runtime path will be undefined and any binaries
# linked against local libraries will fail to resolve them.
- args.append('-Wl,-z,origin')
+ args.extend(self._apply_prefix('-z,origin'))
# In order to avoid relinking for RPATH removal, the binary needs to contain just
# enough space in the ELF header to hold the final installation RPATH.
@@ -514,7 +525,7 @@ class GnuLikeDynamicLinkerMixin:
paths = padding
else:
paths = paths + ':' + padding
- args.append('-Wl,-rpath,' + paths)
+ args.extend(self._apply_prefix('-rpath,' + paths))
# TODO: should this actually be "for solaris/sunos"?
if mesonlib.is_sunos():
@@ -535,7 +546,8 @@ class GnuLikeDynamicLinkerMixin:
# ...instead of just one single looooong option, like this:
#
# -Wl,-rpath-link,/path/to/folder1:/path/to/folder2:...
- args.extend(['-Wl,-rpath-link,' + os.path.join(build_dir, p) for p in rpath_paths])
+ for p in rpath_paths:
+ args.extend(self._apply_prefix('-rpath-link,' + os.path.join(build_dir, p)))
return args
@@ -545,31 +557,32 @@ class AppleDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
"""Apple's ld implementation."""
def get_asneeded_args(self) -> typing.List[str]:
- return ['-Wl,-dead_strip_dylibs']
+ return self._apply_prefix('-dead_strip_dylibs')
def get_allow_undefined_args(self) -> typing.List[str]:
- return ['-Wl,-undefined,dynamic_lookup']
+ return self._apply_prefix('-undefined,dynamic_lookup')
def get_std_shared_module_args(self, options: 'OptionDictType') -> typing.List[str]:
- return ['-bundle', '-Wl,-undefined,dynamic_lookup']
+ return ['-bundle'] + self._apply_prefix('-undefined,dynamic_lookup')
def get_link_whole_for(self, args: typing.List[str]) -> typing.List[str]:
result = [] # type: typing.List[str]
for a in args:
- result.extend(['-Wl,-force_load', a])
+ result.extend(self._apply_prefix('-force_load'))
+ result.append(a)
return result
def no_undefined_args(self) -> typing.List[str]:
- return ['-Wl,-undefined,error']
+ return self._apply_prefix('-undefined,error')
def get_always_args(self) -> typing.List[str]:
- return ['-Wl,-headerpad_max_install_names']
+ return self._apply_prefix('-headerpad_max_install_names')
def bitcode_args(self) -> typing.List[str]:
- return ['-Wl,-bitcode_bundle']
+ return self._apply_prefix('-bitcode_bundle')
def fatal_warnings(self) -> typing.List[str]:
- return ['-Wl,-fatal_warnings']
+ return self._apply_prefix('-fatal_warnings')
def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
suffix: str, soversion: str, darwin_versions: typing.Tuple[str, str],
@@ -593,7 +606,7 @@ class AppleDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
return []
# Ensure that there is enough space for install_name_tool in-place
# editing of large RPATHs
- args = ['-Wl,-headerpad_max_install_names']
+ args = self._apply_prefix('-headerpad_max_install_names')
# @loader_path is the equivalent of $ORIGIN on macOS
# https://stackoverflow.com/q/26280738
origin_placeholder = '@loader_path'
@@ -601,7 +614,8 @@ class AppleDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
all_paths = mesonlib.OrderedSet([os.path.join(origin_placeholder, p) for p in processed_rpaths])
if build_rpath != '':
all_paths.add(build_rpath)
- args.extend(['-Wl,-rpath,' + rp for rp in all_paths])
+ for rp in all_paths:
+ args.extend(self._apply_prefix('-rpath,' + rp))
return args
@@ -649,7 +663,7 @@ class CcrxDynamicLinker(DynamicLinker):
def __init__(self, for_machine: mesonlib.MachineChoice,
*, version: str = 'unknown version'):
- super().__init__(['rlink.exe'], for_machine, 'rlink',
+ super().__init__(['rlink.exe'], for_machine, 'rlink', '',
version=version)
def get_accepts_rsp(self) -> bool:
@@ -682,7 +696,7 @@ class ArmDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
def __init__(self, for_machine: mesonlib.MachineChoice,
*, version: str = 'unknown version'):
- super().__init__(['armlink'], for_machine, 'armlink',
+ super().__init__(['armlink'], for_machine, 'armlink', '',
version=version)
def get_accepts_rsp(self) -> bool:
@@ -751,9 +765,13 @@ class VisualStudioLikeLinkerMixin:
'custom': [],
} # type: typing.Dict[str, typing.List[str]]
- def __init__(self, *args, **kwargs):
+ def __init__(self, *args, direct: bool = True, machine: str = 'x86', **kwargs):
super().__init__(*args, **kwargs)
- self.machine = 'x86'
+ self.direct = direct
+ self.machine = machine
+
+ def invoked_by_compiler(self) -> bool:
+ return self.direct
def get_debug_crt_args(self) -> typing.List[str]:
"""Arguments needed to select a debug crt for the linker.
@@ -763,33 +781,36 @@ class VisualStudioLikeLinkerMixin:
MSVC won't auto-select a CRT for us in that case and will error out
asking us to select one.
"""
- return ['/MDd']
+ return self._apply_prefix('/MDd')
def get_output_args(self, outputname: str) -> typing.List[str]:
- return ['/MACHINE:' + self.machine, '/OUT:' + outputname]
+ return self._apply_prefix('/MACHINE:' + self.machine) + self._apply_prefix('/OUT:' + outputname)
def get_always_args(self) -> typing.List[str]:
- return ['/nologo']
+ return self._apply_prefix('/nologo')
def get_search_args(self, dirname: str) -> typing.List[str]:
- return ['/LIBPATH:' + dirname]
+ return self._apply_prefix('/LIBPATH:' + dirname)
def get_std_shared_lib_args(self) -> typing.List[str]:
- return ['/DLL']
+ return self._apply_prefix('/DLL')
def get_debugfile_args(self, targetfile: str) -> typing.List[str]:
pdbarr = targetfile.split('.')[:-1]
pdbarr += ['pdb']
- return ['/DEBUG', '/PDB:' + '.'.join(pdbarr)]
+ return self._apply_prefix('/DEBUG') + self._apply_prefix('/PDB:' + '.'.join(pdbarr))
def get_link_whole_for(self, args: typing.List[str]) -> typing.List[str]:
# Only since VS2015
args = mesonlib.listify(args)
- return ['/WHOLEARCHIVE:' + x for x in args]
+ l = [] # typing.List[str]
+ for a in args:
+ l.extend(self._apply_prefix('/WHOLEARCHIVE:' + a))
+ return l
def get_allow_undefined_args(self) -> typing.List[str]:
# link.exe
- return ['/FORCE:UNRESOLVED']
+ return self._apply_prefix('/FORCE:UNRESOLVED')
def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
suffix: str, soversion: str, darwin_versions: typing.Tuple[str, str],
@@ -801,19 +822,24 @@ class MSVCDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
"""Microsoft's Link.exe."""
- def __init__(self, for_machine: mesonlib.MachineChoice,
- *, version: str = 'unknown version'):
- super().__init__(['link.exe'], for_machine, 'link', version=version)
+ def __init__(self, for_machine: mesonlib.MachineChoice, *,
+ exelist: typing.Optional[typing.List[str]] = None,
+ prefix: typing.Union[str, typing.List[str]] = '',
+ machine: str = 'x86', version: str = 'unknown version'):
+ super().__init__(exelist or ['link.exe'], for_machine, 'link',
+ prefix, machine=machine, version=version)
class ClangClDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
"""Clang's lld-link.exe."""
- def __init__(self, for_machine: mesonlib.MachineChoice,
- *, version: str = 'unknown version'):
- super().__init__(['lld-link.exe'], for_machine, 'lld-link',
- version=version)
+ def __init__(self, for_machine: mesonlib.MachineChoice, *,
+ exelist: typing.Optional[typing.List[str]] = None,
+ prefix: typing.Union[str, typing.List[str]] = '',
+ version: str = 'unknown version'):
+ super().__init__(exelist or ['lld-link.exe'], for_machine,
+ 'lld-link', prefix, version=version)
class XilinkDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
@@ -822,7 +848,7 @@ class XilinkDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
def __init__(self, for_machine: mesonlib.MachineChoice,
*, version: str = 'unknown version'):
- super().__init__(['xilink.exe'], for_machine, 'xilink', version=version)
+ super().__init__(['xilink.exe'], for_machine, 'xilink', '', version=version)
class SolarisDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
@@ -832,7 +858,7 @@ class SolarisDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
def get_link_whole_for(self, args: typing.List[str]) -> typing.List[str]:
if not args:
return args
- return ['-Wl,--whole-archive'] + args + ['-Wl,--no-whole-archive']
+ return self._apply_prefix('--whole-archive') + args + self._apply_prefix('--no-whole-archive')
def no_undefined_args(self) -> typing.List[str]:
return ['-z', 'defs']
@@ -862,13 +888,13 @@ class SolarisDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
paths = padding
else:
paths = paths + ':' + padding
- return ['-Wl,-rpath,{}'.format(paths)]
+ return self._apply_prefix('-rpath,{}'.format(paths))
def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
suffix: str, soversion: str, darwin_versions: typing.Tuple[str, str],
is_shared_module: bool) -> typing.List[str]:
sostr = '' if soversion is None else '.' + soversion
- return ['-Wl,-soname,{}{}.{}{}'.format(prefix, shlib_name, suffix, sostr)]
+ return self._apply_prefix('-soname,{}{}.{}{}'.format(prefix, shlib_name, suffix, sostr))
class OptlinkDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
@@ -879,7 +905,7 @@ class OptlinkDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
*, version: str = 'unknown version'):
# Use optlink instead of link so we don't interfer with other link.exe
# implementations.
- super().__init__(['optlink.exe'], for_machine, 'optlink', version=version)
+ super().__init__(['optlink.exe'], for_machine, 'optlink', prefix_arg='', version=version)
def get_allow_undefined_args(self) -> typing.List[str]:
return []