From eef4b30d3112c7533ca9682be4b3e90702fafb51 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 13 Nov 2024 12:42:44 -0600 Subject: [PATCH 01/11] docs(build-rs): Split out short descriptions --- crates/build-rs/src/input.rs | 21 +++++++++++++----- crates/build-rs/src/output.rs | 41 ++++++++++++++++++++++++++--------- 2 files changed, 47 insertions(+), 15 deletions(-) diff --git a/crates/build-rs/src/input.rs b/crates/build-rs/src/input.rs index 1b7adc36cd4..01a4a3946ae 100644 --- a/crates/build-rs/src/input.rs +++ b/crates/build-rs/src/input.rs @@ -97,7 +97,9 @@ pub fn cargo() -> PathBuf { } /// The directory containing the manifest for the package being built (the package -/// containing the build script). Also note that this is the value of the current +/// containing the build script). +/// +/// Also note that this is the value of the current /// working directory of the build script when it starts. #[track_caller] pub fn cargo_manifest_dir() -> PathBuf { @@ -105,7 +107,9 @@ pub fn cargo_manifest_dir() -> PathBuf { } /// Contains parameters needed for Cargo’s [jobserver] implementation to parallelize -/// subprocesses. Rustc or cargo invocations from build.rs can already read +/// subprocesses. +/// +/// Rustc or cargo invocations from build.rs can already read /// `CARGO_MAKEFLAGS`, but GNU Make requires the flags to be specified either /// directly as arguments, or through the `MAKEFLAGS` environment variable. /// Currently Cargo doesn’t set the `MAKEFLAGS` variable, but it’s free for build @@ -129,7 +133,9 @@ pub fn cargo_feature(name: &str) -> bool { } /// For each [configuration option] of the package being built, this will contain -/// the value of the configuration. This includes values built-in to the compiler +/// the value of the configuration. +/// +/// This includes values built-in to the compiler /// (which can be seen with `rustc --print=cfg`) and values set by build scripts /// and extra flags passed to rustc (such as those defined in `RUSTFLAGS`). /// @@ -374,6 +380,7 @@ mod cfg { } /// The folder in which all output and intermediate artifacts should be placed. +/// /// This folder is inside the build directory for the package being built, and /// it is unique for the package in question. #[track_caller] @@ -396,7 +403,9 @@ pub fn host() -> String { get_str("HOST") } -/// The parallelism specified as the top-level parallelism. This can be useful to +/// The parallelism specified as the top-level parallelism. +/// +/// This can be useful to /// pass a `-j` parameter to a system like `make`. Note that care should be taken /// when interpreting this value. For historical purposes this is still provided /// but Cargo, for example, does not need to run `make -j`, and instead can set the @@ -421,7 +430,9 @@ pub fn debug() -> String { get_str("DEBUG") } -/// `release` for release builds, `debug` for other builds. This is determined based +/// `release` for release builds, `debug` for other builds. +/// +/// This is determined based /// on if the [profile] inherits from the [`dev`] or [`release`] profile. Using this /// function is not recommended. Using other functions like [`opt_level`] provides /// a more correct view of the actual settings being used. diff --git a/crates/build-rs/src/output.rs b/crates/build-rs/src/output.rs index 318185a040e..c275338c611 100644 --- a/crates/build-rs/src/output.rs +++ b/crates/build-rs/src/output.rs @@ -21,7 +21,9 @@ fn emit(directive: &str, value: impl Display) { } /// The `rerun-if-changed` instruction tells Cargo to re-run the build script if the -/// file at the given path has changed. Currently, Cargo only uses the filesystem +/// file at the given path has changed. +/// +/// Currently, Cargo only uses the filesystem /// last-modified “mtime” timestamp to determine if the file has changed. It /// compares against an internal cached timestamp of when the build script last ran. /// @@ -70,6 +72,7 @@ pub fn rerun_if_env_changed(key: impl AsRef) { /// The `rustc-link-arg` instruction tells Cargo to pass the /// [`-C link-arg=FLAG` option][link-arg] to the compiler, but only when building /// supported targets (benchmarks, binaries, cdylib crates, examples, and tests). +/// /// Its usage is highly platform specific. It is useful to set the shared library /// version or linker script. /// @@ -84,7 +87,9 @@ pub fn rustc_link_arg(flag: &str) { /// The `rustc-link-arg-bin` instruction tells Cargo to pass the /// [`-C link-arg=FLAG` option][link-arg] to the compiler, but only when building -/// the binary target with name `BIN`. Its usage is highly platform specific. It +/// the binary target with name `BIN`. Its usage is highly platform specific. +/// +/// It /// is useful to set a linker script or other linker options. /// /// [link-arg]: https://doc.rust-lang.org/rustc/codegen-options/index.html#link-arg @@ -101,7 +106,9 @@ pub fn rustc_link_arg_bin(bin: &str, flag: &str) { /// The `rustc-link-arg-bins` instruction tells Cargo to pass the /// [`-C link-arg=FLAG` option][link-arg] to the compiler, but only when building -/// the binary target. Its usage is highly platform specific. It is useful to set +/// the binary target. +/// +/// Its usage is highly platform specific. It is useful to set /// a linker script or other linker options. /// /// [link-arg]: https://doc.rust-lang.org/rustc/codegen-options/index.html#link-arg @@ -147,7 +154,9 @@ pub fn rustc_link_arg_benches(flag: &str) { } /// The `rustc-link-lib` instruction tells Cargo to link the given library using -/// the compiler’s [`-l` flag][-l]. This is typically used to link a native library +/// the compiler’s [`-l` flag][-l]. +/// +/// This is typically used to link a native library /// using [FFI]. /// /// The `LIB` string is passed directly to rustc, so it supports any syntax that @@ -229,7 +238,9 @@ pub fn rustc_link_search_kind(kind: &str, path: impl AsRef) { } /// The `rustc-flags` instruction tells Cargo to pass the given space-separated -/// flags to the compiler. This only allows the `-l` and `-L` flags, and is +/// flags to the compiler. +/// +/// This only allows the `-l` and `-L` flags, and is /// equivalent to using [`rustc_link_lib`] and [`rustc_link_search`]. #[track_caller] pub fn rustc_flags(flags: &str) { @@ -240,7 +251,9 @@ pub fn rustc_flags(flags: &str) { } /// The `rustc-cfg` instruction tells Cargo to pass the given value to the -/// [`--cfg` flag][cfg] to the compiler. This may be used for compile-time +/// [`--cfg` flag][cfg] to the compiler. +/// +/// This may be used for compile-time /// detection of features to enable conditional compilation. /// /// Note that this does not affect Cargo’s dependency resolution. This cannot @@ -264,7 +277,9 @@ pub fn rustc_cfg(key: &str) { emit("rustc-cfg", key); } -/// Like [`rustc_cfg`], but with the value specified separately. To replace the +/// Like [`rustc_cfg`], but with the value specified separately. +/// +/// To replace the /// less convenient `rustc_cfg(r#"my_component="foo""#)`, you can instead use /// `rustc_cfg_value("my_component", "foo")`. #[track_caller] @@ -342,7 +357,9 @@ pub fn rustc_check_cfg_values(key: &str, values: &[&str]) { } /// The `rustc-env` instruction tells Cargo to set the given environment variable -/// when compiling the package. The value can be then retrieved by the +/// when compiling the package. +/// +/// The value can be then retrieved by the /// [`env!` macro][env!] in the compiled crate. This is useful for embedding /// additional metadata in crate’s code, such as the hash of git HEAD or the /// unique identifier of a continuous integration server. @@ -363,7 +380,9 @@ pub fn rustc_env(key: &str, value: &str) { /// The `rustc-cdylib-link-arg` instruction tells Cargo to pass the /// [`-C link-arg=FLAG` option][link-arg] to the compiler, but only when building -/// a `cdylib` library target. Its usage is highly platform specific. It is useful +/// a `cdylib` library target. +/// +/// Its usage is highly platform specific. It is useful /// to set the shared library version or the runtime-path. /// /// [link-arg]: https://doc.rust-lang.org/rustc/codegen-options/index.html#link-arg @@ -376,7 +395,9 @@ pub fn rustc_cdylib_link_arg(flag: &str) { } /// The `warning` instruction tells Cargo to display a warning after the build -/// script has finished running. Warnings are only shown for path dependencies +/// script has finished running. +/// +/// Warnings are only shown for path dependencies /// (that is, those you’re working on locally), so for example warnings printed /// out in [crates.io] crates are not emitted by default. The `-vv` “very verbose” /// flag may be used to have Cargo display warnings for all crates. From e4e7a36eaaa769402982a4d45d542efaacdef39c Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 13 Nov 2024 12:43:26 -0600 Subject: [PATCH 02/11] docs(build-rs): Correct documentation for manifest_links --- crates/build-rs/src/input.rs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/crates/build-rs/src/input.rs b/crates/build-rs/src/input.rs index 01a4a3946ae..0636623e991 100644 --- a/crates/build-rs/src/input.rs +++ b/crates/build-rs/src/input.rs @@ -106,16 +106,7 @@ pub fn cargo_manifest_dir() -> PathBuf { get_path("CARGO_MANIFEST_DIR") } -/// Contains parameters needed for Cargo’s [jobserver] implementation to parallelize -/// subprocesses. -/// -/// Rustc or cargo invocations from build.rs can already read -/// `CARGO_MAKEFLAGS`, but GNU Make requires the flags to be specified either -/// directly as arguments, or through the `MAKEFLAGS` environment variable. -/// Currently Cargo doesn’t set the `MAKEFLAGS` variable, but it’s free for build -/// scripts invoking GNU Make to set it to the contents of `CARGO_MAKEFLAGS`. -/// -/// [jobserver]: https://www.gnu.org/software/make/manual/html_node/Job-Slots.html +/// The manifest `links` value. #[track_caller] pub fn cargo_manifest_links() -> Option { get_opt_str("CARGO_MANIFEST_LINKS") From 58ac23d60a58fbf5155ae8afcdb940604d7750e1 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 13 Nov 2024 12:43:43 -0600 Subject: [PATCH 03/11] feat(build-rs): Add cargo_makeflags --- crates/build-rs/src/input.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/crates/build-rs/src/input.rs b/crates/build-rs/src/input.rs index 0636623e991..e8fb90fb5f0 100644 --- a/crates/build-rs/src/input.rs +++ b/crates/build-rs/src/input.rs @@ -112,6 +112,21 @@ pub fn cargo_manifest_links() -> Option { get_opt_str("CARGO_MANIFEST_LINKS") } +/// Contains parameters needed for Cargo’s [jobserver] implementation to parallelize +/// subprocesses. +/// +/// Rustc or cargo invocations from build.rs can already read +/// `CARGO_MAKEFLAGS`, but GNU Make requires the flags to be specified either +/// directly as arguments, or through the `MAKEFLAGS` environment variable. +/// Currently Cargo doesn’t set the `MAKEFLAGS` variable, but it’s free for build +/// scripts invoking GNU Make to set it to the contents of `CARGO_MAKEFLAGS`. +/// +/// [jobserver]: https://www.gnu.org/software/make/manual/html_node/Job-Slots.html +#[track_caller] +pub fn cargo_makeflags() -> Option { + get_opt_str("CARGO_MAKEFLAGS") +} + /// For each activated feature of the package being built, this will be `true`. #[track_caller] pub fn cargo_feature(name: &str) -> bool { From 5e53b21e19d7c32531c5fff93ddef0b9bf5c758b Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 13 Nov 2024 12:54:59 -0600 Subject: [PATCH 04/11] refactor(build-rs): Clarify bool policy --- crates/build-rs/src/input.rs | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/crates/build-rs/src/input.rs b/crates/build-rs/src/input.rs index e8fb90fb5f0..7274af6c2c6 100644 --- a/crates/build-rs/src/input.rs +++ b/crates/build-rs/src/input.rs @@ -27,7 +27,7 @@ macro_rules! invalid { } #[track_caller] -fn get_bool(key: &str) -> bool { +fn is_present(key: &str) -> bool { env::var_os(key).is_some() } @@ -135,7 +135,7 @@ pub fn cargo_feature(name: &str) -> bool { } let name = name.to_uppercase().replace('-', "_"); let key = format!("CARGO_FEATURE_{name}"); - get_bool(&key) + is_present(&key) } /// For each [configuration option] of the package being built, this will contain @@ -162,31 +162,31 @@ mod cfg { #[cfg(any())] #[track_caller] pub fn cargo_cfg_clippy() -> bool { - get_bool("CARGO_CFG_CLIPPY") + is_present("CARGO_CFG_CLIPPY") } /// If we are compiling with debug assertions enabled. #[track_caller] pub fn cargo_cfg_debug_assertions() -> bool { - get_bool("CARGO_CFG_DEBUG_ASSERTIONS") + is_present("CARGO_CFG_DEBUG_ASSERTIONS") } #[cfg(any())] #[track_caller] pub fn cargo_cfg_doc() -> bool { - get_bool("CARGO_CFG_DOC") + is_present("CARGO_CFG_DOC") } #[cfg(any())] #[track_caller] pub fn cargo_cfg_docsrs() -> bool { - get_bool("CARGO_CFG_DOCSRS") + is_present("CARGO_CFG_DOCSRS") } #[cfg(any())] #[track_caller] pub fn cargo_cfg_doctest() -> bool { - get_bool("CARGO_CFG_DOCTEST") + is_present("CARGO_CFG_DOCTEST") } /// The level of detail provided by derived [`Debug`] implementations. @@ -200,7 +200,7 @@ mod cfg { #[cfg(any())] #[track_caller] pub fn cargo_cfg_miri() -> bool { - get_bool("CARGO_CFG_MIRI") + is_present("CARGO_CFG_MIRI") } /// If we are compiling with overflow checks enabled. @@ -208,7 +208,7 @@ mod cfg { #[cfg(feature = "unstable")] #[track_caller] pub fn cargo_cfg_overflow_checks() -> bool { - get_bool("CARGO_CFG_OVERFLOW_CHECKS") + is_present("CARGO_CFG_OVERFLOW_CHECKS") } /// The [panic strategy](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#panic). @@ -220,7 +220,7 @@ mod cfg { /// If the crate is being compiled as a procedural macro. #[track_caller] pub fn cargo_cfg_proc_macro() -> bool { - get_bool("CARGO_CFG_PROC_MACRO") + is_present("CARGO_CFG_PROC_MACRO") } /// The target relocation model. @@ -234,7 +234,7 @@ mod cfg { #[cfg(any())] #[track_caller] pub fn cargo_cfg_rustfmt() -> bool { - get_bool("CARGO_CFG_RUSTFMT") + is_present("CARGO_CFG_RUSTFMT") } /// Sanitizers enabled for the crate being compiled. @@ -251,7 +251,7 @@ mod cfg { #[cfg(feature = "unstable")] #[track_caller] pub fn cargo_cfg_sanitizer_cfi_generalize_pointers() -> bool { - get_bool("CARGO_CFG_SANITIZER_CFI_GENERALIZE_POINTERS") + is_present("CARGO_CFG_SANITIZER_CFI_GENERALIZE_POINTERS") } /// If CFI sanitization is normalizing integers. @@ -259,7 +259,7 @@ mod cfg { #[cfg(feature = "unstable")] #[track_caller] pub fn cargo_cfg_sanitizer_cfi_normalize_integers() -> bool { - get_bool("CARGO_CFG_SANITIZER_CFI_NORMALIZE_INTEGERS") + is_present("CARGO_CFG_SANITIZER_CFI_NORMALIZE_INTEGERS") } /// Disambiguation of the [target ABI](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#target_abi) @@ -349,7 +349,7 @@ mod cfg { #[cfg(feature = "unstable")] #[track_caller] pub fn cargo_cfg_target_thread_local() -> bool { - get_bool("CARGO_CFG_TARGET_THREAD_LOCAL") + is_present("CARGO_CFG_TARGET_THREAD_LOCAL") } /// The [target vendor](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#target_vendor). @@ -361,7 +361,7 @@ mod cfg { #[cfg(any())] #[track_caller] pub fn cargo_cfg_test() -> bool { - get_bool("CARGO_CFG_TEST") + is_present("CARGO_CFG_TEST") } /// If we are compiling with UB checks enabled. @@ -369,19 +369,19 @@ mod cfg { #[cfg(feature = "unstable")] #[track_caller] pub fn cargo_cfg_ub_checks() -> bool { - get_bool("CARGO_CFG_UB_CHECKS") + is_present("CARGO_CFG_UB_CHECKS") } /// Set on [unix-like platforms](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#unix-and-windows). #[track_caller] pub fn cargo_cfg_unix() -> bool { - get_bool("CARGO_CFG_UNIX") + is_present("CARGO_CFG_UNIX") } /// Set on [windows-like platforms](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#unix-and-windows). #[track_caller] pub fn cargo_cfg_windows() -> bool { - get_bool("CARGO_CFG_WINDOWS") + is_present("CARGO_CFG_WINDOWS") } } From f4193559c21228698805d73a17a692ddd3b7958a Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 13 Nov 2024 13:32:25 -0600 Subject: [PATCH 05/11] refactor(build-rs): Make env vars more composable --- crates/build-rs/src/input.rs | 251 ++++++++++++++++------------------- 1 file changed, 114 insertions(+), 137 deletions(-) diff --git a/crates/build-rs/src/input.rs b/crates/build-rs/src/input.rs index 7274af6c2c6..cd457e073da 100644 --- a/crates/build-rs/src/input.rs +++ b/crates/build-rs/src/input.rs @@ -6,94 +6,17 @@ //! //! Reference: -use crate::ident::{is_ascii_ident, is_crate_name, is_feature_name}; -use std::{ - env, - fmt::Display, - path::PathBuf, - str::{self, FromStr}, -}; - -macro_rules! missing { - ($key:expr) => { - panic!("cargo environment variable `{}` is missing", $key) - }; -} - -macro_rules! invalid { - ($key:expr, $err:expr) => { - panic!("cargo environment variable `{}` is invalid: {}", $key, $err) - }; -} - -#[track_caller] -fn is_present(key: &str) -> bool { - env::var_os(key).is_some() -} - -#[track_caller] -fn get_opt_path(key: &str) -> Option { - let var = env::var_os(key)?; - Some(PathBuf::from(var)) -} - -#[track_caller] -fn get_path(key: &str) -> PathBuf { - get_opt_path(key).unwrap_or_else(|| missing!(key)) -} - -#[track_caller] -fn get_opt_str(key: &str) -> Option { - let var = env::var_os(key)?; - match str::from_utf8(var.as_encoded_bytes()) { - Ok(s) => Some(s.to_owned()), - Err(err) => invalid!(key, err), - } -} - -#[track_caller] -fn get_str(key: &str) -> String { - get_opt_str(key).unwrap_or_else(|| missing!(key)) -} - -#[track_caller] -fn get_num(key: &str) -> T -where - T::Err: Display, -{ - let val = get_str(key); - match val.parse() { - Ok(num) => num, - Err(err) => invalid!(key, err), - } -} - -#[track_caller] -fn get_opt_cfg(cfg: &str) -> (String, Option>) { - if !is_ascii_ident(cfg) { - panic!("invalid configuration option {cfg:?}") - } - let cfg = cfg.to_uppercase().replace('-', "_"); - let key = format!("CARGO_CFG_{cfg}"); - let Some(var) = env::var_os(&key) else { - return (key, None); - }; - let val = str::from_utf8(var.as_encoded_bytes()).unwrap_or_else(|err| invalid!(key, err)); - (key, Some(val.split(',').map(str::to_owned).collect())) -} +use std::env::var_os; +use std::path::PathBuf; -#[track_caller] -fn get_cfg(cfg: &str) -> Vec { - let (key, val) = get_opt_cfg(cfg); - val.unwrap_or_else(|| missing!(key)) -} +use crate::ident::{is_ascii_ident, is_crate_name, is_feature_name}; // docs last updated to match release 1.82.0 reference /// Path to the `cargo` binary performing the build. #[track_caller] pub fn cargo() -> PathBuf { - get_path("CARGO") + to_path(var_or_panic("CARGO")) } /// The directory containing the manifest for the package being built (the package @@ -103,13 +26,13 @@ pub fn cargo() -> PathBuf { /// working directory of the build script when it starts. #[track_caller] pub fn cargo_manifest_dir() -> PathBuf { - get_path("CARGO_MANIFEST_DIR") + to_path(var_or_panic("CARGO_MANIFEST_DIR")) } /// The manifest `links` value. #[track_caller] pub fn cargo_manifest_links() -> Option { - get_opt_str("CARGO_MANIFEST_LINKS") + var_os("CARGO_MANIFEST_LINKS").map(to_string) } /// Contains parameters needed for Cargo’s [jobserver] implementation to parallelize @@ -124,7 +47,7 @@ pub fn cargo_manifest_links() -> Option { /// [jobserver]: https://www.gnu.org/software/make/manual/html_node/Job-Slots.html #[track_caller] pub fn cargo_makeflags() -> Option { - get_opt_str("CARGO_MAKEFLAGS") + var_os("CARGO_MAKEFLAGS").map(to_string) } /// For each activated feature of the package being built, this will be `true`. @@ -148,8 +71,18 @@ pub fn cargo_feature(name: &str) -> bool { /// [configuration option]: https://doc.rust-lang.org/stable/reference/conditional-compilation.html #[track_caller] pub fn cargo_cfg(cfg: &str) -> Option> { - let (_, val) = get_opt_cfg(cfg); - val + let var = cargo_cfg_var(cfg); + var_os(&var).map(|v| to_strings(v, ',')) +} + +#[track_caller] +fn cargo_cfg_var(cfg: &str) -> String { + if !is_ascii_ident(cfg) { + panic!("invalid configuration option {cfg:?}") + } + let cfg = cfg.to_uppercase().replace('-', "_"); + let key = format!("CARGO_CFG_{cfg}"); + key } pub use self::cfg::*; @@ -194,7 +127,7 @@ mod cfg { #[cfg(feature = "unstable")] #[track_caller] pub fn cargo_cfg_fmt_debug() -> String { - get_str("CARGO_CFG_FMT_DEBUG") + to_string(var_or_panic("CARGO_CFG_FMT_DEBUG")) } #[cfg(any())] @@ -214,7 +147,7 @@ mod cfg { /// The [panic strategy](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#panic). #[track_caller] pub fn cargo_cfg_panic() -> String { - get_str("CARGO_CFG_PANIC") + to_string(var_or_panic("CARGO_CFG_PANIC")) } /// If the crate is being compiled as a procedural macro. @@ -228,7 +161,7 @@ mod cfg { #[cfg(feature = "unstable")] #[track_caller] pub fn cargo_cfg_relocation_model() -> String { - get_str("CARGO_CFG_RELOCATION_MODEL") + to_string(var_or_panic("CARGO_CFG_RELOCATION_MODEL")) } #[cfg(any())] @@ -242,8 +175,7 @@ mod cfg { #[cfg(feature = "unstable")] #[track_caller] pub fn cargo_cfg_sanitize() -> Option> { - let (_, val) = get_opt_cfg("CARGO_CFG_SANITIZE"); - val + var_os("CARGO_CFG_SANITIZE").map(|v| to_strings(v, ',')) } /// If CFI sanitization is generalizing pointers. @@ -270,20 +202,20 @@ mod cfg { /// this value will be empty. #[track_caller] pub fn cargo_cfg_target_abi() -> String { - get_str("CARGO_CFG_TARGET_ABI") + to_string(var_or_panic("CARGO_CFG_TARGET_ABI")) } /// The CPU [target architecture](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#target_arch). /// This is similar to the first element of the platform's target triple, but not identical. #[track_caller] pub fn cargo_cfg_target_arch() -> String { - get_str("CARGO_CFG_TARGET_ARCH") + to_string(var_or_panic("CARGO_CFG_TARGET_ARCH")) } /// The CPU [target endianness](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#target_endian). #[track_caller] pub fn cargo_cfg_target_endian() -> String { - get_str("CARGO_CFG_TARGET_ENDIAN") + to_string(var_or_panic("CARGO_CFG_TARGET_ENDIAN")) } /// The [target environment](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#target_env) ABI. @@ -294,25 +226,25 @@ mod cfg { /// this value will be empty. #[track_caller] pub fn cargo_cfg_target_env() -> String { - get_str("CARGO_CFG_TARGET_ENV") + to_string(var_or_panic("CARGO_CFG_TARGET_ENV")) } /// The [target family](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#target_family). #[track_caller] pub fn cargo_target_family() -> Vec { - get_cfg("target_family") + to_strings(var_or_panic(&cargo_cfg_var("target_family")), ',') } /// List of CPU [target features](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#target_feature) enabled. #[track_caller] pub fn cargo_cfg_target_feature() -> Vec { - get_cfg("target_feature") + to_strings(var_or_panic(&cargo_cfg_var("target_feature")), ',') } /// List of CPU [supported atomic widths](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#target_has_atomic). #[track_caller] pub fn cargo_cfg_target_has_atomic() -> Vec { - get_cfg("target_has_atomic") + to_strings(var_or_panic(&cargo_cfg_var("target_has_atomic")), ',') } /// List of atomic widths that have equal alignment requirements. @@ -320,7 +252,10 @@ mod cfg { #[cfg(feature = "unstable")] #[track_caller] pub fn cargo_cfg_target_has_atomic_equal_alignment() -> Vec { - get_cfg("target_has_atomic_equal_alignment") + to_strings( + var_or_panic(&cargo_cfg_var("target_has_atomic_equal_alignment")), + ',', + ) } /// List of atomic widths that have atomic load and store operations. @@ -328,20 +263,23 @@ mod cfg { #[cfg(feature = "unstable")] #[track_caller] pub fn cargo_cfg_target_has_atomic_load_store() -> Vec { - get_cfg("target_has_atomic_load_store") + to_strings( + var_or_panic(&cargo_cfg_var("target_has_atomic_load_store")), + ',', + ) } /// The [target operating system](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#target_os). /// This value is similar to the second and third element of the platform's target triple. #[track_caller] pub fn cargo_cfg_target_os() -> String { - get_str("CARGO_CFG_TARGET_OS") + to_string(var_or_panic("CARGO_CFG_TARGET_OS")) } /// The CPU [pointer width](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#target_pointer_width). #[track_caller] pub fn cargo_cfg_target_pointer_width() -> u32 { - get_num("CARGO_CFG_TARGET_POINTER_WIDTH") + to_parsed(var_or_panic("CARGO_CFG_TARGET_POINTER_WIDTH")) } /// If the target supports thread-local storage. @@ -355,7 +293,7 @@ mod cfg { /// The [target vendor](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#target_vendor). #[track_caller] pub fn cargo_cfg_target_vendor() -> String { - get_str("CARGO_CFG_TARGET_VENDOR") + to_string(var_or_panic("CARGO_CFG_TARGET_VENDOR")) } #[cfg(any())] @@ -391,7 +329,7 @@ mod cfg { /// it is unique for the package in question. #[track_caller] pub fn out_dir() -> PathBuf { - get_path("OUT_DIR") + to_path(var_or_panic("OUT_DIR")) } /// The [target triple] that is being compiled for. Native code should be compiled @@ -400,13 +338,13 @@ pub fn out_dir() -> PathBuf { /// [target triple]: https://doc.rust-lang.org/stable/cargo/appendix/glossary.html#target #[track_caller] pub fn target() -> String { - get_str("TARGET") + to_string(var_or_panic("TARGET")) } /// The host triple of the Rust compiler. #[track_caller] pub fn host() -> String { - get_str("HOST") + to_string(var_or_panic("HOST")) } /// The parallelism specified as the top-level parallelism. @@ -421,19 +359,19 @@ pub fn host() -> String { /// [jobserver]: https://www.gnu.org/software/make/manual/html_node/Job-Slots.html #[track_caller] pub fn num_jobs() -> u32 { - get_num("NUM_JOBS") + to_parsed(var_or_panic("NUM_JOBS")) } /// The [level of optimization](https://doc.rust-lang.org/stable/cargo/reference/profiles.html#opt-level). #[track_caller] pub fn opt_level() -> String { - get_str("OPT_LEVEL") + to_string(var_or_panic("OPT_LEVEL")) } /// The amount of [debug information](https://doc.rust-lang.org/stable/cargo/reference/profiles.html#debug) included. #[track_caller] pub fn debug() -> String { - get_str("DEBUG") + to_string(var_or_panic("DEBUG")) } /// `release` for release builds, `debug` for other builds. @@ -448,7 +386,7 @@ pub fn debug() -> String { /// [`release`]: https://doc.rust-lang.org/stable/cargo/reference/profiles.html#release #[track_caller] pub fn profile() -> String { - get_str("PROFILE") + to_string(var_or_panic("PROFILE")) } /// [Metadata] set by dependencies. For more information, see build script @@ -468,19 +406,19 @@ pub fn dep_metadata(name: &str, key: &str) -> Option { let name = name.to_uppercase().replace('-', "_"); let key = key.to_uppercase().replace('-', "_"); let key = format!("DEP_{name}_{key}"); - get_opt_str(&key) + var_os(&key).map(to_string) } /// The compiler that Cargo has resolved to use. #[track_caller] pub fn rustc() -> PathBuf { - get_path("RUSTC") + to_path(var_or_panic("RUSTC")) } /// The documentation generator that Cargo has resolved to use. #[track_caller] pub fn rustdoc() -> PathBuf { - get_path("RUSTDOC") + to_path(var_or_panic("RUSTDOC")) } /// The rustc wrapper, if any, that Cargo is using. See [`build.rustc-wrapper`]. @@ -488,7 +426,7 @@ pub fn rustdoc() -> PathBuf { /// [`build.rustc-wrapper`]: https://doc.rust-lang.org/stable/cargo/reference/config.html#buildrustc-wrapper #[track_caller] pub fn rustc_wrapper() -> Option { - get_opt_path("RUSTC_WRAPPER") + var_os("RUSTC_WRAPPER").map(to_path) } /// The rustc wrapper, if any, that Cargo is using for workspace members. See @@ -497,7 +435,7 @@ pub fn rustc_wrapper() -> Option { /// [`build.rustc-workspace-wrapper`]: https://doc.rust-lang.org/stable/cargo/reference/config.html#buildrustc-workspace-wrapper #[track_caller] pub fn rustc_workspace_wrapper() -> Option { - get_opt_path("RUSTC_WORKSPACE_WRAPPER") + var_os("RUSTC_WORKSPACE_WRAPPER").map(to_path) } /// The linker that Cargo has resolved to use for the current target, if specified. @@ -505,7 +443,7 @@ pub fn rustc_workspace_wrapper() -> Option { /// [`target.*.linker`]: https://doc.rust-lang.org/stable/cargo/reference/config.html#targettriplelinker #[track_caller] pub fn rustc_linker() -> Option { - get_opt_path("RUSTC_LINKER") + var_os("RUSTC_LINKER").map(to_path) } /// Extra flags that Cargo invokes rustc with. See [`build.rustflags`]. @@ -513,96 +451,135 @@ pub fn rustc_linker() -> Option { /// [`build.rustflags`]: https://doc.rust-lang.org/stable/cargo/reference/config.html#buildrustflags #[track_caller] pub fn cargo_encoded_rustflags() -> Vec { - get_str("CARGO_ENCODED_RUSTFLAGS") - .split('\x1f') - .map(str::to_owned) - .collect() + to_strings(var_or_panic("CARGO_ENCODED_RUSTFLAGS"), '\x1f') } /// The full version of your package. #[track_caller] pub fn cargo_pkg_version() -> String { - get_str("CARGO_PKG_VERSION") + to_string(var_or_panic("CARGO_PKG_VERSION")) } /// The major version of your package. #[track_caller] pub fn cargo_pkg_version_major() -> u64 { - get_num("CARGO_PKG_VERSION_MAJOR") + to_parsed(var_or_panic("CARGO_PKG_VERSION_MAJOR")) } /// The minor version of your package. #[track_caller] pub fn cargo_pkg_version_minor() -> u64 { - get_num("CARGO_PKG_VERSION_MINOR") + to_parsed(var_or_panic("CARGO_PKG_VERSION_MINOR")) } /// The patch version of your package. #[track_caller] pub fn cargo_pkg_version_patch() -> u64 { - get_num("CARGO_PKG_VERSION_PATCH") + to_parsed(var_or_panic("CARGO_PKG_VERSION_PATCH")) } /// The pre-release version of your package. #[track_caller] pub fn cargo_pkg_version_pre() -> String { - get_str("CARGO_PKG_VERSION_PRE") + to_string(var_or_panic("CARGO_PKG_VERSION_PRE")) } /// Colon separated list of authors from the manifest of your package. #[track_caller] pub fn cargo_pkg_authors() -> Vec { - get_str("CARGO_PKG_AUTHORS") - .split(':') - .map(str::to_owned) - .collect() + to_strings(var_or_panic("CARGO_PKG_AUTHORS"), ':') } /// The name of your package. #[track_caller] pub fn cargo_pkg_name() -> String { - get_str("CARGO_PKG_NAME") + to_string(var_or_panic("CARGO_PKG_NAME")) } /// The description from the manifest of your package. #[track_caller] pub fn cargo_pkg_description() -> String { - get_str("CARGO_PKG_DESCRIPTION") + to_string(var_or_panic("CARGO_PKG_DESCRIPTION")) } /// The home page from the manifest of your package. #[track_caller] pub fn cargo_pkg_homepage() -> String { - get_str("CARGO_PKG_HOMEPAGE") + to_string(var_or_panic("CARGO_PKG_HOMEPAGE")) } /// The repository from the manifest of your package. #[track_caller] pub fn cargo_pkg_repository() -> String { - get_str("CARGO_PKG_REPOSITORY") + to_string(var_or_panic("CARGO_PKG_REPOSITORY")) } /// The license from the manifest of your package. #[track_caller] pub fn cargo_pkg_license() -> String { - get_str("CARGO_PKG_LICENSE") + to_string(var_or_panic("CARGO_PKG_LICENSE")) } /// The license file from the manifest of your package. #[track_caller] pub fn cargo_pkg_license_file() -> PathBuf { - get_path("CARGO_PKG_LICENSE_FILE") + to_path(var_or_panic("CARGO_PKG_LICENSE_FILE")) } /// The Rust version from the manifest of your package. Note that this is the /// minimum Rust version supported by the package, not the current Rust version. #[track_caller] pub fn cargo_pkg_rust_version() -> String { - get_str("CARGO_PKG_RUST_VERSION") + to_string(var_or_panic("CARGO_PKG_RUST_VERSION")) } /// Path to the README file of your package. #[track_caller] pub fn cargo_pkg_readme() -> PathBuf { - get_path("CARGO_PKG_README") + to_path(var_or_panic("CARGO_PKG_README")) +} + +fn is_present(key: &str) -> bool { + var_os(key).is_some() +} + +#[track_caller] +fn var_or_panic(key: &str) -> std::ffi::OsString { + var_os(key).unwrap_or_else(|| panic!("cargo environment variable `{key}` is missing")) +} + +fn to_path(value: std::ffi::OsString) -> PathBuf { + PathBuf::from(value) +} + +#[track_caller] +fn to_string(value: std::ffi::OsString) -> String { + match value.into_string() { + Ok(s) => s, + Err(value) => { + let err = std::str::from_utf8(value.as_encoded_bytes()).unwrap_err(); + panic!("{err}") + } + } +} + +#[track_caller] +fn to_strings(value: std::ffi::OsString, sep: char) -> Vec { + let value = to_string(value); + value.split(sep).map(str::to_owned).collect() +} + +#[track_caller] +fn to_parsed(value: std::ffi::OsString) -> T +where + T: std::str::FromStr, + T::Err: std::fmt::Display, +{ + let value = to_string(value); + match value.parse() { + Ok(s) => s, + Err(err) => { + panic!("{err}") + } + } } From 347fa09b1bab20e3d633a08276e16307c2cbf8e9 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 13 Nov 2024 13:42:46 -0600 Subject: [PATCH 06/11] perf(build-rs): Remove an allocation --- crates/build-rs/src/allow_use.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/build-rs/src/allow_use.rs b/crates/build-rs/src/allow_use.rs index 15e9787aa4b..c46dbbfc02f 100644 --- a/crates/build-rs/src/allow_use.rs +++ b/crates/build-rs/src/allow_use.rs @@ -25,7 +25,7 @@ fn cargo_version_minor() -> u32 { // > cargo -V # example output // cargo 1.82.0 (8f40fc59f 2024-08-21) - String::from_utf8(out.stdout).expect("`cargo -V` should output valid UTF-8") + std::str::from_utf8(&out.stdout).expect("`cargo -V` should output valid UTF-8") ["cargo 1.".len()..] .split('.') .next() From 27c577286ea59632da3ca6baff4422654fbfdc57 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 13 Nov 2024 13:44:04 -0600 Subject: [PATCH 07/11] refactor(build-rs): Extract minor version extraction --- crates/build-rs/src/allow_use.rs | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/crates/build-rs/src/allow_use.rs b/crates/build-rs/src/allow_use.rs index c46dbbfc02f..06220e388a1 100644 --- a/crates/build-rs/src/allow_use.rs +++ b/crates/build-rs/src/allow_use.rs @@ -3,13 +3,9 @@ use std::{process::Command, sync::OnceLock}; fn rust_version_minor() -> u32 { static VERSION_MINOR: OnceLock = OnceLock::new(); *VERSION_MINOR.get_or_init(|| { - crate::input::cargo_pkg_rust_version() - .split('.') - .nth(1) + version_minor(&crate::input::cargo_pkg_rust_version()) // assume build-rs's MSRV if none specified for the current package - .unwrap_or(env!("CARGO_PKG_RUST_VERSION").split('.').nth(1).unwrap()) - .parse() - .unwrap() + .unwrap_or_else(|| version_minor(env!("CARGO_PKG_RUST_VERSION")).unwrap()) }) } @@ -25,16 +21,18 @@ fn cargo_version_minor() -> u32 { // > cargo -V # example output // cargo 1.82.0 (8f40fc59f 2024-08-21) - std::str::from_utf8(&out.stdout).expect("`cargo -V` should output valid UTF-8") - ["cargo 1.".len()..] - .split('.') - .next() - .expect("`cargo -V` format should be stable") - .parse() - .unwrap() + let out = std::str::from_utf8(&out.stdout).expect("`cargo -V` should output valid UTF-8"); + let version = out.split(' ').nth(1).unwrap(); + version_minor(version).unwrap() }) } +fn version_minor(version: &str) -> Option { + let minor = version.split('.').nth(1)?; + let minor = minor.parse().unwrap(); + Some(minor) +} + pub(crate) fn double_colon_directives() -> bool { // cargo errors on `cargo::` directives with insufficient package.rust-version rust_version_minor() >= 77 From 4ff0809afde4588f580d80b3d12bd9896b658cb2 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 13 Nov 2024 13:49:23 -0600 Subject: [PATCH 08/11] fix(build-rs)!: Prefer None/empty-Vec to empty-String --- crates/build-rs/src/allow_use.rs | 2 +- crates/build-rs/src/input.rs | 47 ++++++++++++++++++-------------- 2 files changed, 28 insertions(+), 21 deletions(-) diff --git a/crates/build-rs/src/allow_use.rs b/crates/build-rs/src/allow_use.rs index 06220e388a1..7818e722edb 100644 --- a/crates/build-rs/src/allow_use.rs +++ b/crates/build-rs/src/allow_use.rs @@ -3,7 +3,7 @@ use std::{process::Command, sync::OnceLock}; fn rust_version_minor() -> u32 { static VERSION_MINOR: OnceLock = OnceLock::new(); *VERSION_MINOR.get_or_init(|| { - version_minor(&crate::input::cargo_pkg_rust_version()) + version_minor(&crate::input::cargo_pkg_rust_version().unwrap_or_default()) // assume build-rs's MSRV if none specified for the current package .unwrap_or_else(|| version_minor(env!("CARGO_PKG_RUST_VERSION")).unwrap()) }) diff --git a/crates/build-rs/src/input.rs b/crates/build-rs/src/input.rs index cd457e073da..94d19302a90 100644 --- a/crates/build-rs/src/input.rs +++ b/crates/build-rs/src/input.rs @@ -197,12 +197,12 @@ mod cfg { /// Disambiguation of the [target ABI](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#target_abi) /// when the [target env](cargo_cfg_target_env) isn't sufficient. /// - /// For historical reasons, this value is only defined as not the empty-string when + /// For historical reasons, this value is only defined as `Some` when /// actually needed for disambiguation. Thus, for example, on many GNU platforms, - /// this value will be empty. + /// this value will be `None`. #[track_caller] - pub fn cargo_cfg_target_abi() -> String { - to_string(var_or_panic("CARGO_CFG_TARGET_ABI")) + pub fn cargo_cfg_target_abi() -> Option { + to_opt(var_or_panic("CARGO_CFG_TARGET_ABI")).map(to_string) } /// The CPU [target architecture](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#target_arch). @@ -480,8 +480,8 @@ pub fn cargo_pkg_version_patch() -> u64 { /// The pre-release version of your package. #[track_caller] -pub fn cargo_pkg_version_pre() -> String { - to_string(var_or_panic("CARGO_PKG_VERSION_PRE")) +pub fn cargo_pkg_version_pre() -> Option { + to_opt(var_or_panic("CARGO_PKG_VERSION_PRE")).map(to_string) } /// Colon separated list of authors from the manifest of your package. @@ -498,45 +498,45 @@ pub fn cargo_pkg_name() -> String { /// The description from the manifest of your package. #[track_caller] -pub fn cargo_pkg_description() -> String { - to_string(var_or_panic("CARGO_PKG_DESCRIPTION")) +pub fn cargo_pkg_description() -> Option { + to_opt(var_or_panic("CARGO_PKG_DESCRIPTION")).map(to_string) } /// The home page from the manifest of your package. #[track_caller] -pub fn cargo_pkg_homepage() -> String { - to_string(var_or_panic("CARGO_PKG_HOMEPAGE")) +pub fn cargo_pkg_homepage() -> Option { + to_opt(var_or_panic("CARGO_PKG_HOMEPAGE")).map(to_string) } /// The repository from the manifest of your package. #[track_caller] -pub fn cargo_pkg_repository() -> String { - to_string(var_or_panic("CARGO_PKG_REPOSITORY")) +pub fn cargo_pkg_repository() -> Option { + to_opt(var_or_panic("CARGO_PKG_REPOSITORY")).map(to_string) } /// The license from the manifest of your package. #[track_caller] -pub fn cargo_pkg_license() -> String { - to_string(var_or_panic("CARGO_PKG_LICENSE")) +pub fn cargo_pkg_license() -> Option { + to_opt(var_or_panic("CARGO_PKG_LICENSE")).map(to_string) } /// The license file from the manifest of your package. #[track_caller] -pub fn cargo_pkg_license_file() -> PathBuf { - to_path(var_or_panic("CARGO_PKG_LICENSE_FILE")) +pub fn cargo_pkg_license_file() -> Option { + to_opt(var_or_panic("CARGO_PKG_LICENSE_FILE")).map(to_path) } /// The Rust version from the manifest of your package. Note that this is the /// minimum Rust version supported by the package, not the current Rust version. #[track_caller] -pub fn cargo_pkg_rust_version() -> String { - to_string(var_or_panic("CARGO_PKG_RUST_VERSION")) +pub fn cargo_pkg_rust_version() -> Option { + to_opt(var_or_panic("CARGO_PKG_RUST_VERSION")).map(to_string) } /// Path to the README file of your package. #[track_caller] -pub fn cargo_pkg_readme() -> PathBuf { - to_path(var_or_panic("CARGO_PKG_README")) +pub fn cargo_pkg_readme() -> Option { + to_opt(var_or_panic("CARGO_PKG_README")).map(to_path) } fn is_present(key: &str) -> bool { @@ -563,8 +563,15 @@ fn to_string(value: std::ffi::OsString) -> String { } } +fn to_opt(value: std::ffi::OsString) -> Option { + (!value.is_empty()).then_some(value) +} + #[track_caller] fn to_strings(value: std::ffi::OsString, sep: char) -> Vec { + if value.is_empty() { + return Vec::new(); + } let value = to_string(value); value.split(sep).map(str::to_owned).collect() } From 611ec991fbf4fe5af4714563d0906c1c2aee1981 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 13 Nov 2024 13:54:48 -0600 Subject: [PATCH 09/11] feat(build-rs): Add cargo_manifest_path --- crates/build-rs-test-lib/build.rs | 1 + crates/build-rs/src/input.rs | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/crates/build-rs-test-lib/build.rs b/crates/build-rs-test-lib/build.rs index a6065ef0385..1167a34907e 100644 --- a/crates/build-rs-test-lib/build.rs +++ b/crates/build-rs-test-lib/build.rs @@ -47,6 +47,7 @@ fn smoke_test_inputs() { dbg!(cargo_encoded_rustflags()); dbg!(cargo_feature("unstable")); dbg!(cargo_manifest_dir()); + dbg!(cargo_manifest_path()); dbg!(cargo_manifest_links()); dbg!(cargo_pkg_authors()); dbg!(cargo_pkg_description()); diff --git a/crates/build-rs/src/input.rs b/crates/build-rs/src/input.rs index 94d19302a90..93faf140041 100644 --- a/crates/build-rs/src/input.rs +++ b/crates/build-rs/src/input.rs @@ -29,6 +29,18 @@ pub fn cargo_manifest_dir() -> PathBuf { to_path(var_or_panic("CARGO_MANIFEST_DIR")) } +/// The path to the manifest of your package. +#[track_caller] +pub fn cargo_manifest_path() -> PathBuf { + var_os("CARGO_MANIFEST_PATH") + .map(to_path) + .unwrap_or_else(|| { + let mut path = cargo_manifest_dir(); + path.push("Cargo.toml"); + path + }) +} + /// The manifest `links` value. #[track_caller] pub fn cargo_manifest_links() -> Option { From 8b43030bb7b6eb8ad5957ea406418c082ef06634 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 13 Nov 2024 13:55:14 -0600 Subject: [PATCH 10/11] chore(build-rs): Remove comment about update At this point, it is assumed to always be up-to-date --- crates/build-rs/src/input.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/build-rs/src/input.rs b/crates/build-rs/src/input.rs index 93faf140041..51c7c85448a 100644 --- a/crates/build-rs/src/input.rs +++ b/crates/build-rs/src/input.rs @@ -11,8 +11,6 @@ use std::path::PathBuf; use crate::ident::{is_ascii_ident, is_crate_name, is_feature_name}; -// docs last updated to match release 1.82.0 reference - /// Path to the `cargo` binary performing the build. #[track_caller] pub fn cargo() -> PathBuf { From c02c9f2517f34a9850f8e297d48c87d1047a07e2 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 13 Nov 2024 14:46:11 -0600 Subject: [PATCH 11/11] docs(build-rs): Remove reference to encoding --- crates/build-rs/src/input.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/build-rs/src/input.rs b/crates/build-rs/src/input.rs index 51c7c85448a..6f564f8c68b 100644 --- a/crates/build-rs/src/input.rs +++ b/crates/build-rs/src/input.rs @@ -494,7 +494,7 @@ pub fn cargo_pkg_version_pre() -> Option { to_opt(var_or_panic("CARGO_PKG_VERSION_PRE")).map(to_string) } -/// Colon separated list of authors from the manifest of your package. +/// The authors from the manifest of your package. #[track_caller] pub fn cargo_pkg_authors() -> Vec { to_strings(var_or_panic("CARGO_PKG_AUTHORS"), ':')