use std::path::Path;
use std::process::Command;
use crate::container::podman_exec;
pub fn build_asm(workdir: &str) -> Result<(), String> {
println!("Assembling .asm files...");
let asm_dir = Path::new(workdir).join("src/asm");
let target_dir = Path::new(workdir).join("target/asm");
std::fs::create_dir_all(&target_dir)
.map_err(|e| format!("Failed to create target/asm: {}", e))?;
if asm_dir.exists() {
for entry in std::fs::read_dir(&asm_dir).map_err(|e| e.to_string())? {
let entry = entry.map_err(|e| e.to_string())?;
let path = entry.path();
if path.extension().map_or(false, |ext| ext == "asm") {
let filename = path.file_stem().unwrap().to_string_lossy();
println!(" Assembling {}...", filename);
let status = Command::new("llvm-mc")
.args([
"--filetype=obj",
"-triple=mos",
"-mcpu=mosw65c02",
path.to_str().unwrap(),
"-o",
&format!("{}/target/asm/{}.o", workdir, filename),
])
.status()
.map_err(|e| format!("Failed to assemble {}: {}", filename, e))?;
if !status.success() {
return Err(format!("Failed to assemble {}", filename));
}
}
}
}
println!(" Creating libasm.a...");
let o_files: Vec<_> = std::fs::read_dir(&target_dir)
.map_err(|e| e.to_string())?
.filter_map(|e| e.ok())
.filter(|e| e.path().extension().map_or(false, |ext| ext == "o"))
.map(|e| e.path().to_string_lossy().to_string())
.collect();
if !o_files.is_empty() {
let mut args = vec!["rcs".to_string(), format!("{}/target/asm/libasm.a", workdir)];
args.extend(o_files.clone());
let status = Command::new("llvm-ar")
.args(&args)
.status()
.map_err(|e| format!("Failed to archive: {}", e))?;
if !status.success() {
return Err("Failed to create libasm.a".to_string());
}
for o_file in o_files {
let _ = std::fs::remove_file(o_file);
}
}
Ok(())
}
pub fn build_asm_in_container(workdir: &Path, working_dir: &Path) -> Result<(), String> {
println!("Assembling .asm files...");
let asm_dir = workdir.join("src/asm");
let target_dir = workdir.join("target/asm");
std::fs::create_dir_all(&target_dir)
.map_err(|e| format!("Failed to create target/asm: {}", e))?;
let rel_workdir = workdir.strip_prefix(working_dir).unwrap_or(workdir);
let workspace_dir = format!("/workspace/{}", rel_workdir.to_string_lossy());
if asm_dir.exists() {
for entry in std::fs::read_dir(&asm_dir).map_err(|e| e.to_string())? {
let entry = entry.map_err(|e| e.to_string())?;
let path = entry.path();
if path.extension().map_or(false, |ext| ext == "asm") {
let filename = path.file_stem().unwrap().to_string_lossy();
println!(" Assembling {}...", filename);
podman_exec("/workspace", &[
"llvm-mc",
"--filetype=obj",
"-triple=mos",
"-mcpu=mosw65c02",
&format!("{}/src/asm/{}.asm", workspace_dir, filename),
"-o",
&format!("{}/target/asm/{}.o", workspace_dir, filename),
])?;
}
}
}
let o_files: Vec<_> = std::fs::read_dir(&target_dir)
.map_err(|e| e.to_string())?
.filter_map(|e| e.ok())
.filter(|e| e.path().extension().map_or(false, |ext| ext == "o"))
.map(|e| format!("{}/target/asm/{}", workspace_dir, e.path().file_name().unwrap().to_string_lossy()))
.collect();
if !o_files.is_empty() {
println!(" Creating libasm.a...");
let mut args = vec![
"llvm-ar".to_string(),
"rcs".to_string(),
format!("{}/target/asm/libasm.a", workspace_dir),
];
args.extend(o_files);
let args_ref: Vec<&str> = args.iter().map(|s| s.as_str()).collect();
podman_exec("/workspace", &args_ref)?;
for entry in std::fs::read_dir(&target_dir).map_err(|e| e.to_string())? {
let entry = entry.map_err(|e| e.to_string())?;
if entry.path().extension().map_or(false, |ext| ext == "o") {
let _ = std::fs::remove_file(entry.path());
}
}
}
Ok(())
}