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