C++ 使用 cmake 处理头文件依赖项

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7461000/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 16:59:11  来源:igfitidea点击:

Handling header files dependencies with cmake

c++dependenciescmakeheader-files

提问by Matthieu M.

I am using CMake on a small C++ project and so far it works great... with one twist :x

我在一个小型 C++ 项目上使用 CMake,到目前为止它工作得很好......有一个转折: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 someof 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.

当我更改头文件时,它通常需要重新编译许多源文件(直接或间接包含它的那些),但是 cmake 似乎只检测到一些要重新编译的源文件,从而导致损坏状态。我可以通过清除项目并从头开始重建来解决这个问题,但这绕过了使用 make 实用程序的目标:只重新编译所需的内容。

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
  • 所有资源所在的顶级目录,主 CMakeLists.txt 就在那里
  • 所有公共标题所在的“包含”目录(在各个子目录中)
  • 一个“src”目录,其中包含源文件的所有子目录,src CMakeLists.txt 位于那里
  • “src”目录中每个子目录的 CMakeLists.txt

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:

“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)

Where sub4depends on sub3which depends on sub2which depends on sub1

哪里sub4取决于sub3哪个取决于sub2哪个取决于sub1

And an example of a subdirectory (sub3):

以及子目录 (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...

如果有人能指出我的错误,我会很高兴,在这里或在 CMake 上搜索没有产生任何结果,所以我想这很容易,或者应该开箱即用......

(for reference, I am using cmake version 2.8.2 on MSYS)

(作为参考,我在 MSYS 上使用的是 cmake 2.8.2 版)

EDIT:

编辑

Thanks to Bill's suggestion I have checked the depend.makefile generated by CMake, and it is indeed lacking (severely). Here is an example:

感谢Bill的建议,我检查了depend.makeCMake生成的文件,确实缺少(严重)。下面是一个例子:

src/sub3/CMakeFiles/sub3.dir/File1.cpp.obj: ../src/sub3/File1.cpp

Yep, that's all, non of the includes were referenced at all :x

是的,就是这样,根本没有引用任何包含:x

回答by Bill Hoffman

You should look at the depend.makefiles in your binary tree. It will be in CMakeFiles/target.dir/depend.make. Try to find one of those that is missing a .hfile that you think it should have. Then create a bug report for cmake or email the cmake mailing list.

您应该查看depend.make二叉树中的文件。它将在CMakeFiles/target.dir/depend.make. 尝试找到其中一个缺少.h您认为应该具有的文件的文件。然后为 cmake 创建错误报告或通过电子邮件发送 cmake 邮件列表。

回答by ony

I just hit the same issue. After changing paths in include_directories()from absolute to relative it added appropriate dependencies.

我刚刚遇到了同样的问题。在将路径include_directories()从绝对更改为相对后,它添加了适当的依赖项。

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/pathand thus are not presented in generated dependencies.

看起来 CMake 试图猜测哪些头文件是系统的,哪些是项目相关的。我怀疑以/pass as开头的目录-isystem /some/path不会出现在生成的依赖项中。

If you can't replace ${FOO_SOURCE_DIR}with relative path you can try to calculate relative path using appropriate CMake functions. I.e.:

如果您不能${FOO_SOURCE_DIR}用相对路径替换,您可以尝试使用适当的 CMake 函数计算相对路径。IE:

file(RELATIVE_PATH FOO_SOURCE_REL_DIR
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${FOO_SOURCE_DIR}/.)
include_directories(${FOO_SOURCE_REL_DIR}/include)

回答by Edward Strange

Did you run cmake before or after adding the includes to your cpp files?

您是否在将包含添加到 cpp 文件之前或之后运行了 cmake?

I ran into this problem and re-running cmake fixed it. I'd added the include post-cmake.

我遇到了这个问题并重新运行 cmake 修复了它。我添加了包含 post-cmake。

回答by Mark Lakata

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/includea dependency that is NOT optimized away, try this trick: prepend /.to the path.

显然,cmake 从依赖树中删除了系统包含路径(感谢 @ony 提供此提示)。大多数时候这可能是有道理的,但有时 cmake 不知道编译器认为什么是系统路径。我们正在使用忽略的自定义 gcc 构建/usr/include,但 cmake 认为它不会忽略它。要强制 cmake 生成未/usr/include优化的依赖项,请尝试以下技巧:添加/.到路径。

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.

我正在尝试使所有库依赖项都使用 cmake 依赖项功能,包括某些“3rd”方库,这些库并不总是默认安装在 Linux 上,甚至不可用。例如,Z-lib 压缩。

The following interface target worked fine if the Z lib includes were not in /usr/include, but would break if they were.

如果 Z lib 包含不在 中/usr/include,则以下接口目标可以正常工作,但如果在 中,则会中断。

find_package(ZLIB REQUIRED)
message(status "found zlib ${ZLIB_LIBRARIES}")
message(status "found zlib includes ${ZLIB_INCLUDE_DIRS}")
target_link_libraries(zlib_target INTERFACE ${ZLIB_LIBRARIES})
target_include_directories(zlib_target INTERFACE ${ZLIB_INCLUDE_DIRS})

I changed the last line to

我将最后一行更改为

target_include_directories(zlib_target INTERFACE /.${ZLIB_INCLUDE_DIRS})

and it worked. Now targets that depended on zlib_targetwould automatically get -I/./usr/includeduring compilation.

它奏效了。现在依赖的目标zlib_target-I/./usr/include在编译期间自动获取。