diff --git a/Cargo.toml b/Cargo.toml index a633b19..89d2f38 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,4 @@ members = ["test_suite"] [lib] proc-macro = true -[build-dependencies] -version_check = "0.9.2" - [dependencies] diff --git a/README.md b/README.md index bd9af37..325b789 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ pub const fn feature() { ## Alternatives -This crate is proc-macro, but is very lightweight, depending only on [`version_check`](https://github.com/SergioBenitez/version_check) to determine the compiler version. +This crate is proc-macro, but is very lightweight, and has no dependencies. You can manually define declarative macros with similar functionality (see [`if_rust_version`](https://github.com/ogoffart/if_rust_version#examples)), or [you can define the same function twice with different cfg](https://github.com/crossbeam-rs/crossbeam/blob/0b6ea5f69fde8768c1cfac0d3601e0b4325d7997/crossbeam-epoch/src/atomic.rs#L340-L372). (Note: the former approach requires more macros to be defined depending on the number of version requirements, the latter approach requires more functions to be maintained manually) diff --git a/build.rs b/build.rs index e7dd22f..758b390 100644 --- a/build.rs +++ b/build.rs @@ -1,4 +1,9 @@ -use std::{env, fs, path::PathBuf}; +use std::{ + env, fs, + path::{Path, PathBuf}, + process::Command, + str, +}; // The rustc-cfg strings below are *not* public API. Please let us know by // opening a GitHub issue if your build environment requires some way to enable @@ -6,9 +11,10 @@ use std::{env, fs, path::PathBuf}; fn main() { println!("cargo:rustc-cfg=const_fn_has_build_script"); - let version = match Version::new() { - Some(version) => format!("{:#?}\n", version), - None => panic!("unexpected output from `rustc --version`"), + let rustc = env::var_os("RUSTC").map_or_else(|| "rustc".into(), PathBuf::from); + let version = match Version::from_rustc(&rustc) { + Ok(version) => format!("{:#?}\n", version), + Err(e) => panic!("{}", e), }; let out_dir = env::var_os("OUT_DIR").map(PathBuf::from).expect("OUT_DIR not set"); @@ -23,11 +29,50 @@ struct Version { nightly: bool, } +// Based on https://github.com/cuviper/autocfg/blob/1.0.1/src/version.rs +// +// Using our own parser instead of the existing crates to generate better errors. impl Version { - fn new() -> Option { - let (version, channel, _date) = version_check::triple()?; - let (_major, minor, patch) = version.to_mmp(); - let nightly = channel.is_nightly() || channel.is_dev(); + // from the verbose version output + fn from_vv(vv: &str) -> Option { + // Find the release line in the verbose version output. + let release = vv + .lines() + .find(|line| line.starts_with("release: ")) + .map(|line| &line["release: ".len()..])?; + + // Split the version and channel info. + let mut version_channel = release.split('-'); + let version = version_channel.next().unwrap(); + let channel = version_channel.next(); + + // Split the version into semver components. + let mut digits = version.splitn(3, '.'); + let major = digits.next()?; + if major != "1" { + return None; + } + let minor = digits.next()?.parse().ok()?; + let patch = digits.next().unwrap_or("0").parse().ok()?; + + let nightly = channel.map_or(false, |c| c == "dev" || c == "nightly"); Some(Version { minor, patch, nightly }) } + + fn from_rustc(rustc: &Path) -> Result { + let output = + Command::new(rustc).args(&["--version", "--verbose"]).output().map_err(|e| { + format!("failed to run `{} --version --verbose`: {}", rustc.display(), e) + })?; + if !output.status.success() { + return Err("could not execute rustc".to_string()); + } + let output = str::from_utf8(&output.stdout).map_err(|e| { + format!("failed to parse output of `{} --version --verbose`: {}", rustc.display(), e) + })?; + + Self::from_vv(output).ok_or_else(|| { + format!("unexpected output from `{} --version --verbose`: {}", rustc.display(), output) + }) + } } diff --git a/src/lib.rs b/src/lib.rs index 16dff80..af384af 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,7 +34,7 @@ //! //! # Alternatives //! -//! This crate is proc-macro, but is very lightweight, depending only on [`version_check`](https://github.com/SergioBenitez/version_check) to determine the compiler version. +//! This crate is proc-macro, but is very lightweight, and has no dependencies. //! //! You can manually define declarative macros with similar functionality (see [`if_rust_version`](https://github.com/ogoffart/if_rust_version#examples)), or [you can define the same function twice with different cfg](https://github.com/crossbeam-rs/crossbeam/blob/0b6ea5f69fde8768c1cfac0d3601e0b4325d7997/crossbeam-epoch/src/atomic.rs#L340-L372). //! (Note: the former approach requires more macros to be defined depending on the number of version requirements, the latter approach requires more functions to be maintained manually)