从CMake创建Python虚拟环境后find_program查找Conan失败问题排查
问题
我们在CMake中调用Conan等Python包,Python 3.12强制要求使用虚拟环境。参考相关内容实现了虚拟环境内的依赖安装,但find_program无法找到Conan,执行后报错:Could not find CONAN_CMD using the following names: conan。以下是对应的CMake代码:
macro(create_venv) find_package(Python3 3.9 REQUIRED COMPONENTS Interpreter Development) set(SYSTEM_PYTHON_EXE_PATH ${Python3_EXECUTABLE}) message(STATUS "+++++++++++++++++ Found system python located at ${SYSTEM_PYTHON_EXE_PATH}++++++++++++++++") execute_process(COMMAND "${Python3_EXECUTABLE}" -m venv "${PROJECT_BINARY_DIR}/venv" --upgrade-deps COMMAND_ERROR_IS_FATAL ANY) # 模拟activate脚本设置VIRTUAL_ENV变量 set(VENV_PATH "${PROJECT_BINARY_DIR}/venv") set(ENV{VIRTUAL_ENV} "${VENV_PATH}") #[[ 启用此行会强制Conan使用虚拟环境缓存的包(新创建时为空), 意味着每次清理CMake缓存都要重新编译/下载第三方依赖,会增加配置时间 调试Conan配置时可以打开此行,避免影响本地构建 ]] # set (ENV{CONAN_USER_HOME} "${PROJECT_BINARY_DIR}/conan") set(Python3_FIND_VIRTUALENV FIRST) unset(Python3_EXECUTABLE) # 重新查找虚拟环境中的Python find_package(Python3 3.9 REQUIRED COMPONENTS Interpreter Development) message(STATUS "+++++++++++++++++ Found venv python located at ${Python3_EXECUTABLE}++++++++++++++++") if(SYSTEM_PYTHON_EXE_PATH STREQUAL Python3_EXECUTABLE) message(FATAL_ERROR "Python3 executable is the same as the system one, this is not expected") endif() message(STATUS "Trying to install deps") execute_process( COMMAND "${Python3_EXECUTABLE}" -m pip install -r "${TOOLBOX_SOURCE_DIR}/python3/requirements_win32.txt" COMMAND_ERROR_IS_FATAL ANY ) find_program(CONAN_CMD conan REQUIRED) if(NOT CONAN_CMD) message(FATAL_ERROR "Conan executable not found! Please install conan.") endif() endmacro()
解决方案
核心问题是CMake的PATH环境变量未包含虚拟环境的可执行文件目录,find_program依赖PATH查找工具,刚安装在虚拟环境里的conan不在搜索路径中,所以找不到。
具体修改步骤:
- 根据操作系统确定虚拟环境的可执行文件目录:
- Linux/macOS:虚拟环境下的
bin目录 - Windows:虚拟环境下的
Scripts目录
- Linux/macOS:虚拟环境下的
- 将该目录添加到
PATH最前端,确保CMake优先查找虚拟环境内的工具。
修改后的关键代码如下,插入到pip install之后、find_program之前:
# 确定虚拟环境的可执行文件目录 if(WIN32) set(VENV_BIN_DIR "${VENV_PATH}/Scripts") else() set(VENV_BIN_DIR "${VENV_PATH}/bin") endif() # 更新PATH环境变量,优先使用虚拟环境内的工具 if(WIN32) set(ENV{PATH} "${VENV_BIN_DIR};$ENV{PATH}") else() set(ENV{PATH} "${VENV_BIN_DIR}:$ENV{PATH}") endif() # 现在查找Conan就能定位到虚拟环境里的版本了 find_program(CONAN_CMD conan REQUIRED)
额外提一句:你代码里定义了REQUIREMENTS_ARG变量但没实际使用,不过这和当前问题无关。
内容的提问来源于stack exchange,提问作者JuliusCaesar
相关产品推荐
相关产品推荐

