• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 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 use std::env;
6 use std::fs;
7 use std::path::PathBuf;
8 
9 use anyhow::Context;
10 use anyhow::Result;
11 use cbindgen::Config;
12 use cbindgen::Language;
13 use tempfile::TempDir;
14 
15 static COPYRIGHT_CLAUSE: &str = "// Copyright 2022 The ChromiumOS Authors
16 // Use of this source code is governed by a BSD-style license that can be
17 // found in the LICENSE file.";
18 
19 static AUTOGENERATED_DISCLAIMER: &str =
20     "/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */";
21 
22 static INCLUDE_GUARD: &str = "CROSVM_CONTROL_H_";
23 
24 static CROSVM_CONTROL_HEADER_NAME: &str = "crosvm_control.h";
25 
main() -> Result<()>26 fn main() -> Result<()> {
27     // Skip building dependencies when generating documents.
28     if std::env::var("CARGO_DOC").is_ok() {
29         return Ok(());
30     }
31 
32     let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
33 
34     let output_dir = PathBuf::from(env::var("OUT_DIR").context("failed to get OUT_DIR")?);
35 
36     let output_file = output_dir
37         .join(CROSVM_CONTROL_HEADER_NAME)
38         .display()
39         .to_string();
40 
41     let config = Config {
42         language: Language::C,
43         cpp_compat: true,
44         header: Some(String::from(COPYRIGHT_CLAUSE)),
45         include_guard: Some(String::from(INCLUDE_GUARD)),
46         autogen_warning: Some(String::from(AUTOGENERATED_DISCLAIMER)),
47         include_version: true,
48         ..Default::default()
49     };
50 
51     cbindgen::Builder::new()
52         .with_crate(crate_dir)
53         .with_config(config)
54         .generate()
55         .context("Unable to generate bindings")?
56         .write_to_file(&output_file);
57 
58     // Do not perform the compilation check on Windows since GCC might not be installed.
59     if std::env::var("CARGO_CFG_WINDOWS").is_ok() {
60         return Ok(());
61     }
62 
63     // Do a quick compile test of the generated header to ensure it is valid
64     let temp_dir = TempDir::new()?;
65     let test_file = temp_dir
66         .path()
67         .join("crosvm_control_test.c")
68         .display()
69         .to_string();
70 
71     fs::write(
72         &test_file,
73         format!("{}{}{}", "#include \"", CROSVM_CONTROL_HEADER_NAME, "\""),
74     )
75     .context("Failed to write crosvm_control test C file")?;
76 
77     cc::Build::new()
78         .include(output_dir)
79         .file(test_file)
80         .compile("crosvm_control_test");
81 
82     // The above outputs cargo:rerun-if-env-changed directives, so we need to explicitly tell cargo
83     // to rerun this script if anything in src/ is changed.
84     println!("cargo:rerun-if-changed=src");
85     Ok(())
86 }
87