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

时间:2019-05-15 18:34:02

标签: c++ makefile cmake

我设法重现了一个更大项目的问题。我认为这是我所能做到的最小

我正在明确地将该键添加到源列表中,并且对其进行编辑仍然不会导致任何内容重新编译。

~/src/test2/_build£ cat ../CMakeLists.txt
cmake_minimum_required (VERSION 3.14)
set (CMAKE_CXX_STANDARD 11)
# various explicit CXX sets are necessary for this tiny project and don't exist in larger original
project(moduletest CXX)
set (HEADER_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
add_subdirectory(submod)
add_library(moduletest_static STATIC "$<TARGET_OBJECTS:submod>")
set_target_properties(moduletest_static PROPERTIES LINKER_LANGUAGE CXX)

~/src/test2/_build£ cat ../submod/CMakeLists.txt
include_directories (${HEADER_DIR})
add_library(submod OBJECT compileme.cpp ../includeme.h)

~/src/test2/_build£ cat ../submod/compileme.cpp
#include "includeme.h"
int function()
{
  return 5;
}

使输出如下:

~/src/test2/_build£ touch ../submod/compileme.cpp
~/src/test2/_build£ make
[ 50%] Building CXX object submod/CMakeFiles/submod.dir/compileme.cpp.o
[ 50%] Built target submod
[100%] Linking CXX static library libmoduletest_static.a
[100%] Built target moduletest_static
~/src/test2/_build£ touch ../includeme.h
~/src/test2/_build£ make
[ 50%] Built target submod
[100%] Built target moduletest_static

如果我取消使用include_directories,而在我的cpp文件中仅使用#include "../includeme.h",则无论我进行add_library调用如何,一切都可以正常工作。 (但这绝对不是我真正的项目中的选择)

我还应该注意,“扫描目标submod的依赖项”是一种红色鲱鱼。在我较大的项目中,我尝试触摸单个cpp文件,以便发生这种情况。其他应该编译的cpp文件仍然没有。

使用target_include_directories不能解决任何问题,无论绝对/相对路径如何。

问题cmake -GNinja ..消失

4 个答案:

答案 0 :(得分:2)

我的最初答案是:

  

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

但是对于GNU make来说,这不是真的。较新的工具(例如ninja)在编译代码时能够发出源到标题的依赖关系。因此,CMake只跟踪库到源的依赖关系,而底层工具跟踪源到头。

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

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

# Empty dependencies file for submod.
# This may be replaced when dependencies are built.

一旦调用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

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

此问题已经在SO Handling header files dependencies with cmake

上进行了讨论。

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

答案 1 :(得分:2)

从上次查看使用Makemake生成器时CMake如何为“源文件”生成文件依赖关系开始,我只是想按内存进行操作。

“扫描依赖项”步骤是CMake扫描“源文件”并为该“源文件”创建依赖项构建规则时。它使用REGEX和其他一些规则来执行此操作(它跳过了一些预处理规则)。它倾向于跳过它认为是系统头文件的内容,该文件可以包含使用绝对包含路径时找到的文件。将其视为误报。

通常的解决方法是不使用include_directories(),并且在使用target_include_directories()时避免使用绝对路径。因此,请尝试使用target_include_directories( submod PRIVATE .. )

答案 2 :(得分:0)

Fred和R2RT都为我提供了 my 问题的正确答案。我的cmake构建(从主要github存储库中提取)是问题所在。我切换到发行版,此问题消失了。我不太确定为什么我的构建有问题,但是.... (cmake v。从3.14升级到3.10,但我相信 my 构建是问题所在,而不是3.14)

答案 3 :(得分:0)

也有类似的问题。使用cmake,ninja和gcc构建对象库即使不进行更改也将导致重新生成,如果我将编译器切换到另一版本,则不会检测到标头中的某些更改,并且ninja认为没有任何事可做。

然后我切换到GNU make,现在一切都按预期工作,尽管与忍者相比有点慢。对我来说,这似乎是一个错误。

相关问题