1
0

build.rs 3.4 KB

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