66//!
77//! Reference: <https://doc.rust-lang.org/stable/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts>
88
9- use std:: env:: var_os;
109use std:: path:: PathBuf ;
1110
1211use crate :: ident:: { is_ascii_ident, is_crate_name, is_feature_name} ;
1312
13+ /// Abstraction over environment variables
14+ trait Env {
15+ /// Fetches the environment variable `key`, returning `None` if the variable isn’t set or if
16+ /// there is another error.
17+ ///
18+ /// It may return `None` if the environment variable’s name contains the equal sign character
19+ /// (`=`) or the NUL character.
20+ ///
21+ /// Note that this function will not check if the environment variable is valid Unicode.
22+ fn get ( & self , key : & str ) -> Option < std:: ffi:: OsString > ;
23+
24+ /// Checks the environment variable `key` is present
25+ ///
26+ /// It may not be considered present if the environment variable’s name contains the equal sign character
27+ /// (`=`) or the NUL character.
28+ fn is_present ( & self , key : & str ) -> bool ;
29+ }
30+
31+ /// Fetches environment variables from the current process
32+ struct ProcessEnv ;
33+
34+ impl Env for ProcessEnv {
35+ fn get ( & self , key : & str ) -> Option < std:: ffi:: OsString > {
36+ std:: env:: var_os ( key)
37+ }
38+
39+ fn is_present ( & self , key : & str ) -> bool {
40+ self . get ( key) . is_some ( )
41+ }
42+ }
43+
1444/// Path to the `cargo` binary performing the build.
1545#[ track_caller]
1646pub fn cargo ( ) -> PathBuf {
@@ -30,7 +60,8 @@ pub fn cargo_manifest_dir() -> PathBuf {
3060/// The path to the manifest of your package.
3161#[ track_caller]
3262pub fn cargo_manifest_path ( ) -> PathBuf {
33- var_os ( "CARGO_MANIFEST_PATH" )
63+ ProcessEnv
64+ . get ( "CARGO_MANIFEST_PATH" )
3465 . map ( to_path)
3566 . unwrap_or_else ( || {
3667 let mut path = cargo_manifest_dir ( ) ;
@@ -42,7 +73,7 @@ pub fn cargo_manifest_path() -> PathBuf {
4273/// The manifest `links` value.
4374#[ track_caller]
4475pub fn cargo_manifest_links ( ) -> Option < String > {
45- var_os ( "CARGO_MANIFEST_LINKS" ) . map ( to_string)
76+ ProcessEnv . get ( "CARGO_MANIFEST_LINKS" ) . map ( to_string)
4677}
4778
4879/// Contains parameters needed for Cargo’s [jobserver] implementation to parallelize
@@ -57,7 +88,7 @@ pub fn cargo_manifest_links() -> Option<String> {
5788/// [jobserver]: https://www.gnu.org/software/make/manual/html_node/Job-Slots.html
5889#[ track_caller]
5990pub fn cargo_makeflags ( ) -> Option < String > {
60- var_os ( "CARGO_MAKEFLAGS" ) . map ( to_string)
91+ ProcessEnv . get ( "CARGO_MAKEFLAGS" ) . map ( to_string)
6192}
6293
6394/// For each activated feature of the package being built, this will be `true`.
@@ -68,7 +99,7 @@ pub fn cargo_feature(name: &str) -> bool {
6899 }
69100 let name = name. to_uppercase ( ) . replace ( '-' , "_" ) ;
70101 let key = format ! ( "CARGO_FEATURE_{name}" ) ;
71- is_present ( & key)
102+ ProcessEnv . is_present ( & key)
72103}
73104
74105/// For each [configuration option] of the package being built, this will contain
@@ -82,7 +113,7 @@ pub fn cargo_feature(name: &str) -> bool {
82113#[ track_caller]
83114pub fn cargo_cfg ( cfg : & str ) -> Option < Vec < String > > {
84115 let var = cargo_cfg_var ( cfg) ;
85- var_os ( & var) . map ( |v| to_strings ( v, ',' ) )
116+ ProcessEnv . get ( & var) . map ( |v| to_strings ( v, ',' ) )
86117}
87118
88119#[ track_caller]
@@ -112,7 +143,7 @@ mod cfg {
112143 #[ cfg( any( ) ) ]
113144 #[ track_caller]
114145 pub fn cargo_cfg_clippy ( ) -> bool {
115- is_present ( "CARGO_CFG_CLIPPY" )
146+ ProcessEnv . is_present ( "CARGO_CFG_CLIPPY" )
116147 }
117148
118149 /// If we are compiling with debug assertions enabled.
@@ -123,25 +154,25 @@ mod cfg {
123154 #[ cfg( any( ) ) ]
124155 #[ track_caller]
125156 pub fn cargo_cfg_debug_assertions ( ) -> bool {
126- is_present ( "CARGO_CFG_DEBUG_ASSERTIONS" )
157+ ProcessEnv . is_present ( "CARGO_CFG_DEBUG_ASSERTIONS" )
127158 }
128159
129160 #[ cfg( any( ) ) ]
130161 #[ track_caller]
131162 pub fn cargo_cfg_doc ( ) -> bool {
132- is_present ( "CARGO_CFG_DOC" )
163+ ProcessEnv . is_present ( "CARGO_CFG_DOC" )
133164 }
134165
135166 #[ cfg( any( ) ) ]
136167 #[ track_caller]
137168 pub fn cargo_cfg_docsrs ( ) -> bool {
138- is_present ( "CARGO_CFG_DOCSRS" )
169+ ProcessEnv . is_present ( "CARGO_CFG_DOCSRS" )
139170 }
140171
141172 #[ cfg( any( ) ) ]
142173 #[ track_caller]
143174 pub fn cargo_cfg_doctest ( ) -> bool {
144- is_present ( "CARGO_CFG_DOCTEST" )
175+ ProcessEnv . is_present ( "CARGO_CFG_DOCTEST" )
145176 }
146177
147178 /// The level of detail provided by derived [`Debug`] implementations.
@@ -155,15 +186,15 @@ mod cfg {
155186 #[ cfg( any( ) ) ]
156187 #[ track_caller]
157188 pub fn cargo_cfg_miri ( ) -> bool {
158- is_present ( "CARGO_CFG_MIRI" )
189+ ProcessEnv . is_present ( "CARGO_CFG_MIRI" )
159190 }
160191
161192 /// If we are compiling with overflow checks enabled.
162193 #[ doc = unstable ! ( cfg_overflow_checks, 111466 ) ]
163194 #[ cfg( feature = "unstable" ) ]
164195 #[ track_caller]
165196 pub fn cargo_cfg_overflow_checks ( ) -> bool {
166- is_present ( "CARGO_CFG_OVERFLOW_CHECKS" )
197+ ProcessEnv . is_present ( "CARGO_CFG_OVERFLOW_CHECKS" )
167198 }
168199
169200 /// The [panic strategy](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#panic).
@@ -175,7 +206,7 @@ mod cfg {
175206 /// If the crate is being compiled as a procedural macro.
176207 #[ track_caller]
177208 pub fn cargo_cfg_proc_macro ( ) -> bool {
178- is_present ( "CARGO_CFG_PROC_MACRO" )
209+ ProcessEnv . is_present ( "CARGO_CFG_PROC_MACRO" )
179210 }
180211
181212 /// The target relocation model.
@@ -189,31 +220,33 @@ mod cfg {
189220 #[ cfg( any( ) ) ]
190221 #[ track_caller]
191222 pub fn cargo_cfg_rustfmt ( ) -> bool {
192- is_present ( "CARGO_CFG_RUSTFMT" )
223+ ProcessEnv . is_present ( "CARGO_CFG_RUSTFMT" )
193224 }
194225
195226 /// Sanitizers enabled for the crate being compiled.
196227 #[ doc = unstable ! ( cfg_sanitize, 39699 ) ]
197228 #[ cfg( feature = "unstable" ) ]
198229 #[ track_caller]
199230 pub fn cargo_cfg_sanitize ( ) -> Option < Vec < String > > {
200- var_os ( "CARGO_CFG_SANITIZE" ) . map ( |v| to_strings ( v, ',' ) )
231+ ProcessEnv
232+ . get ( "CARGO_CFG_SANITIZE" )
233+ . map ( |v| to_strings ( v, ',' ) )
201234 }
202235
203236 /// If CFI sanitization is generalizing pointers.
204237 #[ doc = unstable ! ( cfg_sanitizer_cfi, 89653 ) ]
205238 #[ cfg( feature = "unstable" ) ]
206239 #[ track_caller]
207240 pub fn cargo_cfg_sanitizer_cfi_generalize_pointers ( ) -> bool {
208- is_present ( "CARGO_CFG_SANITIZER_CFI_GENERALIZE_POINTERS" )
241+ ProcessEnv . is_present ( "CARGO_CFG_SANITIZER_CFI_GENERALIZE_POINTERS" )
209242 }
210243
211244 /// If CFI sanitization is normalizing integers.
212245 #[ doc = unstable ! ( cfg_sanitizer_cfi, 89653 ) ]
213246 #[ cfg( feature = "unstable" ) ]
214247 #[ track_caller]
215248 pub fn cargo_cfg_sanitizer_cfi_normalize_integers ( ) -> bool {
216- is_present ( "CARGO_CFG_SANITIZER_CFI_NORMALIZE_INTEGERS" )
249+ ProcessEnv . is_present ( "CARGO_CFG_SANITIZER_CFI_NORMALIZE_INTEGERS" )
217250 }
218251
219252 /// Disambiguation of the [target ABI](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#target_abi)
@@ -309,7 +342,7 @@ mod cfg {
309342 #[ cfg( feature = "unstable" ) ]
310343 #[ track_caller]
311344 pub fn cargo_cfg_target_thread_local ( ) -> bool {
312- is_present ( "CARGO_CFG_TARGET_THREAD_LOCAL" )
345+ ProcessEnv . is_present ( "CARGO_CFG_TARGET_THREAD_LOCAL" )
313346 }
314347
315348 /// The [target vendor](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#target_vendor).
@@ -321,27 +354,27 @@ mod cfg {
321354 #[ cfg( any( ) ) ]
322355 #[ track_caller]
323356 pub fn cargo_cfg_test ( ) -> bool {
324- is_present ( "CARGO_CFG_TEST" )
357+ ProcessEnv . is_present ( "CARGO_CFG_TEST" )
325358 }
326359
327360 /// If we are compiling with UB checks enabled.
328361 #[ doc = unstable ! ( cfg_ub_checks, 123499 ) ]
329362 #[ cfg( feature = "unstable" ) ]
330363 #[ track_caller]
331364 pub fn cargo_cfg_ub_checks ( ) -> bool {
332- is_present ( "CARGO_CFG_UB_CHECKS" )
365+ ProcessEnv . is_present ( "CARGO_CFG_UB_CHECKS" )
333366 }
334367
335368 /// Set on [unix-like platforms](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#unix-and-windows).
336369 #[ track_caller]
337370 pub fn cargo_cfg_unix ( ) -> bool {
338- is_present ( "CARGO_CFG_UNIX" )
371+ ProcessEnv . is_present ( "CARGO_CFG_UNIX" )
339372 }
340373
341374 /// Set on [windows-like platforms](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#unix-and-windows).
342375 #[ track_caller]
343376 pub fn cargo_cfg_windows ( ) -> bool {
344- is_present ( "CARGO_CFG_WINDOWS" )
377+ ProcessEnv . is_present ( "CARGO_CFG_WINDOWS" )
345378 }
346379}
347380
@@ -428,7 +461,7 @@ pub fn dep_metadata(name: &str, key: &str) -> Option<String> {
428461 let name = name. to_uppercase ( ) . replace ( '-' , "_" ) ;
429462 let key = key. to_uppercase ( ) . replace ( '-' , "_" ) ;
430463 let key = format ! ( "DEP_{name}_{key}" ) ;
431- var_os ( & key) . map ( to_string)
464+ ProcessEnv . get ( & key) . map ( to_string)
432465}
433466
434467/// The compiler that Cargo has resolved to use.
@@ -448,7 +481,7 @@ pub fn rustdoc() -> PathBuf {
448481/// [`build.rustc-wrapper`]: https://doc.rust-lang.org/stable/cargo/reference/config.html#buildrustc-wrapper
449482#[ track_caller]
450483pub fn rustc_wrapper ( ) -> Option < PathBuf > {
451- var_os ( "RUSTC_WRAPPER" ) . map ( to_path)
484+ ProcessEnv . get ( "RUSTC_WRAPPER" ) . map ( to_path)
452485}
453486
454487/// The rustc wrapper, if any, that Cargo is using for workspace members. See
@@ -457,15 +490,15 @@ pub fn rustc_wrapper() -> Option<PathBuf> {
457490/// [`build.rustc-workspace-wrapper`]: https://doc.rust-lang.org/stable/cargo/reference/config.html#buildrustc-workspace-wrapper
458491#[ track_caller]
459492pub fn rustc_workspace_wrapper ( ) -> Option < PathBuf > {
460- var_os ( "RUSTC_WORKSPACE_WRAPPER" ) . map ( to_path)
493+ ProcessEnv . get ( "RUSTC_WORKSPACE_WRAPPER" ) . map ( to_path)
461494}
462495
463496/// The linker that Cargo has resolved to use for the current target, if specified.
464497///
465498/// [`target.*.linker`]: https://doc.rust-lang.org/stable/cargo/reference/config.html#targettriplelinker
466499#[ track_caller]
467500pub fn rustc_linker ( ) -> Option < PathBuf > {
468- var_os ( "RUSTC_LINKER" ) . map ( to_path)
501+ ProcessEnv . get ( "RUSTC_LINKER" ) . map ( to_path)
469502}
470503
471504/// Extra flags that Cargo invokes rustc with. See [`build.rustflags`].
@@ -561,13 +594,11 @@ pub fn cargo_pkg_readme() -> Option<PathBuf> {
561594 to_opt ( var_or_panic ( "CARGO_PKG_README" ) ) . map ( to_path)
562595}
563596
564- fn is_present ( key : & str ) -> bool {
565- var_os ( key) . is_some ( )
566- }
567-
568597#[ track_caller]
569598fn var_or_panic ( key : & str ) -> std:: ffi:: OsString {
570- var_os ( key) . unwrap_or_else ( || panic ! ( "cargo environment variable `{key}` is missing" ) )
599+ ProcessEnv
600+ . get ( key)
601+ . unwrap_or_else ( || panic ! ( "cargo environment variable `{key}` is missing" ) )
571602}
572603
573604fn to_path ( value : std:: ffi:: OsString ) -> PathBuf {
0 commit comments