AppFlowy/frontend/rust-lib/flowy-codegen/src/protobuf_file/mod.rs

207 lines
6.7 KiB
Rust
Raw Normal View History

#![allow(unused_imports)]
2022-02-08 15:52:00 +00:00
#![allow(unused_attributes)]
2022-02-08 23:23:57 +00:00
#![allow(dead_code)]
2022-02-15 13:27:00 +00:00
mod ast;
mod proto_gen;
mod proto_info;
mod template;
2022-12-01 06:56:20 +00:00
use crate::util::path_string_with_component;
2022-05-17 08:00:07 +00:00
use itertools::Itertools;
2022-02-17 12:10:29 +00:00
use log::info;
2022-02-15 13:27:00 +00:00
pub use proto_gen::*;
pub use proto_info::*;
use std::fs::File;
use std::io::Write;
2022-02-18 15:04:55 +00:00
use std::path::{Path, PathBuf};
2022-02-08 23:23:57 +00:00
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();
2022-02-15 05:27:54 +00:00
// 1. generate the proto files to proto_file_dir
2022-02-09 05:08:49 +00:00
#[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![];
2022-06-17 03:19:49 +00:00
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();
2022-06-17 03:19:49 +00:00
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);
}
2022-02-09 05:08:49 +00:00
}
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,
2022-06-17 03:19:49 +00:00
&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,
2022-06-17 03:19:49 +00:00
&proto_file_output_path,
&protobuf_output_path,
);
}
2022-02-15 05:27:54 +00:00
}
fn generate_rust_protobuf_files(
protoc_bin_path: &Path,
proto_file_paths: &[String],
2022-06-17 03:19:49 +00:00
proto_file_output_path: &str,
protobuf_output_path: &str,
) {
2022-02-09 05:08:49 +00:00
protoc_rust::Codegen::new()
2022-06-17 03:19:49 +00:00
.out_dir(protobuf_output_path)
2022-02-15 05:27:54 +00:00
.protoc_path(protoc_bin_path)
2022-02-16 02:00:31 +00:00
.inputs(proto_file_paths)
2022-06-17 03:19:49 +00:00
.include(proto_file_output_path)
2022-02-09 05:08:49 +00:00
.run()
.expect("Running rust protoc failed.");
}
#[cfg(feature = "dart")]
2022-02-15 05:27:54 +00:00
fn generate_dart_protobuf_files(
name: &str,
2022-06-17 03:19:49 +00:00
proto_file_output_path: &str,
paths: &[String],
2022-02-15 05:27:54 +00:00
file_names: &Vec<String>,
protoc_bin_path: &Path,
2022-02-15 05:27:54 +00:00
) {
2022-02-09 10:35:50 +00:00
if std::env::var("CARGO_MAKE_WORKING_DIRECTORY").is_err() {
log::warn!("CARGO_MAKE_WORKING_DIRECTORY was not set, skip generate dart pb");
return;
}
if std::env::var("FLUTTER_FLOWY_SDK_PATH").is_err() {
log::warn!("FLUTTER_FLOWY_SDK_PATH was not set, skip generate dart pb");
return;
}
2022-02-17 12:10:29 +00:00
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();
}
2022-02-08 23:23:57 +00:00
check_pb_dart_plugin();
2022-02-16 02:00:31 +00:00
let protoc_bin_path = protoc_bin_path.to_str().unwrap().to_owned();
paths.iter().for_each(|path| {
let result = cmd_lib::run_cmd! {
2022-06-17 03:19:49 +00:00
${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)
};
});
2022-02-17 12:10:29 +00:00
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);
}
}
}
2022-02-08 23:23:57 +00:00
2022-05-17 08:00:07 +00:00
pub fn check_pb_dart_plugin() {
if cfg!(target_os = "windows") {
2022-02-17 08:32:10 +00:00
//Command::new("cmd")
// .arg("/C")
// .arg(cmd)
// .status()
// .expect("failed to execute process");
//panic!("{}", format!("\n❌ The protoc-gen-dart was not installed correctly."))
2022-02-08 23:23:57 +00:00
} else {
2022-05-17 08:00:07 +00:00
let exit_result = Command::new("sh")
2022-02-08 23:23:57 +00:00
.arg("-c")
2022-02-17 08:32:10 +00:00
.arg("command -v protoc-gen-dart")
2022-02-08 23:23:57 +00:00
.status()
2022-05-17 08:00:07 +00:00
.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()
2022-05-24 06:56:55 +00:00
.split(':')
2022-05-17 08:00:07 +00:00
.map(|s| s.to_string())
.collect::<Vec<String>>();
paths.iter().for_each(|s| msg.push_str(&format!("{}\n", s)));
2022-05-24 06:56:55 +00:00
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()
));
2022-05-17 08:00:07 +00:00
}
2022-02-17 08:32:10 +00:00
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.)");
2022-05-17 08:00:07 +00:00
panic!("{}", msg)
2022-02-17 08:32:10 +00:00
}
}
2022-02-08 23:23:57 +00:00
}
2022-02-09 05:08:49 +00:00
#[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);
2022-02-09 05:08:49 +00:00
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);
});
2022-02-09 05:08:49 +00:00
proto_crates
}