具有多个可执行文件的 CMake 共享库

2023-11-30

我的项目包含多个共享一些通用代码的可执行文件。我想将通用代码放在可执行文件可以链接到的静态库中。 (公共代码非常小,我不喜欢处理共享库)。

源树看起来像这样:

  • project
    • CMakeLists.txt
    • common
      • CMakeLists.txt
      • src
      • include
    • app1
      • src
      • CMakeLists.txt
    • app2
      • src
      • CMakeLists.txt

app1 和 app2 都依赖于共同的代码。

这个通用代码是非常特定于应用程序的,并且永远不需要被该目​​录树之外的另一个项目使用。出于这个原因,我不想将该库安装在任何类型的全球位置。

顶级 CMakeLists.txt 文件仅添加子目录:

project(toplevel)
cmake_minimum_required(VERSION 3.1)

add_subdirectory(common)
add_subdirectory(app1)
add_subdirectory(app2)

公共库的 CMakeLists.txt 文件创建静态库并设置包含目录:

add_library(common STATIC common.cpp) 
target_include_directories(common PUBLIC "${CMAKE_CURRENT_LIST_DIR}/include")

可执行文件的文件如下所示:

project(app1)
cmake_minimum_required(VERSION 3.1)

add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} common)

现在我的问题。如果我从顶级项目目录运行 CMake,我可以构建 app1 和 app2 并且它们构建成功。但是,如果我想构建其中一个项目(例如,通过从 app1 运行 CMake)而不是从顶级目录构建,则会收到错误消息,因为common/include未添加到标头搜索路径中。

我明白为什么会发生这种情况。 app1 或 app2 的 CMakeLists.txt 文件中没有任何“拉入”共同点。这仅在顶层完成。

有没有办法解决这个问题,或者这种行为通常被认为是可以接受的?我的设置是否欠佳?我只是想,如果我们开始开发越来越多使用这个通用库的可执行文件,能够单独构建项目而不是从顶层构建项目会很好,但也许这是我不应该做的事情关心。


当您设置构建环境时,您应该对以下三个主题进行一些思考(除其他主题外,但对于本次讨论/答案,我将其简化为我认为与此处相关的三个主题):

  1. 依赖/耦合
  2. 部署
  3. Teams

“强耦合”

我想到了add_subdirectory()命令支持“强耦合”,并且您当前的设置隐式支持:

  • 一个经常变化的common library
  • 所有应用程序的单一部署(流程和时间安排)
  • A single team working on the complete source base
    • IDE 将在一个解决方案中显示所有内容
    • 您可以为所有内容生成一个构建环境

“松耦合”

如果你想要更多“松耦合”您可以使用其他语言的外部脚本或使用 CMakeExternalProject_Add()宏。所以如果你设置common库(甚至可能包括“二进制交付”)和每个app作为一个单独的项目,您支持:

  • A less often changing common library
    • 可能有自己的发布周期
  • 每个应用程序都有独立的开发/部署周期
  • 由不同的开发人员组成的团队致力于每个项目app

两者的混合体

正如您所看到的,有很多事情需要考虑,CMake 可以为您提供对各种方法的支持。考虑到您的项目可能处于早期阶段,您可能会采用混合方法(而不是立即将common图书馆):

CMakeLists.txt

project(toplevel)
cmake_minimum_required(VERSION 3.1)

include(ExternalProject)

ExternalProject_Add(
    app1 
    SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/app1"
    PREFIX app1
    INSTALL_COMMAND ""
)
ExternalProject_Add(
    app2 
    SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/app2"
    PREFIX app2
    INSTALL_COMMAND ""
)

app1/CMakeLists.txt

project(app1)
cmake_minimum_required(VERSION 3.1)

add_subdirectory(../common common)

add_executable(${PROJECT_NAME} src/main.cpp)
target_link_libraries(${PROJECT_NAME} common)

这实际上会生成三个构建环境。一个直接位于二进制输出目录中,另一个位于app1 and app2子目录。

在这种方法中,您可能需要考虑常见的 CMake 工具链文件。

参考

  • 在 CMake 项目中使用支持 CMake 的库(二)
  • CMake:如何设置源、库和 CMakeLists.txt 依赖项?
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

具有多个可执行文件的 CMake 共享库 的相关文章

随机推荐