让我们说我有一个使用cmake的C ++单元测试项目:
$ tree
.
├── C-API-ConditionVariable-unit-test
│ ├── C-API-ConditionVariable-compile-link-test.c
│ ├── C-API-ConditionVariable-unit-test-0.cpp
│ └── C-API-ConditionVariable-unit-test-1.cpp
├── C-API-Mutex-unit-test
│ ├── C-API-Mutex-compile-link-test.c
│ ├── C-API-Mutex-unit-test-0.cpp
│ └── C-API-Mutex-unit-test-1.cpp
├── some
│ └── deeply
│ └── nested
│ └── path
│ └── SomeFeature-unit-test
│ ├── SomeFeature-compile-link-test.c
│ ├── SomeFeature-unit-test-0.cpp
│ └── SomeFeature-unit-test-1.cpp
└── CMakeLists.txt
子文件夹中的每个源文件都会创建一个单独的可执行文件。我希望项目中的每个子文件夹都是非独立模块 - 即每个子文件夹都是(或多或少)自包含的,但不是一个可以单独编译的独立cmake项目。我希望能够只建造一切或什么都不做。例如,我不想让人觉得你只能从some/deeply/nested/path/SomeFeature-unit-test
运行cmake来构建它。
我应该选择哪个选项?
CMakeLists.txt
中每个子文件夹中的add_subdirectory()
个文件+ CmakeLists.txt
; some-random-name.cmake
中每个子文件夹中的include()
+ CmakeLists.txt
; CMakeLists.txt
中,将其他cmake文件仅作为帮助程序(宏,函数,...); 第一个选项是最方便的,但它表明每个子文件夹实际上是一个可以单独编译的独立项目。
第二个选项似乎清楚地表明这里只有一个cmake项目。但是在子文件夹中的每个some-random-name.cmake
中,我必须使用源文件的完整路径,这违背了我希望每个文件都是自包含的。如果只有一个嵌套级别(比如前两个示例子文件夹),那就没问题了,但对于some/deeply/nested/path/SomeFeature-unit-test
来说这不太好。我还必须在输出文件的名称前加上前缀。
第三个选项似乎是一种快速创建一个带有意大利面条长度的CMakeLists.txt
文件的简单方法,所以我可能更喜欢别的东西。
我想知道哪个是"首选"现代化的方式" cmake项目。我可以找到的多目录项目的所有教程都处理了一个文件夹中的独立库,在另一个文件夹中使用该库的独立应用程序以及在另一个目录中使用相同库的独立测试的情况。使用cmake查看项目我发现没有一致性,所以这并没有多大帮助。
(我是一个cmake noob,尝试将一个相对较大的项目转换为使用cmake)
答案 0 :(得分:15)
最常用的规则是"每个目标一个CMakeLists.txt
"。所以你的选择是第1号。
要实现这一点,您的项目结构可能必须适应,如果"子文件夹中的每个源文件都会创建一个单独的可执行文件"。
根CMakeLists.txt
是您的起点,包含project()
命令。
值得注意的是
add_subdirectory()
和CMakeLists.txt
目录结构add_subdirectory()
电话the big difference to using include()
command)创建一个新的变量范围您应该避免使用类似../some_other_dir/some_other_source.cpp
之类的其他子目录引用源文件。它表明您的CMake结构不是根据上面引用的经验法则设置的。
文档摘录
CMake: add_subdirectory()
command
向构建添加子目录。
source_dir
指定源CMakeLists.txt
和代码文件所在的目录。
当项目具有复杂结构并包含一个或多个子目录(项目根目录和子目录)时,您可以创建子目录
CMakeList.txt
文件。子目录CMakeLists.txt
文件描述子目录的构建,内容和目标规则。
C++Now 2017: Daniel Pfeifer "Effective CMake: a random seletion of best practices
包含
CMakeLists.txt
的目录是构建系统生成器的入口点。子目录可能会添加add_subdirectory()
,并且必须包含CMakeLists.txt
。
<强>参考强>