cmake:add_subdirectory()vs include()

Fre*_*pin 23 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
Run Code Online (Sandbox Code Playgroud)

子文件夹中的每个源文件都会创建一个单独的可执行文件.我希望项目中的每个子文件夹都是非独立模块 - 即每个子文件夹都是(或多或少)自包含的,但不是一个可以单独编译的独立cmake项目.我希望能够只建造一切或什么都不做.例如,我不想让人觉得你只能运行cmake some/deeply/nested/path/SomeFeature-unit-test来构建它.

我应该选择哪个选项?

  1. CMakeLists.txt文件在每个子文件夹+ add_subdirectory()顶级CmakeLists.txt;
  2. some-random-name.cmake在每个子文件夹+ include()顶级CmakeLists.txt;
  3. 忽略我的想法,让每个子文件夹都是自包含的,并将所有相关的构建信息放在顶级的CMakeLists.txt附加cmake文件中,仅作为帮助程序(宏,函数,...);

第一个选项是最方便的,但它表明每个子文件夹实际上是一个可以单独编译的独立项目.

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

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

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

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

Flo*_*ian 26

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

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

CMakeLists.txt是你的起点并包含project()命令.

重要的是要注意到这一点

  • CMake的将反映您add_subdirectory()CMakeLists.txt目录结构,其产生的构建环境
  • CMake将为每次add_subdirectory()调用创建一个新的变量范围(与使用include()命令的最大区别)

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

文档摘录

  1. CMake:add_subdirectory()命令

    将子目录添加到构建中.该source_dir指定了源目录CMakeLists.txt和代码文件的位置.

  2. CLION:CMakeLists文件

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

  3. C++ Now 2017:Daniel Pfeifer"有效的CMake:随机选择最佳实践

    包含a的目录是CMakeLists.txt构建系统生成器的入口点.可以添加子目录,也可以add_subdirectory()包含子目录CMakeLists.txt.

参考

  • 第二个参考:《CMake教程》已损坏 (3认同)
  • 谢谢弗洛里安。这是一个绝妙的答案。我希望我在阅读其他所有内容之前已经找到了这个。 (2认同)