|
| 1 | +//! This build script ensures that clippy is not compiled with an |
| 2 | +//! incompatible version of rust. It will panic with a descriptive |
| 3 | +//! error message instead. |
| 4 | +//! |
| 5 | +//! We specifially want to ensure that clippy is only built with a |
| 6 | +//! rustc version that is newer or equal to the one specified in the |
| 7 | +//! `min_version.txt` file. |
| 8 | +//! |
| 9 | +//! `min_version.txt` is in the repo but also in the `.gitignore` to |
| 10 | +//! make sure that it is not updated manually by accident. Only CI |
| 11 | +//! should update that file. |
| 12 | +//! |
| 13 | +//! This build script was originally taken from the Rocket web framework: |
| 14 | +//! https://github.com/SergioBenitez/Rocket |
| 15 | +
|
| 16 | +extern crate rustc_version; |
| 17 | +extern crate ansi_term; |
| 18 | + |
1 | 19 | use std::env;
|
| 20 | +use rustc_version::{version_meta, version_meta_for, Channel, Version, VersionMeta}; |
| 21 | +use ansi_term::Colour::Red; |
2 | 22 |
|
3 | 23 | fn main() {
|
| 24 | + let string = include_str!("min_version.txt"); |
| 25 | + let min_version_meta = version_meta_for(string) |
| 26 | + .expect("Could not parse version string in min_version.txt"); |
| 27 | + let current_version_meta = version_meta() |
| 28 | + .expect("Could not retrieve current rustc version information from ENV"); |
| 29 | + |
| 30 | + let min_version = min_version_meta.clone().semver; |
| 31 | + let min_date_str = min_version_meta.clone().commit_date |
| 32 | + .expect("min_version.txt does not contain a rustc commit date"); |
| 33 | + |
| 34 | + let current_version = current_version_meta.clone().semver; |
| 35 | + let current_date_str = current_version_meta.clone().commit_date |
| 36 | + .expect("current rustc version information does not contain a rustc commit date"); |
| 37 | + |
| 38 | + let print_version_err = |version: &Version, date: &str| { |
| 39 | + eprintln!("> {} {}. {} {}.\n", |
| 40 | + "Installed rustc version is:", |
| 41 | + format!("{} ({})", version, date), |
| 42 | + "Minimum required rustc version:", |
| 43 | + format!("{} ({})", min_version, min_date_str)); |
| 44 | + }; |
| 45 | + |
| 46 | + if !correct_channel(¤t_version_meta) { |
| 47 | + eprintln!("\n{} {}", |
| 48 | + Red.bold().paint("error:"), |
| 49 | + "clippy requires a nightly version of Rust."); |
| 50 | + print_version_err(¤t_version, &*current_date_str); |
| 51 | + eprintln!("{}{}{}", |
| 52 | + "See the README (", |
| 53 | + "https://github.com/rust-lang-nursery/rust-clippy#usage", |
| 54 | + ") for more information."); |
| 55 | + panic!("Aborting compilation due to incompatible compiler.") |
| 56 | + } |
| 57 | + |
| 58 | + let current_date = str_to_ymd(¤t_date_str).unwrap(); |
| 59 | + let min_date = str_to_ymd(&min_date_str).unwrap(); |
| 60 | + |
| 61 | + if current_date < min_date { |
| 62 | + eprintln!("\n{} {}", |
| 63 | + Red.bold().paint("error:"), |
| 64 | + "clippy does not support this version of rustc nightly."); |
| 65 | + eprintln!("> {}{}{}", |
| 66 | + "Use `", |
| 67 | + "rustup update", |
| 68 | + "` or your preferred method to update Rust."); |
| 69 | + print_version_err(¤t_version, &*current_date_str); |
| 70 | + panic!("Aborting compilation due to incompatible compiler.") |
| 71 | + } |
| 72 | + |
4 | 73 | // Forward the profile to the main compilation
|
5 | 74 | println!("cargo:rustc-env=PROFILE={}", env::var("PROFILE").unwrap());
|
6 | 75 | // Don't rebuild even if nothing changed
|
7 | 76 | println!("cargo:rerun-if-changed=build.rs");
|
8 | 77 | }
|
| 78 | + |
| 79 | +fn correct_channel(version_meta: &VersionMeta) -> bool { |
| 80 | + match version_meta.channel { |
| 81 | + Channel::Stable | Channel::Beta => { |
| 82 | + false |
| 83 | + }, |
| 84 | + Channel::Nightly | Channel::Dev => { |
| 85 | + true |
| 86 | + } |
| 87 | + } |
| 88 | +} |
| 89 | + |
| 90 | +/// Convert a string of %Y-%m-%d to a single u32 maintaining ordering. |
| 91 | +fn str_to_ymd(ymd: &str) -> Option<u32> { |
| 92 | + let ymd: Vec<u32> = ymd.split("-").filter_map(|s| s.parse::<u32>().ok()).collect(); |
| 93 | + if ymd.len() != 3 { |
| 94 | + return None |
| 95 | + } |
| 96 | + |
| 97 | + let (y, m, d) = (ymd[0], ymd[1], ymd[2]); |
| 98 | + Some((y << 9) | (m << 5) | d) |
| 99 | +} |
0 commit comments