Skip to content

Commit

Permalink
environment: Consider compiler and linker arguments for the dynamic l…
Browse files Browse the repository at this point in the history
…inker

There are at least two cases that we could run into here, one is someone
could use an argument -fuse-ld=...; which would cause is to misdetect
the linker being used. The other is that someone could use clang
--target=, which will cause clang to use a different linker than without
--target=; causing more mis-detection.

This considers environment variables, -D<lang>_args, and both cross and
native file appropriately.

This patch is very much not perfect, there's some code duplication and
some "working around the design" going on. That needs to be addressed,
but this unbreaks things, and thats good.

Fixes mesonbuild#6057
  • Loading branch information
dcbaker committed Nov 13, 2019
1 parent 61a5c75 commit 71f520b
Showing 1 changed file with 42 additions and 16 deletions.
58 changes: 42 additions & 16 deletions mesonbuild/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -759,9 +759,8 @@ def _guess_win_linker(compiler: typing.List[str], for_machine: MachineChoice,
version=search_version(o))
raise MesonException('Cannot guess dynamic linker')

@staticmethod
def _guess_nix_linker(compiler: typing.List[str], for_machine: MachineChoice,
prefix: typing.Union[str, typing.List[str]], *,
def _guess_nix_linker(self, compiler: typing.List[str], for_machine: MachineChoice,
prefix: typing.Union[str, typing.List[str]], lang: str, *,
extra_args: typing.Optional[typing.List[str]] = None) -> 'DynamicLinker':
"""Helper for guessing what linker to use on Unix-Like OSes.
Expand All @@ -775,6 +774,29 @@ def _guess_nix_linker(compiler: typing.List[str], for_machine: MachineChoice,
:extra_args: Any additional arguments required (such as a source file)
"""
extra_args = typing.cast(typing.List[str], extra_args or [])

# We aditionally need to use the arguments in the cross/native file, as
# they may affect the linker chosen: https://github.com/mesonbuild/meson/issues/6057

# TODO: we really want to not check the raw command line, but we have a
# chicken and egg problem, and a bugfix is needed for the stable
# release.

# TODO: We really want to be able to share this code with other places,
# but that code is tied up very tightly with having an instantiated
# compiler class. We can't have one of those yet, because we're
# detecting the linker, which is part of the compiler.
extra_args.extend(self.properties[for_machine].get(lang + '_args', []))
if for_machine is (MachineChoice.HOST if not self.is_cross_build() else MachineChoice.BUILD):
extra_args.extend(mesonlib.listify(self.cmd_line_options.get(lang + '_args', [])))
extra_args.extend(split_args(os.environ.get(compilers.compilers.cflags_mapping[lang], '')))

if lang in compilers.compilers.languages_using_ldflags:
extra_args.extend(self.properties[for_machine].get(lang + '_link_args', []))
if for_machine is (MachineChoice.HOST if not self.is_cross_build() else MachineChoice.BUILD):
extra_args.extend(mesonlib.listify(self.cmd_line_options.get(lang + '_link_args', [])))
extra_args.extend(split_args(os.environ.get('LDFLAGS', '')))

if isinstance(prefix, str):
check_args = [prefix + '--version'] + extra_args
else:
Expand Down Expand Up @@ -897,7 +919,7 @@ def sanitize(p):
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)
linker = self._guess_nix_linker(compiler, for_machine, cls.LINKER_PREFIX, lang)
return cls(
ccache + compiler, version, for_machine, is_cross,
info, exe_wrap, defines, full_version=full_version,
Expand Down Expand Up @@ -966,7 +988,7 @@ def sanitize(p):
except MesonException:
pass
if linker is None:
linker = self._guess_nix_linker(compiler, for_machine, cls.LINKER_PREFIX)
linker = self._guess_nix_linker(compiler, for_machine, cls.LINKER_PREFIX, lang)

return cls(
ccache + compiler, version, for_machine, is_cross, info,
Expand Down Expand Up @@ -1112,23 +1134,23 @@ def detect_fortran_compiler(self, for_machine: MachineChoice):
version = self.get_gnu_version_from_defines(defines)
cls = GnuFortranCompiler
linker = self._guess_nix_linker(
compiler, for_machine, cls.LINKER_PREFIX)
compiler, for_machine, cls.LINKER_PREFIX, 'fortran')
return cls(
compiler, version, for_machine, is_cross, info,
exe_wrap, defines, full_version=full_version,
linker=linker)

if 'G95' in out:
linker = self._guess_nix_linker(
compiler, for_machine, cls.LINKER_PREFIX)
compiler, for_machine, cls.LINKER_PREFIX, 'fortran')
return G95FortranCompiler(
compiler, version, for_machine, is_cross, info,
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, cls.LINKER_PREFIX)
compiler, for_machine, cls.LINKER_PREFIX, 'fortran')
return SunFortranCompiler(
compiler, version, for_machine, is_cross, info,
exe_wrap, full_version=full_version, linker=linker)
Expand Down Expand Up @@ -1163,21 +1185,21 @@ def detect_fortran_compiler(self, for_machine: MachineChoice):

if 'flang' in out or 'clang' in out:
linker = self._guess_nix_linker(
compiler, for_machine, FlangFortranCompiler.LINKER_PREFIX)
compiler, for_machine, FlangFortranCompiler.LINKER_PREFIX, 'fortran')
return FlangFortranCompiler(
compiler, version, for_machine, is_cross, info,
exe_wrap, full_version=full_version, linker=linker)

if 'Open64 Compiler Suite' in err:
linker = self._guess_nix_linker(
compiler, for_machine, Open64FortranCompiler.LINKER_PREFIX)
compiler, for_machine, Open64FortranCompiler.LINKER_PREFIX, 'fortran')
return Open64FortranCompiler(
compiler, version, for_machine, is_cross, info,
exe_wrap, full_version=full_version, linker=linker)

if 'NAG Fortran' in err:
linker = self._guess_nix_linker(
compiler, for_machine, NAGFortranCompiler.LINKER_PREFIX)
compiler, for_machine, NAGFortranCompiler.LINKER_PREFIX, 'fortran')
return NAGFortranCompiler(
compiler, version, for_machine, is_cross, info,
exe_wrap, full_version=full_version, linker=linker)
Expand All @@ -1193,9 +1215,10 @@ def detect_objc_compiler(self, for_machine: MachineInfo) -> 'Compiler':
def detect_objcpp_compiler(self, for_machine: MachineInfo) -> 'Compiler':
return self._detect_objc_or_objcpp_compiler(for_machine, False)

def _detect_objc_or_objcpp_compiler(self, for_machine: MachineInfo, objc: bool) -> 'Compiler':
def _detect_objc_or_objcpp_compiler(self, for_machine: MachineChoice, objc: bool) -> 'Compiler':
popen_exceptions = {}
compilers, ccache, exe_wrap = self._get_compilers('objc' if objc else 'objcpp', for_machine)
lang = 'objc' if objc else 'objcpp'
compilers, ccache, exe_wrap = self._get_compilers(lang, for_machine)
is_cross = not self.machines.matches_build_machine(for_machine)
info = self.machines[for_machine]

Expand All @@ -1216,7 +1239,7 @@ def _detect_objc_or_objcpp_compiler(self, for_machine: MachineInfo, objc: bool)
continue
version = self.get_gnu_version_from_defines(defines)
comp = GnuObjCCompiler if objc else GnuObjCPPCompiler
linker = self._guess_nix_linker(compiler, for_machine, comp.LINKER_PREFIX)
linker = self._guess_nix_linker(compiler, for_machine, comp.LINKER_PREFIX, lang)
return comp(
ccache + compiler, version, for_machine, is_cross, info,
exe_wrap, defines, linker=linker)
Expand All @@ -1232,7 +1255,7 @@ def _detect_objc_or_objcpp_compiler(self, for_machine: MachineInfo, objc: bool)

if not linker:
linker = self._guess_nix_linker(
compiler, for_machine, comp.LINKER_PREFIX)
compiler, for_machine, comp.LINKER_PREFIX, lang)
return comp(
ccache + compiler, version, for_machine,
is_cross, info, exe_wrap, linker=linker)
Expand Down Expand Up @@ -1389,12 +1412,13 @@ def detect_d_compiler(self, for_machine: MachineChoice):
linker = self._guess_nix_linker(
exelist, for_machine,
compilers.LLVMDCompiler.LINKER_PREFIX,
'd',
extra_args=[f.name])
return compilers.LLVMDCompiler(
exelist, version, for_machine, info, arch,
full_version=full_version, linker=linker)
elif 'gdc' in out:
linker = self._guess_nix_linker(exelist, for_machine, compilers.GnuDCompiler.LINKER_PREFIX)
linker = self._guess_nix_linker(exelist, for_machine, compilers.GnuDCompiler.LINKER_PREFIX, 'd')
return compilers.GnuDCompiler(
exelist, version, for_machine, info, arch,
full_version=full_version, linker=linker)
Expand All @@ -1415,6 +1439,7 @@ def detect_d_compiler(self, for_machine: MachineChoice):
linker = self._guess_nix_linker(
exelist, for_machine,
compilers.LLVMDCompiler.LINKER_PREFIX,
'd',
extra_args=[f.name])
return compilers.DmdDCompiler(
exelist, version, for_machine, info, arch,
Expand All @@ -1440,6 +1465,7 @@ def detect_swift_compiler(self, for_machine):
linker = self._guess_nix_linker(
exelist, for_machine,
compilers.SwiftCompiler.LINKER_PREFIX,
'swift',
extra_args=[f.name])
return compilers.SwiftCompiler(
exelist, version, for_machine, info, is_cross, linker=linker)
Expand Down

0 comments on commit 71f520b

Please sign in to comment.