单个CMakeLists.txt就足够我的项目了吗?

时间:2018-12-14 03:03:00

标签: cmake

我正在尝试将旧的CMake移植到现代CMake(CMake 3.0.2或更高版本)。在旧的设计中,我有多个CMakelists.txt,每个目录都包含一个CMakeLists.txt文件。

我当前项目的目录结构如下:

.
├── VizSim.cpp
├── algo
├── contacts
│   ├── BoundingVolumeHierarchies
│   │   └── AABBTree.h
│   └── SpatialPartitoning
├── geom
│   └── Geometry.h
├── math
│   ├── Tolerance.h
│   ├── Vector3.cpp
│   └── Vector3.h
├── mesh
│   ├── Edge.h
│   ├── Face.h
│   ├── Mesh.cpp
│   ├── Mesh.h
│   └── Node.h
├── util
|   |__ Defines.h
|   |__ Math.h
|
└── viz
    └── Renderer.h

我打算做的只是使用一个CMakelists.txt,并将所有cpp文件放在SOURCE中,并将所有标头放在HEADER中,并使用add_executable。

set (SOURCE
    ${SOURCE}
    ${CMAKE_CURRENT_SOURCE_DIR}/src/mesh/Mesh.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/math/Vector3.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/VizSim.cpp
    ....
)

set (HEADER
    ${HEADER}
    ${CMAKE_CURRENT_SOURCE_DIR}/src/mesh/Mesh.h
    ${CMAKE_CURRENT_SOURCE_DIR}/src/math/Vector3.h
    .... 
)

add_library(${PROJECT_NAME} SHARED ${SOURCE})

这样做,我担心使用单个CMakeLists.txt是否是一个好习惯。那么单个CMakeLists.txt是否足够?每个文件夹都需要CMakeLists.txt吗?

我只能想到一个很好的理由在我的项目中拥有多个CMakeLists.txt,那就是模块化。

考虑到我的项目最终会发展起来。

2 个答案:

答案 0 :(得分:2)

我总是建议每个目录都有一个CMakeList.txt文件。我的原因:

  • 位置:将所有内容都放在同一个文件夹中。这包括构建系统的相关部分。我讨厌它导航到根文件夹,以查看如何调用库或目标。
  • 构建工件和相关构建代码的分离:测试属于test之下,lib之下的库,bin之下的二进制文件,doc之下的文档以及{{ 1}}。这可能因项目而异。当我不得不更改文档时,为什么要遍历数十个不相关的CMake代码?只需查看正确的CMakeLists.txt。
  • 避免处理路径:在大多数情况下,可以避免相对或绝对路径,包括诸如utils之类的东西。这导致可维护的构建代码,并减少了错误路径产生的错误。尤其是对于资源外构建,无论如何都应使用。
  • 错误的本地化:如果发生CMake错误,则更容易定位问题。通常,可以排除子目录作为第一种解决方法。

答案 1 :(得分:1)

对于评论,这有点长-所以我将其作为答案:

在我的一个项目(一个库)中,我拥有许多源,因此我开始将其中一些移到子目录util中。

为此,我制作了单独的变量:

file(GLOB headers *.h)
file(GLOB sources *.cc)
file(GLOB utilHeaders
  RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
  ${CMAKE_CURRENT_SOURCE_DIR}/util/*.h)
file(GLOB utilSources
  RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
  ${CMAKE_CURRENT_SOURCE_DIR}/util/*.cc)

为了在Visual Studio中看起来更好/更方便,我插入了source_group,它们在VS项目中生成适当的子文件夹。我相信它们被称为“过滤器”。

source_group("Header Files\\Utilities" FILES ${utilHeaders})
source_group("Source Files\\Utilities" FILES ${utilSources})

当然,我必须考虑变量utilHeadersutilSources以及必须提供源的位置:

add_library(libName
  ${sources} ${headers}
  ${utilSources} ${utilHeaders})

就是这样。


Fred在他的评论中提醒我,我不应忘记提及file(GLOB有一定的弱点(尽管我发现它在我们的日常工作中非常有价值)。 CMake doc.中甚至提到了这一点:

  

注意:我们不建议您使用GLOB从源代码树中收集源文件列表。如果在添加或删除源时没有CMakeLists.txt文件更改,则生成的生成系统无法知道何时要求CMake重新生成。 CONFIGURE_DEPENDS标志可能无法在所有生成器上可靠地工作,或者如果将来添加了不支持它的新生成器,则使用该生成器的项目将被卡住。即使CONFIGURE_DEPENDS可以可靠地工作,在每次重新构建时都要进行检查。

因此,使用file(GLOB,一旦添加,移动或删除文件,您就永远不会忘记重新运行CMake。也可以选择直接在生成的内置脚本中添加,移动,删除文件(例如VS项目文件),并依赖于下一次重新运行CMake也会覆盖这些文件这一事实。最后但并非最不重要的一点是,git pull是另外一回事,值得考虑重新运行CMake。