aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2023-07-04 20:32:20 +0300
committerGitHub <noreply@github.com>2023-07-04 20:32:20 +0300
commit73b3b60436addbca4233073ae5e12945576bf2d4 (patch)
treed6f8b22dbcf377d367172700fec8235d574eea58
parent42c68291c4c2512de04de31a90cb1c408d75a277 (diff)
parent9067139acb5f133e08ed15eba8a6d41246200b5b (diff)
downloadmeson-73b3b60436addbca4233073ae5e12945576bf2d4.zip
meson-73b3b60436addbca4233073ae5e12945576bf2d4.tar.gz
meson-73b3b60436addbca4233073ae5e12945576bf2d4.tar.bz2
Merge pull request #11924 from dcbaker/submit/c++stdlib-fixes
Do a better job of detecting libc++ vs libstdc++
-rw-r--r--mesonbuild/compilers/cpp.py75
1 files changed, 44 insertions, 31 deletions
diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py
index 3f8bf00..2605670 100644
--- a/mesonbuild/compilers/cpp.py
+++ b/mesonbuild/compilers/cpp.py
@@ -183,7 +183,48 @@ class CPPCompiler(CLikeCompiler, Compiler):
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,
info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None,
linker: T.Optional['DynamicLinker'] = None,
@@ -249,16 +290,6 @@ class ClangCPPCompiler(ClangCompiler, CPPCompiler):
return libs
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):
@@ -266,15 +297,7 @@ class ArmLtdClangCPPCompiler(ClangCPPCompiler):
class AppleClangCPPCompiler(ClangCPPCompiler):
- 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 + ['-lc++']
+ pass
class EmscriptenCPPCompiler(EmscriptenMixin, ClangCPPCompiler):
@@ -353,7 +376,7 @@ class ArmclangCPPCompiler(ArmclangCompiler, CPPCompiler):
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,
info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = 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]:
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):
def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool,