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::path::Path;
12
13 use anyhow::{Context, Result};
14 use bindgen::{Builder, EnumVariation};
15
16 static COMMON_CFLAGS: &[&str] = &[
17 "-DUSE_BINDGEN",
18 "-D_FILE_OFFSET_BITS=64",
19 "-D_LARGEFILE_SOURCE",
20 "-D_LARGEFILE64_SOURCE",
21 ];
22
get_bindgen_builder() -> Builder23 fn get_bindgen_builder() -> Builder {
24 bindgen::builder()
25 .default_enum_style(EnumVariation::Rust {
26 non_exhaustive: false,
27 })
28 .layout_tests(false)
29 .disable_header_comment()
30 }
31
generate_crossystem_bindings() -> Result<()>32 fn generate_crossystem_bindings() -> Result<()> {
33 let out_dir = env::var("OUT_DIR").unwrap();
34 let gen_file = Path::new(&out_dir).join("./crossystem.rs");
35 if gen_file.exists() {
36 remove_file(&gen_file).expect("Failed to remove generated file.");
37 }
38 let header_dir = Path::new(".");
39 let header_path = header_dir.join("crossystem.h");
40 println!("cargo:rerun-if-changed={}", header_path.display());
41
42 let bindings = get_bindgen_builder()
43 .allowlist_function("Vb.*")
44 .clang_args(COMMON_CFLAGS)
45 .header(header_path.display().to_string())
46 .generate()
47 .context("unable to generate bindings for crossystem.h")?;
48
49 bindings
50 .write_to_file(gen_file.display().to_string())
51 .context("unable to write bindings to file")?;
52
53 Ok(())
54 }
55
generate_vboot_host_binding() -> Result<()>56 fn generate_vboot_host_binding() -> Result<()> {
57 let out_dir = env::var("OUT_DIR").unwrap();
58 let gen_file = Path::new(&out_dir).join("./vboot_host.rs");
59 if gen_file.exists() {
60 remove_file(&gen_file).expect("Failed to remove generated file.");
61 }
62 let header_dir = Path::new(".");
63 let header_path = header_dir.join("vboot_host.h");
64 println!("cargo:rerun-if-changed={}", header_path.display());
65 for file in std::fs::read_dir("include")? {
66 println!("cargo:rerun-if-changed={}", file?.path().display());
67 }
68
69 let bindings = get_bindgen_builder()
70 .allowlist_function("Cgpt.*")
71 .allowlist_function(".*Guid.*")
72 .allowlist_function("FindKernelConfig")
73 .allowlist_function("ExtractVmlinuz")
74 .allowlist_function("vb2_.*")
75 .size_t_is_usize(false)
76 .clang_args(COMMON_CFLAGS)
77 .clang_arg("-Iinclude")
78 .header(header_path.display().to_string())
79 .generate()
80 .context("unable to generate bindings for vboot_host.h")?;
81
82 bindings
83 .write_to_file(gen_file.display().to_string())
84 .context("unable to write bindings to file")?;
85
86 Ok(())
87 }
88
main() -> Result<()>89 fn main() -> Result<()> {
90 if pkg_config::Config::new().probe("vboot_host").is_err() {
91 // Fallback to generate bindings even if the library is not installed.
92 println!("cargo:rustc-link-lib=dylib=vboot_host");
93 println!("cargo:rustc-link-lib=dylib=dl");
94 }
95 generate_crossystem_bindings()?;
96 generate_vboot_host_binding()
97 }
98