From 675b47b0692131fae974298829ba807d730ab098 Mon Sep 17 00:00:00 2001 From: Sam James Date: Tue, 12 Mar 2024 23:35:48 +0000 Subject: [PATCH] compilers: cpp: improve libc++ vs libstdc++ detection (again) The previous approach wasn't great because you couldn't control what the detected C++ stdlib impl was. We just had a preference list we tweaked the searched order for per OS. That doesn't work great for e.g. Gentoo with libc++ or Gentoo Prefix on macOS where we might be using libstdc++ even though the host is libc++. Jonathan Wakely, the libstdc++ maintainer, gave a helpful answer on how to best detect libc++ vs libstdc++ via macros on SO [0]. Implement it. TL;DR: Use from C++20 if we can, use otherwise. Check for _LIBCPP_VERSION as libstdc++ doesn't always define a macro. [0] https://stackoverflow.com/a/31658120 Signed-off-by: Sam James Signed-off-by: Eli Schwartz --- mesonbuild/compilers/cpp.py | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index c5c2735ad6f6..fdf632a8c858 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -203,17 +203,14 @@ def language_stdlib_only_link_flags(self, env: Environment) -> T.List[str]: machine = env.machines[self.for_machine] assert machine is not None, 'for mypy' - # We need to determine whether to use libc++ or libstdc++. We can't - # really know the answer in most cases, only the most likely answer, - # because a user can install things themselves or build custom images. - search_order: T.List[str] = [] - if machine.system in {'android', 'darwin', 'dragonfly', 'freebsd', 'netbsd', 'openbsd'}: - search_order = ['c++', 'stdc++'] - else: - search_order = ['stdc++', 'c++'] - for lib in search_order: - if self.find_library(lib, env, []) is not None: - return search_dirs + [f'-l{lib}'] + # https://stackoverflow.com/a/31658120 + header = 'version' if self.has_header('', '', env) else 'ciso646' + is_libcxx = self.has_header_symbol(header, '_LIBCPP_VERSION', '', env)[0] + lib = 'c++' if is_libcxx else 'stdc++' + + if self.find_library(lib, env, []) is not None: + return search_dirs + [f'-l{lib}'] + # TODO: maybe a bug exception? raise MesonException('Could not detect either libc++ or libstdc++ as your C++ stdlib implementation.')