使用 cmake 处理头文件依赖关系
我正在一个小型 C++ 项目上使用 CMake,到目前为止,它运行得很好...有一个转折:x
当我更改头文件时,通常需要重新编译许多源文件(直接或间接包含它的文件),然而,cmake 似乎只检测到一些要重新编译的源文件,从而导致损坏状态。我可以通过清除项目并从头开始重建来解决这个问题,但这规避了使用 make 实用程序的目标:仅重新编译所需的内容。
因此,我想我做错了什么。
我的项目组织起来非常简单:
- 一个顶级目录,其中包含所有资源,主 CMakeLists.txt 位于
- 一个“include”目录,其中所有公共标头都位于(在各个子目录中)
- 一个“src”目录,其中所有源文件的子目录都在,src CMakeLists.txt 位于
- “src”目录中的每个子目录中一个 CMakeLists.txt
主目录有:
cmake_minimum_required(VERSION 2.8)
project(FOO)
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
# Compiler Options
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -std=c++0x -Wall -Wextra -Werror")
include_directories($(FOO_SOURCE_DIR)/include)
add_subdirectory(src)
“src”目录:
add_subdirectory(sub1)
add_subdirectory(sub2)
add_subdirectory(sub3)
add_subdirectory(sub4)
add_executable(foo main.cpp)
target_link_libraries(foo sub1 sub2 sub3 sub4)
其中 sub4
取决于sub3
依赖于 sub2
,而 sub2
依赖于 sub1
以及子目录(sub3)的示例:
set(SUB3_SRCS
File1.cpp
File2.cpp
File3.cpp
File4.cpp
File5.cpp
File6.cpp
)
add_library(sub3 ${SUB3_SRCS})
target_link_libraries(sub3 sub1 sub2)
如果有人能指出我的内容,我会很高兴对我来说错误的是,在这里或在 CMake 上搜索没有产生任何结果,所以我想这很容易或者应该开箱即用...
(作为参考,我在 MSYS 上使用 cmake 版本 2.8.2)
编辑< /strong>:
感谢比尔的建议我检查了CMake生成的depend.make
文件,确实缺少(严重)。这是一个示例:
src/sub3/CMakeFiles/sub3.dir/File1.cpp.obj: ../src/sub3/File1.cpp
是的,仅此而已,根本没有引用任何包含内容:x
I am using CMake on a small C++ project and so far it works great... with one twist :x
When I change a header file, it typically requires recompiling a number of sources files (those which include it, directly or indirectly), however it seems that cmake only detects some of the source files to be recompiled, leading to a corrupted state. I can work around this by wiping out the project and rebuilding from scratch, but this circumvents the goal of using a make utility: only recompiling what is needed.
Therefore, I suppose I am doing something wrong.
My project is very simply organized:
- a top directory where all resources sit, the main CMakeLists.txt sits there
- a "include" directory where all public headers lies (in various subdirectories)
- a "src" directory where all the subdirectories for sources files are, the src CMakeLists.txt sits there
- a CMakeLists.txt per subdirectory in the "src" directory
The main directory has:
cmake_minimum_required(VERSION 2.8)
project(FOO)
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
# Compiler Options
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -std=c++0x -Wall -Wextra -Werror")
include_directories($(FOO_SOURCE_DIR)/include)
add_subdirectory(src)
The "src" directory:
add_subdirectory(sub1)
add_subdirectory(sub2)
add_subdirectory(sub3)
add_subdirectory(sub4)
add_executable(foo main.cpp)
target_link_libraries(foo sub1 sub2 sub3 sub4)
Where sub4
depends on sub3
which depends on sub2
which depends on sub1
And an example of a subdirectory (sub3):
set(SUB3_SRCS
File1.cpp
File2.cpp
File3.cpp
File4.cpp
File5.cpp
File6.cpp
)
add_library(sub3 ${SUB3_SRCS})
target_link_libraries(sub3 sub1 sub2)
I'd be glad if anyone could point my mistake to me, searching here or on CMake didn't yield anything so I guess it's very easy or should work out of the box...
(for reference, I am using cmake version 2.8.2 on MSYS)
EDIT:
Thanks to Bill's suggestion I have checked the depend.make
file generated by CMake, and it is indeed lacking (severely). Here is an example:
src/sub3/CMakeFiles/sub3.dir/File1.cpp.obj: ../src/sub3/File1.cpp
Yep, that's all, none of the includes were referenced at all :x
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您应该查看二叉树中的
depend.make
文件。它将位于CMakeFiles/target.dir/depend.make
中。尝试找到其中一个缺少您认为应该具有的.h
文件的文件。然后为 cmake 创建错误报告或通过电子邮件发送到 cmake 邮件列表。You should look at the
depend.make
files in your binary tree. It will be inCMakeFiles/target.dir/depend.make
. Try to find one of those that is missing a.h
file that you think it should have. Then create a bug report for cmake or email the cmake mailing list.我刚刚遇到了同样的问题。将
include_directories()
中的路径从绝对路径更改为相对路径后,它添加了适当的依赖项。看起来 CMake 试图猜测哪些标头是系统的,哪些是与项目相关的。我怀疑以
/
开头的目录作为-isystem /some/path
传递,因此不会出现在生成的依赖项中。如果您无法将
${FOO_SOURCE_DIR}
替换为相对路径,您可以尝试使用适当的 CMake 函数来计算相对路径。 IE:I just hit the same issue. After changing paths in
include_directories()
from absolute to relative it added appropriate dependencies.Looks like CMake tries to guess which headers are system and which are project related. I suspect that directories that starts with
/
passed as-isystem /some/path
and thus are not presented in generated dependencies.If you can't replace
${FOO_SOURCE_DIR}
with relative path you can try to calculate relative path using appropriate CMake functions. I.e.:您是否在将包含内容添加到 cpp 文件之前或之后运行了 cmake?
我遇到了这个问题并重新运行 cmake 修复了它。我添加了 include post-cmake.
Did you run cmake before or after adding the includes to your cpp files?
I ran into this problem and re-running cmake fixed it. I'd added the include post-cmake.
显然,cmake 从依赖树中删除了系统包含路径(感谢@ony 的提示)。这在大多数情况下可能是有意义的,但有时 cmake 不知道编译器认为什么是系统路径。我们正在使用忽略
/usr/include
的自定义 gcc 构建,但 cmake 认为它不会忽略它。要强制 cmake 将/usr/include
设为未优化的依赖项,请尝试以下技巧:在路径前面添加/.
。我试图使所有库依赖项都使用 cmake 依赖项功能,包括某些“第 3 方”库,这些库默认情况下并不总是安装在 Linux 上,甚至不可用。例如,Z-lib 压缩。
如果 Z lib 包含文件不在
/usr/include
中,则以下接口目标可以正常工作,但如果在/usr/include
中,则会中断。我将最后一行更改为
并且有效。现在,依赖于
zlib_target
的目标将在编译期间自动获取-I/./usr/include
。Apparently cmake removes system include paths from the dependency trees (thank you @ony for this hint). This probably makes sense most of the time, but sometimes cmake doesn't know what the compiler thinks is a system path or not. We are using a custom gcc build that ignores
/usr/include
, but cmake thinks it doesn't ignore it. To force cmake to make/usr/include
a dependency that is NOT optimized away, try this trick: prepend/.
to the path.I am trying to make all of the library dependencies use the cmake dependency feature, including certain "3rd" party libraries that are not always installed by default on Linux or even available. For example, Z-lib compression.
The following interface target worked fine if the Z lib includes were not in
/usr/include
, but would break if they were.I changed the last line to
and it worked. Now targets that depended on
zlib_target
would automatically get-I/./usr/include
during compilation.确保缺少标头的包含语句位于第一个程序指令之前。就我而言, cmake dependent.make 不包含头文件,因为它遵循第一条程序指令。
Make sure that the include statement for the missing header is placed before the first program instruction. In my case cmake depend.make was not including the header file, because it was following the first program instruction.