check for repr(transparent) in build.rs
This commit is contained in:
parent
ca3e48f699
commit
51c83a7b02
|
@ -0,0 +1,117 @@
|
||||||
|
// Copyright © 2018 Trevor Spiteri
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
use std::env;
|
||||||
|
use std::ffi::OsString;
|
||||||
|
use std::fs::{self, File};
|
||||||
|
use std::io::{Result as IoResult, Write};
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
struct Environment {
|
||||||
|
out_dir: PathBuf,
|
||||||
|
rustc: OsString,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let env = Environment {
|
||||||
|
out_dir: PathBuf::from(cargo_env("OUT_DIR")),
|
||||||
|
rustc: cargo_env("RUSTC"),
|
||||||
|
};
|
||||||
|
env.check_feature(
|
||||||
|
"repr_transparent",
|
||||||
|
TRY_REPR_TRANSPARENT,
|
||||||
|
Some("repr_transparent"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Environment {
|
||||||
|
fn check_feature(&self, name: &str, contents: &str, nightly_features: Option<&str>) {
|
||||||
|
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);
|
||||||
|
|
||||||
|
enum Iteration {
|
||||||
|
Stable,
|
||||||
|
Unstable,
|
||||||
|
}
|
||||||
|
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() {
|
||||||
|
println!("cargo:rustc-cfg={}", name);
|
||||||
|
if let Iteration::Unstable = *i {
|
||||||
|
println!("cargo:rustc-cfg=nightly_{}", name);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_dir_or_panic(&try_dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
const TRY_REPR_TRANSPARENT: &str = r#"// try_repr_transparent.rs
|
||||||
|
#[repr(transparent)]
|
||||||
|
struct Foo(i32);
|
||||||
|
fn main() {
|
||||||
|
let _ = Foo(12);
|
||||||
|
}
|
||||||
|
"#;
|
|
@ -81,6 +81,7 @@ additional terms or conditions.
|
||||||
#![warn(missing_docs)]
|
#![warn(missing_docs)]
|
||||||
#![doc(html_root_url = "https://docs.rs/fixed/0.0.1")]
|
#![doc(html_root_url = "https://docs.rs/fixed/0.0.1")]
|
||||||
#![doc(test(attr(deny(warnings))))]
|
#![doc(test(attr(deny(warnings))))]
|
||||||
|
#![cfg_attr(nightly_repr_transparent, feature(repr_transparent))]
|
||||||
|
|
||||||
extern crate typenum;
|
extern crate typenum;
|
||||||
|
|
||||||
|
@ -415,7 +416,7 @@ macro_rules! fixed {
|
||||||
"[const generics]: https://github.com/rust-lang/rust/issues/44580\n",
|
"[const generics]: https://github.com/rust-lang/rust/issues/44580\n",
|
||||||
"[typenum crate]: https://crates.io/crates/typenum\n"
|
"[typenum crate]: https://crates.io/crates/typenum\n"
|
||||||
),
|
),
|
||||||
#[repr(transparent)]
|
#[cfg_attr(repr_transparent, repr(transparent))]
|
||||||
pub struct $Fixed<Frac: Unsigned>(($Inner, PhantomData<Frac>));
|
pub struct $Fixed<Frac: Unsigned>(($Inner, PhantomData<Frac>));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue