diff --git a/src/build_rule.rs b/src/build_rule.rs index 95575ce..1b7206a 100644 --- a/src/build_rule.rs +++ b/src/build_rule.rs @@ -1,4 +1,4 @@ -use std::{path::PathBuf, fs}; +use std::{fs, path::PathBuf}; use path_clean::PathClean; use regex::Regex; @@ -15,7 +15,7 @@ pub enum BuildRuleKind { Convenience(T), } -#[derive(Debug,Clone)] +#[derive(Debug, Clone)] pub struct BuildRule { pub target: String, pub prerequisites: Vec, @@ -40,7 +40,7 @@ impl BuildRule { true => { headers.push(String::from(path.to_str().unwrap())); continue; - }, + } false => (), } @@ -51,7 +51,7 @@ impl BuildRule { true => { headers.push(String::from(path.to_str().unwrap())); continue 'fileloop; - }, + } false => (), } } @@ -63,7 +63,6 @@ impl BuildRule { headers } pub fn new_from_c_file(path: &str, makefile: &Makefile) -> BuildRule { - let mut prerequisites: Vec = Vec::new(); prerequisites.push((PathBuf::from(path)).clean().to_str().unwrap().to_string()); @@ -82,7 +81,11 @@ impl BuildRule { let compile_command = format!("$(CC) $(CFLAGS) $(INCS) -o {} -c {}", obj_path, path); - BuildRule { target: String::from(obj_path), prerequisites, recipe_commands: vec![compile_command] } + BuildRule { + target: String::from(obj_path), + prerequisites, + recipe_commands: vec![compile_command], + } } } diff --git a/src/main.rs b/src/main.rs index 597a30d..737727d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ -use std::process::exit; use clap::Parser; +use std::process::exit; mod build_rule; mod makefile; @@ -52,9 +52,11 @@ fn main() { let makefile = Makefile::new_from_path(&makefile_name); let mut rule_list = RuleList::new(); - rule_list.recursively_gen_objects(".", &makefile).unwrap_or_else(|e| { - panic!("error: problem in recursive search: {e}"); - }); + rule_list + .recursively_gen_objects(".", &makefile) + .unwrap_or_else(|e| { + panic!("error: problem in recursive search: {e}"); + }); if rule_list.0.is_empty() { eprintln!("no source files found, nothing to do. exiting..."); @@ -65,12 +67,12 @@ fn main() { // Only include directory defaults if the user has not specified them let mut dirdefwritten = false; - if ! makefile.contains_builddir_def() { + if !makefile.contains_builddir_def() { generated_content.push_str("BUILDDIR = build\n"); dirdefwritten = true; } - if ! makefile.contains_objdir_def() { + if !makefile.contains_objdir_def() { generated_content.push_str("OBJDIR = $(BUILDDIR)/obj\n"); dirdefwritten = true; } @@ -81,8 +83,10 @@ fn main() { ARGS.with(|args| { if args.dynamic_library { - generated_content.push_str("# dynamic library\nCFLAGS += -fPIC\nLDFLAGS += -shared\n\n"); - } else {} + generated_content + .push_str("# dynamic library\nCFLAGS += -fPIC\nLDFLAGS += -shared\n\n"); + } else { + } }); rule_list.add_target_rule(); @@ -101,7 +105,9 @@ fn main() { generated_content.push_str(&rule_list.to_string()); // Write makefile - makefile.write_new_generated_content(generated_content).unwrap_or_else(|e| { - panic!("error: could not write makefile at {}: {e}", makefile.path); - }); + makefile + .write_new_generated_content(generated_content) + .unwrap_or_else(|e| { + panic!("error: could not write makefile at {}: {e}", makefile.path); + }); } diff --git a/src/makefile.rs b/src/makefile.rs index 5810a71..4a64eab 100644 --- a/src/makefile.rs +++ b/src/makefile.rs @@ -1,5 +1,5 @@ -use std::{fs, io::ErrorKind}; use regex::Regex; +use std::{fs, io::ErrorKind}; const START_KEY: &str = "#=mgen_start=#\n"; const END_KEY: &str = "\n#=mgen_end=#"; @@ -19,28 +19,37 @@ impl Makefile { let contents = match fs::read_to_string(path) { Ok(v) => v, Err(e) => match e.kind() { - // doesn't matter if the file doesn't exist, it will be created + // doesn't matter if the file doesn't exist, it will be created // later. - ErrorKind::NotFound => return Makefile { - path: String::from(path), prologue: String::from(""), - mgen_zone: String::from(""), epilogue: String::from(""), - include_dirs: vec![String::from("")] }, - _ => panic!("error: cannot read makefile: {e}") - } + ErrorKind::NotFound => { + return Makefile { + path: String::from(path), + prologue: String::from(""), + mgen_zone: String::from(""), + epilogue: String::from(""), + include_dirs: vec![String::from("")], + } + } + _ => panic!("error: cannot read makefile: {e}"), + }, }; let contains_start = contents.find(START_KEY).is_some(); let contains_end = contents.find(END_KEY).is_some(); - if (contains_start && !contains_end) || (!contains_start && - contains_end) { + if (contains_start && !contains_end) || (!contains_start && contains_end) { panic!("error: makefile contains one mgen guard but not the other. cannot continue."); } if !(contains_start && contains_end) { let include_dirs = Makefile::get_include_dirs(&contents); - return Makefile { path: String::from(path), prologue: contents, - mgen_zone: String::from(""), epilogue: String::from(""), include_dirs }; + return Makefile { + path: String::from(path), + prologue: contents, + mgen_zone: String::from(""), + epilogue: String::from(""), + include_dirs, + }; } // contains the part before the start key and everything after @@ -49,16 +58,16 @@ impl Makefile { let gen_and_post: Vec<&str> = pre_and_after[1].split(END_KEY).collect(); let include_dirs = Makefile::get_include_dirs(&contents); - - Makefile { + + Makefile { path: String::from(path), prologue: String::from(pre_and_after[0]), mgen_zone: String::from(gen_and_post[0]), epilogue: String::from(gen_and_post[1]), - include_dirs + include_dirs, } } - + pub fn get_include_dirs(search: &String) -> Vec { let mut include_dirs: Vec = Vec::new(); @@ -66,23 +75,18 @@ impl Makefile { let caps = makefile_regex.captures_iter(search); let dirlist = match caps.map(|c| c.extract()).last() { Some((_, [v])) => v, - None => { - return include_dirs - } - , + None => return include_dirs, }; - let incdir_regex = Regex::new(r"\s*-I\s*(.*?)(?:[\s]|$)").unwrap(); let caps = incdir_regex.captures_iter(&dirlist); for (_, [dir]) in caps.map(|c| c.extract()) { include_dirs.push(String::from(dir)); } - include_dirs } - + pub fn contains_builddir_def(&self) -> bool { let re = Regex::new(r"\s+BUILDDIR = ").unwrap(); re.is_match(&(self.prologue)) || re.is_match(&(self.epilogue)) @@ -92,9 +96,16 @@ impl Makefile { let re = Regex::new(r"\s+OBJDIR = ").unwrap(); re.is_match(&(self.prologue)) || re.is_match(&(self.epilogue)) } - + pub fn write_new_generated_content(&self, generated_content: String) -> std::io::Result<()> { - let content = [&self.prologue, START_KEY, &generated_content, END_KEY, &self.epilogue].concat(); + let content = [ + &self.prologue, + START_KEY, + &generated_content, + END_KEY, + &self.epilogue, + ] + .concat(); fs::write(&self.path, &content)?; diff --git a/src/rule_list.rs b/src/rule_list.rs index 6e85d8b..802856c 100644 --- a/src/rule_list.rs +++ b/src/rule_list.rs @@ -9,11 +9,15 @@ use crate::ARGS; pub struct RuleList(pub Vec>); impl RuleList { - pub fn new() -> RuleList{ + pub fn new() -> RuleList { RuleList(vec![]) } - pub fn recursively_gen_objects(&mut self, proj_dir_path: &str, makefile: &Makefile) -> std::io::Result<()>{ + pub fn recursively_gen_objects( + &mut self, + proj_dir_path: &str, + makefile: &Makefile, + ) -> std::io::Result<()> { let files = fs::read_dir(proj_dir_path)?; for file in files { let file = file?; @@ -36,18 +40,21 @@ impl RuleList { continue; } let path = path.to_str().unwrap(); - self.0.push(BuildRuleKind::Object(BuildRule::new_from_c_file(path, makefile))); - }, + self.0 + .push(BuildRuleKind::Object(BuildRule::new_from_c_file( + path, makefile, + ))); + } None => { continue; - }, + } } } } Ok(()) } - pub fn get_obj_targets(&self) -> Vec{ + pub fn get_obj_targets(&self) -> Vec { let mut ret: Vec = Vec::new(); for rule in &self.0 { match rule { @@ -63,13 +70,15 @@ impl RuleList { let mut target_comm = String::new(); ARGS.with(|args| { if args.static_library { - target_comm = String::from( - format!("$(AR) $(ARFLAGS) $(BUILDDIR)/$(TARGET) {}", objects.join(" ")) - ); + target_comm = String::from(format!( + "$(AR) $(ARFLAGS) $(BUILDDIR)/$(TARGET) {}", + objects.join(" ") + )); } else { - target_comm = String::from( - format!("$(CC) $(LDFLAGS) $(INCS) -o $(BUILDDIR)/$(TARGET) {} $(LDLIBS)", objects.join(" ")) - ); + target_comm = String::from(format!( + "$(CC) $(LDFLAGS) $(INCS) -o $(BUILDDIR)/$(TARGET) {} $(LDLIBS)", + objects.join(" ") + )); } }); @@ -87,7 +96,7 @@ impl RuleList { self.0.push(BuildRuleKind::Directory(BuildRule { target: dir.to_string(), prerequisites: vec![], - recipe_commands: vec![format!("mkdir -p {dir}").to_string()] + recipe_commands: vec![format!("mkdir -p {dir}").to_string()], })); } @@ -95,7 +104,10 @@ impl RuleList { self.0.push(BuildRuleKind::Convenience(BuildRule { target: String::from(".PHONY: clean\nclean"), prerequisites: vec![], - recipe_commands: vec![String::from("rm -r $(OBJDIR)"), String::from("rm -r $(BUILDDIR)")] + recipe_commands: vec![ + String::from("rm -r $(OBJDIR)"), + String::from("rm -r $(BUILDDIR)"), + ], })); } @@ -103,7 +115,7 @@ impl RuleList { self.0.push(BuildRuleKind::Convenience(BuildRule { target: String::from(".PHONY: run\nrun"), prerequisites: vec![String::from("$(BUILDDIR)/$(TARGET)")], - recipe_commands: vec![String::from("./$(BUILDDIR)/$(TARGET)")] + recipe_commands: vec![String::from("./$(BUILDDIR)/$(TARGET)")], })); } @@ -152,7 +164,7 @@ impl RuleList { } } -fn file_is_hidden(file: &DirEntry) -> bool{ +fn file_is_hidden(file: &DirEntry) -> bool { let file_name = file.file_name(); let str_name = file_name.to_str().unwrap(); let first_char = str_name.chars().nth(0).unwrap(); @@ -165,10 +177,30 @@ fn file_is_hidden(file: &DirEntry) -> bool{ impl ToString for RuleList { fn to_string(&self) -> String { - let targets = &self.get_target_rules().iter().map(|v| v.to_string()).collect::>().join("\n"); - let objects = &self.get_object_rules().iter().map(|v| v.to_string()).collect::>().join("\n"); - let directories = &self.get_directory_rules().iter().map(|v| v.to_string()).collect::>().join("\n"); - let conveniences = &self.get_convenience_rules().iter().map(|v| v.to_string()).collect::>().join("\n"); + let targets = &self + .get_target_rules() + .iter() + .map(|v| v.to_string()) + .collect::>() + .join("\n"); + let objects = &self + .get_object_rules() + .iter() + .map(|v| v.to_string()) + .collect::>() + .join("\n"); + let directories = &self + .get_directory_rules() + .iter() + .map(|v| v.to_string()) + .collect::>() + .join("\n"); + let conveniences = &self + .get_convenience_rules() + .iter() + .map(|v| v.to_string()) + .collect::>() + .join("\n"); let all = [targets, objects, directories, conveniences]; let mut nonzero: Vec = Vec::new(); @@ -178,7 +210,7 @@ impl ToString for RuleList { nonzero.push(category.clone()); } } - + nonzero.join("\n\n") } }