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