我看到gcc有一个 -include file 选项,它的行为类似于文件的第一行。
#include "file"
这个选项有哪些好的用途?
我看到gcc有一个 -include file 选项,它的行为类似于文件的第一行。
#include "file"
这个选项有哪些好的用途?
-include
选项的一个实际用途是在Linux内核构建系统中。
在构建Linux内核时,您可以运行大量的配置选项菜单来自定义构建的内核。例如,以下是Linux 3.0内核中是否支持x86架构上的多个CPU核心的配置选项:
config SMP
bool "Symmetric multi-processing support"
---help---
This enables support for systems with more than one CPU. If you have
a system with only one CPU, like most personal computers, say N. If
you have a system with more than one CPU, say Y.
[...]
在源代码中,这个选项被表示为预处理器符号CONFIG_SMP
。当需要不同的代码来适应多处理器时,内核和驱动程序中的源代码可以使用#ifdef CONFIG_SMP
。(还可以在Makefile
中使用不同的语法,选择是否编译.c
文件或子目录。)
这些预处理器符号如何定义?它们不是在编译器命令行上定义的,因为那样将变得非常冗长(在典型的发行版内核中有数千个这些符号;我在这台机器上运行的内核中计算出超过4000个)。相反,会自动生成一个神奇的头文件,其中包含了所有这些选项。然后,通过-include include/generated/autoconf.h
选项,在所有编译的文件中自动包含此头文件。
由于CONFIG_
预处理器符号应该在所有内核源代码文件的任何地方都可用,所以使用-include
(在文件的第一行之前隐式地包含它)是一件好事情。否则,您将不得不执行以下任一操作:
kernel.h
)中明确包含它,并希望在第一个直接或间接包含该头文件之前不会出现任何依赖于CONFIG_
符号的内容。这两个选项都明显劣于-include
。
Linux内核中还有另一种使用-include
的方法,但它更为深奥。内核的某些部分(特别是启动代码的早期部分)必须在实模式下运行。与过去完全用汇编语言编写的方式不同,内核的这些部分使用了一种技巧,在这种技巧中,汇编器被指示发出32位实模式代码(.code16gcc
)。这必须在任何其他事物之前作为源代码的第一件事情完成,这使其非常适合使用-include
(此时包含的头文件仅具有一个asm(".code16gcc");
语句)。
这对于像是前缀头文件的东西非常有用,这些文件将在项目中的所有文件中被 #include - 有点像 Windows 中可怕的 StdAfx.h 或 Mac OS 上的 .prefix.h 文件。
它可以在编译时使用,类似于运行时的库预加载:临时覆盖源文件中的某些内容。例如,您可以使用它来包含一个头文件,覆盖默认的 glibc 符号版本,如果您想支持比系统上的版本旧的 glibc 版本。