|
1 | 1 | //! Type definitions for the result of a compilation.
|
2 | 2 |
|
3 |
| -use std::collections::{BTreeSet, HashMap}; |
| 3 | +use std::collections::BTreeSet; |
| 4 | +use std::collections::HashMap; |
| 5 | +use std::collections::HashSet; |
4 | 6 | use std::ffi::{OsStr, OsString};
|
5 | 7 | use std::path::PathBuf;
|
| 8 | +use std::sync::LazyLock; |
6 | 9 |
|
7 | 10 | use cargo_platform::CfgExpr;
|
8 | 11 | use cargo_util::{paths, ProcessBuilder};
|
@@ -529,3 +532,88 @@ fn target_linker(bcx: &BuildContext<'_, '_>, kind: CompileKind) -> CargoResult<O
|
529 | 532 | }
|
530 | 533 | Ok(matching_linker.map(|(_k, linker)| linker.val.clone().resolve_program(bcx.gctx)))
|
531 | 534 | }
|
| 535 | + |
| 536 | +/// This tracks environment variables Cargo sets to rustc when building a crate. |
| 537 | +/// |
| 538 | +/// This only inclues variables with statically known keys. |
| 539 | +/// For environment variable keys that vary like `CARG_BIN_EXE_<name>` or |
| 540 | +/// `-Zbindeps` related env vars, we compare only their prefixes to determine |
| 541 | +/// if they are internal. |
| 542 | +/// See [`is_env_set_by_cargo`] and |
| 543 | +/// <https://doc.rust-lang.org/nightly/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-crates>. |
| 544 | +static ENV_VARS_SET_FOR_CRATES: LazyLock<HashSet<&'static str>> = LazyLock::new(|| { |
| 545 | + HashSet::from_iter([ |
| 546 | + crate::CARGO_ENV, |
| 547 | + "CARGO_MANIFEST_DIR", |
| 548 | + "CARGO_MANIFEST_PATH", |
| 549 | + "CARGO_PKG_VERSION", |
| 550 | + "CARGO_PKG_VERSION_MAJOR", |
| 551 | + "CARGO_PKG_VERSION_MINOR", |
| 552 | + "CARGO_PKG_VERSION_PATCH", |
| 553 | + "CARGO_PKG_VERSION_PRE", |
| 554 | + "CARGO_PKG_AUTHORS", |
| 555 | + "CARGO_PKG_NAME", |
| 556 | + "CARGO_PKG_DESCRIPTION", |
| 557 | + "CARGO_PKG_HOMEPAGE", |
| 558 | + "CARGO_PKG_REPOSITORY", |
| 559 | + "CARGO_PKG_LICENSE", |
| 560 | + "CARGO_PKG_LICENSE_FILE", |
| 561 | + "CARGO_PKG_RUST_VERSION", |
| 562 | + "CARGO_PKG_README", |
| 563 | + "CARGO_CRATE_NAME", |
| 564 | + "CARGO_BIN_NAME", |
| 565 | + "OUT_DIR", |
| 566 | + "CARGO_PRIMARY_PACKAGE", |
| 567 | + "CARGO_TARGET_TMPDIR", |
| 568 | + paths::dylib_path_envvar(), |
| 569 | + ]) |
| 570 | +}); |
| 571 | + |
| 572 | +/// Asserts if the given env vars are controlled by Cargo. |
| 573 | +/// |
| 574 | +/// This is only for reminding Cargo developer to keep newly added environment |
| 575 | +/// variables in sync with [`ENV_VARS_SET_FOR_CRATES`]. |
| 576 | +#[cfg(debug_assertions)] |
| 577 | +pub(crate) fn assert_only_envs_set_by_cargo<'a>( |
| 578 | + keys: impl Iterator<Item = impl AsRef<str>>, |
| 579 | + env_config: &HashMap<String, OsString>, |
| 580 | +) { |
| 581 | + for key in keys { |
| 582 | + let key = key.as_ref(); |
| 583 | + // When running Cargo's test suite, |
| 584 | + // we're fine if it is from the `[env]` table |
| 585 | + if env_config.contains_key(key) { |
| 586 | + continue; |
| 587 | + } |
| 588 | + assert!( |
| 589 | + is_env_set_by_cargo(key), |
| 590 | + "`{key}` is not tracked as an environment variable set by Cargo\n\ |
| 591 | + Add it to `ENV_VARS_SET_FOR_CRATES` if you intend to introduce a new one" |
| 592 | + ); |
| 593 | + } |
| 594 | +} |
| 595 | + |
| 596 | +/// True if the given env var is controlled or set by Cargo. |
| 597 | +/// See [`ENV_VARS_SET_FOR_CRATES`]. |
| 598 | +pub(crate) fn is_env_set_by_cargo(key: &str) -> bool { |
| 599 | + ENV_VARS_SET_FOR_CRATES.contains(key) |
| 600 | + || key.starts_with("CARGO_BIN_EXE_") |
| 601 | + || key.starts_with("__CARGO") // internal/test-only envs |
| 602 | + || key == "RUSTC_BOOTSTRAP" // for -Zbuild-std |
| 603 | + || is_artifact_dep_env_vars(key) |
| 604 | +} |
| 605 | + |
| 606 | +/// Whether an env var is set because of `-Zbindeps`. |
| 607 | +fn is_artifact_dep_env_vars(key: &str) -> bool { |
| 608 | + let Some(key) = key.strip_prefix("CARGO_") else { |
| 609 | + return false; |
| 610 | + }; |
| 611 | + let Some(key) = key |
| 612 | + .strip_prefix("BIN_") |
| 613 | + .or_else(|| key.strip_prefix("CDYLIB_")) |
| 614 | + .or_else(|| key.strip_prefix("STATICLIB_")) |
| 615 | + else { |
| 616 | + return false; |
| 617 | + }; |
| 618 | + key.starts_with("FILE_") || key.starts_with("DIR_") |
| 619 | +} |
0 commit comments