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}