use std::fs; use std::path::{Path, PathBuf}; use std::str::FromStr; fn main() { cxx_build::bridges(["src/lib.rs", "src/config.rs", "src/login.rs"]) .std("c++20") .compile("dnf_utils"); println!("cargo:rerun-if-changed=src/lib.rs"); println!("cargo:rerun-if-changed=src/config.rs"); let out_dir = "src/protobuf"; if PathBuf::from_str(out_dir).unwrap().exists() { fs::remove_dir_all(out_dir).expect("清空输出目录出错"); } fs::create_dir_all(out_dir).expect("创建输出目录出错"); let proto_list = get_filenames("proto") .expect("读取Protobuf定义文件列表失败") .iter() .filter_map(|file| { if file.ends_with(".proto") { Some(file.clone()) } else { None } }) .collect::>(); prost_build::Config::new() .out_dir(out_dir) .compile_protos(&proto_list, &["proto/".to_string()]) .unwrap(); //tonic_prost_build::configure() // .out_dir(out_dir) // .compile_protos(&proto_list, &["proto/".to_string()])?; let mod_file = format!("{}/mod.rs", out_dir); let mod_content = get_filenames(out_dir).expect("无法列出目录内容"); let mod_content = mod_content .iter() .map(|file| format!("pub mod {};", file.trim_end_matches(".rs"))) .collect::>() .join("\n"); fs::write(&mod_file, mod_content).expect("写出文件失败"); fs::write( format!("{}/README.md", out_dir), "# Warning!\n\n[protobuf](../protobuf) 中的文件由构建脚本生成,重新生成时将会**删除**此目录内的**全部文件**\ ,请不要在此目录内工作,否则可能丢失工作进度!\n\n## 你被警告了!", ).unwrap(); } fn get_filenames(dir: &str) -> Result, std::io::Error> { println!("cargo:rerun-if-changed=proto"); let entries = fs::read_dir(Path::new(dir))?; let filenames: Vec = entries .filter_map(|entry| { let path = entry.ok()?.path(); if path.is_file() { path.file_name()?.to_str().map(|s| s.to_owned()) } else { None } }) .collect(); Ok(filenames) }