@@ -4,7 +4,9 @@ use paths::{Utf8Path, Utf8PathBuf};
44use rustc_hash:: FxHashMap ;
55use toolchain:: Tool ;
66
7- use crate :: { ManifestPath , PackageData , Sysroot , TargetKind , utf8_stdout} ;
7+ use crate :: {
8+ ManifestPath , PackageData , Sysroot , TargetKind , cargo_config_file:: CargoConfigFile , utf8_stdout,
9+ } ;
810
911/// Recreates the compile-time environment variables that Cargo sets.
1012///
@@ -61,104 +63,68 @@ pub(crate) fn inject_rustc_tool_env(env: &mut Env, cargo_name: &str, kind: Targe
6163 env. set ( "CARGO_CRATE_NAME" , cargo_name. replace ( '-' , "_" ) ) ;
6264}
6365
64- pub ( crate ) fn cargo_config_env (
65- manifest : & ManifestPath ,
66- extra_env : & FxHashMap < String , Option < String > > ,
67- sysroot : & Sysroot ,
68- ) -> Env {
69- let mut cargo_config = sysroot. tool ( Tool :: Cargo , manifest. parent ( ) , extra_env) ;
70- cargo_config
71- . args ( [ "-Z" , "unstable-options" , "config" , "get" , "env" ] )
72- . env ( "RUSTC_BOOTSTRAP" , "1" ) ;
73- if manifest. is_rust_manifest ( ) {
74- cargo_config. arg ( "-Zscript" ) ;
75- }
76- // if successful we receive `env.key.value = "value" per entry
77- tracing:: debug!( "Discovering cargo config env by {:?}" , cargo_config) ;
78- utf8_stdout ( & mut cargo_config)
79- . map ( |stdout| parse_output_cargo_config_env ( manifest, & stdout) )
80- . inspect ( |env| {
81- tracing:: debug!( "Discovered cargo config env: {:?}" , env) ;
82- } )
83- . inspect_err ( |err| {
84- tracing:: debug!( "Failed to discover cargo config env: {:?}" , err) ;
85- } )
86- . unwrap_or_default ( )
87- }
88-
89- fn parse_output_cargo_config_env ( manifest : & ManifestPath , stdout : & str ) -> Env {
66+ pub ( crate ) fn cargo_config_env ( manifest : & ManifestPath , config : & Option < CargoConfigFile > ) -> Env {
9067 let mut env = Env :: default ( ) ;
91- let mut relatives = vec ! [ ] ;
92- for ( key, val) in
93- stdout. lines ( ) . filter_map ( |l| l. strip_prefix ( "env." ) ) . filter_map ( |l| l. split_once ( " = " ) )
94- {
95- let val = val. trim_matches ( '"' ) . to_owned ( ) ;
96- if let Some ( ( key, modifier) ) = key. split_once ( '.' ) {
97- match modifier {
98- "relative" => relatives. push ( ( key, val) ) ,
99- "value" => _ = env. insert ( key, val) ,
100- _ => {
101- tracing:: warn!(
102- "Unknown modifier in cargo config env: {}, expected `relative` or `value`" ,
103- modifier
104- ) ;
105- continue ;
106- }
107- }
108- } else {
109- env. insert ( key, val) ;
110- }
111- }
68+ let Some ( serde_json:: Value :: Object ( env_json) ) = config. as_ref ( ) . and_then ( |c| c. get ( "env" ) )
69+ else {
70+ return env;
71+ } ;
72+
11273 // FIXME: The base here should be the parent of the `.cargo/config` file, not the manifest.
11374 // But cargo does not provide this information.
11475 let base = <_ as AsRef < Utf8Path > >:: as_ref ( manifest. parent ( ) ) ;
115- for ( key, relative) in relatives {
116- if relative != "true" {
76+
77+ for ( key, entry) in env_json {
78+ let serde_json:: Value :: Object ( entry) = entry else {
11779 continue ;
118- }
119- if let Some ( suffix) = env. get ( key) {
120- env. insert ( key, base. join ( suffix) . to_string ( ) ) ;
121- }
122- }
123- env
124- }
80+ } ;
81+ let Some ( value) = entry. get ( "value" ) . and_then ( |v| v. as_str ( ) ) else {
82+ continue ;
83+ } ;
12584
126- pub ( crate ) fn cargo_config_build_target_dir (
127- manifest : & ManifestPath ,
128- extra_env : & FxHashMap < String , Option < String > > ,
129- sysroot : & Sysroot ,
130- ) -> Option < Utf8PathBuf > {
131- let mut cargo_config = sysroot. tool ( Tool :: Cargo , manifest. parent ( ) , extra_env) ;
132- cargo_config
133- . args ( [ "-Z" , "unstable-options" , "config" , "get" , "build.target-dir" ] )
134- . env ( "RUSTC_BOOTSTRAP" , "1" ) ;
135- if manifest. is_rust_manifest ( ) {
136- cargo_config. arg ( "-Zscript" ) ;
85+ let value = if entry
86+ . get ( "relative" )
87+ . and_then ( |v| v. as_bool ( ) )
88+ . is_some_and ( std:: convert:: identity)
89+ {
90+ base. join ( value) . to_string ( )
91+ } else {
92+ value. to_owned ( )
93+ } ;
94+ env. insert ( key, value) ;
13795 }
138- utf8_stdout ( & mut cargo_config)
139- . map ( |stdout| {
140- Utf8Path :: new ( stdout. trim_start_matches ( "build.target-dir = " ) . trim_matches ( '"' ) )
141- . to_owned ( )
142- } )
143- . ok ( )
96+
97+ env
14498}
14599
146100#[ test]
147101fn parse_output_cargo_config_env_works ( ) {
148- let stdout = r#"
149- env.CARGO_WORKSPACE_DIR.relative = true
150- env.CARGO_WORKSPACE_DIR.value = ""
151- env.RELATIVE.relative = true
152- env.RELATIVE.value = "../relative"
153- env.INVALID.relative = invalidbool
154- env.INVALID.value = "../relative"
155- env.TEST.value = "test"
156- "#
157- . trim ( ) ;
102+ let raw = r#"
103+ {
104+ "env": {
105+ "CARGO_WORKSPACE_DIR": {
106+ "relative": true,
107+ "value": ""
108+ },
109+ "INVALID": {
110+ "relative": "invalidbool",
111+ "value": "../relative"
112+ },
113+ "RELATIVE": {
114+ "relative": true,
115+ "value": "../relative"
116+ },
117+ "TEST": {
118+ "value": "test"
119+ }
120+ }
121+ }
122+ "# ;
123+ let config: CargoConfigFile = serde_json:: from_str ( raw) . unwrap ( ) ;
158124 let cwd = paths:: Utf8PathBuf :: try_from ( std:: env:: current_dir ( ) . unwrap ( ) ) . unwrap ( ) ;
159125 let manifest = paths:: AbsPathBuf :: assert ( cwd. join ( "Cargo.toml" ) ) ;
160126 let manifest = ManifestPath :: try_from ( manifest) . unwrap ( ) ;
161- let env = parse_output_cargo_config_env ( & manifest, stdout ) ;
127+ let env = cargo_config_env ( & manifest, & Some ( config ) ) ;
162128 assert_eq ! ( env. get( "CARGO_WORKSPACE_DIR" ) . as_deref( ) , Some ( cwd. join( "" ) . as_str( ) ) ) ;
163129 assert_eq ! ( env. get( "RELATIVE" ) . as_deref( ) , Some ( cwd. join( "../relative" ) . as_str( ) ) ) ;
164130 assert_eq ! ( env. get( "INVALID" ) . as_deref( ) , Some ( "../relative" ) ) ;
0 commit comments