如何解决vcpkg与pybind11在CMake 3.27+下的构建冲突
系统环境
Mac OSX 15.0 apple clang 16.0.0 cmake 3.30.1
CMake 3.26+ 版本移除了旧的FindPythonInterp/FindPythonLibs模块,改用统一的FindPython模块,这是核心背景。
目录结构
extern/vcpkg/ # GitHub克隆并初始化完成 extern/pybind11/ # GitHub克隆 CMakeLists.txt main.cpp
相关文件内容
CMakeLists.txt
# cmake_minimum_required(VERSION 3.26.0 FATAL_ERROR) cmake_minimum_required(VERSION 3.27.0 FATAL_ERROR) set(CMAKE_CXX_STANDARD 20) set(CMAKE_EXPORT_COMPILE_COMMANDS 1) # set (CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/extern/vcpkg/scripts/buildsystems/vcpkg.cmake) set(PROJECT mytest) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}) project(${PROJECT}) add_subdirectory(extern/pybind11) pybind11_add_module(${PROJECT} main.cpp)
main.cpp
#include <pybind11/pybind11.h> #include <iostream> void say_hello(){ std::cout << "Hello world!" << std::endl; } PYBIND11_MODULE(mytest, m) { m.def("say_hello", &say_hello); }
构建命令
rm -rf build || true && cmake -H. -Bbuild && cmake --build build --target all
问题现象
- 默认配置(注释Vcpkg工具链):构建正常,模块可运行。
- 启用Vcpkg工具链:构建失败,报错找不到
PythonInterp配置文件:
CMake Error at extern/vcpkg/scripts/buildsystems/vcpkg.cmake:859 (_find_package):
By not providing "FindPythonInterp.cmake" in CMAKE_MODULE_PATH this project
has asked CMake to find a package configuration file provided by
"PythonInterp", but CMake did not find one.Could not find a package configuration file provided by "PythonInterp"
(requested version 3.8) with any of the following names:PythonInterpConfig.cmake pythoninterp-config.cmakeAdd the installation prefix of "PythonInterp" to CMAKE_PREFIX_PATH or set
"PythonInterp_DIR" to a directory containing one of the above files. If
"PythonInterp" provides a separate development package or SDK, be sure it
has been installed.
Call Stack (most recent call first):
extern/pybind11/tools/FindPythonLibsNew.cmake:114 (find_package)
extern/vcpkg/scripts/buildsystems/vcpkg.cmake:859 (_find_package)
extern/pybind11/tools/pybind11Tools.cmake:44 (find_package)
extern/pybind11/tools/pybind11Common.cmake:200 (include)
extern/pybind11/CMakeLists.txt:229 (include)
- 回退CMake最低版本到3.26以下:构建成功,但收到pybind11警告:
CMake Warning (dev) at extern/pybind11/tools/FindPythonLibsNew.cmake:101 (message):
Policy CMP0148 is not set: The FindPythonInterp and FindPythonLibs modules
are removed. Run "cmake --help-policy CMP0148" for policy details. Use
the cmake_policy command to set the policy and suppress this warning, or
preferably upgrade to using FindPython, either by calling it explicitly
before pybind11, or by setting PYBIND11_FINDPYTHON ON before pybind11.
Call Stack (most recent call first):
extern/vcpkg/scripts/buildsystems/vcpkg.cmake:859 (_find_package)
extern/pybind11/tools/pybind11Tools.cmake:44 (find_package)
extern/pybind11/tools/pybind11Common.cmake:200 (include)
extern/pybind11/CMakeLists.txt:229 (include)
原因分析
核心矛盾
CMake 3.27+ 强制启用CMP0148政策,彻底移除旧的FindPythonInterp/FindPythonLibs模块;而当前使用的pybind11版本默认仍依赖旧的查找逻辑,叠加Vcpkg工具链的拦截,导致查找失败。
Vcpkg的具体影响
Vcpkg工具链会覆盖CMake原生的find_package逻辑,优先查找Vcpkg管理的包而非系统包:
- 未启用Vcpkg时:CMake或pybind11内部的兼容层会处理旧查找逻辑的适配;
- 启用Vcpkg时:Vcpkg的
_find_package函数会跳过兼容逻辑,直接查找名为PythonInterp的Vcpkg包——但Vcpkg仅提供python3端口,不存在PythonInterp包,因此直接报错。
可行解决方案(适配最新CMake政策)
方案1:强制pybind11使用新的FindPython模块
在add_subdirectory(extern/pybind11)之前添加配置,让pybind11跳过旧的查找逻辑,直接使用CMake原生的FindPython模块:
# 启用pybind11的新Python查找逻辑 set(PYBIND11_FINDPYTHON ON) # 显式锁定Python版本(可选,可根据需求调整版本号) find_package(Python 3.8 REQUIRED COMPONENTS Interpreter Development)
修改后的完整CMakeLists.txt关键片段:
cmake_minimum_required(VERSION 3.27.0 FATAL_ERROR) set(CMAKE_CXX_STANDARD 20) set(CMAKE_EXPORT_COMPILE_COMMANDS 1) set (CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/extern/vcpkg/scripts/buildsystems/vcpkg.cmake) set(PROJECT mytest) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}) project(${PROJECT}) # 关键配置:适配最新CMake Python查找政策 set(PYBIND11_FINDPYTHON ON) find_package(Python 3.8 REQUIRED COMPONENTS Interpreter Development) add_subdirectory(extern/pybind11) pybind11_add_module(${PROJECT} main.cpp)
方案2:更新pybind11到最新版本
最新版pybind11已默认适配CMake 3.26+的CMP0148政策,自动使用FindPython模块。直接拉取pybind11的最新GitHub代码替换现有extern/pybind11目录即可,无需额外修改CMake配置。
方案3:通过Vcpkg统一管理Python依赖(可选)
如果希望用Vcpkg管理Python,先安装Python端口:
cd extern/vcpkg ./vcpkg install python3:x64-osx
然后结合方案1的配置,确保CMake优先使用Vcpkg安装的Python。
内容的提问来源于stack exchange,提问作者Vince W.

