wrote readme and added (un)install scripts

This commit is contained in:
Noah Swerhun 2023-10-20 15:15:09 -05:00
parent 58d33da293
commit 9b99602894
4 changed files with 90 additions and 11 deletions

View file

@ -2,14 +2,75 @@
Makefile generator for C projects. Makefile generator for C projects.
`mgen` automatically generates build rules for all source files (extension `.c`) ## Overview
it finds in a recursive search of the directory in which it is run. It reads the
varibles from your existing Makefile and uses them when generating the new
targets.
The following varibles are supported: `mgen` automatically generates build rules for all source files (extension `.c`)
- CC -> C compiler it finds in a recursive search of the directory in which it is run. It places
- CFLAGS -> compilation flags the rules in your existing makefile, meaning you can easily change build options
- LDLIBS -> linker libraries and even write your own rules based on those generated.
`mgen` will place the generated rules between the strings "`#=mgen_start=#`" and
"`#=mgen_end=#`" in your makefile. If these lines are not present, it will add
them to the end of the file and place the rules there. Anything not between
these lines will not be touched by `mgen`.
`mgen` utilizes certain common make variables when generating the build rules.
These are:
- CC -> C compiler
- CFLAGS -> compilation flags
- LDLIBS -> linker libraries
- LDFLAGS -> linker flags - LDFLAGS -> linker flags
- TARGET -> name of final executable/library - TARGET -> name of final executable/library
It is therefore recommended that you set these at the beginning of your
makefile, unless you want to use the `make` defaults.
`mgen`'s rules will place all compiled files in the `BUILD_DIR` specified on the
command line (see *Usage* section of this README). Objects will be placed in the
directory `BUILD_DIR/obj/`, and the `TARGET` will be placed at
`BUILD_DIR/$(TARGET)`.
## Usage
```
$ mgen --help
Usage: mgen [OPTIONS] [BUILD_DIR]
Arguments:
[BUILD_DIR] Directory to place build files [default: ./build]
Options:
-p, --pretty Replace default make output with nice build messages
-m, --makefile <MAKEFILE> Path to makefile [default: ./Makefile]
-h, --help Print help
```
Starting from a "blank slate," i.e. you have no build system configured in your
project, simply run `mgen` in the root directory and then run `make`. It's as
easy as that.
If you already have a makefile in use, remove any rules to build the target or
object files (that what `mgen` is for). You can keep any other, more complex
rules that depend on these things, though. Then, run `mgen` and `make` and you
are good to go.
## Build Instructions
Build: `cargo build --release`
Install (must build first) (needs root): `sh install.sh`
Uninstall (needs root): `sh uninstall.sh`
## Todo
- Add functionality to generate rules to build a library, as opposed to an
executable.
- Add options to generate convenient rules like `clean` to remove all build
files, `run` to execute the target, etc.
- Don't create new makefile if no `.c` files are found.
- Add exclude directory(ies) from search
- Eventually: write man page.
- Maybe: allow build directory to be specified within the Makefile ?
- Maybe: figure out a way to only have the user run `mgen` once, then the
makefile itself will call it again if it needs to be regenerated due to a
change in project structure ?

3
install.sh Normal file
View file

@ -0,0 +1,3 @@
#!/bin/sh
cp ./target/release/mgen /usr/bin/mgen

View file

@ -102,6 +102,14 @@ fn main() {
fs::File::create(&args.makefile).unwrap(); fs::File::create(&args.makefile).unwrap();
} }
if !Path::new(&args.build_dir).exists() {
fs::create_dir(&args.build_dir).unwrap();
}
if !obj_dir.exists() {
fs::create_dir(obj_dir).unwrap();
}
let mut makefile_handle = fs::OpenOptions::new() let mut makefile_handle = fs::OpenOptions::new()
.read(true) .read(true)
.open(args.makefile.clone()).unwrap(); .open(args.makefile.clone()).unwrap();
@ -117,10 +125,11 @@ fn main() {
build_rules.push_str("\n"); build_rules.push_str("\n");
// Target linking rule
let target_path = build_dir.join(Path::new("$(TARGET)")); let target_path = build_dir.join(Path::new("$(TARGET)"));
let target_path = target_path.to_str().unwrap(); let target_path = target_path.to_str().unwrap();
build_rules.push_str(&format!("{}: ", target_path)); build_rules.push_str(&format!("{}:", target_path));
for file in project_files.iter() { for file in project_files.iter() {
build_rules.push_str(&format!(" {}", file.obj_path)); build_rules.push_str(&format!(" {}", file.obj_path));
} }
@ -130,7 +139,7 @@ fn main() {
build_rules.push_str(&format!("\t@printf ':: Linking %s ... ' $(TARGET)\n")); build_rules.push_str(&format!("\t@printf ':: Linking %s ... ' $(TARGET)\n"));
} }
build_rules.push_str(&format!("\t{}$(CC) $(LDFLAGS) -o {} ", build_rules.push_str(&format!("\t{}$(CC) $(LDFLAGS) -o {}",
if pretty {"@"} else {""}, target_path)); if pretty {"@"} else {""}, target_path));
for file in project_files.iter() { for file in project_files.iter() {
build_rules.push_str(&format!(" {}", file.obj_path)); build_rules.push_str(&format!(" {}", file.obj_path));
@ -140,7 +149,9 @@ fn main() {
if pretty { if pretty {
build_rules.push_str(&format!("\t@printf 'done\\n'\n")); build_rules.push_str(&format!("\t@printf 'done\\n'\n"));
} }
// ----------
// Rules for each object file
for file in project_files.iter() { for file in project_files.iter() {
let mut build_rule = String::new(); let mut build_rule = String::new();
@ -168,6 +179,7 @@ fn main() {
build_rules.push_str(&build_rule); build_rules.push_str(&build_rule);
} }
// ----------
build_rules.push_str(&end_key); build_rules.push_str(&end_key);

3
uninstall.sh Normal file
View file

@ -0,0 +1,3 @@
#!/bin/sh
rm /usr/bin/mgen