首页 > 解决方案 > 使用具有外部依赖关系的库构建多个子项目

问题描述

我正在为一个包含 CMake(版本 3.11)和子目录的项目而苦苦挣扎。它包含 ITK 作为外部库。

我想创建一个库,我可以在不同的子目录(如 MyApp)中使用它来构建多个基于 MyLib 的应用程序,并且 MyLib 中的每个更改都会在其他应用程序中更新。MyLib 是一个只有标题的模板库。此外,这种库在 VisualStudio 中没有自己的项目。

我的问题是:

  1. 在这种情况下使用 CMake 的正确方法是什么?我已经搜索并尝试了一些示例,但没有成功。理想情况下,我可以根据 MyLib 独立构建应用程序。顶部的 CMakeLists.txt 可能不会从库中提取包含。这应该由应用程序完成。
  2. 如果 MyLib 成为非仅标头库会发生什么变化?将来我可能会添加非模板类。

奖金问题:

  1. 如何将仅标头库添加到 VisualStudio?这更像是一个方便的问题。

任何帮助表示赞赏,如有必要,我可以提供更多详细信息。

源环境如下所示:

ProjectDirectory
-  CMakeLists.txt
-- MyLib
   - CMakeLists.txt
   -- include
      - File1.h (template header)
      - File1.hxx (template body)
   -- src
      - (empty for now)
-- MyApp
   - CMakeLists.txt
   - AppFile1.cxx (File containing main function)

这是一个源外构建项目。理想情况下,编译的库和应用程序放在这样的目录中(在 Windows 上):

└── bin
    ├── Debug
    │   ├── MyApp.exe
    │   └── MyLib.lib
    └── Release
        ├── MyApp.exe
        └── MyLib.lib

项目目录 CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(project_name)

# Setup build locations.
if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY)
  set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
endif()
if(NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY)
  set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
endif()
if(NOT CMAKE_ARCHIVE_OUTPUT_DIRECTORY)
  set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
endif()

add_subdirectory(MyLib)
add_subdirectory(MyApp)

MyLib CMakeLists.txt:

find_package(ITK REQUIRED
    COMPONENTS RTK ITKImageIO)
include(${ITK_USE_FILE})

set(HDRS
    ${CMAKE_CURRENT_SOURCE_DIR}/include/File1.h
    ${CMAKE_CURRENT_SOURCE_DIR}/include/File1.hxx
)

add_library(MyLib ${HDRS})

target_include_directories(MyLib
    PUBLIC
        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
        $<INSTALL_INTERFACE:include>
    PRIVATE
        src)

target_link_libraries(MyLib
    PUBLIC ${ITK_LIBRARIES})

export(TARGETS MyLib FILE MyLibConfig.cmake)

MyApp CMakeLists.txt

find_package(ITK REQUIRED
    COMPONENTS RTK ITKRegistrationMethodsv4 ITKTransformIO ITKImageIO)
include(${ITK_USE_FILE})

set(SRCS
    AppFile1.cxx)

add_executable(MyApp ${SRCS})
include_directories(${CMAKE_SOURCE_DIR}/MyLib/include)
target_link_libraries(MyApp
    ${ITK_LIBRARIES}
    MyLib)

Edit1:从 MyLib 和 MyApp CMakeLists.txt 中删除项目(X)并将目标更改为 MyLib。

标签: c++cmakeitk

解决方案


您可以有一个空项目,只需创建一个自定义目标:

add_custom_target(MyLib SOURCES ${CMAKE_MYLIB_SRC} ${CMAKE_MYLIB_HDR})

由于您的代码只是标头,因此任何依赖目标都将看到文​​件中的更改并重新编译。在此之上没有什么可做的。您不必创建目标,尽管对于您的第三个问题,这就是答案。

但是,如果 ITK 只是您的依赖项,那么既然您有一个目标,您就可以在其上添加PUBLIC属性,例如由于您的库而需要链接到它的依赖库。

在这种情况下,他们的代码需要添加:

target_link_library(${NEWTARGET} PRIVATE MyLib) # PUBLIC/PRIVATE has to be tailored

这就是问题 1 的答案。

如果您的库仅变为非标题,只需更改add_custom_target调用即可。


推荐阅读