11a0216d1Sopenharmony_ciuse std::env::var; 21a0216d1Sopenharmony_ciuse std::io::Write; 31a0216d1Sopenharmony_ci 41a0216d1Sopenharmony_cifn main() { 51a0216d1Sopenharmony_ci // I/O safety is stabilized in Rust 1.63. 61a0216d1Sopenharmony_ci if has_io_safety() { 71a0216d1Sopenharmony_ci use_feature("io_safety_is_in_std") 81a0216d1Sopenharmony_ci } 91a0216d1Sopenharmony_ci 101a0216d1Sopenharmony_ci // Work around 111a0216d1Sopenharmony_ci // https://github.com/rust-lang/rust/issues/103306. 121a0216d1Sopenharmony_ci use_feature_or_nothing("wasi_ext"); 131a0216d1Sopenharmony_ci 141a0216d1Sopenharmony_ci // Rust 1.56 and earlier don't support panic in const fn. 151a0216d1Sopenharmony_ci if has_panic_in_const_fn() { 161a0216d1Sopenharmony_ci use_feature("panic_in_const_fn") 171a0216d1Sopenharmony_ci } 181a0216d1Sopenharmony_ci 191a0216d1Sopenharmony_ci // Don't rerun this on changes other than build.rs, as we only depend on 201a0216d1Sopenharmony_ci // the rustc version. 211a0216d1Sopenharmony_ci println!("cargo:rerun-if-changed=build.rs"); 221a0216d1Sopenharmony_ci} 231a0216d1Sopenharmony_ci 241a0216d1Sopenharmony_cifn use_feature_or_nothing(feature: &str) { 251a0216d1Sopenharmony_ci if has_feature(feature) { 261a0216d1Sopenharmony_ci use_feature(feature); 271a0216d1Sopenharmony_ci } 281a0216d1Sopenharmony_ci} 291a0216d1Sopenharmony_ci 301a0216d1Sopenharmony_cifn use_feature(feature: &str) { 311a0216d1Sopenharmony_ci println!("cargo:rustc-cfg={}", feature); 321a0216d1Sopenharmony_ci} 331a0216d1Sopenharmony_ci 341a0216d1Sopenharmony_ci/// Test whether the rustc at `var("RUSTC")` supports the given feature. 351a0216d1Sopenharmony_cifn has_feature(feature: &str) -> bool { 361a0216d1Sopenharmony_ci can_compile(&format!( 371a0216d1Sopenharmony_ci "#![allow(stable_features)]\n#![feature({})]", 381a0216d1Sopenharmony_ci feature 391a0216d1Sopenharmony_ci )) 401a0216d1Sopenharmony_ci} 411a0216d1Sopenharmony_ci 421a0216d1Sopenharmony_ci/// Test whether the rustc at `var("RUSTC")` can compile the given code. 431a0216d1Sopenharmony_cifn can_compile<T: AsRef<str>>(test: T) -> bool { 441a0216d1Sopenharmony_ci use std::process::Stdio; 451a0216d1Sopenharmony_ci 461a0216d1Sopenharmony_ci let out_dir = var("OUT_DIR").unwrap(); 471a0216d1Sopenharmony_ci let rustc = var("RUSTC").unwrap(); 481a0216d1Sopenharmony_ci let target = var("TARGET").unwrap(); 491a0216d1Sopenharmony_ci 501a0216d1Sopenharmony_ci let mut cmd = if let Ok(wrapper) = var("CARGO_RUSTC_WRAPPER") { 511a0216d1Sopenharmony_ci let mut cmd = std::process::Command::new(wrapper); 521a0216d1Sopenharmony_ci // The wrapper's first argument is supposed to be the path to rustc. 531a0216d1Sopenharmony_ci cmd.arg(rustc); 541a0216d1Sopenharmony_ci cmd 551a0216d1Sopenharmony_ci } else { 561a0216d1Sopenharmony_ci std::process::Command::new(rustc) 571a0216d1Sopenharmony_ci }; 581a0216d1Sopenharmony_ci 591a0216d1Sopenharmony_ci cmd.arg("--crate-type=rlib") // Don't require `main`. 601a0216d1Sopenharmony_ci .arg("--emit=metadata") // Do as little as possible but still parse. 611a0216d1Sopenharmony_ci .arg("--target") 621a0216d1Sopenharmony_ci .arg(target) 631a0216d1Sopenharmony_ci .arg("--out-dir") 641a0216d1Sopenharmony_ci .arg(out_dir); // Put the output somewhere inconsequential. 651a0216d1Sopenharmony_ci 661a0216d1Sopenharmony_ci // If Cargo wants to set RUSTFLAGS, use that. 671a0216d1Sopenharmony_ci if let Ok(rustflags) = var("CARGO_ENCODED_RUSTFLAGS") { 681a0216d1Sopenharmony_ci if !rustflags.is_empty() { 691a0216d1Sopenharmony_ci for arg in rustflags.split('\x1f') { 701a0216d1Sopenharmony_ci cmd.arg(arg); 711a0216d1Sopenharmony_ci } 721a0216d1Sopenharmony_ci } 731a0216d1Sopenharmony_ci } 741a0216d1Sopenharmony_ci 751a0216d1Sopenharmony_ci let mut child = cmd 761a0216d1Sopenharmony_ci .arg("-") // Read from stdin. 771a0216d1Sopenharmony_ci .stdin(Stdio::piped()) // Stdin is a pipe. 781a0216d1Sopenharmony_ci .stderr(Stdio::null()) // Errors from feature detection aren't interesting and can be confusing. 791a0216d1Sopenharmony_ci .spawn() 801a0216d1Sopenharmony_ci .unwrap(); 811a0216d1Sopenharmony_ci 821a0216d1Sopenharmony_ci writeln!(child.stdin.take().unwrap(), "{}", test.as_ref()).unwrap(); 831a0216d1Sopenharmony_ci 841a0216d1Sopenharmony_ci child.wait().unwrap().success() 851a0216d1Sopenharmony_ci} 861a0216d1Sopenharmony_ci 871a0216d1Sopenharmony_ci/// Test whether the rustc at `var("RUSTC")` supports panic in `const fn`. 881a0216d1Sopenharmony_cifn has_panic_in_const_fn() -> bool { 891a0216d1Sopenharmony_ci can_compile("const fn foo() {{ panic!() }}") 901a0216d1Sopenharmony_ci} 911a0216d1Sopenharmony_ci 921a0216d1Sopenharmony_ci/// Test whether the rustc at `var("RUSTC")` supports the I/O safety feature. 931a0216d1Sopenharmony_cifn has_io_safety() -> bool { 941a0216d1Sopenharmony_ci can_compile( 951a0216d1Sopenharmony_ci "\ 961a0216d1Sopenharmony_ci #[cfg(unix)]\n\ 971a0216d1Sopenharmony_ci use std::os::unix::io::OwnedFd as Owned;\n\ 981a0216d1Sopenharmony_ci #[cfg(target_os = \"wasi\")]\n\ 991a0216d1Sopenharmony_ci use std::os::wasi::io::OwnedFd as Owned;\n\ 1001a0216d1Sopenharmony_ci #[cfg(windows)]\n\ 1011a0216d1Sopenharmony_ci use std::os::windows::io::OwnedHandle as Owned;\n\ 1021a0216d1Sopenharmony_ci \n\ 1031a0216d1Sopenharmony_ci pub type Success = Owned;\n\ 1041a0216d1Sopenharmony_ci ", 1051a0216d1Sopenharmony_ci ) 1061a0216d1Sopenharmony_ci} 107