cmake/make (OBJECT) 依赖问题——标头更改时不重建

zzx*_*xyz 4 c++ makefile cmake

我已经成功地重现了我在一个更大的项目中遇到的问题。我认为这是我能做到的最小限度

\n\n

关键是我已经明确地将标头添加到源列表中,并且编辑它仍然不会导致任何内容重新编译。

\n\n
~/src/test2/_build\xc2\xa3 cat ../CMakeLists.txt\ncmake_minimum_required (VERSION 3.14)\nset (CMAKE_CXX_STANDARD 11)\n# various explicit CXX sets are necessary for this tiny project and don\'t exist in larger original\nproject(moduletest CXX)\nset (HEADER_DIR "${CMAKE_CURRENT_SOURCE_DIR}")\nadd_subdirectory(submod)\nadd_library(moduletest_static STATIC "$<TARGET_OBJECTS:submod>")\nset_target_properties(moduletest_static PROPERTIES LINKER_LANGUAGE CXX)\n\n~/src/test2/_build\xc2\xa3 cat ../submod/CMakeLists.txt\ninclude_directories (${HEADER_DIR})\nadd_library(submod OBJECT compileme.cpp ../includeme.h)\n\n~/src/test2/_build\xc2\xa3 cat ../submod/compileme.cpp\n#include "includeme.h"\nint function()\n{\n  return 5;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

make输出如下:

\n\n
~/src/test2/_build\xc2\xa3 touch ../submod/compileme.cpp\n~/src/test2/_build\xc2\xa3 make\n[ 50%] Building CXX object submod/CMakeFiles/submod.dir/compileme.cpp.o\n[ 50%] Built target submod\n[100%] Linking CXX static library libmoduletest_static.a\n[100%] Built target moduletest_static\n~/src/test2/_build\xc2\xa3 touch ../includeme.h\n~/src/test2/_build\xc2\xa3 make\n[ 50%] Built target submod\n[100%] Built target moduletest_static\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果我删除 , 的使用include_directories,并且仅#include "../includeme.h"在我的 cpp 文件中,则无论我如何add_library调用,一切都会正常工作。(但这绝对不是我实际项目中的选择)

\n\n

我还应该注意到,“扫描目标子模块的依赖关系”是一种转移注意力的东西。在我的较大项目中,我尝试触摸单个 cpp 文件,以便发生这种情况。其他应该编译的cpp文件仍然没有编译。

\n\n

无论绝对/相对路径如何,使用 都target_include_directories没有修复任何问题。

\n\n

问题就消失了cmake -GNinja ..

\n

R2R*_*ica 5

我最初的回答是:

您很可能对着错误的树吠叫。源到标头的依赖关系不是由 CMake 管理,而是由底层生成器管理,因为标头不直接参与库编译。在您的情况下,有责任检测脏标头并重建 .cpp 文件。标头可以在源中列出,但它只能使它们在少数 IDE 中可见,并在它们存在时添加健全性检查。

GNU make事实并非如此。较新的工具,例如ninja能够在编译代码时发出源到标头的依赖关系。因此,CMake 仅跟踪库到源的依赖关系,而底层工具则跟踪源到标头的依赖关系。

对于make,CMake 使用其内部机制为对象 .cpp.o 文件创建 dependent.make 文件。该算法并不完美,对于经过的绝对路径可能会失败include_directories

作为参考,最初(在生成步骤之后)它会创建depend.make带有注释的文件:

# Empty dependencies file for submod.
# This may be replaced when dependencies are built.
Run Code Online (Sandbox Code Playgroud)

一旦调用 make 并第一次构建对象,文件就会填充:

# CMAKE generated file: DO NOT EDIT!
# Generated by "Unix Makefiles" Generator, CMake Version 3.14

submod/CMakeFiles/submod.dir/compileme.cpp.o: ../includeme.h
submod/CMakeFiles/submod.dir/compileme.cpp.o: ../submod/compileme.cpp

Run Code Online (Sandbox Code Playgroud)

感谢@Fred,让我阅读了所有相关内容。

此外,这个问题已经在 SO: Handling header files dependency with cmake上讨论过

和历史阅读:http://www.aosabook.org/en/cmake.html