我正在尝试设置我的项目以使用 CMake 正确编译。
我的目录如下所示:
root
|- bin
| |- // Where I want to build CMake from - using 'cmake ..'
|- build
| |-
|- include
| |- database
| | |- database.h
|- src
|- database
| |- database.cpp
|- main
|- main.cpp
随着我的项目越来越大,我的子目录肯定会增长,并且认为 CMake 可能是学习的好主意。目前我只能让 CMake 在我的 src/中没有子目录的情况下工作。但是,我确实希望这个项目能够发展成许多子目录。
每个目录中是否需要多个 CMakeLists.txt 和 .cpp 文件?谁能指出我正确的方向?
谢谢!
最佳答案
我会推荐你到 this article对于这两种主要方法的深入讨论,但是有几种方法可以构建这样的项目。
- 顶层的一个 CMakeLists.txt 文件列出了所有不同子目录中的所有源文件。您通常只会在非常简单的项目中看到这一点。
- 每个目录中都有一个 CMakeLists.txt 文件,每个目录都由其父目录使用
add_subdirectory()
引入。这种方法很常见。 - 顶层有一个 CMakeLists.txt 文件,每个子目录都有自己的文件,其中列出了自己的源文件和目标。顶级 CMakeLists.txt 文件通过
include()
引入子目录文件。不太常见,但比其他两个更有优势。
各有利弊。只有在文件和子目录很少的情况下,才会推荐只有一个顶级 CMakeLists.txt 文件。一旦项目增长,将所有内容都保留在顶层可能会变得太多,从而使生成的 CMakeLists.txt 文件更难遵循。它还有一个缺点,即文件添加或删除的更改不限于特定目录。这似乎没什么大不了的,但是如果多个人在一个项目上工作,并且您想轻松查看其他人的更改影响了项目的哪个部分(例如,在 git 历史中),那就更难了。如果您都添加/删除文件,则尤其如此,从而更改顶级 CMakeLists.txt 文件并有可能发生冲突。
一旦项目的大小变得不平凡,大多数人会选择在每个子目录中添加一个 CMakeLists.txt 文件,并使用 add_subdirectory()
将它们组合在一起。 @TheQuantumPhysicist 的回答给出了一个很好的例子来说明这如何有用,所以我不会在这里重复大部分细节。这种结构使您能够轻松地打开/关闭构建树的整个部分,但更重要的是它为每个子目录提供了自己的变量范围。如果您想在源代码树的一部分中设置变量等,但在另一部分中看不到这些更改(想想您只想应用于复杂目录结构的一部分的编译器标志),这可能很重要。
第三个选项是一个顶级 CMakeLists.txt 文件,每个子目录提供一个由 include()
引入的文件,但它与在每个子目录中使用一个 CMakeLists.txt 文件有相似之处子目录。两者都将有关目录中文件的详细信息本地化到 CMakeLists.txt 或仅在该目录中的其他类似名称的文件。因此,更改变得更容易在版本控制历史等中合并和理解。第三种方法允许而第二种方法不允许的一件事是在使用 target_link_libraries()
时更自由地使用 >target_sources()
指定每个子目录中的源文件。此答案顶部链接的文章详细介绍了为什么 target_sources()
可能是有利的,这也是为什么许多项目可能需要第三种方法的核心。
最后,我建议您不要养成将构建树放在源代码树中的习惯。相反,将构建树创建为源树的兄弟。旨在使您的源代码树不受构建影响。所要做的就是让某人在源代码树中创建一个与您用于构建树的目录同名的目录,以免出现问题(我已经不止一次看到过这种情况!)。您可能还想为一个源代码树设置多个构建树,例如一个用于 Debug 构建,另一个作为 Release 构建,因此将这些树放在源代码树之外也有助于使您的源代码树不那么困惑。
关于c++ - 带有子目录的 CMake,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42744315/