build.rs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. use std::{
  2. env,
  3. path::PathBuf,
  4. process::{
  5. Command,
  6. Stdio,
  7. },
  8. };
  9. fn main() {
  10. let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
  11. let out_var = env::var("OUT_DIR").unwrap();
  12. // Download the Wormhole repository at a certain tag, which we need to access the protobuf definitions
  13. // for Wormhole P2P message types.
  14. //
  15. // TODO: This is ugly. Instead of this we should have our own tool
  16. // build process that can generate protobuf definitions for this and other user cases. For now
  17. // this is easy and works and matches upstream Wormhole's `Makefile`.
  18. const WORMHOLE_VERSION: &str = "2.18.1";
  19. let wh_curl = Command::new("curl")
  20. .args([
  21. "-s",
  22. "-L",
  23. format!("https://github.com/wormhole-foundation/wormhole/archive/refs/tags/v{WORMHOLE_VERSION}.tar.gz").as_str(),
  24. ])
  25. .stdout(Stdio::piped())
  26. .spawn()
  27. .expect("failed to download wormhole archive");
  28. let _ = Command::new("tar")
  29. .args(["xvz"])
  30. .stdin(Stdio::from(wh_curl.stdout.unwrap()))
  31. .output()
  32. .expect("failed to extract wormhole archive");
  33. // Move the tools directory to the root of the repo because that's where the build script
  34. // expects it to be, paths get hardcoded into the binaries.
  35. let _ = Command::new("mv")
  36. .args([
  37. format!("wormhole-{WORMHOLE_VERSION}/tools").as_str(),
  38. "tools",
  39. ])
  40. .output()
  41. .expect("failed to move wormhole tools directory");
  42. // Move the protobuf definitions to the src/network directory, we don't have to do this
  43. // but it is more intuitive when debugging.
  44. let _ = Command::new("mv")
  45. .args([
  46. format!("wormhole-{WORMHOLE_VERSION}/proto/gossip/v1/gossip.proto").as_str(),
  47. "src/network/p2p.proto",
  48. ])
  49. .output()
  50. .expect("failed to move wormhole protobuf definitions");
  51. // Build the protobuf compiler.
  52. let _ = Command::new("./build.sh")
  53. .current_dir("tools")
  54. .output()
  55. .expect("failed to run protobuf compiler build script");
  56. // Make the protobuf compiler executable.
  57. let _ = Command::new("chmod")
  58. .args(["+x", "tools/bin/*"])
  59. .output()
  60. .expect("failed to make protofuf compiler executable");
  61. // Generate the protobuf definitions. See buf.gen.yaml to see how we rename the module for our
  62. // particular use case.
  63. let _ = Command::new("./tools/bin/buf")
  64. .args(["generate", "--path", "src"])
  65. .output()
  66. .expect("failed to generate protobuf definitions");
  67. let rust_target_arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap();
  68. // Build the Go library.
  69. let mut cmd = Command::new("go");
  70. cmd.arg("build")
  71. .arg("-buildmode=c-archive")
  72. .arg("-o")
  73. .arg(out_dir.join("libpythnet.a"))
  74. .arg("src/network/p2p.go")
  75. .arg("src/network/p2p.pb.go");
  76. // Cross-compile the Go binary based on the Rust target architecture
  77. match &*rust_target_arch {
  78. "x86_64" => {
  79. // CGO_ENABLED required for building amd64 on mac os
  80. cmd.env("GOARCH", "amd64").env("CGO_ENABLED", "1");
  81. }
  82. "aarch64" => {
  83. cmd.env("GOARCH", "arm64");
  84. }
  85. // Add other target architectures as needed.
  86. _ => {}
  87. }
  88. // Tell Rust to link our Go library at compile time.
  89. println!("cargo:rustc-link-search=native={out_var}");
  90. println!("cargo:rustc-link-lib=static=pythnet");
  91. println!("cargo:rustc-link-lib=resolv");
  92. let go_build_output = cmd.output().expect("Failed to execute Go build command");
  93. if !go_build_output.status.success() {
  94. let error_message = String::from_utf8_lossy(&go_build_output.stderr);
  95. panic!("Go build failed:\n{}", error_message);
  96. }
  97. }