123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300 |
- #![allow(unused_imports)]
- #![allow(unused_attributes)]
- #![allow(dead_code)]
- mod ast;
- mod proto_gen;
- mod proto_info;
- mod template;
- use crate::util::path_string_with_component;
- use itertools::Itertools;
- use log::info;
- pub use proto_gen::*;
- pub use proto_info::*;
- use std::fs::File;
- use std::io::Write;
- use std::path::{Path, PathBuf};
- use std::process::Command;
- use walkdir::WalkDir;
- pub fn gen(crate_name: &str) {
- let crate_path = std::fs::canonicalize(".")
- .unwrap()
- .as_path()
- .display()
- .to_string();
- // 1. generate the proto files to proto_file_dir
- #[cfg(feature = "proto_gen")]
- let proto_crates = gen_proto_files(crate_name, &crate_path);
- for proto_crate in proto_crates {
- let mut proto_file_paths = vec![];
- let mut file_names = vec![];
- let proto_file_output_path = proto_crate
- .proto_output_path()
- .to_str()
- .unwrap()
- .to_string();
- let protobuf_output_path = proto_crate
- .protobuf_crate_path()
- .to_str()
- .unwrap()
- .to_string();
- for (path, file_name) in WalkDir::new(&proto_file_output_path)
- .into_iter()
- .filter_map(|e| e.ok())
- .map(|e| {
- let path = e.path().to_str().unwrap().to_string();
- let file_name = e.path().file_stem().unwrap().to_str().unwrap().to_string();
- (path, file_name)
- })
- {
- if path.ends_with(".proto") {
- // https://stackoverflow.com/questions/49077147/how-can-i-force-build-rs-to-run-again-without-cleaning-my-whole-project
- println!("cargo:rerun-if-changed={}", path);
- proto_file_paths.push(path);
- file_names.push(file_name);
- }
- }
- let protoc_bin_path = protoc_bin_vendored::protoc_bin_path().unwrap();
- // 2. generate the protobuf files(Dart)
- #[cfg(feature = "dart")]
- generate_dart_protobuf_files(
- crate_name,
- &proto_file_output_path,
- &proto_file_paths,
- &file_names,
- &protoc_bin_path,
- );
- #[cfg(feature = "ts")]
- generate_ts_protobuf_files(
- crate_name,
- &proto_file_output_path,
- &proto_file_paths,
- &file_names,
- &protoc_bin_path,
- );
- // 3. generate the protobuf files(Rust)
- generate_rust_protobuf_files(
- &protoc_bin_path,
- &proto_file_paths,
- &proto_file_output_path,
- &protobuf_output_path,
- );
- }
- }
- fn generate_rust_protobuf_files(
- protoc_bin_path: &Path,
- proto_file_paths: &[String],
- proto_file_output_path: &str,
- protobuf_output_path: &str,
- ) {
- protoc_rust::Codegen::new()
- .out_dir(protobuf_output_path)
- .protoc_path(protoc_bin_path)
- .inputs(proto_file_paths)
- .include(proto_file_output_path)
- .run()
- .expect("Running rust protoc failed.");
- }
- #[cfg(feature = "ts")]
- fn generate_ts_protobuf_files(
- name: &str,
- proto_file_output_path: &str,
- paths: &[String],
- file_names: &Vec<String>,
- protoc_bin_path: &Path,
- ) {
- let root = std::env::var("CARGO_MAKE_WORKING_DIRECTORY").unwrap_or("../../".to_string());
- let tauri_backend_service_path = std::env::var("TAURI_BACKEND_SERVICE_PATH")
- .unwrap_or("appflowy_tauri/src/services/backend".to_string());
- let mut output = PathBuf::new();
- output.push(root);
- output.push(tauri_backend_service_path);
- output.push("models");
- output.push(name);
- if !output.as_path().exists() {
- std::fs::create_dir_all(&output).unwrap();
- }
- let protoc_bin_path = protoc_bin_path.to_str().unwrap().to_owned();
- paths.iter().for_each(|path| {
- // if let Err(err) = Command::new(protoc_bin_path.clone())
- // .arg(format!("--ts_out={}", output.to_str().unwrap()))
- // .arg(format!("--proto_path={}", proto_file_output_path))
- // .arg(path)
- // .spawn()
- // {
- // panic!("Generate ts pb file failed: {}, {:?}", path, err);
- // }
- let result = cmd_lib::run_cmd! {
- ${protoc_bin_path} --ts_out=${output} --proto_path=${proto_file_output_path} ${path}
- };
- if result.is_err() {
- panic!("Generate ts pb file failed with: {}, {:?}", path, result)
- };
- });
- let ts_index = path_string_with_component(&output, vec!["index.ts"]);
- match std::fs::OpenOptions::new()
- .create(true)
- .write(true)
- .append(false)
- .truncate(true)
- .open(&ts_index)
- {
- Ok(ref mut file) => {
- let mut export = String::new();
- export.push_str("// Auto-generated, do not edit \n");
- for file_name in file_names {
- let c = format!("export * from \"./{}\";\n", file_name);
- export.push_str(c.as_ref());
- }
- file.write_all(export.as_bytes()).unwrap();
- File::flush(file).unwrap();
- },
- Err(err) => {
- panic!("Failed to open file: {}", err);
- },
- }
- }
- #[cfg(feature = "dart")]
- fn generate_dart_protobuf_files(
- name: &str,
- proto_file_output_path: &str,
- paths: &[String],
- file_names: &Vec<String>,
- protoc_bin_path: &Path,
- ) {
- if std::env::var("CARGO_MAKE_WORKING_DIRECTORY").is_err() {
- log::error!("CARGO_MAKE_WORKING_DIRECTORY was not set, skip generate dart pb");
- return;
- }
- if std::env::var("FLUTTER_FLOWY_SDK_PATH").is_err() {
- log::error!("FLUTTER_FLOWY_SDK_PATH was not set, skip generate dart pb");
- return;
- }
- let mut output = PathBuf::new();
- output.push(std::env::var("CARGO_MAKE_WORKING_DIRECTORY").unwrap());
- output.push(std::env::var("FLUTTER_FLOWY_SDK_PATH").unwrap());
- output.push("lib");
- output.push("protobuf");
- output.push(name);
- if !output.as_path().exists() {
- std::fs::create_dir_all(&output).unwrap();
- }
- check_pb_dart_plugin();
- let protoc_bin_path = protoc_bin_path.to_str().unwrap().to_owned();
- paths.iter().for_each(|path| {
- let result = cmd_lib::run_cmd! {
- ${protoc_bin_path} --dart_out=${output} --proto_path=${proto_file_output_path} ${path}
- };
- if result.is_err() {
- panic!("Generate dart pb file failed with: {}, {:?}", path, result)
- };
- });
- let protobuf_dart = path_string_with_component(&output, vec!["protobuf.dart"]);
- match std::fs::OpenOptions::new()
- .create(true)
- .write(true)
- .append(false)
- .truncate(true)
- .open(&protobuf_dart)
- {
- Ok(ref mut file) => {
- let mut export = String::new();
- export.push_str("// Auto-generated, do not edit \n");
- for file_name in file_names {
- let c = format!("export './{}.pb.dart';\n", file_name);
- export.push_str(c.as_ref());
- }
- file.write_all(export.as_bytes()).unwrap();
- File::flush(file).unwrap();
- },
- Err(err) => {
- panic!("Failed to open file: {}", err);
- },
- }
- }
- pub fn check_pb_dart_plugin() {
- if cfg!(target_os = "windows") {
- //Command::new("cmd")
- // .arg("/C")
- // .arg(cmd)
- // .status()
- // .expect("failed to execute process");
- //panic!("{}", format!("\n❌ The protoc-gen-dart was not installed correctly."))
- } else {
- let exit_result = Command::new("sh")
- .arg("-c")
- .arg("command -v protoc-gen-dart")
- .status()
- .expect("failed to execute process");
- if !exit_result.success() {
- let mut msg = "\n❌ Can't find protoc-gen-dart in $PATH:\n".to_string();
- let output = Command::new("sh").arg("-c").arg("echo $PATH").output();
- let paths = String::from_utf8(output.unwrap().stdout)
- .unwrap()
- .split(':')
- .map(|s| s.to_string())
- .collect::<Vec<String>>();
- paths.iter().for_each(|s| msg.push_str(&format!("{}\n", s)));
- if let Ok(output) = Command::new("sh")
- .arg("-c")
- .arg("which protoc-gen-dart")
- .output()
- {
- msg.push_str(&format!(
- "Installed protoc-gen-dart path: {:?}\n",
- String::from_utf8(output.stdout).unwrap()
- ));
- }
- msg.push_str("✅ You can fix that by adding:");
- msg.push_str("\n\texport PATH=\"$PATH\":\"$HOME/.pub-cache/bin\"\n");
- msg.push_str("to your shell's config file.(.bashrc, .bash, .profile, .zshrc etc.)");
- panic!("{}", msg)
- }
- }
- }
- #[cfg(feature = "proto_gen")]
- fn gen_proto_files(crate_name: &str, crate_path: &str) -> Vec<ProtobufCrate> {
- let crate_context = ProtoGenerator::gen(crate_name, crate_path);
- let proto_crates = crate_context
- .iter()
- .map(|info| info.protobuf_crate.clone())
- .collect::<Vec<_>>();
- crate_context
- .into_iter()
- .flat_map(|info| info.files)
- .for_each(|file| {
- println!("cargo:rerun-if-changed={}", file.file_path);
- });
- proto_crates
- }
|