如何在ExternalProject_Add中处理强依赖问题?
解决ExternalProject依赖中find_program提前检测的问题
问题描述
主项目依赖两个外部项目X和Y,Y同时依赖X。使用make构建时失败,原因是Y的CMake配置阶段通过find_program()查找X生成的二进制文件,若找不到该文件会触发致命错误。尝试给Y的ExternalProject_Add()添加DEPENDS X属性无效,传递路径变量也无法解决问题,且无法/不愿修改Y的CMakeLists.txt,寻求替代解决方案。
核心原因
ExternalProject_Add()的DEPENDS仅保证构建阶段的依赖顺序,但Y的配置阶段(cmake configure)会在X构建完成前执行——此时X的二进制文件尚未生成,导致find_program()检测失败。
解决方案
方法1:强制Y的配置阶段等待X完成安装
通过ExternalProject_Add_Step()给Y添加预配置步骤,确保Y的配置流程在X完成构建和安装后再执行,同时传递X的二进制路径给Y:
ExternalProject_Add(X ... INSTALL_COMMAND "${MAKE}" install # 确保X安装到指定前缀目录 ) # 给Y添加等待X安装完成的步骤 ExternalProject_Add_Step(Y wait_for_X_install COMMAND "" DEPENDEES download DEPENDERS configure DEPENDS X ) ExternalProject_Add(Y ... # 传递X的二进制路径给Y的配置流程 CMAKE_ARGS "-DX_BINARY_PATH=${CMAKE_INSTALL_PREFIX}/bin/x_binary" # 其他配置参数 )
方法2:通过CMAKE_PROGRAM_PATH传递搜索路径
将X的二进制输出目录加入Y的CMAKE_PROGRAM_PATH,让find_program()能找到目标文件,同时结合步骤依赖确保顺序:
ExternalProject_Add(X ... BINARY_DIR "${DEPS_DIR}/x-build" RUNTIME_OUTPUT_DIRECTORY "${GLOBAL_OUTPUT_PATH}" ) ExternalProject_Add(Y DEPENDS X ... # 将X的二进制目录加入程序搜索路径 CMAKE_ARGS "-DCMAKE_PROGRAM_PATH=${GLOBAL_OUTPUT_PATH}" # 其他配置参数 ) # 强制Y的配置在X构建完成后执行 ExternalProject_Add_Step(Y reconfigure_after_X COMMAND ${CMAKE_COMMAND} --build <BINARY_DIR> --target reconfigure DEPENDEES download DEPENDERS configure DEPENDS X )
针对SQLite3+PROJ示例的修改
结合你提供的代码,调整后可解决PROJ配置阶段找不到sqlite3二进制的问题:
cmake_minimum_required(VERSION 3.22) project(TEST) # Global settings set(GLOBAL_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) set(CMAKE_INSTALL_PREFIX ${PROJECT_BINARY_DIR}/install) set(DEPS_DIR ${CMAKE_SOURCE_DIR}/deps) # 设置输出目录 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${GLOBAL_OUTPUT_PATH}) foreach(OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES}) string(TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${GLOBAL_OUTPUT_PATH}) endforeach() include(ExternalProject) ExternalProject_Add(sqlite3 GIT_REPOSITORY "https://github.com/sqlite/sqlite.git" GIT_TAG "master" UPDATE_COMMAND "" PATCH_COMMAND "" SOURCE_DIR "${DEPS_DIR}/sqlite" CONFIGURE_COMMAND ${DEPS_DIR}/sqlite/configure --all --prefix=${CMAKE_INSTALL_PREFIX} CFLAGS="-Os" SQLITE_THREADSAFE=2 BUILD_SHARED_LIBS=0 --disable-debug BUILD_COMMAND "${MAKE}" INSTALL_COMMAND "${MAKE}" install # 将sqlite3安装到指定前缀 TEST_COMMAND "" ) ExternalProject_Add(proj DEPENDS sqlite3 GIT_REPOSITORY "https://github.com/OSGeo/PROJ.git" GIT_TAG "master" UPDATE_COMMAND "" PATCH_COMMAND "" SOURCE_DIR "${DEPS_DIR}/proj" CMAKE_ARGS "-DBUILD_SHARED_LIBS=0" "-DBUILD_TESTING=0" "-DBUILD_APPS=0" "-DSQLite3_LIBRARY_DIR=${CMAKE_INSTALL_PREFIX}/lib" "-DCMAKE_PROGRAM_PATH=${CMAKE_INSTALL_PREFIX}/bin" # 加入sqlite3二进制搜索路径 BUILD_COMMAND "${MAKE}" ) # 强制PROJ配置阶段等待sqlite3安装完成 ExternalProject_Add_Step(proj wait_for_sqlite_install COMMAND "" DEPENDEES download DEPENDERS configure DEPENDS sqlite3 )
内容的提问来源于stack exchange,提问作者rbaleksandar
相关产品推荐
相关产品推荐

