Skip to content

Commit

Permalink
RUSTC_AR
Browse files Browse the repository at this point in the history
  • Loading branch information
lexi-the-cute committed May 25, 2023
1 parent 6ec9649 commit 287fb2a
Show file tree
Hide file tree
Showing 4 changed files with 302 additions and 0 deletions.
7 changes: 7 additions & 0 deletions src/cargo/core/compiler/custom_build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,13 @@ fn build_work(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Job> {
);
}

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);
}
Expand Down
5 changes: 5 additions & 0 deletions src/cargo/util/config/target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ pub struct TargetConfig {
pub rustflags: OptValue<StringList>,
/// The path of the linker for this target.
pub linker: OptValue<ConfigRelativePath>,
/// The path of the archiver for this target.
pub ar: OptValue<ConfigRelativePath>,
/// Build script override for the given library name.
///
/// Any package with a `links` value for the given library name will skip
Expand Down Expand Up @@ -96,6 +98,7 @@ pub(super) fn load_host_triple(config: &Config, triple: &str) -> CargoResult<Tar
runner: None,
rustflags: None,
linker: None,
ar: None,
links_overrides: BTreeMap::new(),
})
}
Expand All @@ -116,6 +119,7 @@ fn load_config_table(config: &Config, prefix: &str) -> CargoResult<TargetConfig>
let runner: OptValue<PathAndArgs> = config.get(&format!("{}.runner", prefix))?;
let rustflags: OptValue<StringList> = config.get(&format!("{}.rustflags", prefix))?;
let linker: OptValue<ConfigRelativePath> = config.get(&format!("{}.linker", prefix))?;
let ar: OptValue<ConfigRelativePath> = 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)? {
Expand All @@ -126,6 +130,7 @@ fn load_config_table(config: &Config, prefix: &str) -> CargoResult<TargetConfig>
runner,
rustflags,
linker,
ar,
links_overrides,
})
}
Expand Down
5 changes: 5 additions & 0 deletions src/doc/src/reference/environment-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
285 changes: 285 additions & 0 deletions tests/testsuite/build_script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -566,6 +567,7 @@ fn custom_build_invalid_host_config_feature_flag() {
r#"
[target.{}]
linker = "/path/to/linker"
ar = "/path/to/ar"
"#,
target
),
Expand Down Expand Up @@ -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();
Expand Down

0 comments on commit 287fb2a

Please sign in to comment.