started working on build system
This commit is contained in:
+1
-1
@@ -1,7 +1,7 @@
|
||||
cargo-features = ["codegen-backend"]
|
||||
|
||||
[workspace]
|
||||
members = ["emulator", "common", "assembler", "dsa_editor", "compiler"]
|
||||
members = ["emulator", "common", "assembler", "dsa_editor", "compiler", "dsx-build"]
|
||||
resolver = "3"
|
||||
|
||||
[workspace.package]
|
||||
|
||||
@@ -24,5 +24,22 @@ pub mod prelude {
|
||||
pub use crate::tooling::project;
|
||||
}
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
use num_cpus as _;
|
||||
use threadpool as _;
|
||||
|
||||
use crate::prelude::CompilerEngine;
|
||||
|
||||
pub fn assemble_file(input: &str, output: &str) -> Result<(), std::io::Error> {
|
||||
let mut engine = CompilerEngine::new();
|
||||
engine.start_compilation(Path::new(input));
|
||||
let result = engine.wait_for_result().unwrap();
|
||||
for instruction in result {
|
||||
if let Err(e) = std::fs::write(output, instruction.encode().to_be_bytes()) {
|
||||
eprintln!("Failed to write to output file: {e}");
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "dsx-build"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
authors.workspace = true
|
||||
|
||||
[dependencies]
|
||||
compiler = { path = "../compiler" }
|
||||
assembler = { path = "../assembler" }
|
||||
chrono = "0.4.43"
|
||||
@@ -0,0 +1,223 @@
|
||||
use std::process::{Command, Stdio};
|
||||
use std::{
|
||||
env, fs,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
/// Run a command and exit on failure.
|
||||
fn run(cmd: &mut Command) {
|
||||
let status = cmd.status().expect("failed to execute command");
|
||||
if !status.success() {
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Very small CLI – only three sub‑commands.
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if args.len() < 2 {
|
||||
eprintln!("Usage: dsx-build <new|build|package> [options]");
|
||||
std::process::exit(1);
|
||||
}
|
||||
match args[1].as_str() {
|
||||
"new" => cmd_new(&args[2..]),
|
||||
"build" => cmd_build(),
|
||||
"package" => todo!("Package manager stub – not implemented yet."),
|
||||
_ => {
|
||||
eprintln!("Unknown command: {}", args[1]);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- new project ----------------------------------------------------
|
||||
fn cmd_new(args: &[String]) {
|
||||
let mut lang = "dsa";
|
||||
for i in 0..args.len() {
|
||||
if args[i] == "--lang" && i + 1 < args.len() {
|
||||
lang = &args[i + 1];
|
||||
}
|
||||
}
|
||||
|
||||
// Determine project root: a subdirectory named after the supplied --name argument.
|
||||
let mut name_opt = None;
|
||||
for i in 0..args.len() {
|
||||
if args[i] == "--name" && i + 1 < args.len() {
|
||||
name_opt = Some(&args[i + 1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let project_name = match name_opt {
|
||||
Some(name) => name.to_string(),
|
||||
None => {
|
||||
eprintln!("Error: --name argument required");
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
let cwd = env::current_dir().unwrap();
|
||||
let src_path = cwd.join(&project_name).join("src");
|
||||
fs::create_dir_all(&src_path).expect("Failed to create project directory");
|
||||
|
||||
match lang {
|
||||
"dsa" => {
|
||||
// Minimal DSA binary template.
|
||||
let path = src_path.join(format!("main.dsa"));
|
||||
let template = format!(
|
||||
r#"
|
||||
// GENERATED BY DSX-BUILD
|
||||
// Generated at: {timestamp}
|
||||
// Project name: {project_name}
|
||||
|
||||
// Imports
|
||||
include print: "./lib/io/print.dsa"
|
||||
|
||||
// Globals & Reserved Memory
|
||||
dw stack: 0x10000
|
||||
db message: "Process Exited with code:"
|
||||
|
||||
// Entry Point
|
||||
_init:
|
||||
ldw stack, bpr
|
||||
mov bpr, spr
|
||||
push zero
|
||||
call main
|
||||
call print::print_newline
|
||||
lwi message, rg0
|
||||
push rg0
|
||||
call print::print
|
||||
pop zero
|
||||
call print::print_hex_word
|
||||
pop zero
|
||||
hlt
|
||||
|
||||
main:
|
||||
push bpr
|
||||
mov spr, bpr
|
||||
|
||||
lli 0, rg0
|
||||
stw rg0, bpr, 8
|
||||
|
||||
mov bpr, spr
|
||||
pop bpr
|
||||
return"#,
|
||||
project_name = project_name,
|
||||
timestamp = chrono::Utc::now().format("%Y-%m-%d %H:%M:%S").to_string()
|
||||
);
|
||||
fs::write(path, template).expect("Unable to write DSA file");
|
||||
}
|
||||
"dsc" => {
|
||||
let path = src_path.join(format!("main.dsc"));
|
||||
let template = r#"
|
||||
include print: "./lib/io/print.dsa";
|
||||
|
||||
fn main() -> u32 {
|
||||
return 0;
|
||||
}"#;
|
||||
fs::write(path, template).expect("Unable to write DSC file");
|
||||
}
|
||||
_ => {
|
||||
eprintln!("Unsupported language: {}", lang);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
println!(
|
||||
"Created new {} project in {}.",
|
||||
lang,
|
||||
src_path.parent().unwrap().display()
|
||||
);
|
||||
}
|
||||
|
||||
// ---------- build ----------------------------------------------------------
|
||||
fn cmd_build() {
|
||||
let cwd = env::current_dir().unwrap();
|
||||
|
||||
// Detect .dsc or .dsa files in current directory.
|
||||
let mut has_dsc = false;
|
||||
let mut has_dsa = false;
|
||||
for entry in fs::read_dir(&cwd.join("src")).expect("unable to read dir") {
|
||||
if let Ok(entry) = entry {
|
||||
let path = entry.path();
|
||||
if path.extension().and_then(|s| s.to_str()) == Some("dsc") {
|
||||
has_dsc = true;
|
||||
} else if path.extension().and_then(|s| s.to_str()) == Some("dsa") {
|
||||
has_dsa = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !has_dsc && !has_dsa {
|
||||
eprintln!("No .dsc or .dsa source found in src directory.");
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
// Assemble main.dsa to a dsb binary.
|
||||
println!("Assembling Project to a DSB binary...");
|
||||
let build_dir = cwd.join("build");
|
||||
fs::create_dir_all(&build_dir).expect("Failed to create build directory");
|
||||
|
||||
// Copy everything from `cwd/src` to the build directory.
|
||||
fn copy_recursively(src: &Path, dst: &Path) {
|
||||
if src.is_file() {
|
||||
fs::create_dir_all(dst.parent().unwrap())
|
||||
.expect("Failed to create parent directory");
|
||||
fs::copy(src, dst).expect("Failed to copy file");
|
||||
} else if src.is_dir() {
|
||||
for entry in fs::read_dir(src).expect("Unable to read source dir") {
|
||||
let entry = entry.expect("Failed to read entry");
|
||||
let child_src = entry.path();
|
||||
let child_dst = dst.join(entry.file_name());
|
||||
copy_recursively(&child_src, &child_dst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let src_dir = cwd.join("src");
|
||||
if src_dir.exists() {
|
||||
copy_recursively(&src_dir, &build_dir);
|
||||
}
|
||||
|
||||
// Change current working directory to the build directory.
|
||||
env::set_current_dir(&build_dir).expect("Failed to change to build directory");
|
||||
|
||||
if has_dsc {
|
||||
println!("Compiling DSC to DSA...");
|
||||
fn compile_recursive(path: &Path) {
|
||||
if path.is_dir() {
|
||||
for entry in fs::read_dir(path).expect("unable to read dir") {
|
||||
let entry = entry.expect("failed to read entry");
|
||||
compile_recursive(&entry.path());
|
||||
}
|
||||
} else if path.extension().and_then(|s| s.to_str()) == Some("dsc") {
|
||||
let input_path = path;
|
||||
let output_path = path.with_extension("dsa");
|
||||
compiler::compile_file(&input_path, &output_path).unwrap_or_else(|e| {
|
||||
eprintln!("Failed to compile {:?}: {}", input_path, e);
|
||||
std::process::exit(1);
|
||||
});
|
||||
}
|
||||
}
|
||||
compile_recursive(&build_dir);
|
||||
}
|
||||
|
||||
// Replace .dsc with .dsa only in include statements, recursively for each file.
|
||||
let mut sed_cmd = Command::new("bash");
|
||||
sed_cmd.args(&[
|
||||
"-c",
|
||||
&format!(
|
||||
"find \"{}\" -type f -name '*.dsa' -exec sed -i '/^include/ s/\\.dsc/.dsa/g' {{}} +",
|
||||
build_dir.display()
|
||||
),
|
||||
]);
|
||||
run(&mut sed_cmd);
|
||||
|
||||
fs::create_dir_all(&cwd.join("artifacts")).expect("Failed to create build directory");
|
||||
assembler::assemble_file("./main.dsa", "../artifacts/out.dsb").unwrap_or_else(|e| {
|
||||
eprintln!("Failed to assemble {:?}: {}", "./main.dsa", e);
|
||||
std::process::exit(1);
|
||||
});
|
||||
|
||||
println!("Build finished. Binary at {}/main.dsb", build_dir.display());
|
||||
}
|
||||
Reference in New Issue
Block a user