build.rs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. use anyhow::{bail, Result};
  2. use std::env;
  3. use std::io::ErrorKind;
  4. use std::path::{Path, PathBuf};
  5. use std::process::Command;
  6. fn cfiles<P: AsRef<Path>>(out: &mut Vec<PathBuf>, path: P) -> Result<()> {
  7. for entry in std::fs::read_dir(path)? {
  8. let entry = entry?;
  9. let p = entry.path();
  10. if !p.is_dir() {
  11. out.push(p);
  12. continue;
  13. }
  14. let file = p.file_name().unwrap();
  15. if file == "target" || file == ".git" || file == "dependencies" {
  16. continue;
  17. }
  18. cfiles(out, p)?;
  19. }
  20. Ok(())
  21. }
  22. fn main() -> Result<()> {
  23. // Generate C bindings from rust
  24. {
  25. println!("Generating rtypes");
  26. let mut conf = cbindgen::Config {
  27. language: cbindgen::Language::C,
  28. autogen_warning: Some(
  29. "// This file is generated from src/rtypes.rs using cbindgen".to_owned(),
  30. ),
  31. style: cbindgen::Style::Type,
  32. include_guard: Some("RTypes_H".to_owned()),
  33. no_includes: true,
  34. includes: vec!["RTypesPrefix.h".to_owned()],
  35. ..Default::default()
  36. };
  37. conf.export.include = vec!["RTypes_ExportMe".to_owned()];
  38. conf.enumeration.prefix_with_name = true;
  39. cbindgen::Builder::new()
  40. .with_src("./src/rtypes.rs")
  41. .with_config(conf)
  42. .generate()
  43. .expect("Unable to generate rtypes")
  44. .write_to_file("RTypes.h");
  45. println!("Generating rtypes done");
  46. //
  47. println!("Generating rffi");
  48. let conf = cbindgen::Config {
  49. language: cbindgen::Language::C,
  50. autogen_warning: Some(
  51. "// This file is generated from src/rffi.rs using cbindgen".to_owned(),
  52. ),
  53. style: cbindgen::Style::Type,
  54. include_guard: Some("rffi_H".to_owned()),
  55. no_includes: true,
  56. includes: vec!["RffiPrefix.h".to_owned()],
  57. ..Default::default()
  58. };
  59. cbindgen::Builder::new()
  60. .with_src("./src/rffi/mod.rs")
  61. .with_config(conf)
  62. .generate()
  63. .expect("Unable to generate rffi")
  64. .write_to_file("Rffi.h");
  65. println!("Generating rffi done");
  66. }
  67. let ret = Command::new("node")
  68. .current_dir("../../")
  69. .arg("./node_build/make.js")
  70. .status();
  71. let ret = match ret {
  72. Ok(es) => es,
  73. Err(e) => {
  74. if e.kind() == ErrorKind::NotFound {
  75. bail!(concat!(
  76. "\n\n",
  77. "Could not find nodejs `node` executable\n",
  78. "In order to build cjdns, you must have nodejs installed"
  79. ));
  80. } else {
  81. bail!("Failed to start nodejs: {e}");
  82. }
  83. }
  84. };
  85. let ret = ret.code().unwrap();
  86. if ret != 0 {
  87. bail!("Failed to build cjdns: {ret}");
  88. }
  89. let mut cf: Vec<PathBuf> = Vec::new();
  90. cfiles(&mut cf, "../../")?;
  91. cf.sort();
  92. for f in cf {
  93. println!("cargo:rerun-if-changed={}", f.to_str().unwrap());
  94. }
  95. let out_dir = env::var("OUT_DIR").unwrap();
  96. let target = env::var("TARGET").unwrap();
  97. if target.contains("-windows-gnu") {
  98. println!("cargo:rustc-link-lib=iphlpapi"); // ConvertInterfaceAliasToLuid (cjdns)
  99. println!("cargo:rustc-link-lib=psapi"); // GetProcessMemoryInfo (libuv)
  100. println!("cargo:rustc-link-lib=ssp"); // memcpy_chk (libuv)
  101. }
  102. let mut build = cc::Build::new();
  103. let mut paths = std::fs::read_dir(out_dir)?
  104. .map(|x| x.unwrap().path())
  105. .collect::<Vec<PathBuf>>();
  106. paths.sort();
  107. for path in paths {
  108. if !path.is_dir() && path.extension().unwrap() == "o" {
  109. build.object(path);
  110. }
  111. }
  112. build.compile("cjdns_sys");
  113. // Generate rust bindings from C
  114. #[cfg(feature = "generate-cffi")]
  115. {
  116. let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
  117. bindgen::Builder::default()
  118. .header(out_path.join("rust_cjdns_sys_cffi_h.i").to_str().unwrap())
  119. .generate_comments(false)
  120. .layout_tests(false)
  121. .default_enum_style(bindgen::EnumVariation::Rust {
  122. non_exhaustive: false,
  123. })
  124. .raw_line("#![allow(non_snake_case)]")
  125. .raw_line("#![allow(dead_code)]")
  126. .raw_line("#![allow(non_camel_case_types)]")
  127. .raw_line("#![allow(clippy::enum_variant_names)]")
  128. .whitelist_function(".*")
  129. .whitelist_type("RBindings_Whitelist")
  130. .whitelist_var("Sockaddr_AF_INET")
  131. .whitelist_var("Sockaddr_AF_INET6")
  132. .generate()
  133. .expect("Unable to generate rbindings")
  134. .write_to_file("src/cffi.rs")
  135. .expect("Couldn't write rbindings");
  136. }
  137. Ok(())
  138. }