use std::fmt;
#[allow(clippy::needless_return)]
fn main() {
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-env-changed=TARGET");
println!("cargo:rerun-if-env-changed=CARGO_CFG_TARGET_OS");
println!("cargo:rerun-if-env-changed=CARGO_CFG_DOCS_RS");
if std::env::var("CARGO_CFG_DOCS_RS").is_ok() {
use_feature("outline_syscalls");
return;
}
let os = std::env::var("CARGO_CFG_TARGET_OS").unwrap();
if !["linux", "android"].contains(&os.as_str()) {
return;
}
println!("cargo:rerun-if-env-changed=CARGO_CFG_TARGET_ARCH");
println!("cargo:rerun-if-env-changed=RUSTFLAGS");
if std::env::var("CARGO_CFG_OUTLINE_SYSCALLS").is_ok()
&& std::env::var("CARGO_CFG_FORCE_INLINE_SYSCALLS").is_ok()
{
panic!("`--cfg outline_syscalls` and `--cfg force_inline_syscalls` are mutually exclusive");
}
let arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap();
let pointer_width = std::env::var("CARGO_CFG_TARGET_POINTER_WIDTH").unwrap();
let endian = std::env::var("CARGO_CFG_TARGET_ENDIAN").unwrap();
match arch.as_str() {
"x86_64" if pointer_width == "64" && endian == "little" => main_x86_64(),
"x86" if pointer_width == "32" && endian == "little" => main_x86(),
"aarch64" if pointer_width == "64" && endian == "little" => main_aarch64(),
"arm" if pointer_width == "32" && endian == "little" => main_arm(),
"riscv32" if pointer_width == "32" && endian == "little" && os == "linux" => main_riscv(),
"riscv64" if pointer_width == "64" && endian == "little" && os == "linux" => main_riscv(),
"powerpc" if pointer_width == "32" && endian == "big" && os == "linux" => main_powerpc(),
"powerpc64" if pointer_width == "64" && os == "linux" => main_powerpc64(),
"mips" if pointer_width == "32" && os == "linux" => main_mips(),
"mips64" if pointer_width == "64" && os == "linux" => main_mips64(),
"s390x" if pointer_width == "64" && endian == "big" && os == "linux" => main_s390x(),
"loongarch64" if pointer_width == "64" && endian == "little" && os == "linux" => {
main_loongarch64()
}
_ => {
panic!(
"arch {} {}-bits {} endian unsupported on {}",
arch, pointer_width, endian, os
);
}
}
}
fn main_x86_64() {
if needs_outline_asm() {
build_trampoline("x86_64")
}
}
fn main_x86() {
if needs_outline_asm() {
build_trampoline("x86")
}
}
fn main_aarch64() {
if needs_outline_asm() {
build_trampoline("aarch64")
}
}
fn main_arm() {
if has_thumb_mode() {
use_feature("thumb_mode");
}
if needs_outline_asm() {
build_trampoline("arm")
}
}
fn main_riscv() {
if needs_outline_asm() {
build_trampoline("riscv")
}
}
fn main_powerpc() {
if needs_outline_asm() {
build_trampoline("powerpc")
}
}
fn main_powerpc64() {
if needs_outline_asm() {
build_trampoline("powerpc64")
}
}
fn main_mips() {
if needs_outline_asm() {
build_trampoline("mips")
}
}
fn main_mips64() {
if needs_outline_asm() {
build_trampoline("mips64")
}
}
fn main_s390x() {
if needs_outline_asm() {
build_trampoline("s390x")
}
}
fn main_loongarch64() {
if needs_outline_asm() {
build_trampoline("loongarch64")
}
}
fn has_thumb_mode() -> bool {
let target = std::env::var("TARGET").unwrap();
target == "armv7-linux-androideabi" || target.starts_with("thumb")
}
fn build_trampoline(arch: &str) {
println!("cargo:rerun-if-changed=src/outline/{}.s", arch);
cc::Build::new()
.cargo_metadata(true)
.emit_rerun_if_env_changed(true)
.file(format!("src/outline/{}.s", arch))
.compile("liblinux_syscalls_rs.a");
}
fn needs_outline_asm() -> bool {
const STABLE_59: [&str; 5] = ["x86", "arm", "x86_64", "aarch64", "riscv64"];
if std::env::var("CARGO_CFG_OUTLINE_SYSCALLS").is_ok() {
use_feature("outline_syscalls");
true
} else {
let arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap();
let version = rustc_version::version().unwrap();
assert_eq!(version.major, 1);
if version.minor >= 59 && STABLE_59.contains(&arch.as_str()) {
return false;
}
let version_meta = rustc_version::version_meta().unwrap();
if version_meta.channel == rustc_version::Channel::Nightly {
use_feature("asm_experimental_arch");
false
} else {
if std::env::var("CARGO_CFG_FORCE_INLINE_SYSCALLS").is_err() {
use_feature("outline_syscalls");
}
true
}
}
}
fn use_feature<T: fmt::Display>(feat: T) {
println!("cargo:rustc-cfg={}", feat);
}