迁移算法至CUDA时,CMake项目中PROJ与GDAL导出目标问题咨询
问题背景
在将算法从CPU迁移到CUDA的项目中,引入SQLite3、PROJ、GDAL作为Git子模块依赖,CMake配置阶段出现以下错误:
- 初始报错:
export called with target "GDAL" which requires target "proj" that is not in any export set
- 添加自定义
install(EXPORT)后新增报错:
An exported target cannot depend upon another target which is exported multiple times. Consider consolidating the exports of the "proj" target to a single export.
核心原因:PROJ的CMake配置默认会生成自身的导出集(proj-targets.cmake),用户额外添加的install(EXPORT)又重复导出PROJ,导致GDAL导出时检测到PROJ存在于多个导出集中,违反CMake的导出规则。
可行解决方案
方案1:禁用PROJ自身导出,统一管理导出集
利用PROJ的CMake选项禁用其默认安装导出逻辑,改用项目统一的导出集管理PROJ和GDAL:
修改PROJ相关CMake代码:
# PROJ # 禁用PROJ自带的安装导出 set(PROJ_BUILD_INSTALL OFF CACHE BOOL "") set(BUILD_APPS 0) set(BUILD_TESTING 0) add_subdirectory("${DEPS_DIR}/proj") # 统一导出PROJ和GDAL到同一个集合 install(TARGETS proj GDAL EXPORT MyProjectTargets LIBRARY DESTINATION lib ARCHIVE DESTINATION lib RUNTIME DESTINATION bin INCLUDES DESTINATION include) install(EXPORT MyProjectTargets FILE MyProjectTargets.cmake DESTINATION "${CMAKE_BINARY_DIR}/install/")
同时移除GDAL部分的冗余查找代码(add_subdirectory已直接引入目标,无需重复查找):
# GDAL set(SQLite3_HAS_MUTEX_ALLOC 1) set(BUILD_SHARED_LIBS 0) set(BUILD_TESTING 0) set(BUILD_APPS 0) set(GDAL_BUILD_OPTIONAL_DRIVERS 0) set(OGR_BUILD_OPTIONAL_DRIVERS 0) set(GDAL_USE_TIFF_INTERNAL 1) set(GDAL_USE_TIFF 0) set(GDAL_USE_GEOTIFF_INTERNAL 1) set(GDAL_USE_GEOTIFF 0) add_subdirectory("${DEPS_DIR}/gdal") # 移除以下冗余代码 # set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${CMAKE_BINARY_DIR}/bin/lib/cmake/gdal) # find_package(GDAL CONFIG) # if(NOT GDAL_FOUND) # find_package(GDAL REQUIRED) # endif()
方案2:将PROJ作为ExternalProject构建,与GDAL解耦
把PROJ从add_subdirectory改为ExternalProject_Add,让它在独立CMake上下文构建,GDAL通过find_package查找已安装的PROJ,避免同一上下文的导出冲突:
修改前三者的CMake代码:
if(BUILD_DEPS) # SQLite3 include(ExternalProject) ExternalProject_Add(sqlite3 SOURCE_DIR "${DEPS_DIR}/sqlite" CONFIGURE_COMMAND ${DEPS_DIR}/sqlite/configure --all --prefix=${CMAKE_BINARY_DIR} CFLAGS="-Os" CXXFLAGS="-Os" SQLITE_THREADSAFE=2 SQLITE_OMIT_COMPLETE=1 SQLITE_OMIT_CHECK=1 SQLITE_OMIT_DEPRECATED=1 --disable-debug BUILD_COMMAND ${MAKE} INSTALL_COMMAND ${MAKE} install) # PROJ 作为独立外部项目构建 ExternalProject_Add(proj SOURCE_DIR "${DEPS_DIR}/proj" DEPENDS sqlite3 CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR} -DBUILD_APPS=0 -DBUILD_TESTING=0 -DSQLITE3_INCLUDE_DIR=${CMAKE_BINARY_DIR}/include -DSQLite3_LIBRARY=${CMAKE_BINARY_DIR}/lib/libsqlite3.a -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} BUILD_COMMAND ${CMAKE_COMMAND} --build . INSTALL_COMMAND ${CMAKE_COMMAND} --install .) # GDAL set(SQLite3_HAS_MUTEX_ALLOC 1) set(BUILD_SHARED_LIBS 0) set(BUILD_TESTING 0) set(BUILD_APPS 0) set(GDAL_BUILD_OPTIONAL_DRIVERS 0) set(OGR_BUILD_OPTIONAL_DRIVERS 0) set(GDAL_USE_TIFF_INTERNAL 1) set(GDAL_USE_TIFF 0) set(GDAL_USE_GEOTIFF_INTERNAL 1) set(GDAL_USE_GEOTIFF 0) # 让GDAL能找到PROJ的安装目录 set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${CMAKE_BINARY_DIR}) # 确保PROJ安装完成后再构建GDAL add_dependencies(gdal proj) add_subdirectory("${DEPS_DIR}/gdal") endif()
方案3:禁用GDAL的导出逻辑(仅适用于内部使用场景)
如果项目仅在内部使用GDAL,不需要导出其目标供其他项目调用,可以直接禁用GDAL的安装导出:
# GDAL部分添加选项,禁用安装导出 set(GDAL_BUILD_INSTALL OFF CACHE BOOL "")
内容的提问来源于stack exchange,提问作者rbaleksandar

