From 81d51c0dbfd6a65d6d25275cc8d5cbd5cd2ef4d1 Mon Sep 17 00:00:00 2001 From: Noah Swerhun Date: Wed, 13 Dec 2023 14:19:28 -0600 Subject: [PATCH] cleanup + fixed no source files bug --- .gitignore | 1 + Cargo.lock | 128 ----------------------------------- Cargo.toml | 3 +- Makefile | 27 -------- src/main.rs | 189 +++++++++++++++++++++++++++++++++++----------------- 5 files changed, 132 insertions(+), 216 deletions(-) delete mode 100644 Makefile diff --git a/.gitignore b/.gitignore index 5c2df11..1276cc9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /target /testing_grounds /build +Makefile diff --git a/Cargo.lock b/Cargo.lock index 6156965..d879d17 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,54 +11,12 @@ dependencies = [ "memchr", ] -[[package]] -name = "anstream" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "utf8parse", -] - [[package]] name = "anstyle" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" -[[package]] -name = "anstyle-parse" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" -dependencies = [ - "windows-sys", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" -dependencies = [ - "anstyle", - "windows-sys", -] - [[package]] name = "clap" version = "4.4.11" @@ -75,10 +33,8 @@ version = "4.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a216b506622bb1d316cd51328dce24e07bdff4a6128a47c7e7fad11878d5adbb" dependencies = [ - "anstream", "anstyle", "clap_lex", - "strsim", ] [[package]] @@ -99,12 +55,6 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" -[[package]] -name = "colorchoice" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" - [[package]] name = "heck" version = "0.4.1" @@ -179,12 +129,6 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - [[package]] name = "syn" version = "2.0.41" @@ -201,75 +145,3 @@ name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "utf8parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" diff --git a/Cargo.toml b/Cargo.toml index 4cc30f2..f3c2d39 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -clap = { version = "4.4.10", features = ["derive"] } +clap = { version = "4.4.10", default_features = false, features = ["std", +"derive", "usage", "help", "error-context"] } path-clean = "1.0.1" regex = "1.10.2" diff --git a/Makefile b/Makefile deleted file mode 100644 index 64f2e07..0000000 --- a/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -TARGET = foo -CC = gcc -CFLAGS = -std=c99 -LDLIBS = -lm -#=mgen_start=# -BUILDDIR = ./build -OBJDIR = $(BUILDDIR)/obj -$(BUILDDIR)/$(TARGET): $(OBJDIR)/main.o $(OBJDIR)/ops.o $(OBJDIR)/traps.o | $(OBJDIR) $(BUILDDIR) - $(CC) $(LDFLAGS) -o $(BUILDDIR)/$(TARGET) $(OBJDIR)/main.o $(OBJDIR)/ops.o $(OBJDIR)/traps.o $(LDLIBS) -$(OBJDIR)/main.o: ./testing_grounds/src/main.c ./testing_grounds/src/main.h ./testing_grounds/src/ops.h ./testing_grounds/src/traps.h | $(OBJDIR) - $(CC) $(CFLAGS) -o $(OBJDIR)/main.o -c ./testing_grounds/src/main.c -$(OBJDIR)/ops.o: ./testing_grounds/src/ops.c ./testing_grounds/src/main.h | $(OBJDIR) - $(CC) $(CFLAGS) -o $(OBJDIR)/ops.o -c ./testing_grounds/src/ops.c -$(OBJDIR)/traps.o: ./testing_grounds/src/traps.c ./testing_grounds/src/traps.h ./testing_grounds/src/main.h | $(OBJDIR) - $(CC) $(CFLAGS) -o $(OBJDIR)/traps.o -c ./testing_grounds/src/traps.c -$(BUILDDIR): - mkdir -p $(BUILDDIR) -$(OBJDIR): - mkdir -p $(OBJDIR) -.PHONY: clean -clean: - rm -r $(OBJDIR) - rm -r $(BUILDDIR) -.PHONY: run -run: $(BUILDDIR)/$(TARGET) - ./$(BUILDDIR)/$(TARGET) -#=mgen_end=# diff --git a/src/main.rs b/src/main.rs index 6f8f7bb..8af48e3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,25 +1,40 @@ use std::path::PathBuf; use std::io::ErrorKind; use std::fs::{self, DirEntry}; +use std::process::exit; use regex::Regex; use clap::Parser; use path_clean::PathClean; const START_KEY: &str = "#=mgen_start=#\n"; -const END_KEY: &str = "#=mgen_end=#"; +const END_KEY: &str = "\n#=mgen_end=#"; #[derive(Parser, Debug)] struct Args { - /// Replace default make output with nice build messages (not yet implemented) + /// Replace default make output with nice build messages (colors!) #[arg(short, long)] pretty: bool, + /// Generate a 'clean' rule that removes all build files + #[arg(short, long)] + clean: bool, + + /// Generate a 'run' rule that allows you run the executable with 'make run' + #[arg(short, long)] + run: bool, + + /// Configure build rule to create a library rather than an executable (NYI) + #[arg(short, long)] + library: bool, + /// Path to makefile #[arg(short, long, default_value = "./Makefile")] makefile: String, } +thread_local! {static ARGS: Args = Args::parse()} + #[derive(Debug)] #[allow(dead_code)] enum BuildRuleKind { @@ -67,10 +82,9 @@ impl BuildRule { match path.exists() { true => { headers.push(String::from(path.to_str().unwrap())); - println!("e {:?}", path); continue; }, - false => println!("n {:?}", path), + false => (), } for dir in makefile.include_dirs.iter() { @@ -79,15 +93,13 @@ impl BuildRule { match path.exists() { true => { headers.push(String::from(path.to_str().unwrap())); - println!("e {:?}", path); continue 'fileloop; }, - false => println!("n {:?}", path), + false => (), } } let path = file_dir.join(PathBuf::from(include_file)); - println!("t {:?}", path); headers.push(String::from(path.to_str().unwrap())); } @@ -117,17 +129,55 @@ impl BuildRule { } } -impl ToString for BuildRule { +impl ToString for BuildRuleKind { fn to_string(&self) -> String { + let rule = match self { + BuildRuleKind::Object(v) => v, + BuildRuleKind::Target(v) => v, + BuildRuleKind::Directory(v) => v, + BuildRuleKind::Convenience(v) => v, + }; let mut ret = String::new(); - ret.push_str(&format!("{}:", self.target)); - for prereq in &self.prerequisites { - ret.push_str(&format!(" {}", prereq)); - } + ret.push_str(&format!("{}: ", rule.target)); + ret.push_str(&rule.prerequisites.join(" ")); ret.push_str(&format!("\n")); - for recipe_comm in &self.recipe_commands { - ret.push_str(&format!("\t{}\n", recipe_comm)); - } + + ARGS.with(|args| { + let mut command_prefix = "\t"; + let mut special = false; + if args.pretty { + command_prefix = "\t@"; + let verb = match self { + BuildRuleKind::Object(_) => "Building", + BuildRuleKind::Target(_) => "Linking", + BuildRuleKind::Directory(_) => "Creating directory", + BuildRuleKind::Convenience(_) => { + special = true; + if rule.target.contains("clean") { + ret.push_str(&format!("{}printf '\\e[90m:: Cleaning up ...\\e[0m'\n", command_prefix)); + } + if rule.target.contains("run") { + ret.push_str(&format!("{}printf '\\e[34m:: Running\\e[0m \\e[1m%s\\e[0m \\e[34m...\\e[0m\\n' $(TARGET)\n", command_prefix)); + } + "" + }, + }; + if !special { + ret.push_str(&format!("{}printf '\\e[90m:: {}\\e[0m \\e[1m%s\\e[0m \\e[90m...\\e[0m' {}\n", command_prefix, verb, + (PathBuf::from(&rule.target)).file_name().unwrap().to_str().unwrap())); + } + } + + ret.push_str(&rule.recipe_commands.iter() + .map(|v| format!("{}{}", command_prefix, v)) + .collect::>() + .join("\n")); + + if args.pretty { + ret.push_str(&format!("\n{}printf ' \\e[32mdone\\e[0m\\n'", command_prefix)); + } + }); + ret } } @@ -197,7 +247,6 @@ impl Makefile { include_dirs.push(String::from(dir)); } - println!("{:?}", include_dirs); include_dirs } @@ -221,27 +270,23 @@ impl Makefile { } } -fn join_build_rule_vec(vector: &Vec, seperator: &str) -> String{ - let mut ret = String::new(); - - for (i, rule) in vector.iter().enumerate() { - if i != 0 { - ret.push_str(seperator); - } - ret.push_str(&rule.to_string()); - } - - ret -} - impl ToString for RuleList { fn to_string(&self) -> String { - let targets = join_build_rule_vec(&self.get_target_rules(), ""); - let objects = join_build_rule_vec(&self.get_object_rules(), ""); - let directories = join_build_rule_vec(&self.get_directory_rules(), ""); - let conveniences = join_build_rule_vec(&self.get_convenience_rules(), ""); + 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"); - [targets, objects, directories, conveniences].concat() + let all = [targets, objects, directories, conveniences]; + let mut nonzero: Vec = Vec::new(); + + for category in all { + if category.len() != 0 { + nonzero.push(category.clone()); + } + } + + nonzero.join("\n\n") } } @@ -335,44 +380,44 @@ impl RuleList { })); } - fn get_target_rules(&self) -> Vec { - let mut ret: Vec = Vec::new(); + fn get_target_rules(&self) -> Vec> { + let mut ret: Vec> = Vec::new(); for rule in &self.0 { match rule { - BuildRuleKind::Target(r) => ret.push(r.clone()), + BuildRuleKind::Target(r) => ret.push(BuildRuleKind::Target(r.clone())), _ => continue, } } ret } - fn get_object_rules(&self) -> Vec { - let mut ret: Vec = Vec::new(); + fn get_object_rules(&self) -> Vec> { + let mut ret: Vec> = Vec::new(); for rule in &self.0 { match rule { - BuildRuleKind::Object(r) => ret.push(r.clone()), + BuildRuleKind::Object(r) => ret.push(BuildRuleKind::Object(r.clone())), _ => continue, } } ret } - fn get_directory_rules(&self) -> Vec { - let mut ret: Vec = Vec::new(); + fn get_directory_rules(&self) -> Vec> { + let mut ret: Vec> = Vec::new(); for rule in &self.0 { match rule { - BuildRuleKind::Directory(r) => ret.push(r.clone()), + BuildRuleKind::Directory(r) => ret.push(BuildRuleKind::Directory(r.clone())), _ => continue, } } ret } - fn get_convenience_rules(&self) -> Vec { - let mut ret: Vec = Vec::new(); + fn get_convenience_rules(&self) -> Vec> { + let mut ret: Vec> = Vec::new(); for rule in &self.0 { match rule { - BuildRuleKind::Convenience(r) => ret.push(r.clone()), + BuildRuleKind::Convenience(r) => ret.push(BuildRuleKind::Convenience(r.clone())), _ => continue, } } @@ -392,31 +437,55 @@ fn file_is_hidden(file: &DirEntry) -> bool{ } fn main() { - let args = Args::parse(); - let makefile = Makefile::new_from_path(&args.makefile); - let mut generated_content = String::new(); - - // Only include directory defaults if the user has not specified them - if ! makefile.contains_builddir_def() { - generated_content.push_str("BUILDDIR = ./build\n"); - } - - if ! makefile.contains_objdir_def() { - generated_content.push_str("OBJDIR = $(BUILDDIR)/obj\n"); - } + let mut makefile_name = String::new(); + ARGS.with(|args| { + makefile_name.push_str(&args.makefile); + }); + 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}"); }); + if rule_list.0.is_empty() { + eprintln!("no source files found, nothing to do. exiting..."); + exit(0); + } + + let mut generated_content = String::new(); + + // Only include directory defaults if the user has not specified them + let mut dirdefwritten = false; + if ! makefile.contains_builddir_def() { + generated_content.push_str("BUILDDIR = build\n"); + dirdefwritten = true; + } + + if ! makefile.contains_objdir_def() { + generated_content.push_str("OBJDIR = $(BUILDDIR)/obj\n"); + dirdefwritten = true; + } + + if dirdefwritten { + generated_content.push_str("\n"); + } + + + rule_list.add_target_rule(); rule_list.add_directory_rule("$(BUILDDIR)"); rule_list.add_directory_rule("$(OBJDIR)"); - rule_list.add_clean_rule(); - rule_list.add_run_rule(); + ARGS.with(|args| { + if args.clean { + rule_list.add_clean_rule(); + } + if args.run { + rule_list.add_run_rule(); + } + }); generated_content.push_str(&rule_list.to_string());