如何在 Cargo.toml 中创建目标特定配置文件?
How to create target specific profile in Cargo.toml?
我想在 cfg(target_os = "ios")
处于活动状态时为我的图书馆指定一个单独的 [profile.release]
。我试过这个:
[profile.'cfg(not(target_os = "ios"))'.release]
lto = true # Use link-time optimization.
[profile.'cfg(target_os = "ios")'.release]
lto = true # Use link-time optimization.
opt-level = "z" # Mobile devices are fast enough. Optimize for size instead.
strip = "symbols" # Not relevant for windows.
然而,当我现在尝试构建我的项目/工作区时,出现以下错误:
error: failed to parse manifest at `/path/to/Cargo.toml`
Caused by:
invalid character `(` in profile name `cfg(not(target_os = "ios"))`
Allowed characters are letters, numbers, underscore, and hyphen.
这是意料之中的,因为根据 documentation 只允许 [profile.<name>]
。
是否有任何方法可以实现所需的行为?
P.S。如果需要,完整的目标名称将是 aarch64-apple-ios
。
这是在 issue #4897, Per-target profiles? 中提出的要求,但尚未实施。
同时,您可以使用脚本检查目标并设置 environment variables 来覆盖配置(例如,设置 CARGO_PROFILE_RELEASE_LTO
或 CARGO_PROFILE_RELEASE_OPT_LEVEL
),然后用它们调用 Cargo .
这是一个例子,来自users.rust-lang.org - How to modify profile.release only for a target?
在名为 e.g. 的工作区中创建一个二进制文件custom_build
。在 custom_build/src/main.rs
中输入:
use std::env;
use std::process::Command;
fn main() {
let mut cargo = Command::new(env::var_os("CARGO").unwrap());
cargo.env("CARGO_CUSTOM_BUILD", "1"); // So we can disallow regular builds, to prevent mistakes
cargo.args(env::args_os().skip(1));
// You can determine the target OS by various way, but providing it manually to the build script is the simplest.
let for_ios = env::var("build_ios").is_ok();
if for_ios {
cargo.env("CARGO_PROFILE_RELEASE_LTO", "true");
cargo.env("CARGO_PROFILE_RELEASE_OPT_LEVEL", "z");
cargo.env("CARGO_PROFILE_RELEASE_STRIP", "symbols");
} else {
cargo.env("CARGO_PROFILE_RELEASE_LTO", "true");
}
let cargo_succeeded = cargo.status().ok().map_or(false, |status| status.success());
if !cargo_succeeded {
std::process::exit(1);
}
}
然后你可以创建一个build.rs文件来手动防止运行 cargo
:
use std::env;
fn main() {
if !env::var("CARGO_CUSTOM_BUILD").ok().map_or(false, |s| s == "1") {
panic!("Do not run `cargo ...`, run `cargo custom_build ...` instead")
}
}
我想在 cfg(target_os = "ios")
处于活动状态时为我的图书馆指定一个单独的 [profile.release]
。我试过这个:
[profile.'cfg(not(target_os = "ios"))'.release]
lto = true # Use link-time optimization.
[profile.'cfg(target_os = "ios")'.release]
lto = true # Use link-time optimization.
opt-level = "z" # Mobile devices are fast enough. Optimize for size instead.
strip = "symbols" # Not relevant for windows.
然而,当我现在尝试构建我的项目/工作区时,出现以下错误:
error: failed to parse manifest at `/path/to/Cargo.toml`
Caused by:
invalid character `(` in profile name `cfg(not(target_os = "ios"))`
Allowed characters are letters, numbers, underscore, and hyphen.
这是意料之中的,因为根据 documentation 只允许 [profile.<name>]
。
是否有任何方法可以实现所需的行为?
P.S。如果需要,完整的目标名称将是 aarch64-apple-ios
。
这是在 issue #4897, Per-target profiles? 中提出的要求,但尚未实施。
同时,您可以使用脚本检查目标并设置 environment variables 来覆盖配置(例如,设置 CARGO_PROFILE_RELEASE_LTO
或 CARGO_PROFILE_RELEASE_OPT_LEVEL
),然后用它们调用 Cargo .
这是一个例子,来自users.rust-lang.org - How to modify profile.release only for a target?
在名为 e.g. 的工作区中创建一个二进制文件custom_build
。在 custom_build/src/main.rs
中输入:
use std::env;
use std::process::Command;
fn main() {
let mut cargo = Command::new(env::var_os("CARGO").unwrap());
cargo.env("CARGO_CUSTOM_BUILD", "1"); // So we can disallow regular builds, to prevent mistakes
cargo.args(env::args_os().skip(1));
// You can determine the target OS by various way, but providing it manually to the build script is the simplest.
let for_ios = env::var("build_ios").is_ok();
if for_ios {
cargo.env("CARGO_PROFILE_RELEASE_LTO", "true");
cargo.env("CARGO_PROFILE_RELEASE_OPT_LEVEL", "z");
cargo.env("CARGO_PROFILE_RELEASE_STRIP", "symbols");
} else {
cargo.env("CARGO_PROFILE_RELEASE_LTO", "true");
}
let cargo_succeeded = cargo.status().ok().map_or(false, |status| status.success());
if !cargo_succeeded {
std::process::exit(1);
}
}
然后你可以创建一个build.rs文件来手动防止运行 cargo
:
use std::env;
fn main() {
if !env::var("CARGO_CUSTOM_BUILD").ok().map_or(false, |s| s == "1") {
panic!("Do not run `cargo ...`, run `cargo custom_build ...` instead")
}
}