用cmake处理头文件的依赖关系
我正在一个小型的C ++项目上使用CMake,到目前为止,它的工作很好…一个扭曲:x
当我更改头文件时,通常需要重新编译一些源文件(包括直接或间接包含的文件),但似乎cmake只检测到一些源文件需要重新编译,导致损坏的状态。 我可以通过清除项目并从头开始重build来解决这个问题,但是这样规避了使用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
,取决于sub1
取决于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)
我会很高兴,如果有人能把我的错误指向我,在这里search或在CMake没有产生任何东西,所以我想这很容易,或应该开箱即用…
(仅供参考,我在MSYS上使用cmake 2.8.2版本)
编辑 :
感谢Bill的build议,我检查了CMake生成的depend.make
文件,确实缺乏(严重)。 这里是一个例子:
src/sub3/CMakeFiles/sub3.dir/File1.cpp.obj: ../src/sub3/File1.cpp
是的,就是这样,所有的包括都被引用:x
您应该查看二叉树中的depend.make
文件。 它将在CMakeFiles/target.dir/depend.make
。 尝试find那些缺less一个你认为应该有的.h
文件。 然后为cmake创build一个错误报告或通过电子邮件发送cmake邮件列表。
我刚刚遇到同样的问题。 将include_directories()
path从绝对path更改为相对path后,添加了适当的依赖关系。
看起来像CMake试图猜测哪些头是系统,哪些是项目相关的。 我怀疑那些以/
-isystem /some/path
开头的目录,因此不会显示在生成的依赖关系中。
如果不能用相对pathreplace${FOO_SOURCE_DIR}
,可以尝试使用适当的CMake函数来计算相对path。 即:
file(RELATIVE_PATH FOO_SOURCE_REL_DIR ${CMAKE_CURRENT_SOURCE_DIR} ${FOO_SOURCE_DIR}/.) include_directories(${FOO_SOURCE_REL_DIR}/include)
你添加包括你的cpp文件之前或之后运行cmake吗?
我碰到这个问题,并重新运行cmake修复它。 我已经添加了包括后cmake。
显然cmake从依赖关系树中删除系统包括path(谢谢@ony这个提示)。 这在大多数情况下可能是有意义的,但有时cmake不知道编译器认为是系统path还是不是。 我们正在使用一个忽略/usr/include
的自定义gcc版本,但cmake认为它不会忽略它。 为了强制cmake使/usr/include
未被优化的依赖,请试试这个技巧:prepend /.
到path。
我试图使所有的库依赖使用cmake依赖项function,包括某些“第三”党的库,并不总是默认安装在Linux上,甚至可用。 例如,Z-lib压缩。
下面的接口目标工作正常,如果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})
我改变了最后一行
target_include_directories(zlib_target INTERFACE /.${ZLIB_INCLUDE_DIRS})
它的工作。 现在,依赖于zlib_target
目标将在编译期间自动获取-I/./usr/include
。