【问题标题】:Cmake recompiles everything each time I add a new source subfolder每次添加新的源子文件夹时,Cmake 都会重新编译所有内容
【发布时间】:2015-02-14 23:55:10
【问题描述】:

我有一个按如下方式组织的项目树:

MyProjects/ - build - project1 - CMakeLists.txt
            |       | project2 - CMakeLists.txt
            |
            | src - project1 - Project1Class1.h
                             | Project1Class1.cpp
                             | Project1Class2.h
                             | Project1Class2.cpp
                             | more subdirectories ...
                    project2 - Project2Class1.h
                             | Project2Class1.cpp
                             | more subdirectories ...

假设 project2 依赖于 project1。然后 project2 直接使用 project1 文件,而不使用静态或动态 project1 库。 然后 project2/CMakeLists.txt 找出 project1 和 project2 源文件并通过 GLOB_RECURSE 包含它们:

file(
    GLOB_RECURSE
    source_files
    ../../project1/
    ../../project2/
)

这在正确构建我的项目的意义上是有效的。

每次我在新文件夹中添加新的源文件时,例如在 src/project2/ 中文件 MyNewFolder/myTest.cpp,然后输入

~/MyProjects/build/project2/$  cmake .
~/MyProjects/build/project2/$  make

然后文件被 cmake 正确考虑。但是,我的问题是每个文件都重新编译。

当我更改 project1 中的源文件并尝试编译 project2 时也是如此。

请注意,我大大简化了 CMakeLists.txt 中的内容。所以我的问题是:根据我对此的解释,这种行为是 CMake 应该做的吗?如果是的话,它背后的基本原理是什么?我应该为make 做些什么来只编译新文件?我无法在互联网上找到任何有关它的文档。

注意:请随意讨论整个源代码构建文件的组织。请注意,我希望将构建配置与 src/ 文件夹分开。

编辑:我发现 this 解释了为什么 GLOB 和 GLOB_RECURSE 阻止它工作。

编辑 2:即使没有 GLOB,编译也是从头开始完成的其他情况(请参阅this 问题)

【问题讨论】:

  • 您是仅添加 .cpp 还是同时添加 .h? .h 是否包含在某处?
  • 我编辑了我的帖子。实际上,如果新文件在新文件夹中,一切都会重新编译
  • @StenSoft 是的,.h 文件通过 include_directories() 包含在内。所有子目录的列表是通过另一个GLOB_RECURSE确定的

标签: c++ cmake organization


【解决方案1】:

您正在观察file(GLOB_RECURSE ...) 的已知副作用。我不确定为什么会发生这种情况,但为了避免这种情况,大多数基于 CMake 的项目都明确列出了它们的来源:

set(source_files
  ../../project1/Project1Class1.cpp
  ../../project1/Project1Class2.cpp
  ...
  ../../project2/Project2Class1.cpp
  ../../project2/Project2Class1.cpp
  ...
)

【讨论】:

  • 感谢您的回答。你说“已知的副作用”和“大多数基于 CMake 的项目”:你能给我参考吗?如果您明确列出它们,您是如何做到的:手动或借助 CMakeLists.txt 上的某种 sed 脚本?
  • 来自文档:(我们不建议使用 GLOB 从源代码树中收集源文件列表。如果添加或删除源时没有 CMakeLists.txt 文件发生更改,则生成的构建系统不知道何时要求 CMake 重新生成。)
  • 我的头脑 - LLVM 项目足够大(llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/…)。是的,它们是手工列出的。没你想的那么累。
  • @trenki 感谢您对文档的引用。我知道生成的构建系统不知道。但是即使 CMakeLists.txt 没有明显变化,也应该可以强制 cmake 重新生成。我不明白为什么 GLOB_RECURSE 与手动提供 GLOB_RECURSE 会生成的相同文件的效果不同。这似乎不连贯
  • @arrowdodger 感谢您的参考。但我真的看不出有任何理由手动列出源文件。我的意思是,源目录中的任何源文件都是要构建的,我为什么要为每个文件指定它?也许在某些项目中情况并非如此,但这似乎是应该支持的合理默认行为......
猜你喜欢
  • 2020-06-04
  • 2019-08-16
  • 2013-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多