我设法重现了一个更大项目的问题。我认为这是我所能做到的最小
我正在明确地将该键添加到源列表中,并且对其进行编辑仍然不会导致任何内容重新编译。
~/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 ..
消失
答案 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,让我阅读了所有内容。
上进行了讨论。答案 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,现在一切都按预期工作,尽管与忍者相比有点慢。对我来说,这似乎是一个错误。