You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何配置CMake区分#include<...>与#include"..."的头文件加载逻辑?

回答

当然可以!CMake完全支持区分#include<...>和#include"..."的头文件搜索行为,甚至能完美解决你提到的string.h冲突问题。下面分两个场景详细说明:


1. 区分#include "foo.h"和#include <foo.h>的加载目录

你之前用include_directories(src lib)的问题在于,这个命令会把两个目录同时加到全局的包含路径,不管是用引号还是尖括号引入,编译器都会按顺序搜索,自然会优先匹配第一个目录的文件。

要实现你要的区分,关键是利用CMake对包含目录的类型控制,以及编译器本身的搜索规则:

  • 编译器对#include"..."会优先搜索-I参数指定的目录(用户自定义路径)
  • 对#include<...>会优先搜索-isystem参数指定的目录(系统级路径)

CMake里可以通过target_include_directories命令的关键字来控制这一点:

# 先定义你的目标(假设是可执行文件,库文件同理)
add_executable(my_project src/foo.c lib/foo.c)

# 配置包含目录:
target_include_directories(my_project
    # PRIVATE:对应编译器的`-I`参数,优先被`#include"..."`搜索
    PRIVATE
        src
    # SYSTEM:对应编译器的`-isystem`参数,优先被`#include<...>`搜索
    SYSTEM
        lib
)

这样配置后:

  • 当你写#include "foo.h"时,编译器会先搜索src目录,加载src/foo.h
  • 当你写#include <foo.h>时,编译器会先搜索lib目录,加载lib/foo.h

如果你的源文件不在src目录下,还可以开启CMAKE_INCLUDE_CURRENT_DIR让编译器优先搜索当前源文件所在目录,再匹配PRIVATE路径。


2. 解决自定义string.h与系统库的冲突

你遇到的问题是自定义string.h被#include<string.h>加载,本质是因为自定义目录被加到了-I或-isystem路径中,导致编译器在搜索尖括号引入的头文件时,先找到了你的自定义文件。

要实现#include<string.h>加载系统文件,#include"string.h"加载自定义文件,只需把自定义string.h所在的目录仅加到PRIVATE包含路径:

# 假设自定义string.h在src目录下
target_include_directories(my_project
    PRIVATE
        src  # 仅用`-I`参数添加,只会被`#include"..."`优先搜索
    # 不要把src加到SYSTEM路径!
)

原理是:

  • 对于#include<string.h>:编译器会优先搜索系统默认的-isystem路径(比如/usr/include),找到系统的string.h,完全不会去搜PRIVATE的src目录(因为-isystem的优先级高于-I)
  • 对于#include"string.h":编译器会先搜索当前源文件目录,再搜索PRIVATE的src目录,找到你的自定义文件

这种配置和你在Keil里的行为完全一致,不需要重命名或移动自定义文件。


额外注意事项

  • 尽量避免使用全局的include_directories命令,改用target_include_directories针对单个目标配置,这样不会影响其他目标的包含路径
  • 如果你的项目是多目标结构,比如同时有库和可执行文件,可以把公共的包含路径用PUBLIC关键字配置,私有路径用PRIVATE

内容的提问来源于stack exchange,提问作者Simon Schüpbach

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:00:45