为什么Conan配合CMake编译需两次执行cmake --build .才生成二进制文件
问题原因与修复方案
核心问题1:执行顺序错误
你当前CMakeLists.txt的执行顺序存在致命逻辑问题:
conan_basic_setup(KEEP_RPATHS)会自动修改CMAKE_RUNTIME_OUTPUT_DIRECTORY等输出路径变量,你在调用该命令后立刻执行file(WRITE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/qt.conf),首次运行CMake时这个输出目录还未被创建,文件写入操作直接失败,导致首次构建中断。第二次构建时目录已经被第一次构建的中间流程创建,所以可以正常执行。- 你先定义了
add_executable目标,再执行find_package查找依赖,依赖的头文件路径、编译选项无法正确传递到已经定义的目标上,首次构建会报依赖找不到的错误,第二次构建时变量已经被CMake缓存,才能正常识别。
核心问题2:链接逻辑冲突
你同时混用了Conan 1.x旧版的全局CONAN_LIBS链接方式,和单独手动链接opus、portaudio的逻辑,两种方式的参数重复/冲突也会导致首次构建链接失败。
核心问题3:大小写不匹配警告
Conan为opus生成的查找文件是FindOpus.cmake,你写的find_package(opus REQUIRED)大小写不匹配,就是你日志中开发警告的来源,会导致依赖变量匹配异常。
修复后的CMakeLists.txt示例
cmake_minimum_required(VERSION 3.16) project(BABEL) set(CMAKE_CXX_STANDARD 20) set(PROJECT_NAME BABEL) set(SOURCES qt/main.cpp) # 先加载Conan配置 include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) include(${CMAKE_BINARY_DIR}/conan_paths.cmake) conan_basic_setup(KEEP_RPATHS) if (APPLE) set(CMAKE_INSTALL_RPATH "@executable_path/../lib") endif () # 先查找所有依赖,注意opus大小写修正 find_package(portaudio REQUIRED) find_package(Opus REQUIRED) find_package(Qt5 COMPONENTS Widgets Network Core Gui REQUIRED) # 再定义目标 add_executable(${PROJECT_NAME} ${SOURCES}) # 确认输出目录存在后再写入qt.conf file(MAKE_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) file(WRITE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/qt.conf "[Paths]\nPrefix=${CONAN_QT_ROOT}") # 统一用目标方式链接,不需要再用CONAN_LIBS target_link_libraries(${PROJECT_NAME} Opus::opus Qt5::Widgets Qt5::Network Qt5::Core Qt5::Gui $<IF:$<BOOL:${WIN32}>,portaudio_x64,portaudio> )
构建命令修正
你原命令中cmake --build.缺少空格,修正为:
mkdir build && cd build && conan install .. && cmake .. -G "Unix Makefiles" && cmake --build .
修改后重新执行构建命令,就可以一次构建成功。
内容的提问来源于stack exchange,提问作者Diamonddedo
相关产品推荐
相关产品推荐

