cmake:add_subdirectory()vs include()

时间:2018-01-29 21:02:58

标签: cmake

让我们说我有一个使用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中每个子文件夹中的
  1. add_subdirectory()个文件+ CmakeLists.txt;
  2. 顶级some-random-name.cmake中每个子文件夹中的
  3. include() + CmakeLists.txt;
  4. 忽略我的想法,让每个子文件夹都是自包含的,并将所有相关的构建信息放在顶级CMakeLists.txt中,将其他cmake文件仅作为帮助程序(宏,函数,...);
  5. 第一个选项是最方便的,但它表明每个子文件夹实际上是一个可以单独编译的独立项目。

    第二个选项似乎清楚地表明这里只有一个cmake项目。但是在子文件夹中的每个some-random-name.cmake中,我必须使用源文件的完整路径,这违背了我希望每个文件都是自包含的。如果只有一个嵌套级别(比如前两个示例子文件夹),那就没问题了,但对于some/deeply/nested/path/SomeFeature-unit-test来说这不太好。我还必须在输出文件的名称前加上前缀。

    第三个选项似乎是一种快速创建一个带有意大利面条长度的CMakeLists.txt文件的简单方法,所以我可能更喜欢别的东西。

    我想知道哪个是"首选"现代化的方式" cmake项目。我可以找到的多目录项目的所有教程都处理了一个文件夹中的独立库,在另一个文件夹中使用该库的独立应用程序以及在另一个目录中使用相同库的独立测试的情况。使用cmake查看项目我发现没有一致性,所以这并没有多大帮助。

    (我是一个cmake noob,尝试将一个相对较大的项目转换为使用cmake)

1 个答案:

答案 0 :(得分:15)

最常用的规则是"每个目标一个CMakeLists.txt"。所以你的选择是第1号。

要实现这一点,您的项目结构可能必须适应,如果"子文件夹中的每个源文件都会创建一个单独的可执行文件"。

CMakeLists.txt是您的起点,包含project()命令。

值得注意的是

您应该避免使用类似../some_other_dir/some_other_source.cpp之类的其他子目录引用源文件。它表明您的CMake结构不是根据上面引用的经验法则设置的。

文档摘录

  1. CMake: add_subdirectory() command

      

    向构建添加子目录。 source_dir指定源CMakeLists.txt和代码文件所在的目录。

  2. CLion: CMakeLists File

      

    当项目具有复杂结构并包含一个或多个子目录(项目根目录和子目录)时,您可以创建子目录CMakeList.txt文件。子目录CMakeLists.txt文件描述子目录的构建,内容和目标规则。

  3. C++Now 2017: Daniel Pfeifer "Effective CMake: a random seletion of best practices

      

    包含CMakeLists.txt的目录是构建系统生成器的入口点。子目录可能会添加add_subdirectory(),并且必须包含CMakeLists.txt

  4. <强>参考