Rust/rust/azure-sphere/azure-sphere-sys/build.rs (151 lines of code) (raw):

/* Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. */ use std::env; use std::fs; use std::fs::File; use std::io::{Read, Write}; use std::path::{Path, PathBuf}; extern crate cc; fn replace_string(source: &mut [u8], from: &str, to: &str) -> std::io::Result<()> { let from = from.as_bytes(); let to = to.as_bytes(); let mut found = false; for i in 0..source.len() { let s = &mut source[i..]; if s.starts_with(from) { s[..from.len()].clone_from_slice(to); found = true; } } if found { Ok(()) } else { Err(std::io::Error::new( std::io::ErrorKind::NotFound, "Patch pattern not found", )) } } fn patch_lib(from: &Path, to: &Path) -> std::io::Result<()> { println!("File: {:?}", from); let mut file = File::open(from)?; let mut buffer = Vec::new(); file.read_to_end(&mut buffer)?; replace_string( &mut buffer, "__aeabi_unwind_cpp_pr0", "__aeabi_unwind_bbb_pr0", )?; let mut new_file = File::create(to)?; new_file.write_all(&buffer)?; Ok(()) } fn main() { let arv = env::var("AZURE_SPHERE_ARV").unwrap(); // Tell cargo to invalidate the built crate whenever the wrapper changes println!("cargo:rerun-if-changed=bindings"); let sdk_path = PathBuf::from(std::env::var("AzureSphereDefaultSDKDir").unwrap()); let library_path = Path::new("../azure-sphere-sys/bindings/applibs"); let sysroot = sdk_path.join("Sysroots").join(&arv); let handles = [ "applibs/adc.h", "applibs/application.h", "applibs/applications.h", "applibs/certstore.h", "applibs/eventloop.h", "applibs/gpio.h", "applibs/i2c.h", "applibs/log.h", "applibs/networking.h", // empty outside of an inline function, so not needed: "applibs/networking_curl.h", "applibs/powermanagement.h", "applibs/pwm.h", "applibs/rtc.h", "applibs/spi.h", "applibs/storage.h", "applibs/sysevent.h", "applibs/uart.h", "applibs/wificonfig.h", "tlsutils/deviceauth.h", "tlsutils/deviceauth_curl.h", ] .iter() .map(|header| { let full_header = sysroot.join("usr/include/").join(header); std::thread::spawn(move || { generate_bindings(full_header); }) }) .collect::<Vec<_>>(); handles.into_iter().for_each(|h| h.join().unwrap()); generate_bindings("bindings/applibs/static_inline_helpers.h"); // Tell Cargo that if the given file changes, to rerun this build script. println!("cargo:rerun-if-changed=../azure-sphere-sys/static_inline_helpers.c"); // Use the `cc` crate to build a C file and statically link it. let compiler_path = sysroot.join("tools/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-musleabi/arm-poky-linux-musleabi-gcc"); cc::Build::new() .file("../azure-sphere-sys/static_inline_helpers.c") .include(library_path) .compiler(compiler_path) .flag("--sysroot") .flag(sysroot.to_str().unwrap()) .flag("-fno-strict-aliasing") .flag("-fno-exceptions") .flag("-fstack-protector-strong") .flag("-MD") .flag("-march=armv7ve") .flag("-mthumb") .flag("-mfpu=neon-vfpv4") .flag("-mfloat-abi=hard") .flag("-mcpu=cortex-a7") .target("arm-poky-linux-musleabi") .compile("static_inline_helpers"); let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); let patched_libs_path = out_path.join("patched_libs"); let sysroot_path: PathBuf = [ env::var("AzureSphereDefaultSDKDir").unwrap(), "Sysroots".to_string(), arv, ] .iter() .collect(); let libapplibs = sysroot_path.join("usr/lib/libapplibs.so"); println!("cargo:rerun-if-changed={:?}", libapplibs); fs::create_dir_all(&patched_libs_path).unwrap(); let patched_libapplibs = patched_libs_path.join("libapplibs.so"); patch_lib(libapplibs.as_path(), patched_libapplibs.as_path()).unwrap(); let libc = sysroot_path.join("usr/lib/libc.so"); println!("cargo:rerun-if-changed={:?}", libc); fs::create_dir_all(&patched_libs_path).unwrap(); let patched_libc = patched_libs_path.join("libc.so"); patch_lib(libc.as_path(), patched_libc.as_path()).unwrap(); //println!("cargo:rustc-link-lib=dylib:c"); //println!("cargo:rustc-link-lib=dylib:applibs"); //println!("cargo:rustc-link-lib=dylib:tlsutils"); println!( "cargo:rustc-link-search={}", patched_libs_path.as_path().to_str().unwrap() ); } fn generate_bindings<P: AsRef<Path>>(header: P) { let header = header.as_ref(); let sdk_path = PathBuf::from(std::env::var("AzureSphereDefaultSDKDir").unwrap()); let arv = env::var("AZURE_SPHERE_ARV").unwrap(); let sysroot = sdk_path.join("Sysroots").join(arv); let bindings = bindgen::Builder::default() .header( header .to_str() .expect("Only utf-8 header paths are supported"), ) // Build for no_std .use_core() // use `libc` crate for ctypes .ctypes_prefix("libc") // Tell cargo to invalidate the built crate whenever any of the // included header files changed. .parse_callbacks(Box::new(bindgen::CargoCallbacks)) // Add the bindings folder, so .h files can reference each other without being converted to relative references. .clang_arg("--include-directory=bindings") .clang_arg("--sysroot") .clang_arg(sysroot.to_str().unwrap()) // Finish the builder and generate the bindings. .generate() // Unwrap the Result and panic on failure. .expect("Unable to generate bindings"); // Write the bindings to the $OUT_DIR/bindings.rs file. let out_path = PathBuf::from(std::env::var("OUT_DIR").unwrap()); let mut bindings_file = header .file_stem() .expect("Header file must have a file name") .to_owned(); bindings_file.push(".rs"); bindings .write_to_file(out_path.join(bindings_file)) .expect("Couldn't write bindings!"); }