diff options
author | Dylan Baker <dylan@pnwbakers.com> | 2023-06-29 09:28:19 -0700 |
---|---|---|
committer | Dylan Baker <dylan@pnwbakers.com> | 2023-06-29 13:36:47 -0700 |
commit | a227768b378caa7a5f9faf42936bdad8cd6123dd (patch) | |
tree | ba330c60ae13e793c0aaa12edb11afbbe249116b /mesonbuild/compilers/cpp.py | |
parent | f58bd2ae11429ee7aa911de631faece718fbfe14 (diff) | |
download | meson-a227768b378caa7a5f9faf42936bdad8cd6123dd.zip meson-a227768b378caa7a5f9faf42936bdad8cd6123dd.tar.gz meson-a227768b378caa7a5f9faf42936bdad8cd6123dd.tar.bz2 |
compilers/cpp: try to do a better job of detecting libc++ vs libstdc++
Currently, we hardcode libc++ for MacOS (and derivatives), and libstdc++
for all other cases. Clang had some hackery to make this work in many
cases. However, this doesn't always work, namely if you try to to use
Rust as the linker when libc++ is required.
This implementation does, as an optimization, provide a hardcoded list
of OSes we know always use libc++, and otherwise will attempt to detect
it. As a second optimization, the detected values are cached, so the
lookup is only done once
fixes: #11921
Diffstat (limited to 'mesonbuild/compilers/cpp.py')
-rw-r--r-- | mesonbuild/compilers/cpp.py | 34 |
1 files changed, 31 insertions, 3 deletions
diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index bec4529..081f656 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -187,13 +187,41 @@ class _StdCPPLibMixin(CompilerMixinBase): """Detect whether to use libc++ or libstdc++.""" - def language_stdlib_only_link_flags(self, env: 'Environment') -> T.List[str]: + @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, + # fortran. search_dirs = [f'-L{d}' for d in self.get_compiler_dirs(env, 'libraries')] - return search_dirs + ['-lstdc++'] + + 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): |