修改了屎山代码的同时可以链接静态链接库了
This commit is contained in:
parent
2df87f19c1
commit
e21382ae29
@ -15,6 +15,20 @@ impl File {
|
||||
extension,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_by_path(path: PathBuf) -> Self {
|
||||
let name = path.file_name().unwrap().to_string_lossy().into_owned(); // 带扩展名的文件
|
||||
let extension = std::path::Path::new(&path).extension().unwrap();
|
||||
let extension = extension.to_string_lossy().into_owned();
|
||||
let name = String::from(
|
||||
std::path::Path::new(&name)
|
||||
.file_stem()
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
);
|
||||
Self::new(path, name, extension)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -29,13 +43,61 @@ pub struct FilesSet {
|
||||
|
||||
impl FilesSet {
|
||||
/// 输入root/src的路径, 整理该路径下的所有文件
|
||||
pub fn read(path: PathBuf) -> Self {
|
||||
pub fn read_src(path: PathBuf) -> Self {
|
||||
let mut entry_files = Vec::new();
|
||||
let mut c_files = Vec::new();
|
||||
let mut h_files = Vec::new();
|
||||
|
||||
/// 将路径文件夹内所有文件信息整理到集合中
|
||||
fn read_dir(
|
||||
// 将src文件夹单独处理, 逻辑和fileset_read_dir差不多
|
||||
for file in std::fs::read_dir(&path).unwrap() {
|
||||
let file = file.unwrap();
|
||||
if file.file_type().unwrap().is_dir() {
|
||||
let name = file.file_name().to_string_lossy().into_owned();
|
||||
// 忽略test文件夹
|
||||
if name == "test" {
|
||||
continue;
|
||||
}
|
||||
// 将src/bin文件夹的所有.c/.cpp文件视作入口文件
|
||||
// 将src下其它文件夹视作正常.c/.cpp文件
|
||||
if name == "bin" {
|
||||
let new_path = path.join("bin");
|
||||
fileset_read_dir(&new_path, &mut entry_files, &mut h_files).unwrap();
|
||||
} else {
|
||||
let new_path = path.join(name);
|
||||
fileset_read_dir(&new_path, &mut c_files, &mut h_files).unwrap();
|
||||
}
|
||||
} else {
|
||||
// 如果是文件
|
||||
let file = File::new_by_path(file.path());
|
||||
if file.extension == "c" || file.extension == "cpp" {
|
||||
if file.name == "main" {
|
||||
entry_files.push(file);
|
||||
} else {
|
||||
c_files.push(file);
|
||||
}
|
||||
} else if file.extension == "h" || file.extension == "hpp" {
|
||||
h_files.push(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 如果src目录下仅有一个.c/.cpp文件, 则视为唯一项目入口
|
||||
if entry_files.len() == 0 && c_files.len() == 1 {
|
||||
let t = entry_files;
|
||||
entry_files = c_files;
|
||||
c_files = t;
|
||||
}
|
||||
|
||||
Self {
|
||||
entry_files,
|
||||
c_files,
|
||||
h_files,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 将路径文件夹内所有文件分组整理到集合中
|
||||
fn fileset_read_dir(
|
||||
path: &PathBuf,
|
||||
c_files: &mut Vec<File>,
|
||||
h_files: &mut Vec<File>,
|
||||
@ -49,77 +111,15 @@ impl FilesSet {
|
||||
continue;
|
||||
}
|
||||
let new_path = path.join(name);
|
||||
read_dir(&new_path, c_files, h_files)?;
|
||||
fileset_read_dir(&new_path, c_files, h_files)?;
|
||||
} else {
|
||||
if let Some(name) = file.path().file_name() {
|
||||
let file_name: String = name.to_string_lossy().into_owned();
|
||||
let extension = std::path::Path::new(&file_name).extension().unwrap();
|
||||
let file_name: String = file
|
||||
.path()
|
||||
.file_stem()
|
||||
.unwrap()
|
||||
.to_string_lossy()
|
||||
.into_owned();
|
||||
let extension: String = extension.to_string_lossy().into_owned();
|
||||
if extension == "c" || extension == "cpp" {
|
||||
c_files.push(File::new(file.path(), file_name, extension));
|
||||
} else if extension == "h" || extension == "hpp" {
|
||||
h_files.push(File::new(file.path(), file_name, extension));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
for file in std::fs::read_dir(&path).unwrap() {
|
||||
let file = file.unwrap();
|
||||
if file.file_type().unwrap().is_dir() {
|
||||
let name = file.file_name().to_string_lossy().into_owned();
|
||||
// 忽略test文件夹
|
||||
if name == "test" {
|
||||
continue;
|
||||
}
|
||||
// 将src/bin文件夹的所有.c/.cpp文件视作入口文件
|
||||
// 将src下其它文件夹视作正常.c/.cpp文件
|
||||
if name == "bin" {
|
||||
let new_path = path.join("bin");
|
||||
read_dir(&new_path, &mut entry_files, &mut h_files).unwrap();
|
||||
} else {
|
||||
let new_path = path.join(name);
|
||||
read_dir(&new_path, &mut c_files, &mut h_files).unwrap();
|
||||
}
|
||||
} else {
|
||||
// 如果是文件
|
||||
if let Some(name) = file.path().file_name() {
|
||||
let file_name = name.to_string_lossy().into_owned();
|
||||
let file_path = file.path();
|
||||
let extension = std::path::Path::new(&file_name).extension().unwrap();
|
||||
let file_name: String = file
|
||||
.path()
|
||||
.file_stem()
|
||||
.unwrap()
|
||||
.to_string_lossy()
|
||||
.into_owned();
|
||||
let extension: String = extension.to_string_lossy().into_owned();
|
||||
let file = File::new(file_path, file_name, extension);
|
||||
let file = File::new_by_path(file.path());
|
||||
if file.extension == "c" || file.extension == "cpp" {
|
||||
if file.name == "main" {
|
||||
entry_files.push(file);
|
||||
} else {
|
||||
c_files.push(file);
|
||||
}
|
||||
} else if file.extension == "h" || file.extension == "hpp" {
|
||||
h_files.push(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Self {
|
||||
entry_files,
|
||||
c_files,
|
||||
h_files,
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
mod command;
|
||||
mod files;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::const_value::console_log;
|
||||
|
||||
use self::files::FilesSet;
|
||||
@ -11,10 +13,6 @@ pub struct CommandsBuild {
|
||||
#[clap(short, long, default_value = "false")]
|
||||
quiet: bool,
|
||||
|
||||
/// 对构建优化(默认只有o3优化)
|
||||
#[clap(long, default_value = "false")]
|
||||
release: bool,
|
||||
|
||||
/// 编译后是否立即运行
|
||||
#[clap(short, long, default_value = "false")]
|
||||
run: bool,
|
||||
@ -26,13 +24,17 @@ pub struct CommandsBuild {
|
||||
/// 采用gcc编译指令而不是g++
|
||||
#[clap(short, default_value = "false")]
|
||||
c: bool,
|
||||
|
||||
/// 其它自定义选项, 需要在语句前加'.', 举例: --other ".-O3 .-mwindows"
|
||||
#[clap(long)]
|
||||
other: Option<String>,
|
||||
}
|
||||
|
||||
pub fn run(config: CommandsBuild) -> Result<(), std::io::Error> {
|
||||
// 获取项目路径
|
||||
let project_path = std::env::current_dir().unwrap();
|
||||
|
||||
// 获取指定的路径
|
||||
// 获取生成文件的目标路径
|
||||
// let bin_path = project_path.join("target").join("bin");
|
||||
let bin_path = project_path.join("target");
|
||||
std::fs::create_dir_all(&bin_path).unwrap(); // 确保bin目录存在
|
||||
@ -43,25 +45,20 @@ pub fn run(config: CommandsBuild) -> Result<(), std::io::Error> {
|
||||
}
|
||||
|
||||
// 将src目录下的文件整理归纳
|
||||
let files: FilesSet = {
|
||||
let mut files = FilesSet::read(project_path.join("src"));
|
||||
// 如果src目录下仅有一个.c/.cpp文件, 则视为唯一项目入口
|
||||
if files.entry_files.len() == 0 && files.c_files.len() == 1 {
|
||||
let t = files.entry_files;
|
||||
files.entry_files = files.c_files;
|
||||
files.c_files = t;
|
||||
}
|
||||
files
|
||||
};
|
||||
let files: FilesSet = FilesSet::read_src(project_path.join("src"));
|
||||
|
||||
// build指令需要读取rust-cmaker下的config文件
|
||||
let r_config = crate::rtools::config::RConfig::read();
|
||||
let mut need_run = None;
|
||||
|
||||
// 命令通用部分
|
||||
let current_args: Vec<String> = make_current_args(&config, &files, project_path.join("lib"));
|
||||
|
||||
// 将每一个entry_file构建到指定目录下
|
||||
for entry_file in &files.entry_files {
|
||||
let mut gcc_cmd = command::get_gcc_command(&config, &r_config);
|
||||
|
||||
// 指定生成文件名称
|
||||
gcc_cmd.arg("-o").arg({
|
||||
let mut target_name = entry_file.name.clone();
|
||||
if cfg!(target_os = "windows") {
|
||||
@ -71,27 +68,35 @@ pub fn run(config: CommandsBuild) -> Result<(), std::io::Error> {
|
||||
target_path
|
||||
});
|
||||
|
||||
// 添加入口文件
|
||||
gcc_cmd.arg(&entry_file.path);
|
||||
|
||||
for c_file in &files.c_files {
|
||||
gcc_cmd.arg(&c_file.path);
|
||||
}
|
||||
|
||||
if !config.run {
|
||||
console_log(&format!("{:?}", gcc_cmd));
|
||||
// 组装通用命令
|
||||
for item in ¤t_args {
|
||||
gcc_cmd.arg(item);
|
||||
}
|
||||
|
||||
// 执行命令
|
||||
let output = gcc_cmd.output();
|
||||
|
||||
match output {
|
||||
Ok(output) => {
|
||||
if !config.run {
|
||||
console_log(&format!("编译成功: {:?}", output));
|
||||
if !output.status.success() {
|
||||
if !config.quiet {
|
||||
let msg = String::from_utf8_lossy(&output.stderr);
|
||||
console_log(&format!("编译失败: {}", msg));
|
||||
}
|
||||
continue;
|
||||
} else if !config.quiet {
|
||||
console_log(&format!(
|
||||
"编译成功: {}.{}",
|
||||
entry_file.name, entry_file.extension
|
||||
));
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
if !config.run {
|
||||
console_log(&format!("执行出错: {}", err));
|
||||
if !config.quiet {
|
||||
console_log(&format!("编译失败: {:?}", err));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@ -103,6 +108,7 @@ pub fn run(config: CommandsBuild) -> Result<(), std::io::Error> {
|
||||
}
|
||||
}
|
||||
|
||||
// 如果满足条件, 运行需要立即执行的程序
|
||||
if let Some(run_file) = need_run {
|
||||
if !config.quiet {
|
||||
console_log(&format!("{}开始执行: ", run_file.name));
|
||||
@ -120,3 +126,49 @@ pub fn run(config: CommandsBuild) -> Result<(), std::io::Error> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn make_current_args(config: &CommandsBuild, files: &FilesSet, lib_path: PathBuf) -> Vec<String> {
|
||||
let mut current_args: Vec<String> = Vec::new();
|
||||
|
||||
// 添加所有非入口文件
|
||||
for c_file in &files.c_files {
|
||||
let arg = String::from(&c_file.path.clone().into_os_string().into_string().unwrap());
|
||||
current_args.push(arg);
|
||||
}
|
||||
|
||||
// 从project/lib文件夹里获取所有的.a文件作为静态链接库
|
||||
if let Ok(entries) = std::fs::read_dir(&lib_path) {
|
||||
let mut a_files = Vec::new();
|
||||
|
||||
for entry in entries {
|
||||
if let Ok(entry) = &entry {
|
||||
let file_path = entry.path();
|
||||
if file_path.is_file() {
|
||||
let file = files::File::new_by_path(file_path);
|
||||
if file.extension == "a" && file.name.starts_with("lib") {
|
||||
a_files.push(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if a_files.len() != 0 {
|
||||
current_args.push(String::from("-L"));
|
||||
current_args.push(lib_path.into_os_string().into_string().to_owned().unwrap());
|
||||
for item in a_files {
|
||||
let ans = item.name.replacen("lib", "-l", 1);
|
||||
current_args.push(ans);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 组装config.other
|
||||
if let Some(other) = &config.other {
|
||||
for option in other.split_whitespace() {
|
||||
let op: String = option.chars().skip(1).collect(); // 去除前置'.'
|
||||
current_args.push(op);
|
||||
}
|
||||
}
|
||||
|
||||
current_args
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user