From 287fb2aceb0ba5e4d427b1af0fe7e97bec17f283 Mon Sep 17 00:00:00 2001 From: Alexis <120563837+alexisart@users.noreply.github.com> Date: Thu, 25 May 2023 15:12:07 -0400 Subject: [PATCH] RUSTC_AR --- src/cargo/core/compiler/custom_build.rs | 7 + src/cargo/util/config/target.rs | 5 + .../src/reference/environment-variables.md | 5 + tests/testsuite/build_script.rs | 285 ++++++++++++++++++ 4 files changed, 302 insertions(+) diff --git a/src/cargo/core/compiler/custom_build.rs b/src/cargo/core/compiler/custom_build.rs index 01890e54291..70bfbcd5c50 100644 --- a/src/cargo/core/compiler/custom_build.rs +++ b/src/cargo/core/compiler/custom_build.rs @@ -265,6 +265,13 @@ fn build_work(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult { ); } + if let Some(ar) = &bcx.target_data.target_config(unit.kind).ar { + cmd.env( + "RUSTC_AR", + ar.val.clone().resolve_program(bcx.config), + ); + } + if let Some(links) = unit.pkg.manifest().links() { cmd.env("CARGO_MANIFEST_LINKS", links); } diff --git a/src/cargo/util/config/target.rs b/src/cargo/util/config/target.rs index a7f2f3ef269..c6bcbf0bdd4 100644 --- a/src/cargo/util/config/target.rs +++ b/src/cargo/util/config/target.rs @@ -28,6 +28,8 @@ pub struct TargetConfig { pub rustflags: OptValue, /// The path of the linker for this target. pub linker: OptValue, + /// The path of the archiver for this target. + pub ar: OptValue, /// Build script override for the given library name. /// /// Any package with a `links` value for the given library name will skip @@ -96,6 +98,7 @@ pub(super) fn load_host_triple(config: &Config, triple: &str) -> CargoResult CargoResult let runner: OptValue = config.get(&format!("{}.runner", prefix))?; let rustflags: OptValue = config.get(&format!("{}.rustflags", prefix))?; let linker: OptValue = config.get(&format!("{}.linker", prefix))?; + let ar: OptValue = config.get(&format!("{}.ar", prefix))?; // Links do not support environment variables. let target_key = ConfigKey::from_str(prefix); let links_overrides = match config.get_table(&target_key)? { @@ -126,6 +130,7 @@ fn load_config_table(config: &Config, prefix: &str) -> CargoResult runner, rustflags, linker, + ar, links_overrides, }) } diff --git a/src/doc/src/reference/environment-variables.md b/src/doc/src/reference/environment-variables.md index 353742877a4..b1eec076aa8 100644 --- a/src/doc/src/reference/environment-variables.md +++ b/src/doc/src/reference/environment-variables.md @@ -381,6 +381,11 @@ let out_dir = env::var("OUT_DIR").unwrap(); changed by editing `.cargo/config.toml`; see the documentation about [cargo configuration][cargo-config] for more information. +* `RUSTC_AR` --- The path to the linkerar binary that Cargo has resolved to use + for the current target, if specified. The ar can be + changed by editing `.cargo/config.toml`; see the documentation + about [cargo configuration][cargo-config] for more + information. * `CARGO_ENCODED_RUSTFLAGS` --- extra flags that Cargo invokes `rustc` with, separated by a `0x1f` character (ASCII Unit Separator). See [`build.rustflags`]. Note that since Rust 1.55, `RUSTFLAGS` is removed from diff --git a/tests/testsuite/build_script.rs b/tests/testsuite/build_script.rs index 80a24960edd..63697379eca 100644 --- a/tests/testsuite/build_script.rs +++ b/tests/testsuite/build_script.rs @@ -226,6 +226,7 @@ fn custom_build_env_vars() { assert!(env::var("RUSTC_WORKSPACE_WRAPPER").is_err()); assert!(env::var("RUSTC_LINKER").is_err()); + assert!(env::var("RUSTC_AR").is_err()); assert!(env::var("RUSTFLAGS").is_err()); let rustflags = env::var("CARGO_ENCODED_RUSTFLAGS").unwrap(); @@ -566,6 +567,7 @@ fn custom_build_invalid_host_config_feature_flag() { r#" [target.{}] linker = "/path/to/linker" + ar = "/path/to/ar" "#, target ), @@ -732,6 +734,289 @@ fn custom_build_env_var_rustc_linker_cross_arch_host() { .run(); } +#[cargo_test] +fn custom_build_env_var_rustc_ar() { + if cross_compile::disabled() { + return; + } + let target = cross_compile::alternate(); + let p = project() + .file( + ".cargo/config", + &format!( + r#" + [target.{}] + ar = "/path/to/ar" + "#, + target + ), + ) + .file( + "build.rs", + r#" + use std::env; + + fn main() { + assert!(env::var("RUSTC_AR").unwrap().ends_with("/path/to/ar")); + } + "#, + ) + .file("src/lib.rs", "") + .build(); + + // no crate type set => ar never called => build succeeds if and + // only if build.rs succeeds, despite ar binary not existing. + p.cargo("build --target").arg(&target).run(); +} + +// #[cargo_test] +// fn custom_build_env_var_rustc_ar_bad_host_target() { +// let target = rustc_host(); +// let p = project() +// .file( +// ".cargo/config", +// &format!( +// r#" +// [target.{}] +// ar = "/path/to/ar" +// "#, +// target +// ), +// ) +// .file("build.rs", "fn main() {}") +// .file("src/lib.rs", "") +// .build(); + +// // build.rs should fail since host == target when no target is set +// p.cargo("build --verbose") +// .with_status(101) +// .with_stderr_contains( +// "\ +// [COMPILING] foo v0.0.1 ([CWD]) +// [RUNNING] `rustc --crate-name build_script_build build.rs [..]--crate-type bin [..]-C ar=[..]/path/to/ar [..]` +// [ERROR] ar `[..]/path/to/ar` not found +// " +// ) +// .run(); +// } + +#[cargo_test] +fn custom_build_env_var_rustc_ar_host_target() { + let target = rustc_host(); + let p = project() + .file( + ".cargo/config", + &format!( + r#" + target-applies-to-host = false + [target.{}] + ar = "/path/to/ar" + "#, + target + ), + ) + .file( + "build.rs", + r#" + use std::env; + + fn main() { + assert!(env::var("RUSTC_AR").unwrap().ends_with("/path/to/ar")); + } + "#, + ) + .file("src/lib.rs", "") + .build(); + + // no crate type set => ar never called => build succeeds if and + // only if build.rs succeeds, despite ar binary not existing. + p.cargo("build -Z target-applies-to-host --target") + .arg(&target) + .masquerade_as_nightly_cargo(&["target-applies-to-host"]) + .run(); +} + +#[cargo_test] +fn custom_build_env_var_rustc_ar_host_target_env() { + let target = rustc_host(); + let p = project() + .file( + ".cargo/config", + &format!( + r#" + [target.{}] + ar = "/path/to/ar" + "#, + target + ), + ) + .file( + "build.rs", + r#" + use std::env; + + fn main() { + assert!(env::var("RUSTC_AR").unwrap().ends_with("/path/to/ar")); + } + "#, + ) + .file("src/lib.rs", "") + .build(); + + // no crate type set => ar never called => build succeeds if and + // only if build.rs succeeds, despite ar binary not existing. + p.cargo("build -Z target-applies-to-host --target") + .env("CARGO_TARGET_APPLIES_TO_HOST", "false") + .arg(&target) + .masquerade_as_nightly_cargo(&["target-applies-to-host"]) + .run(); +} + +// #[cargo_test] +// fn custom_build_ar_host_target_with_bad_host_config() { +// let target = rustc_host(); +// let p = project() +// .file( +// ".cargo/config", +// &format!( +// r#" +// [host] +// ar = "/path/to/host/ar" +// [target.{}] +// ar = "/path/to/target/ar" +// "#, +// target +// ), +// ) +// .file("build.rs", "fn main() {}") +// .file("src/lib.rs", "") +// .build(); + +// // build.rs should fail due to bad host ar being set +// p.cargo("build -Z target-applies-to-host -Z host-config --verbose --target") +// .arg(&target) +// .masquerade_as_nightly_cargo(&["target-applies-to-host", "host-config"]) +// .with_status(101) +// .with_stderr_contains( +// "\ +// [COMPILING] foo v0.0.1 ([CWD]) +// [RUNNING] `rustc --crate-name build_script_build build.rs [..]--crate-type bin [..]-C ar=[..]/path/to/host/ar [..]` +// [ERROR] ar `[..]/path/to/host/ar` not found +// " +// ) +// .run(); +// } + +// #[cargo_test] +// fn custom_build_ar_bad_host() { +// let target = rustc_host(); +// let p = project() +// .file( +// ".cargo/config", +// &format!( +// r#" +// [host] +// ar = "/path/to/host/ar" +// [target.{}] +// ar = "/path/to/target/ar" +// "#, +// target +// ), +// ) +// .file("build.rs", "fn main() {}") +// .file("src/lib.rs", "") +// .build(); + +// // build.rs should fail due to bad host ar being set +// p.cargo("build -Z target-applies-to-host -Z host-config --verbose --target") +// .arg(&target) +// .masquerade_as_nightly_cargo(&["target-applies-to-host", "host-config"]) +// .with_status(101) +// .with_stderr_contains( +// "\ +// [COMPILING] foo v0.0.1 ([CWD]) +// [RUNNING] `rustc --crate-name build_script_build build.rs [..]--crate-type bin [..]-C ar=[..]/path/to/host/ar [..]` +// [ERROR] ar `[..]/path/to/host/ar` not found +// " +// ) +// .run(); +// } + +// #[cargo_test] +// fn custom_build_ar_bad_host_with_arch() { +// let target = rustc_host(); +// let p = project() +// .file( +// ".cargo/config", +// &format!( +// r#" +// [host] +// ar = "/path/to/host/ar" +// [host.{}] +// ar = "/path/to/host/arch/ar" +// [target.{}] +// ar = "/path/to/target/ar" +// "#, +// target, target +// ), +// ) +// .file("build.rs", "fn main() {}") +// .file("src/lib.rs", "") +// .build(); + +// // build.rs should fail due to bad host ar being set +// p.cargo("build -Z target-applies-to-host -Z host-config --verbose --target") +// .arg(&target) +// .masquerade_as_nightly_cargo(&["target-applies-to-host", "host-config"]) +// .with_status(101) +// .with_stderr_contains( +// "\ +// [COMPILING] foo v0.0.1 ([CWD]) +// [RUNNING] `rustc --crate-name build_script_build build.rs [..]--crate-type bin [..]-C ar=[..]/path/to/host/arch/ar [..]` +// [ERROR] ar `[..]/path/to/host/arch/ar` not found +// " +// ) +// .run(); +// } + +#[cargo_test] +fn custom_build_env_var_rustc_ar_cross_arch_host() { + let target = rustc_host(); + let cross_target = cross_compile::alternate(); + let p = project() + .file( + ".cargo/config", + &format!( + r#" + [host.{}] + ar = "/path/to/host/arch/ar" + [target.{}] + ar = "/path/to/target/ar" + "#, + cross_target, target + ), + ) + .file( + "build.rs", + r#" + use std::env; + + fn main() { + assert!(env::var("RUSTC_AR").unwrap().ends_with("/path/to/target/ar")); + } + "#, + ) + .file("src/lib.rs", "") + .build(); + + // build.rs should be built fine since cross target != host target. + // assertion should succeed since it's still passed the target ar + p.cargo("build -Z target-applies-to-host -Z host-config --verbose --target") + .arg(&target) + .masquerade_as_nightly_cargo(&["target-applies-to-host", "host-config"]) + .run(); +} + #[cargo_test] fn custom_build_linker_bad_cross_arch_host() { let target = rustc_host();