配置
配置提供了一种更改编译器设置的方法,从而影响诸如优化和调试符号之类的事项。
Cargo 有 4 个内置配置:dev
、release
、test
和 bench
。如果没有在命令行上指定配置,则会根据正在运行的命令自动选择配置。除了内置配置外,还可以指定自定义的用户定义配置。
可以使用 [profile]
表在 Cargo.toml
中更改配置设置。在每个命名配置中,可以使用键/值对来更改各个设置,如下所示
[profile.dev]
opt-level = 1 # Use slightly better optimizations.
overflow-checks = false # Disable integer overflow checks.
Cargo 只会查看工作区根目录下的 Cargo.toml
清单中的配置设置。依赖项中定义的配置设置将被忽略。
此外,可以从 配置定义中覆盖配置。在配置文件或环境变量中指定配置将覆盖 Cargo.toml
中的设置。
配置设置
以下是可以再配置中控制的设置列表。
opt-level
opt-level
设置控制 -C opt-level
标志,该标志控制优化级别。更高的优化级别可能会产生更快的运行时代码,但会增加编译时间。更高的级别也可能会更改和重新排列已编译的代码,这可能会使其更难与调试器一起使用。
有效的选项为
0
:不进行优化1
:基本优化2
:一些优化3
:所有优化"s"
:为二进制大小进行优化"z"
:为二进制大小进行优化,但也关闭循环向量化。
建议尝试不同的级别,以找到适合您项目的平衡点。可能会出现令人惊讶的结果,例如级别 3
比 2
慢,或者 "s"
和 "z"
级别不一定更小。您可能还希望随着 rustc
新版本的优化行为发生变化而重新评估您的设置。
另请参阅 Profile Guided Optimization,了解更高级的优化技术。
debug
debug
设置控制 -C debuginfo
标志,该标志控制编译后的二进制文件中包含的调试信息的数量。
有效的选项为
0
、false
或"none"
:根本没有调试信息,release
的默认值"line-directives-only"
:仅限行信息指令。对于 nvptx* 目标,这会启用分析。对于其他用例,line-tables-only
是更好、更兼容的选择。"line-tables-only"
:仅限行表。生成用于回溯的最小调试信息,其中包含文件名/行号信息,但不包含其他任何信息,即没有变量或函数参数信息。1
或"limited"
:不包含类型或变量级别信息的调试信息。生成比line-tables-only
更详细的模块级信息。2
、true
或"full"
:完整的调试信息,dev
的默认值
有关每个选项执行的操作的更多信息,请参阅 rustc
关于 debuginfo 的文档。
您可能还希望根据您的需要配置 split-debuginfo
选项。
MSRV:
none
、limited
、full
、line-directives-only
和line-tables-only
需要 1.71
split-debuginfo
split-debuginfo
设置控制 -C split-debuginfo
标志,该标志控制调试信息(如果生成)是放置在可执行文件本身中还是放置在可执行文件旁边。
此选项是一个字符串,可接受的值与 编译器接受的值相同。对于启用了调试信息的配置,此选项在 macOS 上的默认值为 unpacked
。否则,此选项的默认值如rustc 文档中所述,并且是平台特定的。某些选项仅在nightly 通道上可用。一旦执行了更多测试并且 DWARF 的支持稳定下来,Cargo 默认值可能会在将来发生变化。
请注意,Cargo 和 rustc 对于此选项具有不同的默认值。此选项的存在是为了允许 Cargo 尝试不同的标志组合,从而提供更好的调试和开发人员体验。
strip
strip
选项控制 -C strip
标志,该标志指示 rustc 从二进制文件中删除符号或调试信息。可以像这样启用它
[package]
# ...
[profile.release]
strip = "debuginfo"
strip
的可能字符串值为 "none"
、"debuginfo"
和 "symbols"
。默认值为 "none"
。
您还可以使用布尔值 true
或 false
配置此选项。strip = true
等同于 strip = "symbols"
。strip = false
等同于 strip = "none"
,并完全禁用 strip
。
debug-assertions
debug-assertions
设置控制 -C debug-assertions
标志,该标志打开或关闭 cfg(debug_assertions)
条件编译。调试断言旨在包含仅在调试/开发版本中可用的运行时验证。这些可能是发布版本中过于昂贵或不受欢迎的内容。调试断言启用标准库中的 debug_assert!
宏。
有效的选项为
true
:已启用false
:已禁用
overflow-checks
overflow-checks
设置控制 -C overflow-checks
标志,该标志控制 运行时整数溢出的行为。启用溢出检查后,发生溢出时将发生恐慌。
有效的选项为
true
:已启用false
:已禁用
lto
lto
设置控制 rustc
的 -C lto
、-C linker-plugin-lto
和 -C embed-bitcode
选项,这些选项控制 LLVM 的 链接时优化。LTO 可以通过使用整个程序分析来生成更好的优化代码,但会增加链接时间。
有效的选项为
false
:执行“瘦局部 LTO”,该 LTO 仅在其 代码生成单元上对本地 crate 执行“瘦”LTO。如果代码生成单元为 1 或 opt-level 为 0,则不执行 LTO。true
或"fat"
:执行“胖”LTO,它会尝试在依赖关系图中的所有 crate 上执行优化。"thin"
:执行 “瘦”LTO。这与“胖”类似,但运行时间大大减少,同时仍然可以实现与“胖”类似的性能提升。"off"
:禁用 LTO。
如果您对跨语言 LTO 感兴趣,请参阅 linker-plugin-lto 章节。Cargo 尚不支持本机 LTO,但可以通过 RUSTFLAGS
执行。
panic
panic
设置控制 -C panic
标志,该标志控制要使用的 panic 策略。
有效的选项为
"unwind"
:在发生 panic 时展开堆栈。"abort"
:在发生 panic 时终止进程。
设置为 "unwind"
时,实际值取决于目标平台的默认值。例如,NVPTX 平台不支持展开,因此始终使用 "abort"
。
测试、基准测试、构建脚本和 proc 宏会忽略 panic
设置。rustc
测试框架当前需要 unwind
行为。请参阅 panic-abort-tests
不稳定标志,该标志启用 abort
行为。
此外,当使用 abort
策略并构建测试时,所有依赖项也将被强制使用 unwind
策略进行构建。
incremental
incremental
设置控制 -C incremental
标志,该标志控制是否启用增量编译。增量编译会导致 rustc
将其他信息保存到磁盘,这些信息将在重新编译 crate 时重用,从而缩短重新编译时间。其他信息存储在 target
目录中。
有效的选项为
true
:已启用false
:已禁用
增量编译仅用于工作区成员和“路径”依赖项。
可以使用 CARGO_INCREMENTAL
环境变量或 build.incremental
配置变量全局覆盖增量值。
codegen-units
codegen-units
设置控制 -C codegen-units
标志,该标志控制 crate 将被拆分为多少个“代码生成单元”。更多的代码生成单元允许并行处理 crate 的更多部分,从而可能缩短编译时间,但可能会生成较慢的代码。
此选项采用大于 0 的整数。
对于增量构建,默认值为 256,对于非增量构建,默认值为 16。
rpath
rpath
设置控制 -C rpath
标志,该标志控制是否启用 rpath
。
默认配置
dev
dev
配置用于正常的开发和调试。它是诸如 cargo build
之类的构建命令的默认值,并且用于 cargo install --debug
。
dev
配置的默认设置为
[profile.dev]
opt-level = 0
debug = true
split-debuginfo = '...' # Platform-specific.
strip = "none"
debug-assertions = true
overflow-checks = true
lto = false
panic = 'unwind'
incremental = true
codegen-units = 256
rpath = false
release
release
配置旨在用于发布和生产中使用的优化过的工件。当使用 --release
标志时,将使用此配置,并且它是 cargo install
的默认值。
release
配置的默认设置为
[profile.release]
opt-level = 3
debug = false
split-debuginfo = '...' # Platform-specific.
strip = "none"
debug-assertions = false
overflow-checks = false
lto = false
panic = 'unwind'
incremental = false
codegen-units = 16
rpath = false
test
test
配置是 cargo test
使用的默认配置。test
配置继承 dev
配置的设置。
bench
bench
配置是 cargo bench
使用的默认配置。bench
配置继承 release
配置的设置。
构建依赖项
为了快速编译,默认情况下,所有配置都不会优化构建依赖项(构建脚本、proc 宏及其依赖项),并且当构建依赖项不作为运行时依赖项使用时,会避免计算调试信息。构建覆盖的默认设置为
[profile.dev.build-override]
opt-level = 0
codegen-units = 256
debug = false # when possible
[profile.release.build-override]
opt-level = 0
codegen-units = 256
但是,如果在运行构建依赖项时发生错误,则在需要时打开完整的调试信息将改善回溯和可调试性
debug = true
否则,构建依赖项会继承正在使用的活动配置中的设置,如 配置选择中所述。
自定义配置
除了内置的配置文件外,还可以定义其他自定义配置文件。这些配置文件对于设置多个工作流程和构建模式可能很有用。定义自定义配置文件时,必须指定 inherits
键来指定当未指定设置时,自定义配置文件从哪个配置文件继承设置。
例如,假设您想比较普通的发布版本与带有 LTO 优化的发布版本,您可以在 Cargo.toml
中指定类似以下内容:
[profile.release-lto]
inherits = "release"
lto = true
然后可以使用 --profile
标志来选择此自定义配置文件
cargo build --profile release-lto
每个配置文件的输出将放置在 target
目录中与该配置文件名称相同的目录中。如上面的示例所示,输出将进入 target/release-lto
目录。
配置文件选择
使用的配置文件取决于命令、命令行标志(如 --release
或 --profile
)以及包(在 覆盖 的情况下)。如果未指定,则默认配置文件为
命令 | 默认配置文件 |
---|---|
cargo run 、cargo build 、cargo check 、cargo rustc | dev 配置文件 |
cargo test | test 配置文件 |
cargo bench | bench 配置文件 |
cargo install | release 配置文件 |
您可以使用 --profile=NAME
选项切换到不同的配置文件,这将使用给定的配置文件。--release
标志等同于 --profile=release
。
选定的配置文件适用于所有 Cargo 目标,包括 库、二进制文件、示例、测试 和 基准测试。
可以使用 覆盖 来指定特定包的配置文件,如下所述。
覆盖
可以为特定的包和构建时 crate 覆盖配置文件设置。要覆盖特定包的设置,请使用 package
表来更改命名包的设置
# The `foo` package will use the -Copt-level=3 flag.
[profile.dev.package.foo]
opt-level = 3
包名称实际上是 包 ID 规范,因此您可以使用诸如 [profile.dev.package."foo:2.1.0"]
之类的语法来定位包的各个版本。
要覆盖所有依赖项(但不包括任何工作区成员)的设置,请使用 "*"
包名称
# Set the default for dependencies.
[profile.dev.package."*"]
opt-level = 2
要覆盖构建脚本、过程宏及其依赖项的设置,请使用 build-override
表
# Set the settings for build scripts and proc-macros.
[profile.dev.build-override]
opt-level = 3
注意:当一个依赖项既是普通依赖项又是构建依赖项时,如果没有指定
--target
,Cargo 会尝试仅构建一次。当使用build-override
时,依赖项可能需要构建两次,一次作为普通依赖项,一次使用覆盖的构建设置。这可能会增加初始构建时间。
使用哪个值的优先级按以下顺序进行(首先匹配的胜出)
[profile.dev.package.name]
— 命名包。[profile.dev.package."*"]
— 对于任何非工作区成员。[profile.dev.build-override]
— 仅用于构建脚本、过程宏及其依赖项。[profile.dev]
—Cargo.toml
中的设置。- Cargo 中内置的默认值。
覆盖不能指定 panic
、lto
或 rpath
设置。
覆盖和泛型
实例化泛型代码的位置会影响用于该泛型代码的优化设置。当使用配置文件覆盖来更改特定 crate 的优化级别时,这可能会导致细微的交互。如果您尝试提高定义泛型函数的依赖项的优化级别,则当在本地 crate 中使用这些泛型函数时,它们可能不会被优化。这是因为代码可能在实例化它的 crate 中生成,因此可能会使用该 crate 的优化设置。
例如,nalgebra 是一个定义向量和矩阵的库,大量使用了泛型参数。如果您的本地代码定义了诸如 Vector4<f64>
之类的具体 nalgebra 类型并使用它们的方法,则将在您的 crate 中实例化和构建相应的 nalgebra 代码。因此,如果您尝试使用配置文件覆盖来提高 nalgebra
的优化级别,则可能不会导致更快的性能。
更复杂的是,rustc
有一些优化,它会尝试在 crate 之间共享单态化的泛型。如果 opt-level 为 2 或 3,则 crate 将不会使用来自其他 crate 的单态化泛型,也不会导出本地定义的单态化项以与其他 crate 共享。在尝试优化开发中的依赖项时,请考虑尝试 opt-level 1,它将应用一些优化,同时仍然允许共享单态化项。