CMake共享库与多个可执行文件
我的项目包含几个共享一些通用代码的可执行文件。 我想把公共代码放在可执行文件可以链接到的静态库中。 (通用代码非常小,我不想处理共享库)。
源码树看起来像这样:
- 项目
- 的CMakeLists.txt
- 共同
- 的CMakeLists.txt
- SRC
- 包括
- 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文件创build静态库并设置包含目录:
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,我可以构buildapp1和app2,并成功构build。 但是,如果我想要构build这些项目中的一个(例如通过从app1运行CMake)而不是从顶层目录构build,则会出现错误,因为common/include
不会添加到标头searchpath中。
我明白为什么会发生这种情况。 CMakeLists.txt文件中没有任何“引入”常见的app1或app2。 这只在顶层完成。
有没有办法解决这个问题,或者这种行为通常被认为是可以接受的? 是关于我的设置次优? 我只是想,如果我们开始开发使用这个通用库的越来越多的可执行文件,那么能够单独构build项目而不是从顶层构build项目会很好,但也许这是我不应该做的关心。
只有当这个子项目打算作为独立项目和顶层项目的一部分build立时,你应该在子目录中使用project()
命令。 例如,LLVM和Clang就是这种情况:Clang可以单独编译,但是当LLVM构build系统检测到Clang源时,它也包含它的目标。
在你的情况下,你不需要子项目。 仅编译app1
或app2
目标问题在项目中创buildmake app1
/ make app2
构build目录。
当你设置你的构build环境时,你应该考虑以下三个主题(除了其他人之外,对于这个讨论/回答,我把它缩小到了三个我认为与此相关的部分):
- 依赖/耦合
- 部署
- 小组
“强耦合”
我认为add_subdirectory()
命令支持“强耦合”,并且您的当前设置隐式支持:
- 一个经常变化的
common
图书馆 - 针对所有应用的单个部署(stream程和时间安排)
- 一个团队在完整的源代码基础上工作
- IDE将在一个解决scheme中显示所有内容
- 你为每件事生成一个构build环境
“松耦合”
如果你想要更多的“松耦合”,你可以使用其他语言的外部脚本或使用CMake的ExternalProject_Add()
macros。 所以,如果你设置common
库(甚至可能包括“二进制传递”),并将每个app
作为一个单独的项目来支持:
- 不太经常改变的
common
图书馆- 可能有自己的发布周期
- 每个应用程序的独立开发/部署周期
- 一组不同的开发人员在每个
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) ExternalProject_Add(app2 SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/app2 PREFIX app2)
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)
这实际上会产生三个构build环境。 一个直接在你的二进制输出目录中,一个在app1
和app2
子目录中。
在这种方法中,您可能想要考虑一些常见的CMake工具链文件。
参考
- 在CMake项目中使用CMake启用的库(II)
- CMake:如何设置Source,Library和CMakeLists.txt的依赖关系?