build/input.rs
1use std::{env, ffi::OsString, path::PathBuf};
2
3macro_rules! export {
4 () => {};
5 ($(#[$meta:meta])* $f:ident -> String = $var:ident $(; $($rest:tt)*)? ) => {
6 $(#[$meta])*
7 pub fn $f() -> String {
8 env::var_os(stringify!($var))
9 .expect(concat!("cargo buildscript env var $", stringify!($var), " not found"))
10 .into_string()
11 .expect(concat!("cargo buildscript env var $", stringify!($var), " contained invalid UTF-8"))
12 }
13
14 $(export! {
15 $($rest)*
16 })?
17 };
18 ($(#[$meta:meta])* $f:ident -> Option<String> = $var:ident $(; $($rest:tt)*)? ) => {
19 $(#[$meta])*
20 pub fn $f() -> Option<String> {
21 env::var_os(stringify!($var)).map(|it| it
22 .into_string()
23 .expect(concat!("cargo buildscript env var $", stringify!($var), " contained invalid UTF-8"))
24 )
25 }
26
27 $(export! {
28 $($rest)*
29 })?
30 };
31 ($(#[$meta:meta])* $f:ident -> usize = $var:ident $(; $($rest:tt)*)? ) => {
32 $(#[$meta])*
33 pub fn $f() -> usize {
34 env::var_os(stringify!($var))
35 .expect(concat!("cargo buildscript env var $", stringify!($var), " not found"))
36 .into_string()
37 .expect(concat!("cargo buildscript env var $", stringify!($var), " contained invalid UTF-8"))
38 .parse()
39 .expect(concat!("cargo buildscript env var $", stringify!($var), " did not parse as `usize`"))
40 }
41
42 $(export! {
43 $($rest)*
44 })?
45 };
46 ($(#[$meta:meta])* $f:ident -> Vec<String> = $var:ident $(; $($rest:tt)*)? ) => {
47 $(#[$meta])*
48 pub fn $f() -> Vec<String> {
49 env::var_os(stringify!($var))
50 .expect(concat!("cargo buildscript env var $", stringify!($var), " not found"))
51 .into_string()
52 .expect(concat!("cargo buildscript env var $", stringify!($var), " contained invalid UTF-8"))
53 .split(',')
54 .map(Into::into)
55 .collect()
56 }
57
58 $(export! {
59 $($rest)*
60 })?
61 };
62 ($(#[$meta:meta])* $f:ident -> bool = $var:ident $(; $($rest:tt)*)? ) => {
63 $(#[$meta])*
64 pub fn $f() -> bool {
65 env::var_os(stringify!($var))
66 .is_some()
67 }
68
69 $(export! {
70 $($rest)*
71 })?
72 };
73 ($(#[$meta:meta])* $f:ident -> PathBuf = $var:ident $(; $($rest:tt)*)? ) => {
74 $(#[$meta])*
75 pub fn $f() -> PathBuf {
76 env::var_os(stringify!($var))
77 .expect(concat!("cargo buildscript env var $", stringify!($var), " not found"))
78 .into()
79 }
80
81 $(export! {
82 $($rest)*
83 })?
84 };
85 ($(#[$meta:meta])* $f:ident -> Option<PathBuf> = $var:ident $(; $($rest:tt)*)? ) => {
86 $(#[$meta])*
87 pub fn $f() -> Option<PathBuf> {
88 env::var_os(stringify!($var))
89 .map(Into::into)
90 }
91
92 $(export! {
93 $($rest)*
94 })?
95 };
96 ($(#[$meta:meta])* $f:ident -> OsString = $var:ident $(; $($rest:tt)*)? ) => {
97 $(#[$meta])*
98 pub fn $f() -> OsString {
99 env::var_os(stringify!($var))
100 .expect(concat!("cargo buildscript env var $", stringify!($var), " not found"))
101 }
102
103 $(export! {
104 $($rest)*
105 })?
106 };
107 ($(#[$meta:meta])* $f:ident -> $out:ty = $var:ident $(; $($rest:tt)*)? ) => {
108 compile_error!(concat!("Provided unknown output type ", stringify!($out), " to export!"));
109
110 $(export! {
111 $($rest)*
112 })?
113 };
114}
115
116export! {
117 /// Path to the `cargo` binary performing the build.
118 cargo -> PathBuf = CARGO;
119 /// The directory containing the manifest for the package being built (the
120 /// package containing the build script). Also note that this is the value
121 /// of the current working directory of the build script when it starts.
122 cargo_manifest_dir -> PathBuf = CARGO_MANIFEST_DIR;
123 /// The manifest links value.
124 cargo_manifest_links -> String = CARGO_MANIFEST_LINKS;
125 /// Contains parameters needed for Cargo's jobserver implementation to
126 /// parallelize subprocesses. Rustc or cargo invocations from build.rs
127 /// can already read CARGO_MAKEFLAGS, but GNU Make requires the flags
128 /// to be specified either directly as arguments, or through the MAKEFLAGS
129 /// environment variable. Currently Cargo doesn't set the MAKEFLAGS
130 /// variable, but it's free for build scripts invoking GNU Make to set it
131 /// to the contents of CARGO_MAKEFLAGS.
132 cargo_makeflags -> OsString = CARGO_MAKEFLAGS;
133 /// Set on [unix-like platforms](https://doc.rust-lang.org/reference/conditional-compilation.html#unix-and-windows).
134 cargo_cfg_unix -> bool = CARGO_CFG_UNIX;
135 /// Set on [windows-like platforms](https://doc.rust-lang.org/reference/conditional-compilation.html#unix-and-windows).
136 cargo_cfg_windows -> bool = CARGO_CFG_WINDOWS;
137 /// The [target family](https://doc.rust-lang.org/reference/conditional-compilation.html#target_family).
138 cargo_cfg_target_family -> Vec<String> = CARGO_CFG_TARGET_FAMILY;
139 /// The [target operating system](https://doc.rust-lang.org/reference/conditional-compilation.html#target_os).
140 cargo_cfg_target_os -> String = CARGO_CFG_TARGET_OS;
141 /// The CPU [target architecture](https://doc.rust-lang.org/reference/conditional-compilation.html#target_arch).
142 cargo_cfg_target_arch -> String = CARGO_CFG_TARGET_ARCH;
143 /// The [target vendor](https://doc.rust-lang.org/reference/conditional-compilation.html#target_vendor).
144 cargo_cfg_target_vendor -> String = CARGO_CFG_TARGET_VENDOR;
145 /// The [target environment](https://doc.rust-lang.org/reference/conditional-compilation.html#target_env) ABI.
146 cargo_cfg_target_env -> String = CARGO_CFG_TARGET_ENV;
147 /// The CPU [pointer width](https://doc.rust-lang.org/reference/conditional-compilation.html#target_pointer_width).
148 cargo_cfg_pointer_width -> usize = CARGO_CFG_TARGET_POINTER_WIDTH;
149 /// Teh CPU [target endianness](https://doc.rust-lang.org/reference/conditional-compilation.html#target_endian).
150 cargo_cfg_target_endian -> String = CARGO_CFG_TARGET_ENDIAN;
151 /// List of CPU [target features](https://doc.rust-lang.org/reference/conditional-compilation.html#target_feature) enabled.
152 cargo_cfg_target_feature -> Vec<String> = CARGO_CFG_TARGET_FEATURE;
153 /// The folder in which all output should be placed. This folder is inside
154 /// the build directory for the package being built, and it is unique for
155 /// the package in question.
156 out_dir -> PathBuf = OUT_DIR;
157 /// The target triple that is being compiled for. Native code should be
158 /// compiled for this triple. See the [Target Triple] description for
159 /// more information.
160 ///
161 /// [Target Triple]: https://doc.rust-lang.org/cargo/appendix/glossary.html#target
162 target -> String = TARGET;
163 /// The host triple of the Rust compiler.
164 host -> String = HOST;
165 /// The parallelism specified as the top-level parallelism. This can be
166 /// useful to pass a `-j` parameter to a system like `make`. Note that care
167 /// should be taken when interpreting this environment variable. For
168 /// historical purposes this is still provided but recent versions of
169 /// Cargo, for example, do not need to run `make -j`, and instead can set
170 /// the `MAKEFLAGS` env var to the content of `CARGO_MAKEFLAGS` to activate
171 /// the use of Cargo's GNU Make compatible [jobserver] for sub-make
172 /// invocations.
173 ///
174 /// [jobserver]: https://www.gnu.org/software/make/manual/html_node/Job-Slots.html
175 num_jobs -> String = NUM_JOBS;
176 /// Value of the corresponding variable for the profile currently being built.
177 opt_level -> String = OPT_LEVEL;
178 /// Value of the corresponding variable for the profile currently being built.
179 debug -> String = DEBUG;
180 /// `release` for release builds, `debug` for other builds. This is
181 /// determined based on if the profile inherits from the [`dev`] or
182 /// [`release`] profile. Using this environment variable is not
183 /// recommended. Using other environment variables like `OPT_LEVEL`
184 /// provide a more correct view of the actual settings being used.
185 ///
186 /// [`dev`]: https://doc.rust-lang.org/cargo/reference/profiles.html#dev
187 /// [`release`]: https://doc.rust-lang.org/cargo/reference/profiles.html#release
188 profile -> String = PROFILE;
189 /// The compiler that Cargo has resolved to use, passed to the build script
190 /// so it might use it as well.
191 rustc -> PathBuf = RUSTC;
192 /// The documentation generator that Cargo has resolved to use, passed to
193 /// the build script so it might use it as well.
194 rustdoc -> PathBuf = RUSTDOC;
195 /// The `rustc` wrapper, if any, that Cargo is using. See
196 /// [`build.rustc-wrapper`](https://doc.rust-lang.org/cargo/reference/config.html#buildrustc-wrapper).
197 rustc_wrapper -> Option<PathBuf> = RUSTC_WRAPPER;
198 /// The `rustc` wrapper, if any, that Cargo is using for workspace members.
199 /// See [`build.rustc-workspace-wrapper`](https://doc.rust-lang.org/cargo/reference/config.html#buildrustc-workspace-wrapper).
200 rustc_workspace_wrapper -> Option<PathBuf> = RUSTC_WORKSPACE_WRAPPER;
201 /// The path to the linker binary that Cargo has resolved to use for the
202 /// current target, if specified.
203 rustc_linker -> Option<PathBuf> = RUSTC_LINKER;
204 /// The full version of your package.
205 cargo_pkg_version -> String = CARGO_PKG_VERSION;
206 /// The major version of your package.
207 cargo_pkg_version_major -> usize = CARGO_PKG_VERSION_MAJOR;
208 /// The minor version of your package.
209 cargo_pkg_version_minor -> usize = CARGO_PKG_VERSION_MINOR;
210 /// The patch version of your package.
211 cargo_pkg_version_patch -> usize = CARGO_PKG_VERSION_PATCH;
212 /// The pre-release of your package.
213 cargo_pkg_version_pre -> String = CARGO_PKG_VERSION_PRE;
214 /// The name of your package.
215 cargo_pkg_name -> String = CARGO_PKG_NAME;
216 /// The description from the manifest of your package.
217 cargo_pkg_description -> String = CARGO_PKG_DESCRIPTION;
218 /// The home page from the manifest of your package.
219 cargo_pkg_homepage -> String = CARGO_PKG_HOMEPAGE;
220 /// The repository from the manifest of your package.
221 cargo_pkg_repository -> String = CARGO_PKG_REPOSITORY;
222 /// The license from the manifest of your package.
223 cargo_pkg_license -> String = CARGO_PKG_LICENSE;
224 /// The license file from the manifest of your package.
225 cargo_pkg_license_file -> String = CARGO_PKG_LICENSE_FILE;
226}
227
228/// For each activated feature of the package being built, this will be true.
229pub fn cargo_feature(name: &str) -> bool {
230 let key = format!("CARGO_FEATURE_{}", name.to_uppercase().replace('-', "_"));
231 env::var_os(key).is_some()
232}
233
234/// For each [configuration option] of the package being built, this will
235/// contain the value of the configuration. Boolean configurations are present
236/// if they are set, and not present otherwise. This includes values built-in
237/// to the compiler (which can be seen with `rustc --print=cfg`) and values set
238/// by build scripts and extra flags passed to `rustc` (such as those defined
239/// in `RUSTFLAGS`).
240///
241/// [configuration option]: https://doc.rust-lang.org/reference/conditional-compilation.html
242pub fn cargo_cfg(cfg: &str) -> Option<Vec<String>> {
243 let key = format!("CARGO_CFG_{}", cfg.to_uppercase().replace('-', "_"));
244 let val = env::var_os(&key)?.into_string().unwrap_or_else(|_| {
245 panic!("cargo buildscript env var ${key} contained invalid UTF-8");
246 });
247 Some(val.split(',').map(Into::into).collect())
248}
249
250/// Each build script can generate an arbitrary set of metadata in the form of
251/// key-value pairs. This metadata is passed to the build scripts of
252/// **dependent** packages. For example, if the package `bar` depends on `foo`,
253/// then if `foo` generates `key=value` as part of its build script metadata,
254/// then the build script of `bar` will have the environment variables
255/// `DEP_FOO_KEY=value`.
256pub fn dep(name: &str, key: &str) -> Option<String> {
257 let key = format!(
258 "DEP_{}_{}",
259 name.to_uppercase().replace('-', "_"),
260 key.to_uppercase().replace('-', "_")
261 );
262 let val = env::var_os(&key)?.into_string().unwrap_or_else(|_| {
263 panic!("cargo buildscript env var ${key} contained invalid UTF-8");
264 });
265 Some(val)
266}
267
268/// Extra flags that Cargo invokes rustc with. See [`build.rustflags`]. Note
269/// that since Rust 1.55, `RUSTFLAGS` is removed from the environment; scripts
270/// should use `CARGO_ENCODED_RUSTFLAGS` instead.
271///
272/// [`build.rustflags`]: https://doc.rust-lang.org/cargo/reference/config.html#buildrustflags
273pub fn cargo_encoded_rustflags() -> Vec<String> {
274 let val = env::var_os("CARGO_ENCODED_RUSTFLAGS")
275 .expect("cargo buildscript env var $CARGO_ENCODED_RUSTFLAGS")
276 .into_string()
277 .expect("cargo buildscript env var $CARGO_ENCODED_RUSTFLAGS contained invalid UTF-8");
278 val.split('\x1f').map(Into::into).collect()
279}
280
281/// List of authors from the manifest of your package.
282pub fn cargo_pkg_authors() -> Vec<String> {
283 let val = env::var_os("CARGO_PKG_AUTHORS")
284 .expect("cargo buildscript env var $CARGO_PKG_AUTHORS")
285 .into_string()
286 .expect("cargo buildscript env var $CARGO_PKG_AUTHORS contained invalid UTF-8");
287 val.split(':').map(Into::into).collect()
288}