为什么 gcc 有一个 -include 选项?

发布于 2024-11-08 15:56:47 字数 124 浏览 0 评论 0原文

我看到 gcc 有一个 -include file 选项,其行为(有点)类似于文件的第一行:

#include "file"

此选项有什么好的用途?

I see that gcc has a -include file option that behaves (sort of) like the first line of the file was

#include "file"

What are some good uses for this option?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

迎风吟唱 2024-11-15 15:56:47

-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

-include 在 Linux 内核上还有另一种用法,但它更加深奥。内核的某些部分(特别是引导代码的早期部分)必须在实模式下运行。内核的这些部分不像过去那样完全用汇编语言编写,而是使用了一种 hack,指示汇编程序发出 32 位实模式代码 (.code16gcc)。这必须作为源代码中的第一件事完成,在其他任何事情之前,这使得它与 -include 非常匹配(这次包含的标头只有一个 asm(". code16gcc"); 语句)。

One real-life use of the -include option is in the Linux kernel build system.

When building the Linux kernel, you can run through a huge menu of configuration options to customize the built kernel. For instance, here is the configuration option for whether you want to support more than one CPU core on the x86 architecture, for the Linux 3.0 kernel:

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.
          [...]

Within the source code, this option appears as a preprocessor symbol, CONFIG_SMP. Source code within the kernel and drivers can do a #ifdef CONFIG_SMP when different code is needed for more than one processor. (It can also be used within a Makefile, with a different syntax, to chose whether or not to compile a .c file or subdirectory.)

How are these preprocessor symbols defined? They are not defined on the compiler command line, since it would then be ridiculously long (there are literally thousands of these symbols on a typical distribution kernel; I count over 4000 of them for the kernel running on this machine). Instead, a magic header file is automatically generated with all these options. This header file is then automatically included on all the compiled files, via an -include include/generated/autoconf.h option.

Since the CONFIG_ preprocessor symbols should be available everywhere on all the kernel source code files, using -include (which implicitly includes it before the first line of the file) is a good thing. Without it, you would have to do one of the following:

  • Explicitly include it as the first include file on every one of the thousands of kernel source code files, and hope nobody forgets to include it or adds something before the include.
  • Explicitly include it on a commonly used header (like kernel.h), and hope nothing which depends on a CONFIG_ symbol appears before the first direct or indirect inclusion of that header.

Either of these options is clearly inferior to -include.

There is another use of -include on the Linux kernel, but it is more esoteric. Parts of the kernel (in particular the early parts of the boot code) have to run in real mode. Instead of being written completely in assembly, as they were in the past, these parts of the kernel use a hack where the assembler is instructed to emit 32-bit real-mode code (.code16gcc). This must be done as the very first thing in the source code, before anything else, which makes it a great match to -include (the header included this time has only an asm(".code16gcc"); statement).

一杯敬自由 2024-11-15 15:56:47

它对于像前缀头文件这样的东西很有用,这些文件将被 #included 到项目中的所有文件中 - 有点像 Windows 中可怕的 StdAfx.h 或 Mac OS 上的 .prefix.h 文件。

It's useful for things like prefix header files which are going to be #included in all files in a project - somewhat like the dreaded StdAfx.h in Windows or the .prefix.h files on Mac OS.

静若繁花 2024-11-15 15:56:47

它可以在编译时以类似于运行时库预加载的方式使用:临时覆盖源文件中的某些内容。例如,如果您想支持比系统上旧版本的 glibc,您可以使用它来包含一个覆盖默认 glibc 符号版本控制的标头。

It can be used at compile time in a way similar to library pre-loading at run time: to temporarily override certain things in a source file. For example you can use it to include a header overriding the default glibc symbol versioning if you want to support an older version of glibc than the one on your system.

平生欢 2024-11-15 15:56:47

我对此的两分钱:
我碰巧使用了 -include 指令和“编译时”自动生成的标头。
这样,您的代码就可以在默认情况下工作,并且您不会用可能存在或不存在的文件污染您的代码(例如,依赖关系计算会抱怨),但您可以根据外部配置修改代码行为。

My two cents about this:
I have happened to use the -include directive with "compile time" automatically generated headers.
That way your code can work on defaults and you don't taint your code with files that may or may not exist (dependencies calculation will complain for example) but you can modify your code behavior based on external configuration.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文