修改了屎山代码的同时可以链接静态链接库了

This commit is contained in:
Cloyir 2023-05-15 22:01:55 +08:00
parent 2df87f19c1
commit e21382ae29
2 changed files with 138 additions and 86 deletions

View File

@ -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,49 +43,12 @@ 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(
path: &PathBuf,
c_files: &mut Vec<File>,
h_files: &mut Vec<File>,
) -> std::io::Result<()> {
for file in std::fs::read_dir(path)? {
let file = file?;
if file.file_type()?.is_dir() {
let name = file.file_name().to_string_lossy().into_owned();
// 忽略test文件夹
if name == "test" {
continue;
}
let new_path = path.join(name);
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(())
}
// 将src文件夹单独处理, 逻辑和fileset_read_dir差不多
for file in std::fs::read_dir(&path).unwrap() {
let file = file.unwrap();
if file.file_type().unwrap().is_dir() {
@ -84,25 +61,14 @@ impl FilesSet {
// 将src下其它文件夹视作正常.c/.cpp文件
if name == "bin" {
let new_path = path.join("bin");
read_dir(&new_path, &mut entry_files, &mut h_files).unwrap();
fileset_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();
fileset_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);
@ -114,6 +80,12 @@ impl FilesSet {
}
}
}
// 如果src目录下仅有一个.c/.cpp文件, 则视为唯一项目入口
if entry_files.len() == 0 && c_files.len() == 1 {
let t = entry_files;
entry_files = c_files;
c_files = t;
}
Self {
@ -123,3 +95,31 @@ impl FilesSet {
}
}
}
/// 将路径文件夹内所有文件分组整理到集合中
fn fileset_read_dir(
path: &PathBuf,
c_files: &mut Vec<File>,
h_files: &mut Vec<File>,
) -> std::io::Result<()> {
for file in std::fs::read_dir(path)? {
let file = file?;
if file.file_type()?.is_dir() {
let name = file.file_name().to_string_lossy().into_owned();
// 忽略test文件夹
if name == "test" {
continue;
}
let new_path = path.join(name);
fileset_read_dir(&new_path, c_files, h_files)?;
} else {
let file = File::new_by_path(file.path());
if file.extension == "c" || file.extension == "cpp" {
c_files.push(file);
} else if file.extension == "h" || file.extension == "hpp" {
h_files.push(file);
}
}
}
Ok(())
}

View File

@ -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 &current_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
}