Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9d0e1f64d4 |
Vendored
BIN
Binary file not shown.
@@ -1,4 +1,4 @@
|
|||||||
// elb.el — El Build Coordinator
|
// elb.el - El Build Coordinator
|
||||||
//
|
//
|
||||||
// The build system for El programs. Written in El. Builds El.
|
// The build system for El programs. Written in El. Builds El.
|
||||||
//
|
//
|
||||||
@@ -16,11 +16,11 @@
|
|||||||
// 3. For each file: if .el is newer than .elh/.c, compile with elc --emit-header
|
// 3. For each file: if .el is newer than .elh/.c, compile with elc --emit-header
|
||||||
// 4. Link all .c files + el_runtime.c into the final binary
|
// 4. Link all .c files + el_runtime.c into the final binary
|
||||||
//
|
//
|
||||||
// Each module compiles independently — no 128K-line blobs.
|
// Each module compiles independently - no 128K-line blobs.
|
||||||
// Downstream compilations read .elh headers (function signatures only),
|
// Downstream compilations read .elh headers (function signatures only),
|
||||||
// not source. Incremental: only recompile what changed.
|
// not source. Incremental: only recompile what changed.
|
||||||
|
|
||||||
// ── Flags ─────────────────────────────────────────────────────────────────────
|
// -- Flags ---------------------------------------------------------------------
|
||||||
|
|
||||||
fn flag_bool(argv: [String], name: String) -> Bool {
|
fn flag_bool(argv: [String], name: String) -> Bool {
|
||||||
let n: Int = native_list_len(argv)
|
let n: Int = native_list_len(argv)
|
||||||
@@ -47,7 +47,7 @@ fn flag_val(argv: [String], name: String, default_val: String) -> String {
|
|||||||
return default_val
|
return default_val
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Manifest parsing ──────────────────────────────────────────────────────────
|
// -- Manifest parsing ----------------------------------------------------------
|
||||||
//
|
//
|
||||||
// Read the entry file from manifest.el:
|
// Read the entry file from manifest.el:
|
||||||
// build { entry "soul.el" }
|
// build { entry "soul.el" }
|
||||||
@@ -100,7 +100,7 @@ fn parse_manifest_name(src: String) -> String {
|
|||||||
return "out"
|
return "out"
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Path helpers ───────────────────────────────────────────────────────────────
|
// -- Path helpers ---------------------------------------------------------------
|
||||||
|
|
||||||
fn dirname_of(path: String) -> String {
|
fn dirname_of(path: String) -> String {
|
||||||
let n: Int = str_len(path)
|
let n: Int = str_len(path)
|
||||||
@@ -148,14 +148,14 @@ fn file_is_newer(a: String, b: String) -> Bool {
|
|||||||
let cmd: String = "test -f " + b + " && test " + a + " -nt " + b + " && echo yes || echo no"
|
let cmd: String = "test -f " + b + " && test " + a + " -nt " + b + " && echo yes || echo no"
|
||||||
let result: String = str_trim(exec_capture(cmd))
|
let result: String = str_trim(exec_capture(cmd))
|
||||||
if str_eq(result, "yes") { return true }
|
if str_eq(result, "yes") { return true }
|
||||||
// b doesn't exist — check with test -f
|
// b doesn't exist - check with test -f
|
||||||
let exist_cmd: String = "test -f " + b + " && echo exists || echo missing"
|
let exist_cmd: String = "test -f " + b + " && echo exists || echo missing"
|
||||||
let exist: String = str_trim(exec_capture(exist_cmd))
|
let exist: String = str_trim(exec_capture(exist_cmd))
|
||||||
if str_eq(exist, "missing") { return true }
|
if str_eq(exist, "missing") { return true }
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Import graph walker ────────────────────────────────────────────────────────
|
// -- Import graph walker --------------------------------------------------------
|
||||||
//
|
//
|
||||||
// Walk import statements in each .el file to build the dependency graph.
|
// Walk import statements in each .el file to build the dependency graph.
|
||||||
// Returns a list of absolute paths in topological order (deps before dependents).
|
// Returns a list of absolute paths in topological order (deps before dependents).
|
||||||
@@ -219,7 +219,7 @@ fn walk_imports(src_path: String, visited: [String], order: [String]) -> Map<Str
|
|||||||
return { "visited": visited, "order": order }
|
return { "visited": visited, "order": order }
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Build ──────────────────────────────────────────────────────────────────────
|
// -- Build ----------------------------------------------------------------------
|
||||||
|
|
||||||
fn compile_module(src_path: String, out_dir: String, elc_bin: String, dry_run: Bool, verbose: Bool) -> Bool {
|
fn compile_module(src_path: String, out_dir: String, elc_bin: String, dry_run: Bool, verbose: Bool) -> Bool {
|
||||||
let bname: String = basename_noext(src_path)
|
let bname: String = basename_noext(src_path)
|
||||||
@@ -246,13 +246,23 @@ fn compile_module(src_path: String, out_dir: String, elc_bin: String, dry_run: B
|
|||||||
println("elb: compile failed: " + src_path)
|
println("elb: compile failed: " + src_path)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Move the generated .elh (written next to the source by elc) into
|
||||||
|
// out_dir so that #include "module.elh" lines in the generated .c
|
||||||
|
// files resolve correctly when cc is invoked with -I <out_dir>.
|
||||||
|
let src_elh: String = path_with_ext(src_path, ".elh")
|
||||||
|
let mv_cmd: String = "cp " + src_elh + " " + elh_out + " 2>/dev/null || true"
|
||||||
|
exec_command(mv_cmd)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn link_binary(c_files: [String], out_bin: String, runtime_path: String, dry_run: Bool) -> Bool {
|
fn link_binary(c_files: [String], out_bin: String, runtime_path: String, out_dir: String, dry_run: Bool) -> Bool {
|
||||||
let n: Int = native_list_len(c_files)
|
let n: Int = native_list_len(c_files)
|
||||||
let parts: [String] = native_list_empty()
|
let parts: [String] = native_list_empty()
|
||||||
let parts = native_list_append(parts, "cc -O2 -I " + dirname_of(runtime_path))
|
// Include both the runtime dir (for el_runtime.h) and the output dir
|
||||||
|
// (for module.elh cross-module forward declarations).
|
||||||
|
let parts = native_list_append(parts, "cc -O2 -I " + dirname_of(runtime_path) + " -I " + out_dir)
|
||||||
let i = 0
|
let i = 0
|
||||||
while i < n {
|
while i < n {
|
||||||
let f: String = native_list_get(c_files, i)
|
let f: String = native_list_get(c_files, i)
|
||||||
@@ -273,7 +283,7 @@ fn link_binary(c_files: [String], out_bin: String, runtime_path: String, dry_run
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Main ───────────────────────────────────────────────────────────────────────
|
// -- Main -----------------------------------------------------------------------
|
||||||
|
|
||||||
fn main() -> Void {
|
fn main() -> Void {
|
||||||
let argv: [String] = args()
|
let argv: [String] = args()
|
||||||
@@ -311,7 +321,7 @@ fn main() -> Void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if str_eq(runtime_path, "") {
|
if str_eq(runtime_path, "") {
|
||||||
println("elb: cannot locate el_runtime.c — use --runtime=PATH")
|
println("elb: cannot locate el_runtime.c - use --runtime=PATH")
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -359,11 +369,11 @@ fn main() -> Void {
|
|||||||
|
|
||||||
// Link
|
// Link
|
||||||
let out_bin: String = out_dir + "/" + pkg_name
|
let out_bin: String = out_dir + "/" + pkg_name
|
||||||
let linked: Bool = link_binary(c_files, out_bin, runtime_path, dry_run)
|
let linked: Bool = link_binary(c_files, out_bin, runtime_path, out_dir, dry_run)
|
||||||
if !linked {
|
if !linked {
|
||||||
println("elb: link failed")
|
println("elb: link failed")
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
println("elb: done → " + out_bin)
|
println("elb: done -> " + out_bin)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user