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