Skip to content
This repository was archived by the owner on Jul 21, 2026. It is now read-only.

m4: add the process-capable macro processor - #26

Merged
brandonpayton merged 3 commits into
mainfrom
migrate/m4-cli
Jul 12, 2026
Merged

m4: add the process-capable macro processor#26
brandonpayton merged 3 commits into
mainfrom
migrate/m4-cli

Conversation

@brandonpayton

@brandonpayton brandonpayton commented Jul 11, 2026

Copy link
Copy Markdown
Member

Purpose

Migrate GNU m4 from Kandelo's package registry into the first-party Homebrew tap as a normal source-built formula. m4 is a build-tool dependency for Autoconf-based software, and its syscmd/esyscmd builtins make real guest process creation and a declared POSIX shell part of the package contract.

Formula

  • builds current GNU m4 1.4.21 directly with the Kandelo SDK;
  • declares the tap Dash formula as the direct runtime dependency and uses upstream's --with-syscmd-shell=dash option so process builtins resolve that dependency through the guest PATH;
  • runs upstream make install, preserving bin/m4, the manpage, split Info manual, licenses, and standard package documentation;
  • does not fork-instrument the linked binary: GNU m4 1.4.21 implements this path with posix_spawn, and the exact Wasm imports kernel.kernel_clone rather than kernel.kernel_fork;
  • keeps the only source patch at an explicit upstream portability boundary: 2026 gnulib identifies musl from the GNU host tuple but assumes every musl compiler defines __linux__; Kandelo's non-Linux musl target intentionally does not.

The test executes version reporting, an included macro definition, expansion/evaluation, and esyscmd through the exact installed Dash dependency. There is no registry-script bridge.

Validation

The package evidence used a disposable ABI 18 integration checkout with the final Automattic/kandelo#874 config-site facts and Automattic/kandelo#883 host-identity change layered over the ABI 18 runtime. The Dash dependency was source-built from the tap before rebuilding m4.

  • isolated Homebrew source build: 14-file, 1.2 MB keg;
  • literal brew test --keep-tmp --force --verbose local/m4/m4: passed under Kandelo/Node, staging the exact tap Dash keg through KERNEL_PATH;
  • Chromium BrowserKernel: the exact final m4 and Dash keg bytes passed version plus include/macro/esyscmd behavior with exact stdout and empty stderr;
  • brew audit --strict --online local/m4/m4;
  • brew style local/m4/m4;
  • portable Ruby syntax and git diff --check;
  • final m4: 662,874 bytes, SHA-256 a400fd352ce4ef46a936a0f2fb8b588f4b2f296ab6bed5aa3a3262756cb1827e;
  • artifact contract: ABI export present, kernel.kernel_clone imported, no kernel.kernel_fork, no wpk_fork_*, and no legacy Asyncify surface.

Full Kandelo conformance suites were not rerun because this PR changes only tap formula/package behavior.

Source And Bottle Split

This PR is a source-formula change only. Dash's source formula is already on tap main, so the declared source dependency resolves. No bottle block, bottle archive, receipt, provenance sidecar, or package-registry artifact is added or changed here.

Bottle publication and stock-guest acceptance remain separately gated:

Bottle hashes will come only from that final trusted build; none are hand-written in this source PR.

Current-Main Restack

Replayed the three M4-owned commits from the old Dash base onto tap main b9df20653b44fb3125b809c4cf96df27f199c5f9, which includes source-merged Dash, Make, and Ed. The only conflicts were in the additive package catalog; the resolved README retains Make and Ed and adds M4.

Formula/m4.rb is byte-for-byte identical to old validated head be2c319efcbc4cc54695e1b211a803bae34cd117: Git blob 1f7d999b5a33b22a38616a5686e72b3c6c06246e, full-file SHA-256 29d490bdb9c272b0c561cd764a9f4784a8284a12b74c460163147e2f7bb9f73a, and post-support-import SHA-256 cb46bb7ea7b4af2e065f39ffd10d9838f96b3cc6ce8b1dd006dc20b98e7825b7.

Current head: 04b74de64ad540acc390b72b3a30c6eea5a0524d. Through scripts/dev-shell.sh, Ruby syntax, literal Homebrew formula loading with the declared Dash dependency, brew style, the formula-support suite (21 runs/186 assertions), exact old/new formula-blob comparison, range-diff review, current-main ancestry, and git diff --check passed. The main-relative diff contains only Formula/m4.rb and the additive M4 README entry, and the worktree is clean. No source build, runtime result, or bottle is newly claimed by this restack.

@brandonpayton

Copy link
Copy Markdown
Member Author

Devil's-advocate review completed at 8c0d07e.

I found and corrected two material formula defects:

  1. syscmd/esyscmd execute a shell, but the original formula declared no Dash dependency and passed only because the generic test rootfs already carried /bin/sh. The formula now declares Dash, configures upstream's supported --with-syscmd-shell=dash path, and stages the exact dependency keg in the test guest PATH.
  2. The original formula fork-instrumented m4 and described the process builtin as a fork-continuation path. The exact linked program instead imports kernel.kernel_clone: GNU m4 1.4.21 reaches it through posix_spawn. The instrumenter was adding inert wpk_fork_* scaffolding to a module with no kernel.kernel_fork import. That transform is now removed, as is the direct #873 gate.

I also reviewed the embedded gnulib patch against the generated source/configuration. #883 defines MUSL_LIBC from the accepted musl host identity; the patch changes only the two Linux-only musl guards needed to include langinfo.h and select the NL_LOCALE_NAME implementation. It applied during the final source build. Upstream make install preserved the executable, manpage, split Info manual, license, and standard documentation (14 files total).

Final independent evidence:

  • Source-built tap Dash 0.5.12, then rebuilt the exact final m4 formula through scripts/dev-shell.sh against ABI18 plus final #874 and #883 SDK state.
  • Literal brew test --keep-tmp --force --verbose local/m4/m4 passed under Node. The test used the exact Dash formula bytes through KERNEL_PATH and exercised include, macro expansion, esyscmd, child stdout, and child status.
  • Chromium BrowserKernel passed the same final m4/Dash pair: exit 0, exact macro/process stdout, and empty stderr.
  • Final m4 is 662,874 bytes, SHA-256 a400fd352ce4ef46a936a0f2fb8b588f4b2f296ab6bed5aa3a3262756cb1827e.
  • wasm-objdump: __abi_version export and kernel.kernel_clone import present; no kernel.kernel_fork, wpk_fork_*, or Asyncify surface.
  • Strict online audit, style, Ruby syntax, and git diff --check passed.

No formula-local blocker remains. Merge/bottle gates remain: tap #14; main #874 followed by a rebased/rerun #883; main #867 for the final ABI18 baseline; and a trusted fresh bottle from 8c0d07e. Do not merge before those gates and bottle publication complete.

@brandonpayton
brandonpayton changed the base branch from main to migrate/dash-shell July 11, 2026 23:19
@brandonpayton
brandonpayton force-pushed the migrate/dash-shell branch 2 times, most recently from b42c261 to 7a0f649 Compare July 12, 2026 01:08
@brandonpayton
brandonpayton changed the base branch from migrate/dash-shell to main July 12, 2026 01:14
Build GNU m4 directly through the Kandelo SDK, preserve its standard documentation, and instrument the binary so syscmd/esyscmd execute through the real fork path. Limit the source patch to gnulib's Linux-only musl guards for Kandelo's non-Linux musl userland.
Make Dash an explicit runtime dependency, configure GNU m4 to resolve that shell through the guest PATH, and exercise the exact dependency keg in the formula test. Remove the fork-instrumentation transform because the linked program uses posix_spawn through kernel.kernel_clone and does not import kernel.kernel_fork. Document the resulting dependency contract in the tap README.
@brandonpayton

Copy link
Copy Markdown
Member Author

Devil’s-advocate source-only review at 04b74de64ad540acc390b72b3a30c6eea5a0524d: ACCEPT. The M4 formula blob is byte-identical to the previously rebuilt ABI 18 source; the official GNU source SHA/license, scoped musl gnulib patch, Dash runtime dependency, --with-syscmd-shell=dash, version/include/macro/eval/esyscmd/sysval tests, artifact guards, and installed Tap.fetch path were rechecked. Fresh dev-shell syntax, style, literal loading, support (21 runs / 186 assertions), merge-tree, and diff checks pass. The merge tree preserves current main’s bzip2/xz wording. No bottle, sidecar, archive, receipt, or provenance metadata is included; this approval is source-only.

@brandonpayton
brandonpayton merged commit 594ad55 into main Jul 12, 2026
@brandonpayton
brandonpayton deleted the migrate/m4-cli branch July 12, 2026 02:05
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant