From 307469dc3a9a040633e57fa165a45af5c9c4eb47 Mon Sep 17 00:00:00 2001 From: Sergio Benitez Date: Sun, 15 Jan 2017 01:16:47 -0800 Subject: [PATCH] Refuse to build on non-nightly with a nice message. --- codegen/Cargo.toml | 1 + codegen/build.rs | 78 ++++++++++++++++++++++------------------------ lib/Cargo.toml | 5 +++ lib/build.rs | 60 +++++++++++++++++++++++++++++++++++ 4 files changed, 103 insertions(+), 41 deletions(-) create mode 100644 lib/build.rs diff --git a/codegen/Cargo.toml b/codegen/Cargo.toml index 96e937e8..3916b7d8 100644 --- a/codegen/Cargo.toml +++ b/codegen/Cargo.toml @@ -23,3 +23,4 @@ compiletest_rs = "^0.2" [build-dependencies] ansi_term = "^0.9" +version_check = "^0.1" diff --git a/codegen/build.rs b/codegen/build.rs index 5d27bca0..d481e1f9 100644 --- a/codegen/build.rs +++ b/codegen/build.rs @@ -1,20 +1,15 @@ -#![feature(slice_patterns)] - //! This tiny build script ensures that rocket_codegen is not compiled with an -//! incompatible version of rust. It does this by executing `rustc --version` -//! and comparing the version to `MIN_VERSION`, the minimum required version. If -//! the installed version is less than the minimum required version, an error is -//! printed out to the console and compilation is halted. +//! incompatible version of rust. extern crate ansi_term; - -use std::env; -use std::process::Command; +extern crate version_check; use ansi_term::Colour::{Red, Yellow, Blue, White}; +use version_check::{is_nightly, is_min_version, is_min_date}; // Specifies the minimum nightly version needed to compile Rocket's codegen. -const MIN_VERSION: &'static str = "2017-01-03"; +const MIN_DATE: &'static str = "2017-01-03"; +const MIN_VERSION: &'static str = "1.16.0-nightly"; // Convenience macro for writing to stderr. macro_rules! printerr { @@ -25,47 +20,48 @@ macro_rules! printerr { }) } -// Convert a string of %Y-%m-%d to a single u32 maintaining ordering. -fn str_to_ymd(ymd: &str) -> Option { - let ymd: Vec<_> = ymd.split("-").filter_map(|s| s.parse::().ok()).collect(); - match ymd.as_slice() { - &[y, m, d] => Some((y << 9) | (m << 5) | d), - _ => None, - } -} - fn main() { - // Run rustc to get the version information. - let output = env::var("RUSTC").ok() - .and_then(|rustc| Command::new(rustc).arg("--version").output().ok()) - .and_then(|output| String::from_utf8(output.stdout).ok()) - .and_then(|s| s.split(" ").nth(3).map(|s| s.to_string())) - .map(|s| s.trim_right().trim_right_matches(")").to_string()); + let ok_nightly = is_nightly(); + let ok_version = is_min_version(MIN_VERSION); + let ok_date = is_min_date(MIN_DATE); - if let Some(ref version) = output { - let needed = str_to_ymd(MIN_VERSION); - let actual = str_to_ymd(version); - if let (Some(needed), Some(actual)) = (needed, actual) { - if actual < needed { + let print_version_err = |version: &str, date: &str| { + printerr!("{} {}. {} {}.", + White.paint("Installed version is:"), + Yellow.paint(format!("{} ({})", version, date)), + White.paint("Minimum required:"), + Yellow.paint(format!("{} ({})", MIN_VERSION, MIN_DATE))); + }; + + match (ok_nightly, ok_version, ok_date) { + (Some(is_nightly), Some((ok_version, version)), Some((ok_date, date))) => { + if !is_nightly { printerr!("{} {}", Red.bold().paint("Error:"), - White.paint("Rocket codegen requires a newer version of rustc.")); + White.paint("Rocket requires a nightly version of Rust.")); + print_version_err(&*version, &*date); + printerr!("{}{}{}", + Blue.paint("See the getting started guide ("), + White.paint("https://rocket.rs/guide/getting-started/"), + Blue.paint(") for more information.")); + panic!("Aborting compilation due to incompatible compiler.") + } + + if !ok_version || !ok_date { + printerr!("{} {}", + Red.bold().paint("Error:"), + White.paint("Rocket codegen requires a more recent version of rustc.")); printerr!("{}{}{}", Blue.paint("Use `"), White.paint("rustup update"), Blue.paint("` or your preferred method to update Rust.")); - printerr!("{} {}. {} {}.", - White.paint("Installed version is:"), - Yellow.paint(version.as_str()), - White.paint("Minimum required:"), - Yellow.paint(MIN_VERSION)); + print_version_err(&*version, &*date); panic!("Aborting compilation due to incompatible compiler.") - } else { - return; } + }, + _ => { + println!("cargo:warning={}", "Rocket was unable to check rustc compatibility."); + println!("cargo:warning={}", "Build may fail due to incompatible rustc version."); } } - - printerr!("{}", Yellow.paint("Warning: Rocket was unable to check rustc compatibility.")); - printerr!("{}", Yellow.paint("Build may fail due to incompatible rustc version.")); } diff --git a/lib/Cargo.toml b/lib/Cargo.toml index ad75fa92..7336bab0 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -12,6 +12,7 @@ repository = "https://github.com/SergioBenitez/Rocket" readme = "../README.md" keywords = ["rocket", "web", "framework", "server"] license = "MIT/Apache-2.0" +build = "build.rs" [dependencies] term-painter = "^0.2" @@ -29,5 +30,9 @@ default-features = false lazy_static = "0.2" rocket_codegen = { version = "0.1.5", path = "../codegen" } +[build-dependencies] +ansi_term = "^0.9" +version_check = "^0.1" + [features] testing = [] diff --git a/lib/build.rs b/lib/build.rs new file mode 100644 index 00000000..7fa9f524 --- /dev/null +++ b/lib/build.rs @@ -0,0 +1,60 @@ +//! This tiny build script ensures that rocket is not compiled with an +//! incompatible version of rust. + +extern crate ansi_term; +extern crate version_check; + +use ansi_term::Colour::{Red, Yellow, Blue, White}; +use version_check::{is_nightly, is_min_version}; + +// Specifies the minimum nightly version needed to compile Rocket. +const MIN_VERSION: &'static str = "1.16.0-nightly"; + +// Convenience macro for writing to stderr. +macro_rules! printerr { + ($($arg:tt)*) => ({ + use std::io::prelude::*; + write!(&mut ::std::io::stderr(), "{}\n", format_args!($($arg)*)) + .expect("Failed to write to stderr.") + }) +} + +fn main() { + let (ok_nightly, ok_version) = (is_nightly(), is_min_version(MIN_VERSION)); + let print_version_err = |version: &str| { + printerr!("{} {}. {} {}.", + White.paint("Installed version is:"), + Yellow.paint(version), + White.paint("Minimum required:"), + Yellow.paint(MIN_VERSION)); + }; + + if let (Some(is_nightly), Some((ok_version, version))) = (ok_nightly, ok_version) { + if !is_nightly { + printerr!("{} {}", + Red.bold().paint("Error:"), + White.paint("Rocket requires a nightly version of Rust.")); + print_version_err(&*version); + printerr!("{}{}{}", + Blue.paint("See the getting started guide ("), + White.paint("https://rocket.rs/guide/getting-started/"), + Blue.paint(") for more information.")); + panic!("Aborting compilation due to incompatible compiler.") + } + + if !ok_version { + printerr!("{} {}", + Red.bold().paint("Error:"), + White.paint("Rocket requires a newer version of rustc.")); + printerr!("{}{}{}", + Blue.paint("Use `"), + White.paint("rustup update"), + Blue.paint("` or your preferred method to update Rust.")); + print_version_err(&*version); + panic!("Aborting compilation due to incompatible compiler.") + } + } else { + println!("cargo:warning={}", "Rocket was unable to check rustc compatibility."); + println!("cargo:warning={}", "Build may fail due to incompatible rustc version."); + } +}