1 // Copyright 2019 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 /// Minijail's build script invoked by cargo.
6 ///
7 /// This script prefers linking against a pkg-config provided libminijail, but will fall back to
8 /// building libminijail statically.
9 use std::env;
10 use std::fs::remove_file;
11 use std::io;
12 use std::path::Path;
13 use std::process::Command;
14
15 /// Returns the target triplet prefix for gcc commands. No prefix is required
16 /// for native builds.
get_cross_compile_prefix() -> String17 fn get_cross_compile_prefix() -> String {
18 if let Ok(cross_compile) = env::var("CROSS_COMPILE") {
19 return cross_compile;
20 }
21
22 let target = env::var("TARGET").unwrap();
23
24 if env::var("HOST").unwrap() == target {
25 return String::from("");
26 }
27
28 let arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
29 let os = env::var("CARGO_CFG_TARGET_OS").unwrap();
30 let env = if target.ends_with("-gnueabihf") {
31 String::from("gnueabihf")
32 } else {
33 env::var("CARGO_CFG_TARGET_ENV").unwrap()
34 };
35 return format!("{}-{}-{}-", arch, os, env);
36 }
37
set_up_libminijail() -> io::Result<()>38 fn set_up_libminijail() -> io::Result<()> {
39 // Minijail requires libcap at runtime.
40 pkg_config::Config::new().probe("libcap").unwrap();
41
42 // Prefer a system-provided Minijail library.
43 if pkg_config::Config::new().probe("libminijail").is_ok() {
44 return Ok(());
45 }
46
47 let current_dir = env::var("CARGO_MANIFEST_DIR").unwrap() + "/../..";
48 let out_dir = env::var("OUT_DIR").unwrap();
49 let profile = env::var("PROFILE").unwrap();
50
51 let status = Command::new("make")
52 .current_dir(&out_dir)
53 .env("OUT", &out_dir)
54 .env("MODE", if profile == "release" { "opt" } else { "debug" })
55 .env("CROSS_COMPILE", get_cross_compile_prefix())
56 .env("BUILD_STATIC_LIBS", "yes")
57 .arg("-C")
58 .arg(¤t_dir)
59 .status()?;
60 if !status.success() {
61 std::process::exit(status.code().unwrap_or(1));
62 }
63 println!("cargo:rustc-link-search=native={}", &out_dir);
64 println!("cargo:rustc-link-lib=static=minijail.pic");
65 Ok(())
66 }
67
bindings_generation() -> io::Result<()>68 fn bindings_generation() -> io::Result<()> {
69 let bindgen = match which::which("bindgen") {
70 Ok(v) => v,
71 // Use already generated copy if bindgen is not present.
72 _ => return Ok(()),
73 };
74
75 // If CROS_RUST is set, skip generation.
76 let gen_file = Path::new("./libminijail.rs");
77 if gen_file.exists() {
78 if env::var("CROS_RUST") == Ok(String::from("1")) {
79 return Ok(());
80 }
81 remove_file(gen_file).expect("Failed to remove generated file.");
82 }
83 let header_dir = Path::new("../../");
84 let header_path = header_dir.join("libminijail.h");
85 println!("cargo:rerun-if-changed={}", header_path.display());
86 let status = Command::new(&bindgen)
87 .args(&["--default-enum-style", "rust"])
88 .args(&["--blocklist-type", "__rlim64_t"])
89 .args(&["--raw-line", "pub type __rlim64_t = u64;"])
90 .args(&["--blocklist-type", "__u\\d{1,2}"])
91 .args(&["--raw-line", "pub type __u8 = u8;"])
92 .args(&["--raw-line", "pub type __u16 = u16;"])
93 .args(&["--raw-line", "pub type __u32 = u32;"])
94 .args(&["--blocklist-type", "__uint64_t"])
95 .args(&["--allowlist-function", "^minijail_.*"])
96 .args(&["--allowlist-var", "^MINIJAIL_.*"])
97 .arg("--no-layout-tests")
98 .arg("--disable-header-comment")
99 .args(&["--output", gen_file.to_str().unwrap()])
100 .arg(header_path.to_str().unwrap())
101 .args(&[
102 "--",
103 "-DUSE_BINDGEN",
104 "-D_FILE_OFFSET_BITS=64",
105 "-D_LARGEFILE_SOURCE",
106 "-D_LARGEFILE64_SOURCE",
107 ])
108 .status()?;
109 assert!(status.success());
110 Ok(())
111 }
112
main() -> io::Result<()>113 fn main() -> io::Result<()> {
114 set_up_libminijail()?;
115 bindings_generation()
116 }
117