2019-01-26 13:02:58 -08:00
|
|
|
|
// Copyright © 2018–2019 Trevor Spiteri
|
2018-08-10 11:35:09 -07:00
|
|
|
|
|
|
|
|
|
// Copying and distribution of this file, with or without
|
|
|
|
|
// modification, are permitted in any medium without royalty provided
|
|
|
|
|
// the copyright notice and this notice are preserved. This file is
|
|
|
|
|
// offered as-is, without any warranty.
|
|
|
|
|
|
2019-02-02 11:20:53 -08:00
|
|
|
|
#![allow(dead_code)]
|
|
|
|
|
#![allow(unused_variables)]
|
2019-08-03 14:48:43 -07:00
|
|
|
|
#![cfg_attr(feature = "fail-on-warnings", deny(warnings))]
|
2019-02-02 11:20:53 -08:00
|
|
|
|
|
2019-08-06 13:54:21 -07:00
|
|
|
|
use std::{
|
|
|
|
|
env,
|
|
|
|
|
ffi::OsString,
|
|
|
|
|
fs::{self, File},
|
|
|
|
|
io::{Result as IoResult, Write},
|
|
|
|
|
path::{Path, PathBuf},
|
|
|
|
|
process::Command,
|
|
|
|
|
};
|
2018-08-10 11:35:09 -07:00
|
|
|
|
|
|
|
|
|
struct Environment {
|
|
|
|
|
out_dir: PathBuf,
|
|
|
|
|
rustc: OsString,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
|
let env = Environment {
|
|
|
|
|
out_dir: PathBuf::from(cargo_env("OUT_DIR")),
|
|
|
|
|
rustc: cargo_env("RUSTC"),
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-13 03:10:53 -07:00
|
|
|
|
#[derive(PartialEq)]
|
|
|
|
|
struct Optional(bool);
|
|
|
|
|
|
2018-08-10 11:35:09 -07:00
|
|
|
|
impl Environment {
|
2018-08-13 03:10:53 -07:00
|
|
|
|
// 1. If optional feature is availble (both with and without flag), output:
|
|
|
|
|
// cargo:rustc-cfg=<name>
|
|
|
|
|
// 2. If feature is available with flag (both optional and not), output:
|
2019-02-02 11:20:53 -08:00
|
|
|
|
// cargo:rustc-cfg=nightly_<name>
|
2018-08-13 03:10:53 -07:00
|
|
|
|
// 3. If non-optional feature is not available, panic.
|
|
|
|
|
fn check_feature(
|
|
|
|
|
&self,
|
|
|
|
|
name: &str,
|
|
|
|
|
optional: Optional,
|
|
|
|
|
contents: &str,
|
|
|
|
|
nightly_features: Option<&str>,
|
|
|
|
|
) {
|
2018-08-10 11:35:09 -07:00
|
|
|
|
let try_dir = self.out_dir.join(format!("try_{}", name));
|
|
|
|
|
let filename = format!("try_{}.rs", name);
|
|
|
|
|
create_dir_or_panic(&try_dir);
|
|
|
|
|
println!("$ cd {:?}", try_dir);
|
|
|
|
|
|
2018-08-13 03:10:53 -07:00
|
|
|
|
#[derive(PartialEq)]
|
2018-08-10 11:35:09 -07:00
|
|
|
|
enum Iteration {
|
|
|
|
|
Stable,
|
|
|
|
|
Unstable,
|
|
|
|
|
}
|
2018-08-13 03:10:53 -07:00
|
|
|
|
let mut found = false;
|
2018-08-10 11:35:09 -07:00
|
|
|
|
for i in &[Iteration::Stable, Iteration::Unstable] {
|
|
|
|
|
let s;
|
|
|
|
|
let file_contents = match *i {
|
|
|
|
|
Iteration::Stable => contents,
|
|
|
|
|
Iteration::Unstable => match nightly_features {
|
|
|
|
|
Some(features) => {
|
|
|
|
|
s = format!("#![feature({})]\n{}", features, contents);
|
|
|
|
|
&s
|
|
|
|
|
}
|
|
|
|
|
None => continue,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
create_file_or_panic(&try_dir.join(&filename), file_contents);
|
|
|
|
|
let mut cmd = Command::new(&self.rustc);
|
|
|
|
|
cmd.current_dir(&try_dir)
|
|
|
|
|
.args(&[&filename, "--emit=dep-info,metadata"]);
|
|
|
|
|
println!("$ {:?}", cmd);
|
|
|
|
|
let status = cmd
|
|
|
|
|
.status()
|
|
|
|
|
.unwrap_or_else(|_| panic!("Unable to execute: {:?}", cmd));
|
|
|
|
|
if status.success() {
|
2019-02-02 11:20:53 -08:00
|
|
|
|
if optional.0 {
|
2018-08-13 03:10:53 -07:00
|
|
|
|
println!("cargo:rustc-cfg={}", name);
|
|
|
|
|
}
|
|
|
|
|
if *i == Iteration::Unstable {
|
2018-08-10 11:35:09 -07:00
|
|
|
|
println!("cargo:rustc-cfg=nightly_{}", name);
|
|
|
|
|
}
|
2018-08-13 03:10:53 -07:00
|
|
|
|
found = true;
|
2018-08-10 11:35:09 -07:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
remove_dir_or_panic(&try_dir);
|
2018-08-13 03:10:53 -07:00
|
|
|
|
if !found && !optional.0 {
|
|
|
|
|
panic!("essential feature not supported by compiler: {}", name);
|
|
|
|
|
}
|
2018-08-10 11:35:09 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn cargo_env(name: &str) -> OsString {
|
|
|
|
|
env::var_os(name)
|
|
|
|
|
.unwrap_or_else(|| panic!("environment variable not found: {}, please use cargo", name))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn remove_dir(dir: &Path) -> IoResult<()> {
|
|
|
|
|
if !dir.exists() {
|
|
|
|
|
return Ok(());
|
|
|
|
|
}
|
|
|
|
|
assert!(dir.is_dir(), "Not a directory: {:?}", dir);
|
|
|
|
|
println!("$ rm -r {:?}", dir);
|
|
|
|
|
fs::remove_dir_all(dir)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn remove_dir_or_panic(dir: &Path) {
|
|
|
|
|
remove_dir(dir).unwrap_or_else(|_| panic!("Unable to remove directory: {:?}", dir));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn create_dir(dir: &Path) -> IoResult<()> {
|
|
|
|
|
println!("$ mkdir -p {:?}", dir);
|
|
|
|
|
fs::create_dir_all(dir)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn create_dir_or_panic(dir: &Path) {
|
|
|
|
|
create_dir(dir).unwrap_or_else(|_| panic!("Unable to create directory: {:?}", dir));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn create_file_or_panic(filename: &Path, contents: &str) {
|
|
|
|
|
println!("$ printf '%s' {:?}... > {:?}", &contents[0..20], filename);
|
|
|
|
|
let mut file =
|
|
|
|
|
File::create(filename).unwrap_or_else(|_| panic!("Unable to create file: {:?}", filename));
|
|
|
|
|
file.write_all(contents.as_bytes())
|
|
|
|
|
.unwrap_or_else(|_| panic!("Unable to write to file: {:?}", filename));
|
|
|
|
|
}
|