使用pybind11打包C++库Python绑定遇-lstdc++找不到问题(Mac Mojave)
Let's break down why this issue pops up and walk through actionable fixes to get your package installing smoothly via pip:
Root Cause
macOS Mojave shifted Apple's default C++ standard library from libstdc++ to libc++, but older Anaconda environments (like your Python 3.6 setup) still ship with toolchains that expect libstdc++. Your CMake config tries to force libc++, but when pip runs the build, the Python environment's built-in build flags can override this setting—creating a linker mismatch that triggers the error.
Solution 1: Harden CMakeLists.txt to Enforce libc++
Update your CMake configuration to explicitly lock in libc++ and block any conflicting flags from the Python environment:
cmake_minimum_required(VERSION 3.10) # Bump to a newer CMake version for better pybind11 support project(xxx) set(CMAKE_BUILD_TYPE Release) # Force libc++ as the standard library and disable libstdc++ entirely set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++ -lc++") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -stdlib=libc++ -lc++") # Ensure pybind11 adheres to our standard library settings find_package(pybind11 REQUIRED) include_directories(...) pybind11_add_module(xxx xxx/xxx.cpp)
Solution 2: Pass Environment Variables in setup.py
Modify your build_cmake method to explicitly set macOS-specific environment variables that force libc++, even when pip initiates the build:
def build_cmake(self, ext): build_args = ['--config', 'Release', '--', '-j4'] cwd = pathlib.Path().absolute() build_temp = pathlib.Path(self.build_temp) build_temp.mkdir(parents=True, exist_ok=True) # Override environment variables to enforce libc++ env = os.environ.copy() env['CXXFLAGS'] = '-stdlib=libc++' env['LDFLAGS'] = '-stdlib=libc++' os.chdir(str(build_temp)) # Pass the modified environment to CMake self.spawn(['cmake', str(cwd)], env=env) if not self.dry_run: self.spawn(['cmake', '--build', '.'] + build_args, env=env) os.chdir(str(cwd))
Solution 3: Fix Anaconda Python 3.6 Environment Quirks
For older Anaconda envs, you may need to point the build system to the Mojave SDK explicitly:
- First, find your SDK path:
xcrun --show-sdk-path - Set the environment variable before running
pip install:export CONDA_BUILD_SYSROOT=$(xcrun --show-sdk-path) pip install my-package
You can also add this environment variable directly in your setup.py's build_cmake method to make this automatic for users.
Solution 4: Verify Wheel Compatibility (For Distribution)
If you're building wheels for public distribution, use delocate to bundle the correct libc++ library into the wheel, so users don't hit linker issues:
pip install delocate delocate-wheel -w fixed_wheels/ dist/*.whl
Final Notes
- The reason Python 3.4/3.7 works but 3.6 fails is because newer Python versions on macOS use the system's default
libc++toolchain, while older Anaconda 3.6 environments are still configured forlibstdc++. - Bumping CMake to 3.10+ improves pybind11 integration and standard library handling.
内容的提问来源于stack exchange,提问作者craig zhang

