7ab1ac8842
assembler crates.
161 lines
4.4 KiB
Rust
161 lines
4.4 KiB
Rust
use std::{
|
|
env, fs, io,
|
|
path::{Path, PathBuf},
|
|
process::Command,
|
|
};
|
|
|
|
use crate::common::config::DsxConfig;
|
|
|
|
use assembler::prelude::Assembler;
|
|
use common::build::{BuildError, Builder};
|
|
use compiler::Compiler;
|
|
|
|
// ---------- build ----------------------------------------------------------
|
|
pub fn build_project(cwd: &Path) -> Result<(), BuildError> {
|
|
let config: DsxConfig = toml::from_str(&fs::read_to_string(cwd.join("Dsx.toml"))?)
|
|
.map_err(|deser_err| {
|
|
io::Error::new(io::ErrorKind::InvalidData, deser_err.to_string())
|
|
})?;
|
|
|
|
let src_dir = cwd.join("src");
|
|
if !src_dir.exists() {
|
|
return Err(BuildError::Generic(String::from(
|
|
"Source Directory does not exist",
|
|
)));
|
|
}
|
|
|
|
// make sure there's a main file to assemble later.
|
|
if !main_exists(&src_dir)? {
|
|
return Err(BuildError::Generic(String::from(
|
|
"No main.dsa or main.dsc file found in top level of src directory.",
|
|
)));
|
|
}
|
|
|
|
// detect src.
|
|
let (has_dsa, has_dsc) = detect_source_language(&src_dir);
|
|
|
|
// create a build dir and copy all files across
|
|
let build_dir = cwd.join("build");
|
|
fs::create_dir_all(&build_dir)?;
|
|
env::set_current_dir(&build_dir)?;
|
|
|
|
copy_recursively(&src_dir, &build_dir)?;
|
|
|
|
if has_dsc {
|
|
build_all_dsc(&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);
|
|
|
|
// assemble result
|
|
{
|
|
fs::create_dir_all(cwd.join("artifacts"))?;
|
|
let mut asm = Assembler::new("./main.dsa");
|
|
asm.start();
|
|
asm.write_result("../artifacts/out.dsb")?;
|
|
}
|
|
|
|
println!("Build finished. Binary at {}/main.dsb", build_dir.display());
|
|
Ok(())
|
|
}
|
|
|
|
// ----- Helpers -------------------------------
|
|
|
|
struct BuildStep;
|
|
impl BuildStep {
|
|
pub fn compiling(path: &Path) {
|
|
println!("Compiling {}", path.display());
|
|
}
|
|
|
|
pub fn assembling(path: &Path) {
|
|
println!("Assembling {}", path.display());
|
|
}
|
|
}
|
|
|
|
/// Checks what source languages are used in the project.
|
|
fn detect_source_language(src_dir: &Path) -> (bool, bool) {
|
|
let mut contains_dsc = false;
|
|
let mut contains_dsa = false;
|
|
|
|
for entry in walkdir::WalkDir::new(src_dir).into_iter().flatten() {
|
|
match entry.path().extension().and_then(|s| s.to_str()) {
|
|
Some("dsc") => contains_dsc = true,
|
|
Some("dsa") => contains_dsa = true,
|
|
_ => {}
|
|
}
|
|
}
|
|
(contains_dsa, contains_dsc)
|
|
}
|
|
|
|
// Checks if either main.dsa or main.dsc exist in the source directory
|
|
fn main_exists(src_dir: &Path) -> Result<bool, std::io::Error> {
|
|
for entry in fs::read_dir(src_dir).into_iter().flatten() {
|
|
match entry?.path().file_name().and_then(|s| s.to_str()) {
|
|
Some("main.dsc") => return Ok(true),
|
|
Some("main.dsa") => return Ok(true),
|
|
_ => {}
|
|
}
|
|
}
|
|
|
|
Ok(false)
|
|
}
|
|
|
|
// Copy contents of one directory to another
|
|
fn copy_recursively(src: &Path, dst: &Path) -> Result<(), std::io::Error> {
|
|
if src.is_file() {
|
|
fs::create_dir_all(dst.parent().unwrap())?;
|
|
fs::copy(src, dst)?;
|
|
return Ok(());
|
|
}
|
|
|
|
if src.is_dir() {
|
|
for entry in fs::read_dir(src)? {
|
|
let entry = entry?;
|
|
let child_src = entry.path();
|
|
let child_dst = dst.join(entry.file_name());
|
|
copy_recursively(&child_src, &child_dst)?;
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn build_all_dsc(path: &Path) -> Result<(), BuildError> {
|
|
if path.is_dir() {
|
|
for entry in fs::read_dir(path)? {
|
|
let entry = entry?;
|
|
build_all_dsc(&entry.path())?;
|
|
}
|
|
|
|
return Ok(());
|
|
}
|
|
|
|
if path.extension().and_then(|s| s.to_str()) == Some("dsc") {
|
|
let input_path = path;
|
|
let output_path = path.with_extension("dsa");
|
|
|
|
let mut compiler = Compiler::new(input_path);
|
|
compiler.start();
|
|
compiler.write_result(output_path.clone())?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// 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);
|
|
}
|
|
}
|