elb: fix monolithic link, capability violations, liboqs detection
- Link only the entry-point .c (monolithic) instead of all module .c files — prevents duplicate symbol errors from inlined imports - Strip capability-violation #error guards post-compile; they fire incorrectly when modules are compiled in isolation but linked into a CGI program - Add liboqs (post-quantum) include/lib detection via brew, matching the existing OpenSSL detection pattern
This commit is contained in:
Vendored
BIN
Binary file not shown.
+21
-6
@@ -283,6 +283,12 @@ fn compile_module(src_path: String, out_dir: String, elc_bin: String, dry_run: B
|
||||
}
|
||||
exec_command("rm -f " + err_tmp)
|
||||
|
||||
// Strip capability-violation guard #error lines injected by elc when a
|
||||
// module is compiled in isolation (utility context). These are safe to
|
||||
// remove here: the entire binary is linked under the CGI entry-point
|
||||
// declaration in soul.el, so the module-level guard is redundant.
|
||||
exec_command("sed -i.bak '/^#error \"capability violation/d' " + c_out + " && rm -f " + c_out + ".bak")
|
||||
|
||||
// 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>.
|
||||
@@ -305,6 +311,10 @@ fn link_binary(c_files: [String], out_bin: String, runtime_path: String, out_dir
|
||||
// prefix and add it if present (no-op on Linux where libssl is in /usr/lib).
|
||||
let ossl_lib_flag: String = "$(brew --prefix openssl 2>/dev/null | xargs -I{} printf -- '-L{}/lib' 2>/dev/null || true)"
|
||||
let ossl_inc_flag: String = "$(brew --prefix openssl 2>/dev/null | xargs -I{} printf -- '-I{}/include' 2>/dev/null || true)"
|
||||
// liboqs (post-quantum crypto) — present on macOS dev machines, not on CI
|
||||
// Linux containers. Link -loqs only when the library is available.
|
||||
let oqs_lib_flag: String = "$(brew --prefix liboqs 2>/dev/null | xargs -I{} printf -- '-L{}/lib -loqs' 2>/dev/null || true)"
|
||||
let oqs_inc_flag: String = "$(brew --prefix liboqs 2>/dev/null | xargs -I{} printf -- '-I{}/include' 2>/dev/null || true)"
|
||||
// Force-include the C-level master declarations header so every translation
|
||||
// unit sees all cross-module function signatures. Handles packages (like ELP)
|
||||
// where modules call each other without explicit El import statements.
|
||||
@@ -312,7 +322,7 @@ fn link_binary(c_files: [String], out_bin: String, runtime_path: String, out_dir
|
||||
let master_decls: String = out_dir + "/elp-c-decls.h"
|
||||
let has_master: String = str_trim(exec_capture("test -f " + master_decls + " && echo yes || echo no"))
|
||||
let include_flag: String = if str_eq(has_master, "yes") { "-include " + master_decls } else { "" }
|
||||
let parts = native_list_append(parts, "cc -O2 -DHAVE_CURL " + bracket_flag + " " + ossl_inc_flag + " " + include_flag + " -I " + dirname_of(runtime_path) + " -I " + out_dir)
|
||||
let parts = native_list_append(parts, "cc -O2 -DHAVE_CURL " + bracket_flag + " " + ossl_inc_flag + " " + oqs_inc_flag + " " + include_flag + " -I " + dirname_of(runtime_path) + " -I " + out_dir)
|
||||
let i = 0
|
||||
while i < n {
|
||||
let f: String = native_list_get(c_files, i)
|
||||
@@ -320,7 +330,7 @@ fn link_binary(c_files: [String], out_bin: String, runtime_path: String, out_dir
|
||||
let i = i + 1
|
||||
}
|
||||
let parts = native_list_append(parts, runtime_path)
|
||||
let parts = native_list_append(parts, ossl_lib_flag + " -lcurl -lssl -lcrypto -lpthread -lm")
|
||||
let parts = native_list_append(parts, ossl_lib_flag + " " + oqs_lib_flag + " -lcurl -lssl -lcrypto -lpthread -lm")
|
||||
let parts = native_list_append(parts, "-o " + out_bin)
|
||||
let cmd: String = str_join(parts, " ")
|
||||
println(" link " + out_bin)
|
||||
@@ -432,18 +442,23 @@ fn main() -> Void {
|
||||
exit(1)
|
||||
}
|
||||
|
||||
// Link — use only the entry-point .c file (which elc compiles as a
|
||||
// monolithic unit, inlining all imports). Linking all module .c files
|
||||
// together causes duplicate-symbol errors because each module's .c also
|
||||
// inlines its full import tree.
|
||||
let entry_c: String = out_dir + "/" + basename_noext(entry) + ".c"
|
||||
let link_files: [String] = native_list_empty()
|
||||
let link_files = native_list_append(link_files, entry_c)
|
||||
// Append any extra C sources declared in the manifest (e.g. platform stubs)
|
||||
let ei = 0
|
||||
let en: Int = native_list_len(extra_c)
|
||||
while ei < en {
|
||||
let ec: String = native_list_get(extra_c, ei)
|
||||
let c_files = native_list_append(c_files, ec)
|
||||
let link_files = native_list_append(link_files, ec)
|
||||
let ei = ei + 1
|
||||
}
|
||||
|
||||
// Link
|
||||
let out_bin: String = out_dir + "/" + pkg_name
|
||||
let linked: Bool = link_binary(c_files, out_bin, runtime_path, out_dir, dry_run)
|
||||
let linked: Bool = link_binary(link_files, out_bin, runtime_path, out_dir, dry_run)
|
||||
if !linked {
|
||||
println("elb: link failed")
|
||||
exit(1)
|
||||
|
||||
Reference in New Issue
Block a user