代码生成选项

所有这些选项都通过 -C 标志(codegen 的缩写)传递给 rustc。你可以通过运行 rustc -C help 查看适用于你当前编译器的选项列表。

ar

此选项已弃用,不起作用。

code-model

此选项允许你选择要使用的代码模型。
代码模型对程序及其符号可能使用的地址范围施加了约束。
使用较小的地址范围,机器指令可能能够使用更紧凑的寻址模式。

具体的范围取决于目标架构及其可用的寻址模式。
对于 x86,其代码模型的更详细描述可以在 System V 应用二进制接口 规范中找到。

此选项支持的值有:

  • tiny - Tiny 代码模型。
  • small - Small 代码模型。这是大多数受支持目标的默认模型。
  • kernel - Kernel 代码模型。
  • medium - Medium 代码模型。
  • large - Large 代码模型。

也可以通过运行 rustc --print code-models 来发现支持的值。

codegen-units

此标志控制 crate 被分割成的最大代码生成单元数量。它接受一个大于 0 的整数。

当一个 crate 被分割成多个代码生成单元时,LLVM 能够并行处理它们。增加并行度可能会加快编译时间,但也可能产生更慢的代码。将其设置为 1 可能会提高生成代码的性能,但编译可能会变慢。

如果未指定,非增量构建的默认值为 16。对于增量构建,默认值为 256,这使得缓存更细粒度。

collapse-macro-debuginfo

此标志控制在为此 crate 生成调试信息时,是否将宏定义中的代码位置折叠成与该宏的调用点关联的单一位置。

如果传递此选项,它将覆盖默认的折叠行为和代码中的 #[collapse_debuginfo] 属性。

  • y, yes, on, true: 折叠调试信息中的代码位置。
  • n, no, offfalse: 不折叠调试信息中的代码位置。
  • external: 仅当宏来自不同的 crate 时,才折叠调试信息中的代码位置。

control-flow-guard

此标志控制 LLVM 是否启用 Windows Control Flow Guard 平台安全特性。对于非 Windows 目标,此标志当前被忽略。它接受以下值之一:

  • y, yes, on, true, checks,或不带值:启用 Control Flow Guard。
  • nochecks: 发出 Control Flow Guard 元数据,但不进行运行时强制检查(这仅应用于测试目的,因为它不提供安全强制措施)。
  • n, no, off, false: 不启用 Control Flow Guard(默认)。

debug-assertions

此标志允许你打开或关闭 cfg(debug_assertions) 条件编译。它接受以下值之一:

  • y, yes, on, true,或不带值:启用 debug-assertions。
  • n, no, offfalse: 禁用 debug-assertions。

如果未指定,仅当 opt-level 为 0 时,才会自动启用 debug 断言。

debuginfo

此标志控制调试信息的生成。它接受以下值之一:

  • 0none: 完全不生成调试信息(默认)。
  • line-directives-only: 仅生成行信息指令。对于 nvptx* 目标,这会启用 性能分析。对于其他用例,line-tables-only 是更好、更兼容的选择。
  • line-tables-only: 仅生成行表。生成最少量的调试信息,以便回溯时包含文件名/行号信息,但不包含其他任何信息,例如变量或函数参数信息。
  • 1limited: 生成不包含类型或变量级别信息的调试信息。
  • 2full: 生成完整的调试信息。

注意:-g 标志-C debuginfo=2 的别名。

default-linker-libraries

此标志控制链接器是否包含其默认库。它接受以下值之一:

  • y, yes, on, true: 包含默认库。
  • n, no, offfalse,或不带值:排除默认库(默认)。

例如,对于 gcc 类型的链接器,这会向链接器发出 -nodefaultlibs 标志。

dlltool

windows-gnu 目标上,此标志控制 rustc 在使用 raw-dylib 链接类型时调用哪个 dlltool 来生成导入库。它接受 dlltool 可执行文件 的路径。如果未指定此标志,则会根据主机环境和目标推断出 dlltool 可执行文件。

embed-bitcode

此标志控制编译器是否将 LLVM 位码嵌入到目标文件中。它接受以下值之一:

  • y, yes, on, true,或不带值:将位码放入 rlibs 中(默认)。
  • n, no, offfalse: 从 rlibs 中省略位码。

当 rustc 执行链接时优化 (LTO) 时,需要 LLVM 位码。嵌入的位码将出现在 rustc 生成的目标文件中,位于由目标平台定义的节中。大多数情况下,这个节是 .llvmbc

如果你的编译实际上不需要位码(例如,如果你不执行 LTO),使用 -C embed-bitcode=no 可以显著提高编译时间并减小生成文件的大小。出于这些原因,Cargo 尽可能使用 -C embed-bitcode=no。同样,如果你直接使用 rustc 构建,我们建议你在不使用 LTO 的时候使用 -C embed-bitcode=no

如果与 -C lto 结合使用,-C embed-bitcode=no 将导致 rustc 在启动时中止,因为这种组合无效。

注意:如果你使用 LTO 构建 Rust 代码,那么你可能甚至不需要打开 embed-bitcode 选项。你可能想改用 -Clinker-plugin-lto,它完全跳过生成目标文件,而只是用 LLVM 位码替换目标文件。-Cembed-bitcode 的唯一用途是当你生成一个既用于带 LTO 又用于不带 LTO 的 rlib 时。例如,Rust 的标准库附带嵌入的位码,因为用户在使用和不使用 LTO 的情况下都会链接到它。

这可能也会让你想知道为什么此选项的默认值是 yes。原因在于 rustc 1.44 及更早版本就是这样。在 1.45 版本中添加了此选项,以关闭一直以来的默认行为。

extra-filename

此选项允许你在每个输出文件名中添加额外数据。它接受一个字符串作为文件名的后缀。有关更多信息,请参阅 --emit 标志

force-frame-pointers

此标志强制使用帧指针。它接受以下值之一:

  • y, yes, on, true,或不带值:强制启用帧指针。
  • n, no, offfalse: 不强制启用帧指针。这不一定意味着会移除帧指针。

如果未强制启用帧指针,默认行为取决于目标。

force-unwind-tables

此标志强制生成展开表。它接受以下值之一:

  • y, yes, on, true,或不带值:强制生成展开表。
  • n, no, offfalse: 不强制生成展开表。如果目标需要展开表,则会发出错误。

如果未指定,默认行为取决于目标。

incremental

此标志允许你启用增量编译,这使得 rustc 能够在编译 crate 后保存信息,以便在重新编译 crate 时重用,从而缩短重新编译时间。此标志接受一个目录路径,增量文件将存储在该目录中。

inline-threshold

此选项已弃用,不起作用。

考虑使用 -Cllvm-args=--inline-threshold=...

instrument-coverage

此选项启用基于插装的代码覆盖支持。有关更多信息,请参阅基于插装的代码覆盖一章。

请注意,虽然 -C instrument-coverage 选项是稳定的,但生成的插装产生的剖析数据格式可能会更改,并且可能与编译器自带的覆盖工具以外的工具不兼容。

此标志允许你向链接器调用附加一个额外的参数。

“附加”很重要;你可以多次传递此标志来添加多个参数。

此标志允许你向链接器调用附加多个额外的参数。选项应以空格分隔。

尝试生成和链接否则不会被生成或链接的死代码。它接受以下值之一:

  • y, yes, on, true,或不带值:尝试保留死代码。
  • n, no, offfalse: 移除死代码(默认)。

此标志历史上用于帮助改进一些旧形式的代码覆盖度量。不推荐使用此标志。

windows-gnulinux-muslwasi 目标上,此标志控制链接器是使用 Rust 附带的库和对象,还是使用系统中的库和对象。它接受以下值之一:

  • 不带值:如果系统具有必需的工具,rustc 将使用启发式方法禁用自包含模式。
  • y, yes, on, true: 仅使用 Rust 附带的库/对象。
  • n, no, offfalse: 依赖用户或链接器提供非 Rust 的库/对象。

这允许在检测失败或用户想使用附带库时进行覆盖。

linker

此标志控制 rustc 调用哪个链接器来链接你的代码。它接受链接器可执行文件的路径。如果未指定此标志,链接器将根据目标推断。另请参阅 linker-flavor 标志,这是指定链接器的另一种方式。

linker-flavor

此标志控制 rustc 使用的链接器类型。如果使用 -C linker 标志指定了链接器,则链接器类型将从提供的值推断。如果未指定链接器,则使用链接器类型来确定要使用的链接器。每个 rustc 目标都默认使用某种链接器类型。有效选项有:

  • em: 使用 Emscripten emcc
  • gcc: 使用 cc 可执行文件,在许多系统上通常是 gcc 或 clang。
  • ld: 使用 ld 可执行文件。
  • msvc: 使用 Microsoft Visual Studio MSVC 的 link.exe 可执行文件。
  • wasm-ld: 使用 wasm-ld 可执行文件,它是 LLVM lld 的 WebAssembly 移植。
  • ld64.lld: 将 LLVM lld 可执行文件与 -flavor darwin 标志一起使用,用于 Apple 的 ld
  • ld.lld: 将 LLVM lld 可执行文件与 -flavor gnu 标志一起使用,用于 GNU binutils 的 ld
  • lld-link: 将 LLVM lld 可执行文件与 -flavor link 标志一起使用,用于 Microsoft 的 link.exe

linker-plugin-lto

此标志将 LTO 优化推迟到链接器。有关更多详细信息,请参阅链接器插件 LTO。它接受以下值之一:

  • y, yes, on, true,或不带值:启用链接器插件 LTO。
  • n, no, offfalse: 禁用链接器插件 LTO(默认)。
  • 链接器插件的路径。

更具体地说,此标志将导致编译器将其典型的目标文件输出替换为 LLVM 位码文件。例如,使用 -Clinker-plugin-lto 生成的 rlib 仍然包含 *.o 文件,但它们都是 LLVM 位码,而不是实际的机器代码。预期本机平台链接器能够加载这些 LLVM 位码文件并在链接时生成代码(通常在执行优化之后)。

请注意,rustc 也可以读取使用 -Clinker-plugin-lto 生成的目标文件。如果一个 rlib 仅在以后与 -Clto 编译一起使用,则可以传递 -Clinker-plugin-lto 来加快编译速度,并避免生成未使用的目标文件。

llvm-args

此标志可用于将参数列表直接传递给 LLVM。

列表必须用空格分隔。

传递 --help 查看选项列表。

lto

此标志控制 LLVM 是否使用 链接时优化 来生成更好的优化代码(使用全程序分析),代价是链接时间更长。它接受以下值之一:

  • y, yes, on, true, fat,或不带值:执行“fat”LTO,它尝试对依赖关系图中的所有 crate 执行优化。
  • n, no, off, false: 禁用 LTO。
  • thin: 执行“thin” LTO。这与“fat”类似,但运行时间大大减少,同时仍能达到与“fat”类似的性能提升。

如果未指定 -C lto,则编译器将尝试执行“thin local LTO”,它仅对本地 crate 的 codegen units 执行“thin”LTO。当未指定 -C lto 时,如果代码生成单元为 1 或优化被禁用(-C opt-level=0),则 LTO 被禁用。也就是说:

  • 未指定 -C lto
    • codegen-units=1: 禁用 LTO。
    • opt-level=0: 禁用 LTO。
  • 指定 -C lto
    • lto: 16 个代码生成单元,对跨 crate 执行 fat LTO。
    • codegen-units=1 + lto: 1 个代码生成单元,对跨 crate 执行 fat LTO。

另请参阅 linker-plugin-lto 了解跨语言 LTO。

metadata

此选项允许你控制用于符号名称修饰(symbol mangling)的元数据。它接受一个用空格分隔的字符串列表。修饰后的符号将包含元数据的哈希值。这可用于(例如)区分链接的同一 crate 的两个不同版本之间的符号。

no-prepopulate-passes

此标志告诉 Pass 管理器使用空的 Pass 列表,而不是通常预先填充的 Pass 列表。

no-redzone

此标志允许你禁用 red zone。它接受以下值之一:

  • y, yes, on, true,或不带值:禁用 red zone。
  • n, no, offfalse: 启用 red zone。

如果未指定此标志,默认行为取决于目标。

no-stack-check

此选项已弃用,不起作用。

no-vectorize-loops

此标志禁用循环向量化

no-vectorize-slp

此标志禁用使用超字级别并行的向量化。

opt-level

此标志控制优化级别。

  • 0: 无优化,同时启用 cfg(debug_assertions)(默认)。
  • 1: 基础优化。
  • 2: 一些优化。
  • 3: 所有优化。
  • s: 优化二进制文件大小。
  • z: 优化二进制文件大小,但同时关闭循环向量化。

注意:-O 标志-C opt-level=3 的别名。

默认值为 0

overflow-checks

此标志允许你控制运行时整数溢出的行为。启用溢出检查时,发生溢出将导致 panic。此标志接受以下值之一:

  • y, yes, on, true,或不带值:启用溢出检查。
  • n, no, offfalse: 禁用溢出检查。

如果未指定,仅当debug-assertions启用时才启用溢出检查,否则禁用。

panic

此选项允许你控制代码发生 panic 时会发生什么。

  • abort: 在 panic 时终止进程
  • unwind: 在 panic 时展开堆栈

如果未指定,默认行为取决于目标。

passes

此标志可用于向编译中添加额外的 LLVM Passes

列表必须用空格分隔。

另请参阅 no-prepopulate-passes 标志。

prefer-dynamic

默认情况下,rustc 倾向于静态链接依赖项。如果库同时存在静态和动态版本,此选项将指示如果可能,应使用动态链接。

存在一个内部算法来确定是否可以静态或动态链接依赖项。

此标志接受以下值之一:

  • y, yes, on, true,或不带值:优先使用动态链接。
  • n, no, offfalse: 优先使用静态链接(默认)。

profile-generate

此标志允许创建带插装的二进制文件,该文件将收集用于 Profile-Guided Optimization (PGO) 的剖析数据。此标志接受一个可选参数,该参数是带插装的二进制文件将发出收集到的数据的目录路径。有关更多信息,请参阅Profile-Guided Optimization一章。

profile-use

此标志指定用于 Profile-Guided Optimization (PGO) 的剖析数据文件。此标志接受一个必需参数,该参数是有效的 .profdata 文件的路径。有关更多信息,请参阅Profile-Guided Optimization一章。

relocation-model

此选项控制位置无关代码 (PIC) 的生成。

此选项支持的值有:

主要的重定位模型

  • static - 不可重定位的代码,机器指令可以使用绝对寻址模式。

  • pic - 完全可重定位的位置无关代码,机器指令需要使用相对寻址模式。
    等效于其他编译器中的“大写”-fPIC-fPIE 选项,具体取决于生成的 crate 类型。
    这是大多数受支持目标的默认模型。

  • pie - 位置无关可执行文件,可重定位代码,但不支持符号插入(使用 LD_PRELOAD 等按名称替换符号)。等效于其他编译器中的“大写”-fPIE 选项。pie 代码不能链接到共享库中(尝试这样做会收到链接错误)。

特殊的重定位模型

  • dynamic-no-pic - 可重定位的外部引用,不可重定位的代码。
    仅在 Darwin 上有意义,很少使用。
    如果 StackOverflow 告诉你使用此选项作为退出 PIC 或 PIE 的方法,请不要相信,请改用 -C relocation-model=static
  • ropi, rwpiropi-rwpi - 分别表示可重定位代码和只读数据、可重定位读写数据以及两者的组合。
    仅对某些嵌入式 ARM 目标有意义。
  • default - 重定位模型默认为当前目标。
    仅在覆盖命令行上之前显式指定的其他重定位模型时有意义。

也可以通过运行 rustc --print relocation-models 来发现支持的值。

链接时的影响

除了代码生成时的影响外,relocation-model 在链接时也有影响。

如果重定位模型是 pic 且当前目标支持位置无关可执行文件 (PIE),链接器将被指示 (-pie) 生成一个 PIE。
如果目标不支持位置无关可执行文件和静态链接可执行文件,则 -C target-feature=+crt-static 会“优先”于 -C relocation-model=pic,并且链接器将被指示 (-static) 生成一个静态链接但不位置无关的可执行文件。

relro-level

此标志控制启用哪种级别的 RELRO (Relocation Read-Only)。RELRO 是一种漏洞利用缓解技术,它使全局偏移表 (GOT) 只读。

此选项支持的值有:

  • off: 动态链接的函数是延迟解析的,GOT 是可写的。
  • partial: 动态链接的函数是延迟解析的,并写入 GOT 的过程链接表 (PLT) 部分 (.got.plt)。GOT 的非 PLT 部分 (.got) 被设为只读,并且两者都被移动以防止缓冲区溢出写入。
  • full: 动态链接的函数在程序执行开始时解析,全局偏移表 (.got/.got.plt) 被急切填充,然后设为只读。GOT 也被移动以防止缓冲区溢出写入。Full RELRO 会占用更多内存并增加进程启动时间。

在不支持 RELRO 的平台(不使用 ELF 二进制格式的目标,如 Windows 或 macOS)上,此标志被忽略。每个 rustc 目标都有自己的 RELRO 默认设置。rustc 在支持 RELRO 的平台上默认启用 Full RELRO。

remark

此标志允许你为优化 Pass 打印备注。

Pass 列表应以空格分隔。

all 将对每个 Pass 产生备注。

rpath

此标志控制是否启用 rpath。它接受以下值之一:

  • y, yes, on, true,或不带值:启用 rpath。
  • n, no, offfalse: 禁用 rpath(默认)。

save-temps

此标志控制编译期间生成的临时文件在编译完成后是否被删除。它接受以下值之一:

  • y, yes, on, true,或不带值:保存临时文件。
  • n, no, offfalse: 删除临时文件(默认)。

soft-float

此选项控制 rustc 是否生成在软件中模拟浮点指令的代码。它接受以下值之一:

  • y, yes, on, true,或不带值:使用软浮点。
  • n, no, offfalse: 使用硬件浮点(默认)。

split-debuginfo

此选项控制 rustc 生成的调试信息的“拆分调试信息”的输出。此选项的默认行为因平台而异,并非所有可能的值都在所有平台上有效。可能的值有:

  • off - 这是使用 ELF 二进制格式的平台和 windows-gnu(非 Windows MSVC 和非 macOS)的默认值。这通常意味着 DWARF 调试信息可以在最终的可执行文件的节中找到。Windows MSVC 不支持此选项。在 macOS 上,此选项会阻止最后执行 dsymutil 生成调试信息。

  • packed - 这是 Windows MSVC 和 macOS 的默认值。“packed”在此处表示所有调试信息被打包到一个独立于主可执行文件的文件中。在 Windows MSVC 上,这是一个 *.pdb 文件;在 macOS 上,这是一个 *.dSYM 文件夹;在其他平台(如 Linux)上,这是一个 *.dwp 文件。

  • unpacked - 这意味着每个编译单元(目标文件)的调试信息将位于单独的文件中。Windows MSVC 不支持此选项。在 macOS 上,这意味着原始目标文件将包含调试信息。在其他 Unix 平台上,这意味着 *.dwo 文件将包含调试信息。

请注意,Linux 和 Apple 平台支持所有三个选项,Windows-MSVC 支持 packed,而所有其他平台支持 off。尝试使用不支持的选项需要使用 nightly channel 并带有 -Z unstable-options 标志。

strip

选项 -C strip=val 控制在链接期间从二进制文件中剥离调试信息和类似的辅助数据。

此选项支持的值有:

  • none - 调试信息和符号未被修改。
  • debuginfo - 调试信息节和符号表节中的调试信息符号在链接时被剥离,并且不会被复制到生成的二进制文件中。这应该会使回溯基本保持完整,但可能会导致使用 gdb 或 lldb 等调试器无效。在 1.79 版本之前,这无意中禁用了在 MSVC 上生成 *.pdb 文件,导致符号缺失。
  • symbols - 与 debuginfo 相同,但符号表的其余部分也被剥离,具体取决于平台支持。在依赖此符号表进行回溯、性能分析等功能的平台上,这可能会对其产生负面影响,导致跟踪难以理解。可能与其他程序(例如 CLI 管道和开发工具)结合使用的程序,或者任何需要崩溃报告的功能,通常应避免使用 -Cstrip=symbols

请注意,在任何级别,移除调试信息仅会必然影响“友好”的自省功能。-Cstrip 不能作为一种有意义的安全或混淆措施来依赖,因为即使没有符号,反汇编器和反编译仍可以提取大量信息。

symbol-mangling-version

此选项控制用于将 Rust 项名称编码为目标代码和链接目的的名称修饰格式。

此选项支持的值有:

  • v0 — “v0”修饰方案。

如果未指定,默认值将使用编译器选择的默认值,该值将来可能会更改。

有关符号名称修饰和修饰格式的详细信息,请参阅符号名称修饰一章。

target-cpu

这指示 rustc 生成专门针对特定处理器的代码。

你可以运行 rustc --print target-cpus 查看可传递的有效选项以及当前构建目标的默认目标 CPU。每个目标都有一个默认的基础 CPU。特殊值包括:

  • 可以传递 native 来使用主机机器的处理器。
  • generic 指的是具有最小特性但现代优化的 LLVM 目标。

target-feature

不同的目标支持不同的特性;此标志允许你控制启用或禁用某个特性。每个特性应以 + 为前缀来启用,或以 - 为前缀来禁用。

来自多个 -C target-feature 选项的特性将被组合。
可以在单个选项中通过逗号分隔来指定多个特性 - -C target-feature=+x,-y
如果某个特性被指定多次,并且同时带有 +-,则后传递的值将覆盖先传递的值。
例如,-C target-feature=+x,-y,+z -Ctarget-feature=-x,+y 等效于 -C target-feature=-x,+y,+z

要查看有效选项和使用示例,请运行 rustc --print target-features

使用此标志是不安全的,可能导致未定义的运行时行为

另请参阅 target_feature 属性,用于按函数控制特性。

这也支持特性 +crt-static-crt-static 来控制静态 C 运行时链接

每个目标和 target-cpu 都有默认启用的特性集。

tune-cpu

这指示 rustc 专门针对特定处理器安排代码。这不影响兼容性(指令集或 ABI),但应使你的代码在所选 CPU 上稍微更高效。

有效选项与 target-cpu 的选项相同。默认是 None,LLVM 将其翻译为 target-cpu

这是一个不稳定选项。使用 -Z tune-cpu=machine 指定值。

由于 LLVM 的限制 (12.0.0-git9218f92),此选项目前仅对 x86 目标有效。