如何解决app与src文件夹间的CMake库依赖及配置问题
CMake项目配置问题
我有一个包含src和app文件夹的项目,每个文件夹都配有CMakeLists.txt文件。项目根目录的主CMakeLists.txt目前通过add_subdirectory引入src文件夹,会基于src代码生成dll和lib并完成安装。
现在有两个问题:
- 如何配置app文件夹的CMakeLists.txt,使其使用src生成并安装的库?
- 能否从主CMakeLists.txt调用app的CMakeLists.txt?还是应为app创建完全独立的CMakeLists.txt?
以下是相关CMakeLists.txt代码:
主CMakeLists.txt
cmake_minimum_required( VERSION 3.15..3.25 FATAL_ERROR ) # Create Project project( "myproject" VERSION 0.1 LANGUAGES CXX) set(LIBRARY_NAME ${PROJECT_NAME}_lib) set(CMAKE_INSTALL_INCLUDEDIR include) set(CMAKE_INSTALL_LIBDIR lib) set(CMAKE_INSTALL_BINDIR bin) set(CMAKE_INSTALL_PREFIX $ENV{OCTREE_HOME}) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "$ENV{PCL_ROOT}/cmake/Modules/" "$ENV{OCTREE_HOME}/share/cmake/Modules/") message(STATUS "CMAKE_MODULE_PATH: ${CMAKE_MODULE_PATH}") # All users of this library will need at least C++11 if(MSVC) add_compile_options(/Zc:__cplusplus) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++latest /bigobj") set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) else(MSVC) target_compile_features(apps PUBLIC cxx_std_17) endif(MSVC) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -g") set(CMAKE_VERBOSE_MAKEFILE ON) # find packages set(OpenCV_DIR "${VCPKG_INSTALLED_DIR}/x86-windows/share/opencv3") find_package(OpenCV CONFIG REQUIRED) # COMPONENTS opencv_world) if (OpenCV_FOUND) message(STATUS "OpenCV version: ${OpenCV_VERSION}") endif() option(USE_PCL "Use PCL" ON) find_package(PCL CONFIG REQUIRED COMPONENTS common io filters visualization) if (PCL_FOUND) message(STATUS "PCL version: ${PCL_VERSION}") add_definitions(-DPOINTCLOUDREAD_USES_PCL) endif() # The executable code is here add_subdirectory(src) add_subdirectory(apps) #Install the targets and their associated files install(TARGETS ${LIBRARY_NAME} LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" ) install(TARGETS ${LIBRARY_NAME} DESTINATION "$ENV{OCTREE_HOME}/${CMAKE_INSTALL_LIBDIR}") install(TARGETS ${LIBRARY_NAME} LIBRARY DESTINATION "$ENV{OCTREE_HOME}/${CMAKE_INSTALL_BINDIR}") install(DIRECTORY include/ DESTINATION "$ENV{OCTREE_HOME}/${CMAKE_INSTALL_INCLUDEDIR}") install(FILES cmake/Modules/Find${PROJECT_NAME}.cmake DESTINATION "$ENV{OCTREE_HOME}/share/cmake/Modules/")
src目录CMakeLists.txt
set(PROJECT_INCLUDE_DIRS ${CMAKE_HOME_DIRECTORY}/include) set(HEADER_LIST ../include/octreesegmentation.h ../include/templates.h) set(SOURCE_LIST ../src/octreesegmentation.cpp) list(APPEND INCLUDE_DIRS "${EIGEN_INCLUDE_DIR}" "${OpenCV_INCLUDE_DIRS}" "${PROJECT_INCLUDE_DIR}" "${PCL_INCLUDE_DIRS}" "$ENV{PCL_ROOT}/3rdParty/VTK/include/vtk-${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION}" "${PROCESSING_INCLUDE_DIRS}" "${PROJECT_INCLUDE_DIRS}") list(APPEND TARGET_LINK_LIB_DIRS "$ENV{OCTREE_HOME}/lib" "${OpenCV_DIR}/${OpenCV_ARCH}/${OpenCV_RUNTIME}/lib" "${PCL_LIBRARY_DIRS}" "${PCL_LIBRARY_DIRS}/../3rdParty/VTK/lib" "${PCL_LIBRARY_DIRS}/../3rdParty/Eigen/lib" "$ENV{OCTREE_HOME}/lib") list(APPEND TARGET_LINK_LIBRARIES "${OpenCV_LIBS}" "${PCL_LIBRARIES}" "${PCL_VISUALIZATION_LIBRARIES}" "${PREPROCESSING_LIBRARIES}" "${PROCESSING_LIBRARIES}" "${POSTPROCESSING_LIBRARIES}" "${PCL_COMMON_LIBRARY_DEBUG}" "VTK::CommonCore") if(CMAKE_BUILD_TYPE MATCHES Debug) message(STATUS "========================== DEBUG INFO ==========================") message(STATUS "HEADER_LIST: ${HEADER_LIST}") message(STATUS "SOURCE_LIST: ${SOURCE_LIST}") message(STATUS "INCLUDE_DIRS: ${INCLUDE_DIRS}") message(STATUS "TARGET_LINK_LIB_DIRS: ${TARGET_LINK_LIB_DIRS}") message(STATUS "TARGET_LINK_LIBRARIES: ${TARGET_LINK_LIBRARIES}") message(STATUS "========================== END OF DEBUG INFO ==========================") endif() # Generate LIB file add_library(${LIBRARY_NAME} STATIC ${SOURCE_LIST} ${HEADER_LIST}) set_target_properties(${LIBRARY_NAME} PROPERTIES VERSION ${PROJECT_VERSION} OUTPUT_NAME ${LIBRARY_NAME} ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/lib) target_include_directories(${LIBRARY_NAME} PUBLIC ${INCLUDE_DIRS}) target_link_directories(${LIBRARY_NAME} PRIVATE ${TARGET_LINK_LIB_DIRS}) target_link_libraries(${LIBRARY_NAME} PRIVATE ${TARGET_LINK_LIBRARIES}) # Generate DLL file add_library(${LIBRARY_NAME}_dll SHARED ${SOURCE_LIST} ${HEADER_LIST}) set_target_properties(${LIBRARY_NAME}_dll PROPERTIES VERSION ${PROJECT_VERSION} OUTPUT_NAME ${LIBRARY_NAME} LIBRARY_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/lib) target_include_directories(${LIBRARY_NAME} PUBLIC ${INCLUDE_DIRS}) target_link_directories(${LIBRARY_NAME} PRIVATE ${TARGET_LINK_LIB_DIRS}) target_link_libraries(${LIBRARY_NAME} PRIVATE ${TARGET_LINK_LIBRARIES})
app目录CMakeLists.txt(需配置为使用src生成的库)
list(APPEND INCLUDE_DIRS "${EIGEN_INCLUDE_DIR}" "${OpenCV_INCLUDE_DIRS}" "${PROJECT_INCLUDE_DIR}" "${PCL_INCLUDE_DIRS}" "$ENV{PCL_ROOT}/3rdParty/VTK/include/vtk-${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION}" "${PROCESSING_INCLUDE_DIRS}") list(APPEND TARGET_LINK_LIB_DIRS "$ENV{OCTREE_HOME}/lib" "${OpenCV_DIR}/${OpenCV_ARCH}/${OpenCV_RUNTIME}/lib" "${PCL_LIBRARY_DIRS}" "${PCL_LIBRARY_DIRS}/../3rdParty/VTK/lib" "${PCL_LIBRARY_DIRS}/../3rdParty/Eigen/lib") list(APPEND TARGET_LINK_LIBRARIES "${OCTREESEGMENTATION_LIBRARIES}" "${OpenCV_LIBS}" "${PCL_LIBRARIES}" "${PCL_VISUALIZATION_LIBRARIES}" "${PREPROCESSING_LIBRARIES}" "${PROCESSING_LIBRARIES}" "${POSTPROCESSING_LIBRARIES}" "${PCL_COMMON_LIBRARY_DEBUG}" "VTK::CommonCore" "VTK::SystemTools") include_directories("${INCLUDE_DIRS}" ) link_directories(${TARGET_LINK_LIB_DIRS}) #add_definitions(${PCL_DEFINITIONS}) #add_library(main SHARED ${PROCESSING_SOURCES}) add_executable(main main.cpp) target_link_libraries(main ${OCTREESEGMENTATION_LIBRARIES})
问题解答
1. 配置app的CMakeLists.txt使用src生成的库
分两种场景处理:
场景一:同构建流程直接依赖src目标(无需提前安装)
如果app和src在同一个项目构建中,直接利用CMake的目标依赖机制即可,这是开发阶段最便捷的方式:
- 主CMakeLists.txt已通过
add_subdirectory(src)引入src构建,src中定义的${LIBRARY_NAME}(静态库)和${LIBRARY_NAME}_dll(动态库)目标在app的CMakeLists.txt中直接可见。 - 无需手动指定头文件和库路径,修改后的app/CMakeLists.txt如下:
# 继承主项目的C++标准配置,无需重复设置 add_executable(main main.cpp) # 选择链接静态库或动态库,二选一即可 target_link_libraries(main PRIVATE ${LIBRARY_NAME}) # 或者链接动态库:target_link_libraries(main PRIVATE ${LIBRARY_NAME}_dll) # 追加其他依赖(OpenCV、PCL等),直接复用主项目的查找结果 target_link_libraries(main PRIVATE ${OpenCV_LIBS} ${PCL_LIBRARIES} VTK::CommonCore VTK::SystemTools)
场景二:依赖已安装的库(独立构建app)
如果app需要独立构建,依赖已安装到指定目录的src库,需用find_package定位:
- 确保主项目安装时生成了正确的配置文件(或你已编写
Findmyproject.cmake) - 修改后的app/CMakeLists.txt示例:
cmake_minimum_required(VERSION 3.15..3.25 FATAL_ERROR) project(app_project LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # 指定库的安装路径,与主项目的CMAKE_INSTALL_PREFIX一致 set(CMAKE_PREFIX_PATH $ENV{OCTREE_HOME}) # 查找已安装的库 find_package(myproject REQUIRED) # 配置其他依赖 set(OpenCV_DIR "${VCPKG_INSTALLED_DIR}/x86-windows/share/opencv3") find_package(OpenCV CONFIG REQUIRED) find_package(PCL CONFIG REQUIRED COMPONENTS common io filters visualization) add_executable(main main.cpp) # 链接找到的库目标 target_link_libraries(main PRIVATE myproject::myproject_lib ${OpenCV_LIBS} ${PCL_LIBRARIES} VTK::CommonCore VTK::SystemTools)
注意:推荐在主CMakeLists.txt中添加install(EXPORT ...)自动生成Config文件,替代手动安装Find模块的方式。
2. 主CMakeLists调用app vs 独立构建
两种方式都可行,按需选择:
方式一:主CMakeLists调用app的CMakeLists(推荐开发阶段使用)
- 保留主CMakeLists.txt中的
add_subdirectory(apps)即可,优势包括:- 自动处理依赖关系,src代码修改后app会自动触发重建
- 无需手动安装src库,开发效率更高
- 共享主项目的依赖配置(如OpenCV、PCL的查找结果)
- 适合app是项目组成部分的场景。
方式二:为app创建独立CMakeLists
- 适合app是独立应用、无需与src一同构建,或需部署到不同环境的场景
- 此时app必须依赖已安装完成的src库,需按上述场景二的配置方式操作,确保src库已正确安装到指定路径。
内容的提问来源于stack exchange,提问作者xeon123
相关产品推荐
相关产品推荐

