Skip to content

perl: ship a usable core-module runtime (generated files + static XS) so File::Spec/POSIX load on Kandelo#821

Open
brandonpayton wants to merge 1 commit into
mainfrom
gascity/kd-1mr/kd-k7zy-package-perl-generated-core-module-runtime-files
Open

perl: ship a usable core-module runtime (generated files + static XS) so File::Spec/POSIX load on Kandelo#821
brandonpayton wants to merge 1 commit into
mainfrom
gascity/kd-1mr/kd-k7zy-package-perl-generated-core-module-runtime-files

Conversation

@brandonpayton

Copy link
Copy Markdown
Member

Purpose

The Perl Homebrew bottle shipped only perl.wasm with no core-module runtime,
and the interpreter crashed on any real module load — so the port only ever
passed a trivial arithmetic smoke. This makes Perl-on-Kandelo actually usable:
File::Spec, POSIX, Cwd, XSLoader, Config and the pure-perl core all
load and run. Fixes kd-k7zy (follow-up from the kd-p3hr language-runtime wave,
where File::Spec failed because generated runtime files such as XSLoader.pm
were never staged).

Root causes fixed

  1. Generated runtime files were never produced or packaged. build-perl.sh
    ran make perl, which stops before perl-cross's nonxs_ext/extensions
    targets that generate lib/XSLoader.pm (from dist/XSLoader/XSLoader_pm.PL)
    and stage the core-module tree via pm_to_blib. Compounding it, the target
    Config had an empty osname, so ExtUtils::MakeMaker's $Config{osname} eq … probes hit undef and every module's staging failed. Fix:
    -Dosname=linux (Kandelo is a POSIX/linux-like syscall surface) + build with
    make -k, then package lib/perl5/5.40.3 as a new perl-runtime.zip output.

  2. The shipped interpreter miscompiled and panicked on any weak-ref use.
    build-perl.sh already documents -fno-strict-aliasing as load-bearing
    (clang -O2 miscompiles perl's weak-ref machinery into a magic_killbackrefs
    panic) but applied it only to HOSTCFLAGS (host miniperl), not the target
    -Dccflags. So perl.wasm panicked magic_killbackrefs/del_backref the
    moment any module traversed weak refs (use File::Spec, use Config). Fix:
    add -fno-strict-aliasing to the target ccflags.

  3. XS core modules could not load. The config shipped usedl=define; XS
    modules built .sos loaded via dlopen, which Kandelo's wasm musl does not
    implement (dlerror() not implemented). So File::Spec (→ File::Spec::Unix
    Cwd, an XS module), POSIX, Fcntl, List::Util all failed. Fix:
    -Uusedl builds extensions statically, linking their XS into perl.wasm with
    a boot table so XSLoader::load resolves them without dlopen. perl-cross
    ignores -Dnoextensions, so the statically-linked set is curated by editing
    Makefile.config's fullpath_static_ext — dropping ext/re (recompiles
    regcomp.c → duplicate symbols vs core regcomp.o) and extensions needing
    libraries absent from the wasm sysroot / threads.

Changes

  • packages/registry/perl/build-perl.sh — resolver-contract output handling
    (WASM_POSIX_DEP_OUT_DIR, sdk/activate.sh); -Dosname=linux;
    -fno-strict-aliasing on target ccflags; -Uusedl + curated
    fullpath_static_ext; make -k staging + perl-runtime.zip packaging with a
    post-check that the generated files (XSLoader.pm, Config.pm, File/Spec.pm,
    File/Spec/Unix.pm, Cwd.pm) are present.
  • packages/registry/perl/package.toml — declare the perl-runtime output.
  • packages/registry/perl/build.toml — revision 1 → 2 (output bytes change).
  • homebrew/kandelo-homebrew/Formula/perl.rb — install perl.wasm + unzip the
    runtime into lib/perl5/5.40.3; test covers File::Spec, POSIX (a module
    that bootstraps via XSLoader), and XSLoader. (Requires the tap's
    formula_support/kandelo_package.rb; bottle-test acceptance tracks kd-yuef.)
  • packages/registry/perl/demo/runtime-smoke.ts — Node kernel-host smoke.

Verification

Node runCentralizedProgram (host-fs passthrough, LC_ALL=C,
PERL5LIB=staged privlib) against the built perl.wasm (~4.2M static):

RESULTS=Config=ok,XSLoader=ok,FileSpec_catfile=ok,FileSpec_rel2abs=ok,Cwd_xs=ok,POSIX_xs=ok,Fcntl_xs=ok,ListUtil_xs=ok,DataDumper_xs=okPERL_RUNTIME_SMOKE_PASS

  • File::Spec->catfile('a','b','c.txt')a/b/c.txt
  • File::Spec->rel2abs('x','/root')/root/x (Cwd's XS bootstraps via XSLoader)
  • POSIX::floor(3.7) → 3; Fcntl O_RDONLY; List::Util::sum(1..4) → 10; Cwd::getcwd
  • Data::Dumper; XSLoader 0.32; Config version 5.40.3

perl.wasm ≈ 4.2M (static XS); perl-runtime.zip ≈ 10M (711 core .pm incl unicore).

Full gate (cargo test -p kandelo … --lib, vitest, libc/posix suites,
check-abi-version) was not run: this change is package-recipe only (build script,
manifest, formula, demo) and touches no kernel/host/ABI code. Browser bottle run
tracks kd-yuef.

Known boundaries (follow-ups filed)

  • kd-dvph — perl 5.40 panics at startup parsing Kandelo musl's composite
    default locale (C.UTF-8;C;C;C;C;C); tests/smoke set LC_ALL=C.
  • kd-gtxaErrno_pm.PL finds no errno constants under the wasm sysroot, so
    Errno.pm is absent (make -k keeps going past it).
  • kd-14n8 — broaden the static XS set (Encode/Compress/Sys::Syslog/re) by
    wiring the needed libs into the sysroot or implementing a working wasm dlopen.

🤖 Generated with Claude Code

The Perl bottle shipped only perl.wasm with no core-module runtime, and the
interpreter crashed on any real module load, so the port only ever passed a
trivial arithmetic smoke. Make Perl-on-Kandelo usable: File::Spec, POSIX, Cwd,
XSLoader, Config and the pure-perl core all load and run. Fixes kd-k7zy (the
kd-p3hr follow-up where File::Spec failed on missing generated XSLoader.pm).

Three root causes, all in the build recipe:
- Generated runtime files were never produced/packaged: `make perl` stops
  before perl-cross's nonxs/extensions targets that generate lib/XSLoader.pm and
  stage the core tree, and the target Config had an empty osname so MakeMaker's
  probes failed. Fix: -Dosname=linux + build with `make -k`, then package
  lib/perl5/5.40.3 as a new perl-runtime.zip output.
- The interpreter miscompiled and panicked on any weak-ref use: -O2 without
  -fno-strict-aliasing miscompiles perl's weak-ref code into a magic_killbackrefs
  panic. The flag was on HOSTCFLAGS only; add it to the target -Dccflags.
- XS core modules could not load: usedl=define builds .so's loaded via dlopen,
  which Kandelo wasm lacks. -Uusedl links XS into perl.wasm with a boot table so
  XSLoader::load resolves them without dlopen. perl-cross ignores -Dnoextensions,
  so the static set is curated by editing Makefile.config's fullpath_static_ext
  (drop ext/re, which duplicates core regcomp symbols, and external-lib/threads
  exts). Also work around a perl-cross bug where the static-ext recipe never
  runs pm_to_blib: after make -k, stage each curated static ext's .pm.

build.toml revision 1 -> 2 (output bytes change). package.toml declares the
perl-runtime output. Formula/perl.rb installs perl.wasm + the runtime and tests
File::Spec/POSIX/XSLoader. demo/runtime-smoke.ts is a Node kernel-host smoke.

Verified via Node runCentralizedProgram against the packaged perl-runtime.zip
(LC_ALL=C): File::Spec catfile/rel2abs, Cwd, POSIX, Fcntl, List::Util,
Data::Dumper, XSLoader, Config all load (PERL_RUNTIME_SMOKE_PASS). Known
boundaries filed: kd-dvph (default-locale startup panic), kd-gtxa (Errno errno
extraction), kd-14n8 (broaden static XS / dlopen). Browser bottle tracks kd-yuef.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
brandonpayton added a commit that referenced this pull request Jul 1, 2026
…s bottle

This branch's perl.rb staged the runtime by globbing the source tree, which
could not include the generated XSLoader.pm (never produced by `make perl`), so
File::Spec failed. PR #821 (kd-k7zy) fixes this end to end: it generates the
core-module runtime, packages it as perl-runtime.zip, statically links the core
XS (Kandelo wasm has no dlopen), and fixes the target -fno-strict-aliasing
miscompile -- File::Spec/POSIX/Cwd/XSLoader all load (Node-verified).

Per coordinator decision (kd-k7zy owns Perl, same resolution as ruby->#814 /
cpython->#818): revert packages/registry/perl/build-perl.sh to origin/main and
delete this branch's homebrew/kandelo-homebrew/Formula/perl.rb so #821's perl is
the sole owner. This branch no longer touches Perl vs main; php/erlang/texlive
are unchanged. #810's build-perl.sh delta was purely the resolver-contract
refactor, which #821 already carries, so nothing is preserved separately.

Co-Authored-By: Claude Opus 4.8 <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