fix(emit-lib): weak aether_lib_meta so N lib TUs link with no dup flags - #1591
Merged
Conversation
…gs (#1590) Every --emit=lib TU carries the aether_lib_meta() reflection catalog (issue #403) with external linkage, so the 0.539 multi-TU link model — one --emit=lib C per module, one final link, NO -Wl,--allow-multiple-definition — died with N-1 duplicate-symbol errors the moment an orchestrator (aeb regen, observed on avn) linked two lib TUs. The plain-emission multi_tu_import_link regression could not see it: only --emit=lib emits the catalog. The catalog entry point is now emitted weak (__attribute__((weak)) under GCC/Clang — honoured across ELF/Mach-O/COFF; non-GNU compilers keep the old strong emission). A lone .so is unchanged: one definition, same dlsym contract, `ae lib-info` verified against a freshly built .so. In a multi-TU link the first TU's catalog wins and the link proceeds with no escape hatch, on ld64 as well as GNU ld. multi_tu_import_link grows a phase-2: the same four-module program with the three modules emitted --emit=lib (three catalogs in one link), no dedup flags, runs, plus an nm pin that aether_lib_meta is W not T. docs/emit-lib.md documents the weak contract and the multi-TU first-wins caveat. All emit-lib-adjacent suites pass: lib_meta, lib_meta_closures, emit_lib_const, emit_lib_deadline, emit_lib_net, emit_csrc, emit_obj, emit_link_requirements, multi_tu_import_link. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The nm belt in multi_tu_import_link phase 2 grepped for "W" and treated "T" as strong — but Mach-O nm prints a weak definition as a plain T and only `nm -m` shows the "weak external" flag, so the check false-failed on exactly the platform (ld64) the no-dup-flag model exists for; the link and run steps themselves passed on macOS. The belt now branches on uname: Darwin uses `nm -m` + "weak external", everything else keeps the W/T check. Also: the 0.540.0 catch-up merge auto-folded this PR's CHANGELOG entry into the released [0.540.0] section; moved back under a fresh [current]. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1590.
Every
--emit=libTU carries theaether_lib_meta()reflection catalog(issue #403) with external linkage, so the 0.539 multi-TU link model —
one
--emit=libC per module, one final link, no-Wl,--allow-multiple-definition— died with N-1multiple definition of `aether_lib_meta'errors as soon as anorchestrator linked two lib TUs (observed on avn: aether 0.539.0 + aeb
009c830, every ≥2-module binary). The existing
multi_tu_import_linkregression used plain emission, which carries no catalog, so it passed
right through the hole.
Fix (option 1 from the issue)
The catalog entry point is now emitted weak:
the no-escape-hatch link works on GNU ld and ld64 — the whole
point of the 0.539 model.
.sois byte-for-byte the same contract: one definition, dlsymunchanged — verified by rebuilding a single-module
.soand runningae lib-infoagainst it, plus thelib_meta/lib_meta_closuressuites.
says to treat
aether_lib_metaas meaningful only on single-moduleartifacts. (Per-TU catalog symbols — option 2 — remain open as a
follow-up if aeb ever wants per-module introspection in one artifact.)
only), same as before.
Test
multi_tu_import_linkgrows a phase 2 closing the coverage gap theissue called out: the same four-module program with its three modules
emitted
--emit=lib(three catalogs in one link), compiled and linkedwith no duplicate-symbol flags of any kind, output pinned, plus an
nmbelt that
aether_lib_metaisW, notT. Before the codegen changethis phase fails with exactly the avn-reported duplicate-symbol error.
All emit-lib-adjacent suites pass locally: lib_meta, lib_meta_closures,
emit_lib_const, emit_lib_deadline, emit_lib_net, emit_csrc, emit_obj,
emit_link_requirements, multi_tu_import_link.
Downstream: once released, aeb can drop the
link_flag("-Wl,--allow-multiple-definition")workaround from itsmulti-TU targets and macOS stays viable for the
--emit=liborchestrator shape.
🤖 Generated with Claude Code