完成基本功能
This commit is contained in:
parent
394636f5fa
commit
6c6656202d
29
.vscode/settings.json
vendored
Normal file
29
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"terminal.integrated.profiles.windows": {
|
||||
|
||||
"PowerShell": {
|
||||
"source": "PowerShell",
|
||||
"icon": "terminal-powershell"
|
||||
},
|
||||
"Command Prompt": {
|
||||
"path": [
|
||||
"${env:windir}\\Sysnative\\cmd.exe",
|
||||
"${env:windir}\\System32\\cmd.exe"
|
||||
],
|
||||
"args": [],
|
||||
"icon": "terminal-cmd"
|
||||
},
|
||||
"Git Bash": {
|
||||
"source": "Git Bash"
|
||||
}
|
||||
},
|
||||
"rust-analyzer.linkedProjects": [
|
||||
".\\Cargo.toml",
|
||||
".\\Cargo.toml",
|
||||
".\\Cargo.toml",
|
||||
".\\Cargo.toml",
|
||||
".\\Cargo.toml",
|
||||
".\\Cargo.toml"
|
||||
],
|
||||
"rust-analyzer.showUnlinkedFileNotification": false
|
||||
}
|
||||
@ -6,3 +6,4 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "4.2.2", features = ["derive"] }
|
||||
|
||||
26
README.md
26
README.md
@ -1,27 +1,13 @@
|
||||
# rust-cmaker
|
||||
|
||||
#### 介绍
|
||||
|
||||
> 2023年了谁还在用传统cmake啊(大嘘)
|
||||
|
||||
用rust封装MinGW的命令,方便一键在vscode中构建c/c++简单项目
|
||||
|
||||
#### 软件架构
|
||||
软件架构说明
|
||||
|
||||
|
||||
#### 安装教程
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### 使用说明
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### 参与贡献
|
||||
|
||||
1. Fork 本仓库
|
||||
2. 新建 Feat_xxx 分支
|
||||
3. 提交代码
|
||||
4. 新建 Pull Request
|
||||
1. 将本程序加入到Path或者干脆在每一个c/c++项目的根目录中加入一个,反正它不大
|
||||
2. 使用`--help`命令行参数查看使用说明
|
||||
3. 测试版需要环境里已经有gcc、g++的环境变量
|
||||
|
||||
46
src/build_project/cmake_o.rs
Normal file
46
src/build_project/cmake_o.rs
Normal file
@ -0,0 +1,46 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use super::config::BuildConfigTrait;
|
||||
|
||||
pub fn cmake_o(
|
||||
config: &Box<dyn BuildConfigTrait>,
|
||||
src_path: PathBuf,
|
||||
file_o_set: &mut Vec<PathBuf>,
|
||||
) -> Result<(), std::io::Error> {
|
||||
// 遍历文件夹内每个子项
|
||||
let dir = std::fs::read_dir(src_path)?;
|
||||
for path in dir {
|
||||
let path = path?;
|
||||
// 如果子项为文件夹, 递归查找内部项
|
||||
if path.file_type()?.is_dir() {
|
||||
cmake_o(config, path.path(), file_o_set)?;
|
||||
continue;
|
||||
}
|
||||
// 判断是否为需要编译的文件, 即.c/.cpp文件
|
||||
let file_path = path;
|
||||
let file_name = String::from(file_path.file_name().to_str().unwrap());
|
||||
let file_type = super::utils::file_is_c_or_cpp(&file_name);
|
||||
if file_type.is_else() {
|
||||
continue;
|
||||
}
|
||||
// 找到需要编译的文件, 将其输出到target/o目录下
|
||||
let new_file_path =
|
||||
PathBuf::from(config.getpath_target_o()).join((*file_o_set).len().to_string() + ".o");
|
||||
|
||||
use super::gcc::make_file_to_target_o;
|
||||
match file_type {
|
||||
super::utils::FileType::C => {
|
||||
make_file_to_target_o(config.getpath_gcc(), &file_path.path(), &new_file_path)?;
|
||||
}
|
||||
super::utils::FileType::Cpp => {
|
||||
make_file_to_target_o(config.getpath_gpp(), &file_path.path(), &new_file_path)?;
|
||||
}
|
||||
super::utils::FileType::Else => {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
file_o_set.push(new_file_path);
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
89
src/build_project/config.rs
Normal file
89
src/build_project/config.rs
Normal file
@ -0,0 +1,89 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub trait BuildConfigTrait {
|
||||
fn getpath_gcc(&self) -> String;
|
||||
fn getpath_gpp(&self) -> String;
|
||||
fn getpath_src(&self) -> String;
|
||||
fn getpath_target_o(&self) -> String;
|
||||
fn get_project_name(&self) -> &str;
|
||||
fn getpath_target_bin(&self) -> String;
|
||||
fn getpath_target_file(&self) -> String;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BuildConfig {
|
||||
compiler_path: Option<PathBuf>,
|
||||
project_path: PathBuf,
|
||||
project_name: String,
|
||||
}
|
||||
|
||||
impl BuildConfig {
|
||||
pub fn new(
|
||||
compiler_path: Option<PathBuf>,
|
||||
project_path: PathBuf,
|
||||
project_name: String,
|
||||
) -> Self {
|
||||
Self {
|
||||
compiler_path,
|
||||
project_path,
|
||||
project_name,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BuildConfigTrait for BuildConfig {
|
||||
fn getpath_gcc(&self) -> String {
|
||||
return self.getpath_gpp(); // 此处需要修改
|
||||
}
|
||||
|
||||
fn getpath_gpp(&self) -> String {
|
||||
if self.compiler_path.is_none() {
|
||||
return String::from("g++");
|
||||
}
|
||||
String::from(
|
||||
self.compiler_path
|
||||
.clone()
|
||||
.unwrap()
|
||||
.join("bin")
|
||||
.join("g++")
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
)
|
||||
}
|
||||
|
||||
fn getpath_src(&self) -> String {
|
||||
String::from(self.project_path.clone().join("src").to_str().unwrap())
|
||||
}
|
||||
|
||||
fn getpath_target_o(&self) -> String {
|
||||
String::from(
|
||||
self.project_path
|
||||
.clone()
|
||||
.join("target")
|
||||
.join("o")
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_project_name(&self) -> &str {
|
||||
&self.project_name
|
||||
}
|
||||
|
||||
fn getpath_target_bin(&self) -> String {
|
||||
String::from(
|
||||
self.project_path
|
||||
.clone()
|
||||
.join("target")
|
||||
.join("bin")
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
)
|
||||
}
|
||||
|
||||
fn getpath_target_file(&self) -> String {
|
||||
let file_name = String::from(self.get_project_name()) + ".exe";
|
||||
let ans = PathBuf::from(self.getpath_target_bin()).join(file_name);
|
||||
String::from(ans.to_str().unwrap())
|
||||
}
|
||||
}
|
||||
65
src/build_project/gcc.rs
Normal file
65
src/build_project/gcc.rs
Normal file
@ -0,0 +1,65 @@
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
// 根据单个.c/.cpp文件的路径创建.o文件并输出到new_file_path
|
||||
pub fn make_file_to_target_o(
|
||||
command: String,
|
||||
source_file_path: &PathBuf,
|
||||
new_file_path: &PathBuf,
|
||||
) -> Result<(), std::io::Error> {
|
||||
// 获取路径
|
||||
let source_file_path = source_file_path.to_str().unwrap();
|
||||
let new_file_path = new_file_path.to_str().unwrap();
|
||||
|
||||
// 运行指令
|
||||
let mut output = std::process::Command::new(command);
|
||||
output.args(["-o", new_file_path]);
|
||||
output.args(["-c", source_file_path]);
|
||||
let output = output.output()?;
|
||||
|
||||
// 输出调试信息
|
||||
let state = if output.status.success() {
|
||||
format!("{}: success to compile 编译成功", crate::PROJECT_NAME)
|
||||
} else {
|
||||
format!(
|
||||
"{}: failed to compile 编译失败 \n错误信息: {:?}",
|
||||
crate::PROJECT_NAME,
|
||||
String::from_utf8(output.stderr).unwrap()
|
||||
)
|
||||
};
|
||||
println!(
|
||||
"{}: file : {:?} ---> new file : {:?} ---> {}",
|
||||
crate::PROJECT_NAME,
|
||||
Path::new(source_file_path).file_name().unwrap(),
|
||||
Path::new(new_file_path).file_name().unwrap(),
|
||||
state
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// 根据.o文件的集合构建可执行程序
|
||||
pub fn make_o_files_to_bin(
|
||||
command: String,
|
||||
source_paths: &mut Vec<PathBuf>,
|
||||
target_path: String,
|
||||
) -> Result<(), std::io::Error> {
|
||||
// 创建指令
|
||||
let mut output = std::process::Command::new(command);
|
||||
while !source_paths.is_empty() {
|
||||
let item = source_paths.pop().unwrap();
|
||||
output.arg(item.to_str().unwrap());
|
||||
}
|
||||
output.args(["-o", &target_path]);
|
||||
|
||||
// 运行指令
|
||||
let output = output.output()?;
|
||||
if output.status.success() {
|
||||
println!("{}: success to compile 编译成功", crate::PROJECT_NAME);
|
||||
} else {
|
||||
println!(
|
||||
"{}: failed to compile 编译失败\n{:?}",
|
||||
crate::PROJECT_NAME,
|
||||
output
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
49
src/build_project/mod.rs
Normal file
49
src/build_project/mod.rs
Normal file
@ -0,0 +1,49 @@
|
||||
mod cmake_o;
|
||||
mod config;
|
||||
mod gcc;
|
||||
mod utils;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use config::{BuildConfig, BuildConfigTrait};
|
||||
|
||||
pub fn build_project() {
|
||||
let project_path = std::env::current_dir().unwrap();
|
||||
println!("{:?}", project_path);
|
||||
|
||||
// 获取配置
|
||||
let config: Box<dyn BuildConfigTrait> = Box::new(BuildConfig::new(
|
||||
None,
|
||||
// Some(PathBuf::from(r"C:\Program Files\CodeBlocks\MinGW")),
|
||||
PathBuf::from(project_path),
|
||||
String::from("HelloWorld"),
|
||||
));
|
||||
|
||||
// 递归所有src目录下的.c/.cpp文件并编译为.o文件输出到@/target/o目录下
|
||||
let mut file_set: Vec<PathBuf> = 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();
|
||||
|
||||
// 遍历@/target/o联合编译到@/target/bin中
|
||||
println!(
|
||||
"{}: start to compile 开始编译 step: 2/2",
|
||||
crate::PROJECT_NAME
|
||||
);
|
||||
std::fs::create_dir_all(config.getpath_target_bin()).unwrap(); // 先创建这层目录
|
||||
if PathBuf::from(config.getpath_target_file()).exists() {
|
||||
std::fs::remove_file(config.getpath_target_file()).unwrap(); // 先删除目标文件
|
||||
}
|
||||
gcc::make_o_files_to_bin(
|
||||
config.getpath_gpp(),
|
||||
&mut file_set,
|
||||
config.getpath_target_file(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// 删除@/target/o文件夹
|
||||
std::fs::remove_dir_all(config.getpath_target_o()).unwrap();
|
||||
}
|
||||
35
src/build_project/utils.rs
Normal file
35
src/build_project/utils.rs
Normal file
@ -0,0 +1,35 @@
|
||||
pub enum FileType {
|
||||
C,
|
||||
Cpp,
|
||||
Else,
|
||||
}
|
||||
|
||||
impl FileType {
|
||||
pub fn is_else(&self) -> bool {
|
||||
match self {
|
||||
Self::Else => {
|
||||
return true;
|
||||
}
|
||||
_ => {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 判断文件名是否为.c或.cpp结尾
|
||||
pub fn file_is_c_or_cpp(file_name: &String) -> FileType {
|
||||
let t: Vec<&u8> = file_name.as_bytes().iter().collect();
|
||||
if t.len() >= 2 && *t[t.len() - 2] == b'.' && *t[t.len() - 1] == b'c' {
|
||||
return FileType::C;
|
||||
}
|
||||
if t.len() >= 4
|
||||
&& *t[t.len() - 4] == b'.'
|
||||
&& *t[t.len() - 3] == b'c'
|
||||
&& *t[t.len() - 2] == b'p'
|
||||
&& *t[t.len() - 1] == b'p'
|
||||
{
|
||||
return FileType::Cpp;
|
||||
}
|
||||
return FileType::Else;
|
||||
}
|
||||
43
src/main.rs
43
src/main.rs
@ -1,3 +1,42 @@
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
pub mod build_project;
|
||||
pub mod new_project;
|
||||
|
||||
pub const PROJECT_NAME: &str = "rust-cmaker";
|
||||
|
||||
use clap::{command, Parser, Subcommand};
|
||||
|
||||
/// 命令行参数
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(author = "Cloyir min123456@foxmail.com", version = "1.0.0", about = None, long_about = None)]
|
||||
struct Args {
|
||||
#[command(subcommand)]
|
||||
command: Commands,
|
||||
}
|
||||
|
||||
#[derive(Subcommand, Debug)]
|
||||
enum Commands {
|
||||
/// 在当前目录新建项目
|
||||
New {
|
||||
/// 项目名称
|
||||
project_name: String,
|
||||
},
|
||||
/// 在此项目内编译
|
||||
Build,
|
||||
}
|
||||
|
||||
fn main() -> std::io::Result<()> {
|
||||
// 解析命令行参数
|
||||
let args = Args::parse();
|
||||
// println!("args: {:?}", args);
|
||||
|
||||
match args.command {
|
||||
Commands::New { project_name } => {
|
||||
new_project::new_project(project_name);
|
||||
}
|
||||
Commands::Build => {
|
||||
build_project::build_project();
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
23
src/new_project/mod.rs
Normal file
23
src/new_project/mod.rs
Normal file
@ -0,0 +1,23 @@
|
||||
mod text;
|
||||
|
||||
/// 创建新项目
|
||||
pub fn new_project(project_name: String) {
|
||||
println!("新建项目: {}", project_name);
|
||||
let target_path = std::env::current_dir().unwrap().join(&project_name);
|
||||
println!("目标路径: {:?}", target_path);
|
||||
if let Ok(_) = target_path.read_dir() {
|
||||
println!("创建项目失败, 已存在名为{}的文件夹", project_name);
|
||||
return;
|
||||
}
|
||||
let src_path = target_path.join("src");
|
||||
std::fs::create_dir_all(&src_path).unwrap();
|
||||
|
||||
// 新建README.md文件
|
||||
std::fs::write(target_path.join("README.md"), text::get_readme_text()).unwrap();
|
||||
|
||||
// 新建main.cpp文件
|
||||
std::fs::write(src_path.join("main.cpp"), text::get_maincpp_text()).unwrap();
|
||||
|
||||
println!("创建成功");
|
||||
println!("请进入{}文件夹再使用build指令构建项目", project_name);
|
||||
}
|
||||
14
src/new_project/text.rs
Normal file
14
src/new_project/text.rs
Normal file
@ -0,0 +1,14 @@
|
||||
// 返回生成文件的文本
|
||||
|
||||
pub fn get_readme_text() -> &'static str {
|
||||
""
|
||||
}
|
||||
|
||||
pub fn get_maincpp_text() -> &'static str {
|
||||
r##"#include <iostream>
|
||||
|
||||
int main() {
|
||||
std::cout << "Hello World!" << std::endl;
|
||||
}
|
||||
"##
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user