cmake默认不添加头文件目录,需在cmakelists.txt中显式指定:include_directories用于全局路径(影响当前及子目录后续目标),target_include_directories则绑定到具体target并支持private/public/interface作用域控制,是现代cmake推荐做法。

装完 CMake 本身不自动添加任何头文件目录——你得在 CMakeLists.txt 里显式告诉它去哪里找头文件。没加,编译器就真找不到 #include 的东西,报 fatal error: xxx.h: No such file or directory 是最常见结果。
用 include_directories 添加全局头文件路径
这是最直白的方式,适用于整个当前 CMakeLists.txt 及其子目录(但不自动透传给 add_subdirectory 里的子项目)。
- 相对路径按
CMAKE_CURRENT_SOURCE_DIR解析:比如当前CMakeLists.txt在项目根目录,头文件在include/下,写include_directories(include)就行 - 绝对路径更稳妥:比如
include_directories(${PROJECT_SOURCE_DIR}/include),避免因执行位置不同出错 - 多个路径用空格分隔:
include_directories(include core/third_party/boost) - 别滥用
SYSTEM:只对真正系统级头文件(如第三方 SDK 的头)加这个标记,否则可能抑制编译器警告
用 target_include_directories 绑定到具体 target
这是现代 CMake 推荐做法,比 include_directories 更精确、更安全——路径只作用于指定的可执行文件或库,不会污染其他 target。
- 必须配合
add_executable或add_library生成的 target 名使用,比如add_executable(myapp main.cpp)后,再写target_include_directories(myapp PRIVATE include) -
PRIVATE表示只供该 target 源码用;PUBLIC表示该 target 的头文件也能用这些路径(适合库导出头文件时);INTERFACE表示只供依赖它的 target 使用(不编译本 target 自身) - 路径支持生成器表达式,比如
$<install_prefix>/include</install_prefix>,方便后期安装时适配
find_package 找不到头文件?先检查变量是否被正确导出
很多第三方库(如 OpenCV、Boost)通过 find_package(OpenCV) 查找后,会把头文件路径存进 OpenCV_INCLUDE_DIRS 或 OpenCV_TARGET_INCLUDE_DIRECTORIES 这类变量里——但不是所有包都一致。
- 查文档确认变量名:运行
find_package(OpenCV REQUIRED)后,message(STATUS "OpenCV includes: ${OpenCV_INCLUDE_DIRS}")看输出是否为空 - 优先用
target_include_directories(myapp PRIVATE ${OpenCV_INCLUDE_DIRS}),而不是include_directories,避免全局污染 - 某些新版包(如 modern CMake 风格的
find_package)直接提供OpenCV::opencv_core这样的 imported target,这时连路径都不用管,直接target_link_libraries(myapp PRIVATE OpenCV::opencv_core)就自动带上了头文件路径
最容易被忽略的是作用域和继承关系:include_directories 不向下传递给子目录,target_include_directories 的 PUBLIC 和 INTERFACE 才影响依赖链。写完记得用 cmake --build . --verbose 看实际传给编译器的 -I 参数是否符合预期。











