Merge pull request #11924 from dcbaker/submit/c++stdlib-fixes

Do a better job of detecting libc++ vs libstdc++
pull/11942/head
Jussi Pakkanen 1 year ago committed by GitHub
commit 73b3b60436
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 75
      mesonbuild/compilers/cpp.py

@ -183,7 +183,48 @@ class CPPCompiler(CLikeCompiler, Compiler):
return opts return opts
class ClangCPPCompiler(ClangCompiler, CPPCompiler): class _StdCPPLibMixin(CompilerMixinBase):
"""Detect whether to use libc++ or libstdc++."""
@functools.lru_cache(None)
def language_stdlib_only_link_flags(self, env: Environment) -> T.List[str]:
"""Detect the C++ stdlib and default search dirs
As an optimization, this method will cache the value, to avoid building the same values over and over
:param env: An Environment object
:raises MesonException: If a stdlib cannot be determined
"""
# We need to apply the search prefix here, as these link arguments may
# be passed to a different compiler with a different set of default
# search paths, such as when using Clang for C/C++ and gfortran for
# fortran.
search_dirs = [f'-L{d}' for d in self.get_compiler_dirs(env, 'libraries')]
machine = env.machines[self.for_machine]
assert machine is not None, 'for mypy'
# We need to determine whether to us libc++ or libstdc++ In some cases
# we know the answer, so we'll hardcode those cases. There are other
# cases where we can't know the answer just by looking at the OS, namely
# on Linux. In that case we have to fallback to manually checking
stdlib: str
if machine.system in {'android', 'darwin', 'dragonfly', 'freebsd', 'netbsd', 'openbsd'}:
stdlib = 'c++'
elif self.find_library('c++', env, []) is not None:
stdlib = 'c++'
elif self.find_library('stdc++', env, []) is not None:
stdlib = 'stdc++'
else:
# TODO: maybe a bug exception?
raise MesonException('Could not detect either libc++ or libstdc++ as your C++ stdlib implementation.')
return search_dirs + [f'-l{stdlib}']
class ClangCPPCompiler(_StdCPPLibMixin, ClangCompiler, CPPCompiler):
def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool,
info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None,
linker: T.Optional['DynamicLinker'] = None, linker: T.Optional['DynamicLinker'] = None,
@ -249,16 +290,6 @@ class ClangCPPCompiler(ClangCompiler, CPPCompiler):
return libs return libs
return [] return []
def language_stdlib_only_link_flags(self, env: 'Environment') -> T.List[str]:
# We need to apply the search prefix here, as these link arguments may
# be passed to a different compiler with a different set of default
# search paths, such as when using Clang for C/C++ and gfortran for
# fortran,
search_dirs: T.List[str] = []
for d in self.get_compiler_dirs(env, 'libraries'):
search_dirs.append(f'-L{d}')
return search_dirs + ['-lstdc++']
class ArmLtdClangCPPCompiler(ClangCPPCompiler): class ArmLtdClangCPPCompiler(ClangCPPCompiler):
@ -266,15 +297,7 @@ class ArmLtdClangCPPCompiler(ClangCPPCompiler):
class AppleClangCPPCompiler(ClangCPPCompiler): class AppleClangCPPCompiler(ClangCPPCompiler):
def language_stdlib_only_link_flags(self, env: 'Environment') -> T.List[str]: pass
# We need to apply the search prefix here, as these link arguments may
# be passed to a different compiler with a different set of default
# search paths, such as when using Clang for C/C++ and gfortran for
# fortran,
search_dirs: T.List[str] = []
for d in self.get_compiler_dirs(env, 'libraries'):
search_dirs.append(f'-L{d}')
return search_dirs + ['-lc++']
class EmscriptenCPPCompiler(EmscriptenMixin, ClangCPPCompiler): class EmscriptenCPPCompiler(EmscriptenMixin, ClangCPPCompiler):
@ -353,7 +376,7 @@ class ArmclangCPPCompiler(ArmclangCompiler, CPPCompiler):
return [] return []
class GnuCPPCompiler(GnuCompiler, CPPCompiler): class GnuCPPCompiler(_StdCPPLibMixin, GnuCompiler, CPPCompiler):
def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool,
info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None,
linker: T.Optional['DynamicLinker'] = None, linker: T.Optional['DynamicLinker'] = None,
@ -434,16 +457,6 @@ class GnuCPPCompiler(GnuCompiler, CPPCompiler):
def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]: def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]:
return ['-fpch-preprocess', '-include', os.path.basename(header)] return ['-fpch-preprocess', '-include', os.path.basename(header)]
def language_stdlib_only_link_flags(self, env: 'Environment') -> T.List[str]:
# We need to apply the search prefix here, as these link arguments may
# be passed to a different compiler with a different set of default
# search paths, such as when using Clang for C/C++ and gfortran for
# fortran,
search_dirs: T.List[str] = []
for d in self.get_compiler_dirs(env, 'libraries'):
search_dirs.append(f'-L{d}')
return ['-lstdc++']
class PGICPPCompiler(PGICompiler, CPPCompiler): class PGICPPCompiler(PGICompiler, CPPCompiler):
def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool,

Loading…
Cancel
Save