GCC 的编译配置文件(Spec File)
翻译: adie
日期: April,2012
原文作者: Free Software Foundation, Inc
原文地址: http://gcc.gnu.org/onlinedocs/gcc/Spec-Files.html
3.15 配置外部工具程序和参数
[adie: 这篇文章原是 GCC 手册中的一节, 3.15 是它在手册中的编号.]
gcc 是一个驱动式的程序. 它调用其它程序来依次进行编译, 汇编和链接. GCC 分析命令行参数, 然后决定该调用哪一个子程序, 哪些参数应该传递给子程序. 所有这些行为都是由 SPEC 字符串(spec strings)来控制的. 通常情况下, 每一个 GCC 可以调用的子程序都对应着一个 SPEC 字符串, 不过有少数的子程序需要多个 SPEC 字符串来控制他们的行为. 编译到 GCC 中的 SPEC 字符串可以被覆盖, 方法是使用 -specs= 命令行参数来指定一个 SPEC 文件(spec file).
Spec 文件(Spec files) 就是用来配置 SPEC 字符串的. 它包含了一系列用空行分隔的指令. 指令的类型由一行的第一个非空格字符决定, 它们可能是:
- %command
- 定义 SPEC 文件的预处理命令, 预处理命令包括以下的命令:
- %include <file>
- 搜索文件, 并将其内容插入到 SPEC 文件的当前位置.
- %include_noerr <file>
- 和 '%include' 一样, 但是在没有找到文件的情况下不会产生错误消息.
- %renameold_name new_name
-
- 将 SPEC 字符串 old_name 改名为 new_name.
- *[spec_name]:
- 这条命令让编译器创建,覆盖或删除指定名字的 SEPC 字符串. 所有在这条指令之后到下一条指令或空行之前的文本都被认为是这个 SPEC 字符串的内容. 如果它的内容为空, 则这个名字将被删除(如果该名字不存在, 则什么都不会发生). 内容不为空时, 如果该名字不存在, 则会创建一个新的 SPEC 字符串, 如果已经存在了, 他们的内容将会被替换. 如果内容的第一个字符为 '+', 则这些内容会被追加到原来定义的内容后面, 而不是覆盖了.
- [suffix]:
- 创建一个新的 '[suffix] spec'(后缀处理) 组合. 这个指令之后到下一个指令或空行之前的行组成了这个后缀的 SPEC 字符串. 当编译器遇到指这种后缀的输入文件时, 它会依次执行 SPEC 字符串中的指令, 这些指令指明了如何编译那个文件. 例如:
.ZZ: z-compile -input %i
它的意思是: 任何以 '.ZZ' 结尾的输入文件都将使用 'z-compile' 程序进行处理, 调用的时候将会使用 -input 开关以及 '%i' 替换后的结果(详见下文) 作为命令行参数.
作为 SPEC 字符串的内容, suffix 指令后的文本还可以是下面的某一个:
- @language
- 它表明这个后缀是某种已知语言的别名. 它和 GCC 命令行中用于指定语言的 -x 选项类似. 比如:
.ZZ: @c++
这说明 .ZZ 文件实际上是 C++ 的源代码文件.
- #name
- 这会产生一条错误消息:
当前系统没有安装 name 编译器.
GCC 已经内建了一份巨大的后缀列表. 这条指令将后缀添加到列表的结尾处, 由于这个列表使用的时候是从结尾向后搜索的, 实际上可以使用这种技术来覆盖之前的条目.
GCC 已经内置了如下的 SPEC 字符串. SPEC 文件可以覆盖他们或者创建新的. 注意, 某些 GCC 的实现也可能添加它们自己的 SEPC 字符串到这个列表里面.
asm 传递给汇编器的选项 asm_final 传递给汇编后处理器的选项 cpp 传递给 C 预处理器的选项 cc1 传递给 C 编译器的选项 cc1plus 传递给 C++ 编译器的选项 endfile 链接的最后需要包含的目标文件 link 传递给链接器的选项 lib 命令行传递给链接器的要包含的库 libgcc 决定给链接器传递哪个 GCC 支持库 linker 设置链接器的名字 predefines 传递给 C 预处理器的宏定义 signed_char 传递给 CPP 的用于说明 char 默认是否是有符号类型的宏 startfile 一开始就需要传递给链接器的目标文件
下面是一个简单的 SPEC 文件的例子:
%rename lib old_lib *lib: --start-group -lgcc -lc -leval1 --end-group %(old_lib)
这个例子把 'lib' 改名为 'old_lib' 然后用一个新的定义覆盖了之前的 'lib' 定义. 新定义在包含旧的定义文本之前添加了一些额外的命令行选项.
SEPC 字符串是传递给相应程序的命令行选项的列表. 另外, SEPC 字符串可以包含 '%' 作为前缀的字符串来表示变量. 变量可以用来代替一串文本, 或者作为向命令行插入文本的条件. 使用这些概念可以产生非常复杂的命令行.
下面是所有的用于 SPEC 字符串的预定义变量. 注意,这些变量在表示文本时不会自动在结果两边产生空格. 你可以在链接这些变量时使用常量字符串来一起链接.
- %%
- 在程序名字或参数中用于表示一个 '%'.
- %i
- 用来表示当前正在处理的输入文件名
- %b
- 表示输入文件的基本名字. 它不包含最后一个点号以及之后的内容, 也不包含路径名.
- %B
- 和 '%b' 相同, 但是它包含了后缀名(最后一个点号后的内容).
- %d
- 用包含或附加 '%d' 来标记一个临时文件名, GCC 正常退出后会自动删除带有这种标记的文件. 和 '%g' 不同, 这个变量不会在参数中产生文本内容.
- %gsuffix
- 产生指定后缀 suffix 的文件名, 每次编译产生一个. 和 '%d' 一样, 它也会被标记为临时文件. 为了减少拒绝服务攻击的可能性, 即使上一次产生的文件名已经知道了, 下一次产生的文件名也是无法预料的. 例如, '%g.s ... %g.o ... %g.s' 可能被转换成 'ccUVUUAU.s ccXYAXZ12.o ccUVUUAU.s'. 后缀名需要可以和 '[.A-Za-z]*' 这样的正则表达式匹配或者使用特定的 '%O'. '%O' 使用的时候假设它已经被处理过了. 以前, '%g' 只是简单的每次出现都被替换成一个文件名, 没有后缀的情况下使得攻击很容易成功.
- %usuffix
- 和 '%g' 一样, 但是每次出现就会产生一个新的临时文件名, 而不是每次编译的时候一个.
- %Usuffix
- 生成上一次使用 '%usuffix' 时产生的文件名, 如果之前没有过, 就生成一个新的. 在没有使用过 '%usuffix' 的情况下, 它和 '%gsuffix' 一样, 只是他们不会共享后缀名字空间. 因此, '%g.s ... %U.s ... %g.s ... %U.s' 会生成两个不同的文件名, 一个是 '%g.s' 产生的, 另一个是 '%U.s'. 以前, '%U' 只是替换成上一个的 '%u' 产生的文件名, 不会带任何的后缀.
- %jsuffix
- 如果存在 HOST_BIT_BUCKET, 并且它可写, 也没有使用 -save-temps, 这会被替换成 HOST_BIT_BUCKET 的名字. 否则, 产生一个临时文件名, 和 '%u' 效果相同. 这个临时文件并不用来在两个进程间通信, 只是作为垃圾进行处理.
[adie: HOST_BIT_BUCKET 是 GCC 中配置宿主系统环境时用到一个参数. 它是由宿主系统定义的一个路径名, 可以被当作一个文件来进行写入, 但是所有写入的内容都会被丢弃. 这通常被称为 bit bucket(比特流垃圾桶) 或 null device(空设备), 在 UNIX 中它通常就是 /dev/null.
- %|suffix
- %msuffix
- 和 '%g' 类似, 只是可以使用 -pipe (管道). 使用管道时, '%|' 被替换成一个破折号, '%m' 被替换成空. 这是让程序从标准输入读取数据和往标准输出写数据的常用方式. 如果你需要处理更复杂的情况, 你还可以使用 '%{pipe:X}': 参考 f/lang-specs.h 中的例子.
- %.SUFFIX
- 对于匹配后缀的参数进行替换. 后缀到空格或下一个 % 结束.
- %w
- 对包含或跟随有 '%w' 的参数标记为此次编译的输出文件. 这会将这个参数放到 '%o' 的参数序列里面.
- %o
- 替换所有输出文件的名字, 并自动在他们周围放置空格. 你仍然应该在 '%o' 的周围书写空格, 否则结果将是未定义的. '%o' 用于运行链接器. 没有可识别后缀的输入文件将不会被编译, 但是他们被包含在输出文件里, 因此, 他们可以被链接.
- %O
- 为目标文件替换后缀. 注意, 当它紧接在 '%g, %u, 和 %U' 后面时会被特别处理, 因为它们需要完整的文件名. 处理的方法是假设 '%O' 已经被处理过了, 除非 '%g, %u, 和 %U' 当前不支持使用特殊的 '%O' 后缀, 例如, '.o'.
- %p
- 替换标准的预定义宏为当前的目标类型. 运行 cpp 程序时使用.
- %P
- 和 '%p' 类似, 只是会在每个预定义宏的名字前后加上 '__', 除非宏的名字是以 '__' 或 '_L' 开头的. 其中 L 是一个大写字母. 这是 ISO C 所要求的.
- %I
- 贴换所有的 -iprefix(来自 GCC_EXEC_PREFIX), -isysroot(来自 TARGET_SYSTEM_ROOT), -isystem(来自 COMPILER_PATH 和 -B 选项) 以及所需的 -imultilib.
- %s
- 当前参数是某个库或可执行文件的名字. 搜索标准的目录列表来查找这个文件名, 如果找到了, 就用全名来进行替换. 当前目录被包含在扫描的目录列表的第一位.
- %T
- 当前参数是一个连接脚本. 在库文件的目录列表里面搜索那个文件. 如果文件找到了, 插入一个 --script 选项和文件的全路径名到命令行中. 如果文件没找到将会产生一条错误信息. 注意, 当前目录不会被搜索.
- %estr
- 把 str 作为错误消息打印出来. str 使用换行作为结束. 检测到不一致的选项时可以使用它.
- %(name)
- 贴换名字为 name 的 SPEC 字符串内容到当前位置.
- %x{option}
- 为 '%X' 添加一个选项.
- %X
- 输出用 -W1 或 '%x' 添加的所有链接器选项.
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请
点击举报。