From 9c2fd3cd211443f5223f2aa1f1608c16879acd89 Mon Sep 17 00:00:00 2001 From: Cloyir Date: Mon, 17 Apr 2023 16:49:49 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=86=20-r=20-o=20?= =?UTF-8?q?=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + src/build_project/config.rs | 35 ++++++++++++++++++++++++--- src/build_project/gcc.rs | 4 ++++ src/build_project/mod.rs | 48 ++++++++++++++++++++++--------------- src/build_project/utils.rs | 8 +++++++ src/main.rs | 38 ++++++++++++++++++++++++----- 6 files changed, 106 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 2224f37..b6401cd 100644 --- a/README.md +++ b/README.md @@ -11,3 +11,4 @@ 1. 将本程序加入到Path或者干脆在每一个c/c++项目的根目录中加入一个,反正它不大 2. 使用`--help`命令行参数查看使用说明 3. 测试版需要环境里已经有gcc、g++的环境变量 + diff --git a/src/build_project/config.rs b/src/build_project/config.rs index 0077a72..62198f4 100644 --- a/src/build_project/config.rs +++ b/src/build_project/config.rs @@ -8,6 +8,8 @@ pub trait BuildConfigTrait { fn get_project_name(&self) -> &str; fn getpath_target_bin(&self) -> String; fn getpath_target_file(&self) -> String; + fn get_extra_final_args(&self) -> &Vec; + fn need_run(&self) -> bool; } #[derive(Debug)] @@ -15,25 +17,44 @@ pub struct BuildConfig { compiler_path: Option, project_path: PathBuf, project_name: String, + extra_final_args: Vec, + need_run: bool, } impl BuildConfig { pub fn new( compiler_path: Option, - project_path: PathBuf, project_name: String, + build_options: i32, + run: bool, ) -> Self { + let project_path = std::env::current_dir().unwrap(); + let mut extra = Vec::new(); + match build_options { + 1 => { + extra.push(String::from("-O1")); + } + 2 => { + extra.push(String::from("-O2")); + } + 3 => { + extra.push(String::from("-O3")); + } + _ => {} + } Self { compiler_path, project_path, project_name, + extra_final_args: extra, + need_run: run, } } } impl BuildConfigTrait for BuildConfig { fn getpath_gcc(&self) -> String { - return self.getpath_gpp(); // 此处需要修改 + return self.getpath_gpp(); // 此处需要修改 } fn getpath_gpp(&self) -> String { @@ -82,8 +103,16 @@ impl BuildConfigTrait for BuildConfig { } fn getpath_target_file(&self) -> String { - let file_name = String::from(self.get_project_name()) + ".exe"; + let file_name = super::utils::make_app_file_name(self.get_project_name()); let ans = PathBuf::from(self.getpath_target_bin()).join(file_name); String::from(ans.to_str().unwrap()) } + + fn get_extra_final_args(&self) -> &Vec { + return &self.extra_final_args; + } + + fn need_run(&self) -> bool { + return self.need_run; + } } diff --git a/src/build_project/gcc.rs b/src/build_project/gcc.rs index 17a235e..aed9126 100644 --- a/src/build_project/gcc.rs +++ b/src/build_project/gcc.rs @@ -41,6 +41,7 @@ pub fn make_o_files_to_bin( command: String, source_paths: &mut Vec, target_path: String, + extra_args: &Vec, ) -> Result<(), std::io::Error> { // 创建指令 let mut output = std::process::Command::new(command); @@ -48,6 +49,9 @@ pub fn make_o_files_to_bin( let item = source_paths.pop().unwrap(); output.arg(item.to_str().unwrap()); } + for item in extra_args { + output.arg(item); + } output.args(["-o", &target_path]); // 运行指令 diff --git a/src/build_project/mod.rs b/src/build_project/mod.rs index 36c52d9..7d4970d 100644 --- a/src/build_project/mod.rs +++ b/src/build_project/mod.rs @@ -7,43 +7,53 @@ use std::path::PathBuf; use config::{BuildConfig, BuildConfigTrait}; -pub fn build_project() { +pub fn build_project( + build_options: i32, + run: bool, + mingw: Option, +) -> Result<(), std::io::Error> { let project_path = std::env::current_dir().unwrap(); println!("{:?}", project_path); // 获取配置 let config: Box = Box::new(BuildConfig::new( - None, - // Some(PathBuf::from(r"C:\Program Files\CodeBlocks\MinGW")), - PathBuf::from(project_path), - String::from("HelloWorld"), + mingw, + String::from("main"), + build_options, + run, )); + println!("{}: start to compile 开始编译", crate::PROJECT_NAME); + // 递归所有src目录下的.c/.cpp文件并编译为.o文件输出到@/target/o目录下 let mut file_set: Vec = Vec::new(); // 所有应临时存储的文件路径集合 - println!( - "{}: start to compile 开始编译 step: 1/2", - crate::PROJECT_NAME - ); std::fs::create_dir_all(config.getpath_target_o()).unwrap(); // 先创建这层目录 - cmake_o::cmake_o(&config, PathBuf::from(config.getpath_src()), &mut file_set).unwrap(); + cmake_o::cmake_o(&config, PathBuf::from(config.getpath_src()), &mut file_set)?; // 遍历@/target/o联合编译到@/target/bin中 - println!( - "{}: start to compile 开始编译 step: 2/2", - crate::PROJECT_NAME - ); - std::fs::create_dir_all(config.getpath_target_bin()).unwrap(); // 先创建这层目录 + std::fs::create_dir_all(config.getpath_target_bin())?; // 先创建这层目录 if PathBuf::from(config.getpath_target_file()).exists() { - std::fs::remove_file(config.getpath_target_file()).unwrap(); // 先删除目标文件 + std::fs::remove_file(config.getpath_target_file())?; // 先删除目标文件 } gcc::make_o_files_to_bin( config.getpath_gpp(), &mut file_set, config.getpath_target_file(), - ) - .unwrap(); + config.get_extra_final_args(), + )?; // 删除@/target/o文件夹 - std::fs::remove_dir_all(config.getpath_target_o()).unwrap(); + std::fs::remove_dir_all(config.getpath_target_o())?; + + // 构建完之后是否要立即运行 + if config.need_run() { + println!("{}: 开始执行...", crate::PROJECT_NAME); + let mut command = std::process::Command::new(config.getpath_target_file()); + command.stdin(std::process::Stdio::inherit()); + command.stdout(std::process::Stdio::inherit()); + command.output()?; + println!("{}: 执行完毕...", crate::PROJECT_NAME); + } + + Ok(()) } diff --git a/src/build_project/utils.rs b/src/build_project/utils.rs index 9913264..8d7fbf6 100644 --- a/src/build_project/utils.rs +++ b/src/build_project/utils.rs @@ -33,3 +33,11 @@ pub fn file_is_c_or_cpp(file_name: &String) -> FileType { } return FileType::Else; } + +// 生成可执行程序的文件名(仅windows上有.exe结尾) +pub fn make_app_file_name(file_name: &str) -> String { + if cfg!(target_os = "windows") { + return String::from(file_name) + ".exe"; + } + return String::from(file_name); +} diff --git a/src/main.rs b/src/main.rs index ce8c53c..a5095e4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,25 +3,42 @@ pub mod new_project; pub const PROJECT_NAME: &str = "rust-cmaker"; -use clap::{command, Parser, Subcommand}; +use std::path::PathBuf; + +use clap::{command, Parser}; /// 命令行参数 #[derive(Parser, Debug)] -#[command(author = "Cloyir min123456@foxmail.com", version = "1.0.0", about = None, long_about = None)] +#[command(author = "Cloyir mine123456@foxmail.com", version = "1.0.0", about = None, long_about = None)] struct Args { #[command(subcommand)] command: Commands, } -#[derive(Subcommand, Debug)] +#[derive(Parser, Debug)] enum Commands { /// 在当前目录新建项目 + #[command(about = "创建一个新项目")] New { /// 项目名称 + #[clap(name = "new_project_name")] project_name: String, }, /// 在此项目内编译 - Build, + #[command(about = "构建当前文件夹下的项目")] + Build { + /// -O优化选项 + #[clap(short = 'o', long = "option", name = "0~3", default_value = "0")] + build_options: i32, + + /// 编译后是否立即运行 + #[clap(short, long, default_value = "false")] + run: bool, + + /// MinGW编译器地址, 不填默认已配置为环境变量 + #[clap(short, long, default_value = None)] + mingw: Option, + }, } fn main() -> std::io::Result<()> { @@ -33,8 +50,17 @@ fn main() -> std::io::Result<()> { Commands::New { project_name } => { new_project::new_project(project_name); } - Commands::Build => { - build_project::build_project(); + Commands::Build { + build_options, + run, + mingw, + } => { + let mingw = if let Some(t) = mingw { + Some(PathBuf::from(t)) + } else { + None + }; + build_project::build_project(build_options, run, mingw)?; } }