cleanup + fixed no source files bug

This commit is contained in:
Noah Swerhun 2023-12-13 14:19:28 -06:00
parent 70b7b7912b
commit 81d51c0dbf
5 changed files with 132 additions and 216 deletions

1
.gitignore vendored
View file

@ -1,3 +1,4 @@
/target /target
/testing_grounds /testing_grounds
/build /build
Makefile

128
Cargo.lock generated
View file

@ -11,54 +11,12 @@ dependencies = [
"memchr", "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]] [[package]]
name = "anstyle" name = "anstyle"
version = "1.0.4" version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" 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]] [[package]]
name = "clap" name = "clap"
version = "4.4.11" version = "4.4.11"
@ -75,10 +33,8 @@ version = "4.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a216b506622bb1d316cd51328dce24e07bdff4a6128a47c7e7fad11878d5adbb" checksum = "a216b506622bb1d316cd51328dce24e07bdff4a6128a47c7e7fad11878d5adbb"
dependencies = [ dependencies = [
"anstream",
"anstyle", "anstyle",
"clap_lex", "clap_lex",
"strsim",
] ]
[[package]] [[package]]
@ -99,12 +55,6 @@ version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
[[package]]
name = "colorchoice"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]] [[package]]
name = "heck" name = "heck"
version = "0.4.1" version = "0.4.1"
@ -179,12 +129,6 @@ version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.41" version = "2.0.41"
@ -201,75 +145,3 @@ name = "unicode-ident"
version = "1.0.12" version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" 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"

View file

@ -6,6 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [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" path-clean = "1.0.1"
regex = "1.10.2" regex = "1.10.2"

View file

@ -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=#

View file

@ -1,25 +1,40 @@
use std::path::PathBuf; use std::path::PathBuf;
use std::io::ErrorKind; use std::io::ErrorKind;
use std::fs::{self, DirEntry}; use std::fs::{self, DirEntry};
use std::process::exit;
use regex::Regex; use regex::Regex;
use clap::Parser; use clap::Parser;
use path_clean::PathClean; use path_clean::PathClean;
const START_KEY: &str = "#=mgen_start=#\n"; const START_KEY: &str = "#=mgen_start=#\n";
const END_KEY: &str = "#=mgen_end=#"; const END_KEY: &str = "\n#=mgen_end=#";
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
struct Args { 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)] #[arg(short, long)]
pretty: bool, 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 /// Path to makefile
#[arg(short, long, default_value = "./Makefile")] #[arg(short, long, default_value = "./Makefile")]
makefile: String, makefile: String,
} }
thread_local! {static ARGS: Args = Args::parse()}
#[derive(Debug)] #[derive(Debug)]
#[allow(dead_code)] #[allow(dead_code)]
enum BuildRuleKind<T> { enum BuildRuleKind<T> {
@ -67,10 +82,9 @@ impl BuildRule {
match path.exists() { match path.exists() {
true => { true => {
headers.push(String::from(path.to_str().unwrap())); headers.push(String::from(path.to_str().unwrap()));
println!("e {:?}", path);
continue; continue;
}, },
false => println!("n {:?}", path), false => (),
} }
for dir in makefile.include_dirs.iter() { for dir in makefile.include_dirs.iter() {
@ -79,15 +93,13 @@ impl BuildRule {
match path.exists() { match path.exists() {
true => { true => {
headers.push(String::from(path.to_str().unwrap())); headers.push(String::from(path.to_str().unwrap()));
println!("e {:?}", path);
continue 'fileloop; continue 'fileloop;
}, },
false => println!("n {:?}", path), false => (),
} }
} }
let path = file_dir.join(PathBuf::from(include_file)); let path = file_dir.join(PathBuf::from(include_file));
println!("t {:?}", path);
headers.push(String::from(path.to_str().unwrap())); headers.push(String::from(path.to_str().unwrap()));
} }
@ -117,17 +129,55 @@ impl BuildRule {
} }
} }
impl ToString for BuildRule { impl ToString for BuildRuleKind<BuildRule> {
fn to_string(&self) -> String { 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(); let mut ret = String::new();
ret.push_str(&format!("{}:", self.target)); ret.push_str(&format!("{}: ", rule.target));
for prereq in &self.prerequisites { ret.push_str(&rule.prerequisites.join(" "));
ret.push_str(&format!(" {}", prereq));
}
ret.push_str(&format!("\n")); 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::<Vec<_>>()
.join("\n"));
if args.pretty {
ret.push_str(&format!("\n{}printf ' \\e[32mdone\\e[0m\\n'", command_prefix));
}
});
ret ret
} }
} }
@ -197,7 +247,6 @@ impl Makefile {
include_dirs.push(String::from(dir)); include_dirs.push(String::from(dir));
} }
println!("{:?}", include_dirs);
include_dirs include_dirs
} }
@ -221,27 +270,23 @@ impl Makefile {
} }
} }
fn join_build_rule_vec(vector: &Vec<BuildRule>, 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 { impl ToString for RuleList {
fn to_string(&self) -> String { fn to_string(&self) -> String {
let targets = join_build_rule_vec(&self.get_target_rules(), ""); let targets = &self.get_target_rules().iter().map(|v| v.to_string()).collect::<Vec<_>>().join("\n");
let objects = join_build_rule_vec(&self.get_object_rules(), ""); let objects = &self.get_object_rules().iter().map(|v| v.to_string()).collect::<Vec<_>>().join("\n");
let directories = join_build_rule_vec(&self.get_directory_rules(), ""); let directories = &self.get_directory_rules().iter().map(|v| v.to_string()).collect::<Vec<_>>().join("\n");
let conveniences = join_build_rule_vec(&self.get_convenience_rules(), ""); let conveniences = &self.get_convenience_rules().iter().map(|v| v.to_string()).collect::<Vec<_>>().join("\n");
[targets, objects, directories, conveniences].concat() let all = [targets, objects, directories, conveniences];
let mut nonzero: Vec<String> = 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<BuildRule> { fn get_target_rules(&self) -> Vec<BuildRuleKind<BuildRule>> {
let mut ret: Vec<BuildRule> = Vec::new(); let mut ret: Vec<BuildRuleKind<BuildRule>> = Vec::new();
for rule in &self.0 { for rule in &self.0 {
match rule { match rule {
BuildRuleKind::Target(r) => ret.push(r.clone()), BuildRuleKind::Target(r) => ret.push(BuildRuleKind::Target(r.clone())),
_ => continue, _ => continue,
} }
} }
ret ret
} }
fn get_object_rules(&self) -> Vec<BuildRule> { fn get_object_rules(&self) -> Vec<BuildRuleKind<BuildRule>> {
let mut ret: Vec<BuildRule> = Vec::new(); let mut ret: Vec<BuildRuleKind<BuildRule>> = Vec::new();
for rule in &self.0 { for rule in &self.0 {
match rule { match rule {
BuildRuleKind::Object(r) => ret.push(r.clone()), BuildRuleKind::Object(r) => ret.push(BuildRuleKind::Object(r.clone())),
_ => continue, _ => continue,
} }
} }
ret ret
} }
fn get_directory_rules(&self) -> Vec<BuildRule> { fn get_directory_rules(&self) -> Vec<BuildRuleKind<BuildRule>> {
let mut ret: Vec<BuildRule> = Vec::new(); let mut ret: Vec<BuildRuleKind<BuildRule>> = Vec::new();
for rule in &self.0 { for rule in &self.0 {
match rule { match rule {
BuildRuleKind::Directory(r) => ret.push(r.clone()), BuildRuleKind::Directory(r) => ret.push(BuildRuleKind::Directory(r.clone())),
_ => continue, _ => continue,
} }
} }
ret ret
} }
fn get_convenience_rules(&self) -> Vec<BuildRule> { fn get_convenience_rules(&self) -> Vec<BuildRuleKind<BuildRule>> {
let mut ret: Vec<BuildRule> = Vec::new(); let mut ret: Vec<BuildRuleKind<BuildRule>> = Vec::new();
for rule in &self.0 { for rule in &self.0 {
match rule { match rule {
BuildRuleKind::Convenience(r) => ret.push(r.clone()), BuildRuleKind::Convenience(r) => ret.push(BuildRuleKind::Convenience(r.clone())),
_ => continue, _ => continue,
} }
} }
@ -392,31 +437,55 @@ fn file_is_hidden(file: &DirEntry) -> bool{
} }
fn main() { fn main() {
let args = Args::parse();
let makefile = Makefile::new_from_path(&args.makefile);
let mut generated_content = String::new(); let mut makefile_name = String::new();
ARGS.with(|args| {
// Only include directory defaults if the user has not specified them makefile_name.push_str(&args.makefile);
if ! makefile.contains_builddir_def() { });
generated_content.push_str("BUILDDIR = ./build\n"); let makefile = Makefile::new_from_path(&makefile_name);
}
if ! makefile.contains_objdir_def() {
generated_content.push_str("OBJDIR = $(BUILDDIR)/obj\n");
}
let mut rule_list = RuleList::new(); let mut rule_list = RuleList::new();
rule_list.recursively_gen_objects(".", &makefile).unwrap_or_else(|e| { rule_list.recursively_gen_objects(".", &makefile).unwrap_or_else(|e| {
panic!("error: problem in recursive search: {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_target_rule();
rule_list.add_directory_rule("$(BUILDDIR)"); rule_list.add_directory_rule("$(BUILDDIR)");
rule_list.add_directory_rule("$(OBJDIR)"); rule_list.add_directory_rule("$(OBJDIR)");
ARGS.with(|args| {
if args.clean {
rule_list.add_clean_rule(); rule_list.add_clean_rule();
}
if args.run {
rule_list.add_run_rule(); rule_list.add_run_rule();
}
});
generated_content.push_str(&rule_list.to_string()); generated_content.push_str(&rule_list.to_string());