将Meson项目(jose)作为依赖库集成到CMake项目遇阻求助
问题背景
我需要将一个Meson项目(具体为jose库)集成到使用CMake构建的项目中。此前了解到当前推荐使用FetchContent,但该方法仅适用于CMake项目,无法适配这类“非CMake”项目,也未找到示例中运行Meson的方式。
于是尝试使用ExternalProject_Add,它可完成jose的配置与构建,但存在问题:需将jose库添加到target_link_libraries中,可CMake配置项目时该库尚未构建。我认为需在全局CMake配置阶段完成jose构建,遂尝试execute_process和ExternalProject_Add_Step但未成功,代码如下:
ExternalProject_Add( jose UPDATE_COMMAND "" PATCH_COMMAND "" SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/jose # Configure CONFIGURE_HANDLED_BY_BUILD true CONFIGURE_COMMAND meson setup ${CMAKE_CURRENT_SOURCE_DIR}/jose --prefix=${INSTALL_DIR} --pkg-config-path ${CMAKE_CURRENT_BINARY_DIR}/vcpkg_installed/x64-linux/lib/pkgconfig BUILD_COMMAND ninja INSTALL_COMMAND "" TEST_COMMAND "" ) set(jose_BINARY_DIR "${BINARY_DIR}") ExternalProject_Add_Step(jose build COMMENT "Building jose project..." COMMAND ${CMAKE_COMMAND} --build ${jose_BINARY_DIR} RESULT_VARIABLE jose_build_result OUTPUT_QUIET DEPENDEES download update WORKING_DIRECTORY ${jose_BINARY_DIR} ) add_dependencies(${CMAKE_PROJECT_NAME} jose)
目前遇到两个问题:
- target_link_libraries仍会在jose构建完成前尝试查找该库
- 若从target_link_libraries中移除jose(测试用),ExternalProject_Add_Step会报错,提示add_custom_command尝试添加重复自定义规则(jose-build.rule)
疑问:
- 使用ExternalProject_Add_Step的方向是否正确?
- 若正确,如何让它在target_link_libraries评估前执行?
问题解答
1. 使用ExternalProject_Add_Step的方向是否正确?
不正确。ExternalProject_Add本身已经内置了build步骤,手动添加同名的build步骤会导致重复规则冲突,这就是你遇到第二个问题的核心原因。不需要额外调用ExternalProject_Add_Step定义build流程,原配置已经会自动处理构建环节。
2. 如何让jose构建在target_link_libraries评估前执行?
CMake的配置阶段与构建阶段是分离的,target_link_libraries在配置阶段就会尝试解析库路径,而ExternalProject_Add默认在构建阶段才执行外部项目构建。解决这个矛盾有两种可靠方案:
方案一:配置阶段直接构建jose
跳过ExternalProject_Add,用execute_process在CMake配置时就运行Meson和Ninja完成jose的构建,确保配置阶段结束时库已存在:
# 定义jose的目录路径 set(JOSE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/jose") set(JOSE_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/jose-build") set(JOSE_INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/jose-install") # 执行Meson配置 execute_process( COMMAND meson setup ${JOSE_SOURCE_DIR} ${JOSE_BUILD_DIR} --prefix=${JOSE_INSTALL_DIR} --pkg-config-path ${CMAKE_CURRENT_BINARY_DIR}/vcpkg_installed/x64-linux/lib/pkgconfig RESULT_VARIABLE MESON_SETUP_RESULT ERROR_VARIABLE MESON_SETUP_ERROR ) if(NOT MESON_SETUP_RESULT EQUAL 0) message(FATAL_ERROR "Meson配置失败: ${MESON_SETUP_ERROR}") endif() # 执行Ninja构建 execute_process( COMMAND ninja -C ${JOSE_BUILD_DIR} RESULT_VARIABLE NINJA_BUILD_RESULT ERROR_VARIABLE NINJA_BUILD_ERROR ) if(NOT NINJA_BUILD_RESULT EQUAL 0) message(FATAL_ERROR "Ninja构建失败: ${NINJA_BUILD_ERROR}") endif() # 执行安装(按需启用) execute_process( COMMAND ninja -C ${JOSE_BUILD_DIR} install RESULT_VARIABLE NINJA_INSTALL_RESULT ERROR_VARIABLE NINJA_INSTALL_ERROR ) if(NOT NINJA_INSTALL_RESULT EQUAL 0) message(FATAL_ERROR "Ninja安装失败: ${NINJA_INSTALL_ERROR}") endif() # 查找并链接jose库 find_library(JOSE_LIBRARY NAMES jose PATHS ${JOSE_INSTALL_DIR}/lib) find_path(JOSE_INCLUDE_DIR NAMES jose/jose.h PATHS ${JOSE_INSTALL_DIR}/include) target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE ${JOSE_INCLUDE_DIR}) target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE ${JOSE_LIBRARY})
方案二:使用IMPORTED目标延迟库解析
如果希望保留增量构建特性,可创建IMPORTED目标,通过依赖关系让主项目等待外部项目构建,同时用属性指定路径,CMake会延迟到构建阶段再实际查找库:
set(INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/jose-install") set(JOSE_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/jose-build") ExternalProject_Add( jose UPDATE_COMMAND "" PATCH_COMMAND "" SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/jose" BINARY_DIR "${JOSE_BUILD_DIR}" CONFIGURE_COMMAND meson setup ${CMAKE_CURRENT_SOURCE_DIR}/jose ${JOSE_BUILD_DIR} --prefix=${INSTALL_DIR} --pkg-config-path ${CMAKE_CURRENT_BINARY_DIR}/vcpkg_installed/x64-linux/lib/pkgconfig BUILD_COMMAND ninja -C ${JOSE_BUILD_DIR} INSTALL_COMMAND ninja -C ${JOSE_BUILD_DIR} install TEST_COMMAND "" ) # 创建导入式目标 add_library(jose::jose STATIC IMPORTED GLOBAL) add_dependencies(jose::jose jose) # 设置目标属性(路径会在构建阶段生效) set_target_properties(jose::jose PROPERTIES IMPORTED_LOCATION "${INSTALL_DIR}/lib/libjose.a" INTERFACE_INCLUDE_DIRECTORIES "${INSTALL_DIR}/include" ) # 链接到主项目 target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE jose::jose)
针对你遇到的具体问题的修复
- 问题1:方案一通过配置阶段提前构建解决;方案二通过IMPORTED目标延迟库解析解决。
- 问题2:删除手动添加的
ExternalProject_Add_Step(jose build)代码块,避免重复定义构建规则。
内容的提问来源于stack exchange,提问作者Claude

