mod.rs 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. #![allow(unused_imports)]
  2. #![allow(unused_attributes)]
  3. #![allow(dead_code)]
  4. mod ast;
  5. mod proto_gen;
  6. mod proto_info;
  7. mod template;
  8. pub use proto_gen::*;
  9. pub use proto_info::*;
  10. #[cfg(feature = "proto_gen")]
  11. use log::info;
  12. use std::fs::File;
  13. use std::io::Write;
  14. use std::path::PathBuf;
  15. use std::process::Command;
  16. use walkdir::WalkDir;
  17. pub fn gen(crate_name: &str, proto_file_dir: &str) {
  18. // 1. generate the proto files to proto_file_dir
  19. #[cfg(feature = "proto_gen")]
  20. let _ = gen_protos(crate_name);
  21. let mut proto_file_paths = vec![];
  22. let mut file_names = vec![];
  23. for (path, file_name) in WalkDir::new(proto_file_dir)
  24. .into_iter()
  25. .filter_map(|e| e.ok())
  26. .map(|e| {
  27. let path = e.path().to_str().unwrap().to_string();
  28. let file_name = e.path().file_stem().unwrap().to_str().unwrap().to_string();
  29. (path, file_name)
  30. })
  31. {
  32. if path.ends_with(".proto") {
  33. // https://stackoverflow.com/questions/49077147/how-can-i-force-build-rs-to-run-again-without-cleaning-my-whole-project
  34. println!("cargo:rerun-if-changed={}", path);
  35. proto_file_paths.push(path);
  36. file_names.push(file_name);
  37. }
  38. }
  39. let protoc_bin_path = protoc_bin_vendored::protoc_bin_path().unwrap();
  40. // 2. generate the protobuf files(Dart)
  41. // 3. generate the protobuf files(Rust)
  42. generate_rust_protobuf_files(&protoc_bin_path, &proto_file_paths, proto_file_dir);
  43. }
  44. fn generate_rust_protobuf_files(protoc_bin_path: &PathBuf, proto_file_paths: &Vec<String>, proto_file_dir: &str) {
  45. protoc_rust::Codegen::new()
  46. .out_dir("./src/protobuf/model")
  47. .protoc_path(protoc_bin_path)
  48. .inputs(proto_file_paths)
  49. .include(proto_file_dir)
  50. .run()
  51. .expect("Running protoc failed.");
  52. }
  53. #[cfg(feature = "dart")]
  54. fn generate_dart_protobuf_files(
  55. name: &str,
  56. root: &str,
  57. paths: &Vec<String>,
  58. file_names: &Vec<String>,
  59. protoc_bin_path: &PathBuf,
  60. ) {
  61. if std::env::var("CARGO_MAKE_WORKING_DIRECTORY").is_err() {
  62. log::warn!("CARGO_MAKE_WORKING_DIRECTORY was not set, skip generate dart pb");
  63. return;
  64. }
  65. if std::env::var("FLUTTER_FLOWY_SDK_PATH").is_err() {
  66. log::warn!("FLUTTER_FLOWY_SDK_PATH was not set, skip generate dart pb");
  67. return;
  68. }
  69. let workspace_dir = std::env::var("CARGO_MAKE_WORKING_DIRECTORY").unwrap();
  70. let flutter_sdk_path = std::env::var("FLUTTER_FLOWY_SDK_PATH").unwrap();
  71. let output = format!("{}/{}/lib/protobuf/{}", workspace_dir, flutter_sdk_path, name);
  72. if !std::path::Path::new(&output).exists() {
  73. std::fs::create_dir_all(&output).unwrap();
  74. }
  75. check_pb_dart_plugin();
  76. let protoc_bin_path = protoc_bin_path.to_str().unwrap().to_owned();
  77. paths.iter().for_each(|path| {
  78. if cmd_lib::run_cmd! {
  79. ${protoc_bin_path} --dart_out=${output} --proto_path=${root} ${path}
  80. }
  81. .is_err()
  82. {
  83. panic!("Generate dart pb file failed with: {}", path)
  84. };
  85. });
  86. let protobuf_dart = format!("{}/protobuf.dart", output);
  87. match std::fs::OpenOptions::new()
  88. .create(true)
  89. .write(true)
  90. .append(false)
  91. .truncate(true)
  92. .open(&protobuf_dart)
  93. {
  94. Ok(ref mut file) => {
  95. let mut export = String::new();
  96. export.push_str("// Auto-generated, do not edit \n");
  97. for file_name in file_names {
  98. let c = format!("export './{}.pb.dart';\n", file_name);
  99. export.push_str(c.as_ref());
  100. }
  101. file.write_all(export.as_bytes()).unwrap();
  102. File::flush(file).unwrap();
  103. }
  104. Err(err) => {
  105. panic!("Failed to open file: {}", err);
  106. }
  107. }
  108. }
  109. fn check_pb_dart_plugin() {
  110. if cfg!(target_os = "windows") {
  111. //Command::new("cmd")
  112. // .arg("/C")
  113. // .arg(cmd)
  114. // .status()
  115. // .expect("failed to execute process");
  116. //panic!("{}", format!("\n❌ The protoc-gen-dart was not installed correctly."))
  117. } else {
  118. let is_success = Command::new("sh")
  119. .arg("-c")
  120. .arg("command -v protoc-gen-dart")
  121. .status()
  122. .expect("failed to execute process")
  123. .success();
  124. if !is_success {
  125. panic!("{}", format!("\n❌ The protoc-gen-dart was not installed correctly. \n✅ You can fix that by adding \"{}\" to your shell's config file.(.bashrc, .bash, etc.)", "dart pub global activate protoc_plugin"))
  126. }
  127. }
  128. }
  129. #[cfg(feature = "proto_gen")]
  130. fn gen_protos(crate_name: &str) -> Vec<ProtobufCrate> {
  131. let crate_path = std::fs::canonicalize(".").unwrap().as_path().display().to_string();
  132. let crate_context = ProtoGenerator::gen(crate_name, &crate_path);
  133. let proto_crates = crate_context
  134. .iter()
  135. .map(|info| info.protobuf_crate.clone())
  136. .collect::<Vec<_>>();
  137. crate_context
  138. .into_iter()
  139. .map(|info| info.files)
  140. .flatten()
  141. .for_each(|file| {
  142. println!("cargo:rerun-if-changed={}", file.file_path);
  143. });
  144. proto_crates
  145. }