// Copyright 2019 The ChromiumOS Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. /// Minijail's build script invoked by cargo. /// /// This script prefers linking against a pkg-config provided libminijail, but will fall back to /// building libminijail statically. use std::env; use std::fs::remove_file; use std::io; use std::path::Path; use std::process::Command; /// Returns the target triplet prefix for gcc commands. No prefix is required /// for native builds. fn get_cross_compile_prefix() -> String { if let Ok(cross_compile) = env::var("CROSS_COMPILE") { return cross_compile; } let target = env::var("TARGET").unwrap(); if env::var("HOST").unwrap() == target { return String::from(""); } let arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap(); let os = env::var("CARGO_CFG_TARGET_OS").unwrap(); let env = if target.ends_with("-gnueabihf") { String::from("gnueabihf") } else { env::var("CARGO_CFG_TARGET_ENV").unwrap() }; return format!("{}-{}-{}-", arch, os, env); } fn set_up_libminijail() -> io::Result<()> { // Minijail requires libcap at runtime. pkg_config::Config::new().probe("libcap").unwrap(); // Prefer a system-provided Minijail library. if pkg_config::Config::new().probe("libminijail").is_ok() { return Ok(()); } let current_dir = env::var("CARGO_MANIFEST_DIR").unwrap() + "/../.."; let out_dir = env::var("OUT_DIR").unwrap(); let profile = env::var("PROFILE").unwrap(); let status = Command::new("make") .current_dir(&out_dir) .env("OUT", &out_dir) .env("MODE", if profile == "release" { "opt" } else { "debug" }) .env("CROSS_COMPILE", get_cross_compile_prefix()) .env("BUILD_STATIC_LIBS", "yes") .arg("-C") .arg(¤t_dir) .status()?; if !status.success() { std::process::exit(status.code().unwrap_or(1)); } println!("cargo:rustc-link-search=native={}", &out_dir); println!("cargo:rustc-link-lib=static=minijail.pic"); Ok(()) } fn bindings_generation() -> io::Result<()> { let bindgen = match which::which("bindgen") { Ok(v) => v, // Use already generated copy if bindgen is not present. _ => return Ok(()), }; // If CROS_RUST is set, skip generation. let gen_file = Path::new("./libminijail.rs"); if gen_file.exists() { if env::var("CROS_RUST") == Ok(String::from("1")) { return Ok(()); } remove_file(gen_file).expect("Failed to remove generated file."); } let header_dir = Path::new("../../"); let header_path = header_dir.join("libminijail.h"); println!("cargo:rerun-if-changed={}", header_path.display()); let status = Command::new(&bindgen) .args(&["--default-enum-style", "rust"]) .args(&["--blocklist-type", "__rlim64_t"]) .args(&["--raw-line", "pub type __rlim64_t = u64;"]) .args(&["--blocklist-type", "__u\\d{1,2}"]) .args(&["--raw-line", "pub type __u8 = u8;"]) .args(&["--raw-line", "pub type __u16 = u16;"]) .args(&["--raw-line", "pub type __u32 = u32;"]) .args(&["--blocklist-type", "__uint64_t"]) .args(&["--allowlist-function", "^minijail_.*"]) .args(&["--allowlist-var", "^MINIJAIL_.*"]) .arg("--size_t-is-usize") .arg("--no-layout-tests") .arg("--disable-header-comment") .args(&["--output", gen_file.to_str().unwrap()]) .arg(header_path.to_str().unwrap()) .args(&[ "--", "-DUSE_BINDGEN", "-D_FILE_OFFSET_BITS=64", "-D_LARGEFILE_SOURCE", "-D_LARGEFILE64_SOURCE", ]) .status()?; assert!(status.success()); Ok(()) } fn main() -> io::Result<()> { set_up_libminijail()?; bindings_generation() }