gcc头文件搜索

OS: Ubuntu 22.04.1
gcc: 11.2.0
glibc: 2.35

#include “header.h” 与 #include <header.h> 区别

#include “header.h” 引入的头文件,默认会首先在 .c 当前目录查找;而#include <header.h> 则不会。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
$ cat 004_header_search.c 
#include <stdio.h>
#include "my_header.h"

void main() {
printf("macro: %s\n", MY_TEST_MACRO_0911);
}
$ cat my_header.h
#ifndef __MY_HEADER__
#define __MY_HEADER__

#define MY_TEST_MACRO_0911 "in current dir"

#endif //__MY_HEADER__
$ gcc 004_header_search.c
$ ./a.out
macro: in current dir
$
$ vim 004_header_search.c
$ cat 004_header_search.c
#include <stdio.h>
#include <my_header.h>

void main() {
printf("macro: %s\n", MY_TEST_MACRO_0911);
}
$ gcc 004_header_search.c
004_header_search.c:2:10: fatal error: my_header.h: No such file or directory
2 | #include <my_header.h>
| ^~~~~~~~~~~~~
compilation terminated.
$

头文件搜索相关的command option 和环境变量

  • -I dir: 可以同时指定多个,优先级从左到右,可以使用.表示当前目录(-I. -I/special/include)
  • -iquota dir: 只适用于以引号 “” 导入的头文件
  • -isystem dir
  • -idirafter dir
  • CPATH: 可以指定多个,优先级从左到右,冒号分割,适用于C/C++/objc语言;可以包含空的元素(:/special/include)表示当前目录
  • C_INCLUDE_PATH: 只适用于C语言
  • CPLUS_INCLUDE_PATH: 只适用于C++语言
  • OBJC_INCLUDE_PATH: 只适用于objc语言

查找顺序为:

  1. 对于用 #include “” 引号形式引入的头文件,首先搜索当前程序文件所在的目录,其次再前往 -iquote 选项指定的目录中查找;
  2. 搜索 -I 选项指定的目录
  3. 搜索 CPATH 环境变量指定的目录
  4. 搜索 -isystem 选项指定的目录
  5. 搜索C_INCLUDE_PATH/CPLUS_INCLUDE_PATH/OBJC_INCLUDE_PATH 环境变量指定的目录
  6. 搜索默认的系统路径;
    1) /usr/lib/gcc/x86_64-linux-gnu/11/include
    2) /usr/local/include/x86_64-linux-gnu
    3) /usr/local/include
    4) /usr/lib/gcc/x86_64-linux-gnu/11/include-fixed
    5) /usr/x86_64-linux-gnu/include
    6) /usr/include/x86_64-linux-gnu
    7) /usr/include
  7. 搜索-idirafter 选项指定的目录。

如果默认的系统路径或-isystem指定的路径,也被指定在了-I的参数中时,-I里面的不生效。

gcc编译命令查看头文件查找顺序

gcc 命令的-v参数可以显示编译过程中的调用的程序以及相关的日志信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
$ cat 004_header_search.c 
#include <stdio.h>
#include "my_header.h"

void main() {
printf("macro: %s\n", MY_TEST_MACRO_0911);
}
$ ls include |xargs -I dir -t cat include/dir/my_header.h |grep -i macro
cat include/c_include_path/my_header.h
#define MY_TEST_MACRO_0911 "in c_include_path dir"
cat include/c_path/my_header.h
#define MY_TEST_MACRO_0911 "in c_path dir"
cat include/cplus_include_path/my_header.h
#define MY_TEST_MACRO_0911 "in cplus_include_path dir"
cat include/dirafter/my_header.h
#define MY_TEST_MACRO_0911 "in dirafter dir"
cat include/include_1/my_header.h
#define MY_TEST_MACRO_0911 "in -I dir1"
cat include/include_2/my_header.h
#define MY_TEST_MACRO_0911 "in -I dir2"
cat include/objc_include_path/my_header.h
#define MY_TEST_MACRO_0911 "in objc_include_path dir"
cat include/quote/my_header.h
#define MY_TEST_MACRO_0911 "in quote dir"
cat include/system/my_header.h
#define MY_TEST_MACRO_0911 "in system dir"
$
$ CPATH=./include/c_path/ C_INCLUDE_PATH=./include/c_include_path/ CPLUS_INCLUDE_PATH=./include/cplus_include_path/ OBJC_INCLUDE_PATH=./include/objc_include_path/ gcc 004_header_search.c -I ./include/include_1/ -I ./include/include_2/ -iquote ./include/quote/ -isystem ./include/system/ -idirafter ./include/dirafter/ -v

......
#include "..." search starts here:
./include/quote/
#include <...> search starts here:
./include/include_1/
./include/include_2/
./include/c_path/
./include/system/
./include/c_include_path/
/usr/lib/gcc/x86_64-linux-gnu/11/include
/usr/local/include/x86_64-linux-gnu
/usr/local/include
/usr/lib/gcc/x86_64-linux-gnu/11/include-fixed
/usr/x86_64-linux-gnu/include
/usr/include/x86_64-linux-gnu
/usr/include
./include/dirafter/
End of search list.
......
$
$ CPATH=./include/c_path/ gcc 004_header_search.c -I ./include/system/ -isystem ./include/system/
$ ./a.out
macro: in c_path dir
$