Phase 6: P-Code-Bibliotheken und Linker abschließen, Cross-Buildplan festhalten

This commit is contained in:
2026-09-07 16:06:23 +02:00
parent 60d37ec79d
commit 25176947ba
33 changed files with 2416 additions and 203 deletions

View File

@@ -384,3 +384,92 @@ fn native_build_optionen_sind_explizit_und_tbc_bleibt_standard() {
assert!(!dir.join("program").exists());
}
}
#[test]
fn library_cli_links_without_sources_and_protects_all_inputs_and_outputs() {
let dir = std::env::temp_dir().join(format!("tb-library-cli-{}", std::process::id()));
std::fs::create_dir(&dir).unwrap();
struct Cleanup(std::path::PathBuf);
impl Drop for Cleanup {
fn drop(&mut self) {
let _ = std::fs::remove_dir_all(&self.0);
}
}
let _cleanup = Cleanup(dir.clone());
let call = |args: &[&str]| {
Command::new(env!("CARGO_BIN_EXE_tbc"))
.current_dir(&dir)
.env("PATH", "")
.args(args)
.output()
.unwrap()
};
let success = |args: &[&str]| {
let out = call(args);
assert!(out.status.success(), "{args:?}: {out:?}");
out
};
std::fs::write(
dir.join("a.bas"),
"DECLARE SUB Second(n%)\nSUB First(n%)\nSecond n%\nEND SUB\n",
)
.unwrap();
std::fs::write(dir.join("b.bas"), "SUB Second(n%)\nn%=n%+7\nEND SUB\n").unwrap();
success(&["build", "a.bas", "--library"]);
success(&["build", "b.bas", "--library", "--output", "b.tbl"]);
std::fs::remove_file(dir.join("a.bas")).unwrap();
std::fs::remove_file(dir.join("b.bas")).unwrap();
std::fs::write(dir.join("main.bas"), "CALL First(n%)\nPRINT n%\nEND\n").unwrap();
assert!(!call(&["link", "main.bas", "a.tbl"]).status.success());
success(&["link", "main.bas", "a.tbl", "b.tbl", "-o", "linked.tbc"]);
assert_eq!(success(&["run", "linked.tbc"]).stdout, b" 7 \n");
std::fs::write(dir.join("app.mak"), "main.bas\na.tbl\nb.tbl\n").unwrap();
success(&["check", "app.mak"]);
success(&["build", "app.mak"]);
assert_eq!(success(&["run", "app.mak"]).stdout, b" 7 \n");
let before = std::fs::read(dir.join("a.tbl")).unwrap();
let old = std::fs::read(dir.join("linked.tbc")).unwrap();
for args in [
vec![
"link", "main.bas", "a.tbl", "b.tbl", "-o", "a.tbl", "--force",
],
vec!["link", "main.bas", "a.tbl", "b.tbl", "-o", "linked.tbc"],
vec!["build", "main.bas", "--library", "--exe"],
vec![
"build",
"main.bas",
"--library",
"--target",
"aarch64-apple-darwin",
],
vec!["link", "linked.tbc", "a.tbl", "--exe"],
vec!["link", "linked.tbc"],
vec!["run", "a.tbl"],
vec!["check", "a.tbl"],
vec!["link", "a.tbl"],
vec!["link", "main.bas", "main.bas"],
vec!["link", "main.bas", "a.tbl", "a.tbl"],
vec!["link", "app.mak", "-o", "app.mak", "--force"],
vec!["link", "app.mak", "-o", "missing/output.tbc"],
] {
assert!(!call(&args).status.success(), "accepted {args:?}");
assert_eq!(std::fs::read(dir.join("a.tbl")).unwrap(), before);
assert_eq!(std::fs::read(dir.join("linked.tbc")).unwrap(), old);
}
success(&["link", "app.mak", "-o", "linked.tbc", "--force"]);
let old = std::fs::read(dir.join("linked.tbc")).unwrap();
std::fs::write(dir.join("a.tbl"), &before[..before.len() - 1]).unwrap();
assert!(!call(&["link", "app.mak", "-o", "linked.tbc", "--force"])
.status
.success());
assert_eq!(std::fs::read(dir.join("linked.tbc")).unwrap(), old);
for p in ["a.tbl", "b.tbl", "main.bas", "app.mak"] {
std::fs::remove_file(dir.join(p)).unwrap();
}
assert_eq!(success(&["run", "linked.tbc"]).stdout, b" 7 \n");
assert!(!std::fs::read_dir(&dir).unwrap().any(|e| e
.unwrap()
.file_name()
.to_string_lossy()
.contains(".tmp")));
}