cli flags, catch redefinitions

This commit is contained in:
2025-06-29 11:36:48 +02:00
parent 0207228c06
commit 21cac533f2
4 changed files with 304 additions and 44 deletions

View File

@@ -3,13 +3,15 @@ mod parser;
mod tokenizer;
use std::{
env, fs,
fs,
path::Path,
process::{self, Command},
};
use tokenizer::ZernError;
use clap::Parser;
fn compile_file_to(
codegen: &mut codegen_x86_64::CodegenX86_64,
filename: &str,
@@ -27,71 +29,82 @@ fn compile_file_to(
Ok(())
}
fn compile_file(path: String) -> Result<(), ZernError> {
let source = match fs::read_to_string(path.clone()) {
fn compile_file(args: Args) -> Result<(), ZernError> {
let source = match fs::read_to_string(&args.path) {
Ok(x) => x,
Err(_) => {
eprintln!("\x1b[91mERROR\x1b[0m: failed to open {}", path);
eprintln!("\x1b[91mERROR\x1b[0m: failed to open {}", args.path);
process::exit(1);
}
};
let filename = Path::new(&path).file_name().unwrap().to_str().unwrap();
let filename = Path::new(&args.path).file_name().unwrap().to_str().unwrap();
let mut codegen = codegen_x86_64::CodegenX86_64::new();
codegen.emit_prologue()?;
compile_file_to(&mut codegen, "std.zr", include_str!("std.zr").into())?;
compile_file_to(&mut codegen, filename, source)?;
// TODO
if fs::write("out.s", codegen.get_output()).is_err() {
eprintln!("\x1b[91mERROR\x1b[0m: failed to write to out.s");
process::exit(1);
}
if !args.output_asm {
if fs::write(format!("{}.s", args.out), codegen.get_output()).is_err() {
eprintln!("\x1b[91mERROR\x1b[0m: failed to write to {}.s", args.out);
process::exit(1);
}
if !Command::new("nasm")
.args(["-f", "elf64", "-o", "out.o", "out.s"])
.status()
.unwrap()
.success()
{
process::exit(1);
}
if !Command::new("sh")
.args([
"-c",
&format!("nasm -f elf64 -o {}.o {}.s", args.out, args.out),
])
.status()
.unwrap()
.success()
{
process::exit(1);
}
// TODO: drop libc entirely
if !Command::new("./musl-1.2.4/root/bin/musl-gcc")
.args([
"-static",
"-o",
"out",
"out.o",
"-flto",
"-Os",
"-Wl,--gc-sections",
])
.status()
.unwrap()
.success()
{
// TODO: drop libc entirely
if !Command::new("sh")
.args([
"-c",
&format!(
"./musl-1.2.4/root/bin/musl-gcc -static -o {} {}.o -flto -Wl,--gc-sections {}",
args.out, args.out, args.cflags
),
])
.status()
.unwrap()
.success()
{
process::exit(1);
}
} else if fs::write(&args.out, codegen.get_output()).is_err() {
eprintln!("\x1b[91mERROR\x1b[0m: failed to write to {}", args.out);
process::exit(1);
}
Ok(())
}
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
struct Args {
path: String,
#[arg(short, default_value = "out", help = "Output path")]
out: String,
#[arg(short = 'S', help = "Only generate assembly")]
output_asm: bool,
#[arg(short = 'C', default_value = "", help = "Extra flags to pass to gcc")]
cflags: String,
}
fn main() {
let mut args = env::args();
let _ = args.next();
let args = Args::parse();
let path = match args.next() {
Some(x) => x,
None => {
eprintln!("\x1b[91mERROR\x1b[0m: expected an argument");
process::exit(1);
}
};
if let Err(err) = compile_file(path) {
if let Err(err) = compile_file(args) {
eprintln!("{}", err);
process::exit(1);
}