blob: 3375d89affd937fc067cc7dff2e71113f408ca57 [file] [log] [blame]
//! build.rs file to obtain the host information.
// Allow dead code in triple.rs and targets.rs for our purposes here.
#![allow(dead_code)]
use std::env;
use std::fs::File;
use std::io::{self, Write};
use std::path::PathBuf;
use std::process::Command;
use std::str::FromStr;
#[cfg(not(feature = "std"))]
extern crate alloc;
#[cfg(feature = "std")]
extern crate std as alloc;
// Include triple.rs and targets.rs so we can parse the TARGET environment variable.
// targets.rs depends on data_model
mod data_model {
include!("src/data_model.rs");
}
mod triple {
include!("src/triple.rs");
}
mod targets {
include!("src/targets.rs");
}
// Stub out `ParseError` to minimally support triple.rs and targets.rs.
mod parse_error {
#[derive(Debug)]
pub enum ParseError {
UnrecognizedArchitecture(String),
UnrecognizedVendor(String),
UnrecognizedOperatingSystem(String),
UnrecognizedEnvironment(String),
UnrecognizedBinaryFormat(String),
UnrecognizedField(String),
}
}
use self::targets::Vendor;
use self::triple::Triple;
fn main() {
let out_dir = PathBuf::from(
env::var_os("OUT_DIR").expect("The OUT_DIR environment variable must be set"),
);
let target = env::var("TARGET").expect("The TARGET environment variable must be set");
let triple =
Triple::from_str(&target).unwrap_or_else(|_| panic!("Invalid target name: '{}'", target));
let out = File::create(out_dir.join("host.rs")).expect("error creating host.rs");
write_host_rs(out, triple).expect("error writing host.rs");
if using_1_40() {
println!("cargo:rustc-cfg=feature=\"rust_1_40\"");
}
}
fn using_1_40() -> bool {
match (|| {
let rustc = env::var_os("RUSTC").unwrap();
let output = Command::new(rustc).arg("--version").output().ok()?;
let stdout = if output.status.success() {
output.stdout
} else {
return None;
};
std::str::from_utf8(&stdout)
.ok()?
.split(' ')
.nth(1)?
.split('.')
.nth(1)?
.parse::<i32>()
.ok()
})() {
Some(version) => version >= 40,
None => true, // assume we're using an up-to-date compiler
}
}
fn write_host_rs(mut out: File, triple: Triple) -> io::Result<()> {
// The generated Debug implementation for the inner architecture variants
// doesn't print the enum name qualifier, so import them here. There
// shouldn't be any conflicts because these enums all share a namespace
// in the triple string format.
writeln!(
out,
r#"
#[allow(unused_imports)]
use crate::Aarch64Architecture::*;
#[allow(unused_imports)]
use crate::ArmArchitecture::*;
#[allow(unused_imports)]
use crate::CustomVendor;
#[allow(unused_imports)]
use crate::Mips32Architecture::*;
#[allow(unused_imports)]
use crate::Mips64Architecture::*;
#[allow(unused_imports)]
use crate::Riscv32Architecture::*;
#[allow(unused_imports)]
use crate::Riscv64Architecture::*;
#[allow(unused_imports)]
use crate::X86_32Architecture::*;
/// The `Triple` of the current host.
pub const HOST: Triple = Triple {{
architecture: Architecture::{architecture:?},
vendor: Vendor::{vendor},
operating_system: OperatingSystem::{operating_system:?},
environment: Environment::{environment:?},
binary_format: BinaryFormat::{binary_format:?},
}};
impl Architecture {{
/// Return the architecture for the current host.
pub const fn host() -> Self {{
Architecture::{architecture:?}
}}
}}
impl Vendor {{
/// Return the vendor for the current host.
pub const fn host() -> Self {{
Vendor::{vendor}
}}
}}
impl OperatingSystem {{
/// Return the operating system for the current host.
pub const fn host() -> Self {{
OperatingSystem::{operating_system:?}
}}
}}
impl Environment {{
/// Return the environment for the current host.
pub const fn host() -> Self {{
Environment::{environment:?}
}}
}}
impl BinaryFormat {{
/// Return the binary format for the current host.
pub const fn host() -> Self {{
BinaryFormat::{binary_format:?}
}}
}}
impl Triple {{
/// Return the triple for the current host.
pub const fn host() -> Self {{
Self {{
architecture: Architecture::{architecture:?},
vendor: Vendor::{vendor},
operating_system: OperatingSystem::{operating_system:?},
environment: Environment::{environment:?},
binary_format: BinaryFormat::{binary_format:?},
}}
}}
}}"#,
architecture = triple.architecture,
vendor = vendor_display(&triple.vendor),
operating_system = triple.operating_system,
environment = triple.environment,
binary_format = triple.binary_format,
)?;
Ok(())
}
fn vendor_display(vendor: &Vendor) -> String {
match vendor {
Vendor::Custom(custom) => format!("Custom(CustomVendor::Static({:?}))", custom.as_str()),
known => format!("{:?}", known),
}
}