From 4880e7112644f8592caabb698aa937969106fe6c Mon Sep 17 00:00:00 2001 From: Yifeng Li Date: Tue, 25 Apr 2023 15:15:19 +0000 Subject: [PATCH 1/2] Inject -stdlib=libc++ on macOS only when it's supported, close #4637. On macOS, by default, pybind11 currently unconditionally set the compiler flag "-stdlib=libc++" in Pybind11Extension.__init__(), regardless of which compiler is used. This flag is required for clang, but is invalid for GCC. If GCC is used, it causes compilation failures in all Python projects that use pybind11, with the error message: arm64-apple-darwin22-gcc: error: unrecognized command-line option -stdlib=libc++. This commit uses has_flag() to detect whether "-stdlib=libc++" on macOS, and injects this flag from build_ext.build_extensions(), rather than setting it unconditionally. Signed-off-by: Yifeng Li --- pybind11/setup_helpers.py | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/pybind11/setup_helpers.py b/pybind11/setup_helpers.py index 0fb4679e49..110ac79d1c 100644 --- a/pybind11/setup_helpers.py +++ b/pybind11/setup_helpers.py @@ -144,7 +144,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: self.cxx_std = cxx_std cflags = [] - ldflags = [] if WIN: cflags += ["/EHsc", "/bigobj"] else: @@ -154,11 +153,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: c_cpp_flags = shlex.split(env_cflags) + shlex.split(env_cppflags) if not any(opt.startswith("-g") for opt in c_cpp_flags): cflags += ["-g0"] - if MACOS: - cflags += ["-stdlib=libc++"] - ldflags += ["-stdlib=libc++"] self._add_cflags(cflags) - self._add_ldflags(ldflags) @property def cxx_std(self) -> int: @@ -271,22 +266,42 @@ def auto_cpp_level(compiler: Any) -> Union[str, int]: raise RuntimeError(msg) +@lru_cache() +def has_stdlib_libc(compiler: Any) -> bool: + """ + Return whether the flag "-stdlib=libc++" is supported by the compiler. + On macOS, this flag is required for clang but is invalid for GCC. + """ + return has_flag(compiler, "-stdlib=libc++") + + class build_ext(_build_ext): # type: ignore[misc] # noqa: N801 """ Customized build_ext that allows an auto-search for the highest supported - C++ level for Pybind11Extension. This is only needed for the auto-search - for now, and is completely optional otherwise. + C++ level on all systems for Pybind11Extensions, and also auto-determine + whether "-stdlib=libc++" should be used on macOS. This is only needed for + these two auto-detections for now, and is completely optional otherwise. """ def build_extensions(self) -> None: """ - Build extensions, injecting C++ std for Pybind11Extension if needed. + Build extensions, injecting C++ std (and stdlib=libc++ on macOS) for + Pybind11Extension if needed. """ for ext in self.extensions: if hasattr(ext, "_cxx_level") and ext._cxx_level == 0: ext.cxx_std = auto_cpp_level(self.compiler) + if ( + MACOS + and hasattr(ext, "_add_cflags") + and hasattr(ext, "_add_ldflags") + and has_stdlib_libc(self.compiler) + ): + ext._add_cflags(["-stdlib=libc++"]) + ext._add_ldflags(["-stdlib=libc++"]) + super().build_extensions() From 146a89adfce60f4b24ac432496bd08b6090e2f95 Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Fri, 28 Apr 2023 14:36:55 -0400 Subject: [PATCH 2/2] revert: just remove flags --- pybind11/setup_helpers.py | 26 +++----------------------- 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/pybind11/setup_helpers.py b/pybind11/setup_helpers.py index 110ac79d1c..cb279f27e0 100644 --- a/pybind11/setup_helpers.py +++ b/pybind11/setup_helpers.py @@ -266,42 +266,22 @@ def auto_cpp_level(compiler: Any) -> Union[str, int]: raise RuntimeError(msg) -@lru_cache() -def has_stdlib_libc(compiler: Any) -> bool: - """ - Return whether the flag "-stdlib=libc++" is supported by the compiler. - On macOS, this flag is required for clang but is invalid for GCC. - """ - return has_flag(compiler, "-stdlib=libc++") - - class build_ext(_build_ext): # type: ignore[misc] # noqa: N801 """ Customized build_ext that allows an auto-search for the highest supported - C++ level on all systems for Pybind11Extensions, and also auto-determine - whether "-stdlib=libc++" should be used on macOS. This is only needed for - these two auto-detections for now, and is completely optional otherwise. + C++ level for Pybind11Extension. This is only needed for the auto-search + for now, and is completely optional otherwise. """ def build_extensions(self) -> None: """ - Build extensions, injecting C++ std (and stdlib=libc++ on macOS) for - Pybind11Extension if needed. + Build extensions, injecting C++ std for Pybind11Extension if needed. """ for ext in self.extensions: if hasattr(ext, "_cxx_level") and ext._cxx_level == 0: ext.cxx_std = auto_cpp_level(self.compiler) - if ( - MACOS - and hasattr(ext, "_add_cflags") - and hasattr(ext, "_add_ldflags") - and has_stdlib_libc(self.compiler) - ): - ext._add_cflags(["-stdlib=libc++"]) - ext._add_ldflags(["-stdlib=libc++"]) - super().build_extensions()