Skip to content

vms-ca9: LIBRARIAN.EXE + real .OLB object libraries (LINK.EXE consumes) — self-host spine #3 - #429

Merged
baron-3dl merged 5 commits into
mainfrom
vms-ca9-librarian-olb
Aug 13, 2026
Merged

baron-3dl merged 5 commits into
mainfrom
vms-ca9-librarian-olb

Conversation

@baron-3dl

Copy link
Copy Markdown
Contributor

Summary (vms-ca9, self-host spine #3, epic vms-59a)

Adds the object-library half of the OVMX-native toolchain: a native
LIBRARIAN.EXE that produces .OLB object libraries, LINK.EXE that
resolves undefined symbols by selectively pulling the needed .OLB members, and
promotes the DCL LIBRARY/OBJECT path from defined-only to real object-library
semantics.

Design settled in docs/design-self-host-mmk-spine.md §3 (not relitigated here).

.OLB format (Rule 8)

VSI does not publish the byte-level LBR .OLB layout, so OVMX defines its own
and labels it a design choice: a standard ar archive of .OBJ (ELF)
members. Reader/writer live in the header-only src/vmslink/include/ovmx_olb.h
(shared by LIBRARIAN.EXE and the DCL path so both agree on the bytes); GNU
long-name (//) table supported so a stock ar t FOO.OLB can inspect one — used
as an independent test oracle.

What's here

  • LIBRARIAN.EXE (src/vmslink/librarian.c): /CREATE /INSERT /DELETE /LIST /EXTRACT over .OLB, VMS status codes, installed to SYS$SYSTEM: alongside
    LINK.EXE/OVMXDUMP (a host toolchain tool, same category).
  • dcl_library.c: LIBRARY/OBJECT (.OLB) now writes/reads the real ar
    container LINK consumes; TEXT (.TLB)/HELP (.HLB) keep the LBRO format
    unchanged. No new cross-image symbols (format code is header-only), so the
    native DCL.EXE graph is unaffected beyond one added include path.
  • LINK.EXE (link.c): searches a .OLB like a real object library —
    pulls only members that resolve outstanding strong undefined references,
    to a fixpoint; .a keeps whole-archive ingestion. Isolated in its own
    commit
    ("LINK.EXE: consume .OLB — toolchain core", operator-approved
    2026-08-13) for standalone review.

Isolation of the toolchain-core edit

The link.c change is a single dedicated commit that touches only link.c
(215 insertions), distinct from the LIBRARIAN.EXE and dcl_library.c commits.

Tests (veracity Q1/Q2)

  • ctest toolchain-olb-roundtrip (host): LIBRARIAN builds an .OLB from 2
    real .OBJ; ar confirms it; LINK resolves an undefined symbol by pulling
    the one member that defines it (link succeeds with no --allow-undefined,
    so success proves the pull); negative control — a library lacking the
    member makes the same link FAIL; OVMXDUMP confirms image validity. Ran
    synchronously: exit 0.
  • run_olb_native.sh + CI librarian-olb-native-x86_64: the full activates
    and runs
    proof — LIBRARIAN /CREATE, LINK --executable selective pull
    (1 of 2), IMGACT activates the produced image and it RUNS (mul3(14)==42,
    exit 0), VMS-native (no ld/ld.so). Verified locally in the alpine musl
    container.
  • Native-link graph (OVMX_LINK_NATIVE, x86_64 musl container) rebuilds clean
    (9 artifacts incl. DCL.EXE) — dcl_library.c compiles natively with the new
    include and LINK.EXE links the whole graph.

Notes

  • The pre-existing docs/design-self-host-mmk-spine.md §3.4 called selective
    extraction a non-blocking follow-up; the operator approved the link.c edit,
    so it is implemented and isolated here.
  • No deferred gaps.

🤖 Generated with Claude Code

alice and others added 5 commits August 13, 2026 03:00
New SYS$SYSTEM: toolchain image LIBRARIAN.EXE that produces/maintains OVMX
object libraries (.OLB) which LINK.EXE consumes — the object-library half of
the OVMX-native toolchain (TCC.EXE -> LIBRARIAN.EXE -> LINK.EXE -> IMGACT.EXE).

- src/vmslink/include/ovmx_olb.h: the shared .OLB reader/writer. Per Rule 8,
  VSI does not publish the byte-level LBR .OLB layout, so OVMX defines its own
  representation and LABELS it a design choice: a standard `ar` archive of .OBJ
  (ELF) members. Header-only (static inline) so LIBRARIAN.EXE and the DCL
  LIBRARY/OBJECT path share one byte layout; GNU long-name (//) table supported
  so a stock `ar` can inspect an .OLB (used as an independent test oracle).
- src/vmslink/librarian.c: /CREATE /INSERT /DELETE /LIST /EXTRACT over .OLB,
  VMS status codes, %LIBRAR- messages. A host toolchain tool alongside LINK.EXE
  and OVMXDUMP (reads/writes .OLB/.OBJ; not itself a VMS runtime image).
- CMakeLists: install LIBRARIAN.EXE to SYS$SYSTEM:.

Design settled in docs/design-self-host-mmk-spine.md §3.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Promote dcl_library.c's OBJECT path from defined-only to a real object library.
An .OLB (or /OBJECT) LIBRARY command now writes/reads the ar-container format
(shared ovmx_olb.h) that LINK.EXE consumes — LIBRARY/CREATE /INSERT /LIST
/EXTRACT /DELETE — instead of the TEXT/HELP "LBRO" blob that LINK cannot read.
TEXT (.TLB) / HELP (.HLB) libraries keep the LBRO format unchanged.

Module names for OBJECT members derive from the .OBJ basename (upper-cased,
extension stripped) — an OVMX choice, since an OVMX .OBJ carries no VMS
module-name field. No new cross-image symbols (the format code is header-only
static inline), so the native DCL.EXE graph is unaffected beyond an added
include path (src/vmsdcl/CMakeLists.txt + mk_dcl.sh).

tests/dcl/test_library_object.sh: DCL writes an .OLB and the system `ar`
(independent oracle) reads it back with the inserted module.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Isolated toolchain-core edit (operator-approved 2026-08-13), separated for
review. LINK.EXE now searches an OVMX object library (.OLB) like a real object
library: it pulls ONLY the members needed to resolve currently-undefined strong
external references, iterating to a fixpoint (a pulled member may reference a
symbol another member defines) — the classic ELF archive-member selection,
keyed on member symbol tables directly (no dependence on an ar `/` symbol index).

A `.a` archive keeps its whole-archive ingestion (unchanged, still wanted for
the musl C-RTL and OVMX shareables); selection is by the `.OLB` extension.
STRONG (STB_GLOBAL) undefined refs force extraction; WEAK undefined refs do not
(matching ld). Emits %LINK-I-LIBRARY, "<lib>: N of M members pulled (selective)".

The .OLB is an OVMX-labeled `ar` container (Rule 8, docs/design-self-host-mmk-
spine.md §3, src/vmslink/include/ovmx_olb.h); the byte-level ar walk here is the
same as the existing load_archive path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
End-to-end veracity for the object-library toolchain path:

- tests/toolchain/run_olb_roundtrip.sh (ctest toolchain-olb-roundtrip): LIBRARIAN
  builds an .OLB from >=2 real .OBJ; `ar` (independent oracle) confirms it; LINK
  resolves an undefined symbol by SELECTIVELY pulling the one member that defines
  it (link succeeds with NO --allow-undefined, so success proves the pull);
  negative control — a library lacking the member makes the same link FAIL;
  OVMXDUMP confirms the produced image is a valid OVMX shareable. Registered in
  the top CMakeLists (BUILD_TOOLS-gated, since it needs the host toolchain bins).
- src/imgact/test/run_olb_native.sh + CI job librarian-olb-native-x86_64:
  the full "activates and runs" proof — LIBRARIAN /CREATE, LINK.EXE --executable
  selective pull (1 of 2), then IMGACT.EXE activates the produced image and it
  RUNS (mul3(14)==42, exit 0), VMS-native (no ld/ld.so). Shares the producer-
  graph builder with run_link_native.sh.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ink enum)

run_dcl_native.sh compiles the DCL TUs with its OWN INCS list (not mk_dcl.sh's),
so dcl_library.c's new #include "ovmx_olb.h" failed to resolve there — breaking
the "DCL.EXE VMS-native Link + Activate" jobs (S1 aarch64 + x86_64 vms-bdf) at
compile of the 23 DCL objects. Add -I$SRC/vmslink/include to its INCS, matching
the wiring already added to CMake link_native_graph and mk_dcl.sh (the third DCL
native-link enumeration per the project gotcha).

Reproduced in the alpine x86_64 musl container: 23 DCL objects compile clean,
DCL.EXE links (exit 0) and IMGACT-activates + runs a scripted session (exit 0).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@baron-3dl
baron-3dl merged commit 6da9bcc into main Aug 13, 2026
59 of 61 checks passed
baron-3dl added a commit that referenced this pull request Aug 13, 2026
#445)

Bump OVMX_PRODUCT_VERSION V0.4 → V0.4-1. 24 PRs / 32 commits since V0.4,
packed across dimensions (point release toward the 0.5 milestone):

  self-host (R7)  #409 lib$tparse · #411 CLI$ compiled-CLD · #413 sys$setddir
                  #414 lib$get_foreign · #415 sys$filescan (RTL foundation)
                  #418 parse_tables.mar→C (spine #2) · #429 LIBRARIAN.EXE+.OLB (spine #3)
                  #435 shareable-vector freeze (GSMATCH stability)
  authenticity    #421 veracity rubric (Q1 oracle-source/Q2 real-inject) · #424 30 oracle-pinned constants
                  #433 rmsdef.h 74 fabricated RMS codes → oracle
  UX/DCL/RMS      #422 SHOW CLUSTER real membership · #441 DCL per-@-level local scope
                  #442 RMS XAB dates → VMS 1858-epoch quadword
  networking      #419 virtio NIC (user-mode default + opt-in tap/bridge)
  docs            #423 clustering release train
  + swept: other threads' merged work on main since V0.4

Clustering config-authoring UX (vms-098) + its public-manual grounding gate
remain 0.5 (minor) deliverables — not triggered by this point cut.

Co-authored-by: alice <alice@workspace.local>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant