Skip to content

Bootstrap utils/ndate, and stamp version.h without losing local edits - #565

Open
Ticed wants to merge 4 commits into
infernode-os:masterfrom
Ticed:fix/macos-build-ndate-and-version-stamp
Open

Bootstrap utils/ndate, and stamp version.h without losing local edits#565
Ticed wants to merge 4 commits into
infernode-os:masterfrom
Ticed:fix/macos-build-ndate-and-version-stamp

Conversation

@Ticed

@Ticed Ticed commented Aug 28, 2026

Copy link
Copy Markdown

Split out of #550, which is otherwise superseded by #559 and #560. These are
the two parts of it that stand on their own.

utils/ndate

mkhost-MacOSX sets NDATE=ndate and resolves it through PATH. BSD date has
no -n, so without utils/ndate built the emulator compiles KERNDATE from an
empty string and fails on ulong kerndate = ;. The EMUDIRS walk builds it
before emu; both macOS build scripts go straight to the emulator, so neither
gets it.

Both scripts build it first if it is missing. build-macos-sdl3.sh has the
same hole as the headless one and is the build AGENTS.md lists first.

version.h

Two faults in the SDL3 build's stamping.

The restore ran after mk, so a failed build left include/version.h dirty
with a stamp. It runs from an EXIT trap now.

The stamp anchored on InferNode 0.1, which also matches an already-stamped
string, so a second run stamped the stamp. It anchors on the unstamped
InferNode 0.1 ( now.

The restore takes a copy before stamping and puts that back, rather than
git checkout --. A trap that fires on every run must not reach into the work
tree: a developer with an in-progress edit to version.h would lose it, and
2>/dev/null || true would hide that happening.

Tests

tests/host/macos_version_stamp_test.sh is new. It puts a local edit in
version.h, runs the script with mk absent so the build fails after
stamping, and asserts the edit comes back untouched. It runs a second time and
asserts nothing accumulated. pkg-config is stubbed so the SDL3 probe cannot
decide the result.

Against the script before this change:

version.h was not restored to the edited content
expected:
  #define VERSION "InferNode 0.1 (LOCAL EDIT based on Inferno ...)"
got:
  #define VERSION "InferNode 0.1 build 20260828-735da540 (LOCAL EDIT based on Inferno ...)"

After:

macos_version_stamp: PASS

Not included

The mk nuke guard, the verify-dis-paths.sh rewrite and the run-tests.sh
staleness guard are dropped, per the review on #550. The lib/guide speech
path needs a real migration of speech9p.b and its call sites, so it wants its
own change rather than a doc-only edit.

@pdfinn pdfinn left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the right shape and the test is a real one — it fails against the old
mechanism with the exact diagnostic you'd want. Both fixes are what I asked
for and the reasoning in the description is accurate. One finding before it
lands.

tests/host/macos_version_stamp_test.sh passes vacuously on Linux

run-tests.sh globs the whole of tests/host/*_test.sh, so this runs on the
Linux CI jobs too. There, it reports PASS without exercising anything.

build-macos-sdl3.sh uses BSD sed -i ''. GNU sed reads '' as the -i
suffix and then treats the script as a filename, so on Linux the script dies
at the stamp:

sed: can't read s|InferNode 0.1 (|InferNode 0.1 build 20260831-c352cafd (|:
     No such file or directory

set -e aborts, the EXIT trap restores a file that was never stamped, and
cmp against version.h.edited succeeds. I ran it on Linux arm64 to check:

macos_version_stamp: PASS

with include/version.h untouched throughout — the stamp never landed, so
neither the restore path nor the idempotence check was tested. Both assertions
are trivially true when nothing happened.

That matters more than the usual "test doesn't run here", because a green
result on three of the CI jobs reads as coverage that isn't there — and this
test exists specifically to protect a path that already went wrong once.

The convention for this is three files away, in tests/host/build_test.sh:

if [ "$(uname -s)" != "Darwin" ]; then
    echo "SKIP: build_test is macOS-only (use build-linux-*.sh on Linux)"
    exit 77
fi

run-tests.sh counts 77 as SKIP, so it shows as skipped rather than passed.
Same guard at the top here and it's honest about where it runs.

Smaller note, not blocking

The test requires the build to fail after stamping, and what guarantees that
on macOS is the pkg-config stub: it answers --exists and --modversion,
and falls through to a bare exit 0 for --cflags/--libs, so the compile
gets no SDL3 include paths and dies. That works, but it's incidental rather
than stated — on a machine with SDL3 genuinely installed, the thing keeping
the build failing is the stub returning nothing, not the absence of mk. The
comment says "the build is expected to fail here: mk is not on PATH", but the
script puts $ROOT/MacOSX/arm64/bin on PATH itself, so on a dev machine with
the native tools built mk is found. Worth a sentence so the next person
doesn't tighten the stub and quietly break the premise.

The rest

utils/ndate in both scripts, with the same comment: correct, and matches
what the EMUDIRS walk does. ndate still appears in no other .sh or .yml
in the tree, so these two were the whole gap.

The version.h mechanism is right: copy taken before stamping, restored from
the copy on an EXIT trap, anchor on InferNode 0.1 ( so a second run cannot
stamp a stamp. That closes both faults, and doing it without reaching into
git means an in-progress edit survives — which was the thing I was worried
about.

Add the Darwin guard and I'm happy.

@Ticed

Ticed commented Aug 31, 2026

Copy link
Copy Markdown
Author

Darwin guard added, worded like build_test.sh's and exiting 77 so
run-tests.sh counts it as a skip. You were right that a green result on three
Linux jobs was worse than no result.

The stub comment is corrected too. It now says what actually keeps the build
failing — the pkg-config stub returning nothing for --cflags/--libs — and
warns against tightening it, since the script puts MacOSX/arm64/bin on PATH
itself and mk is found on a dev machine.

While proving the guard I found a second problem in my own test: the
idempotence assertion could not fail.
Every run starts from the restored file,
so the stamp sed sees the same input both times, and a missing anchor is only
visible on a run where the restore did not happen — where the first cmp
already fails. A hybrid with the new copy/restore mechanism but the old
unanchored
sed passed the test unchanged. The one thing the test existed to
pin was invisible to it.

It now asserts on the build output and feeds in an already-stamped
include/version.h, requiring exactly one build in the echoed Version:
line. That goes red against the hybrid and green here, with version.h
byte-identical after every run.

Two faults in the SDL3 build's version stamping.

The restore ran after mk, so a failed build left include/version.h dirty
with a stamp. It now runs from an EXIT trap.

The stamp anchored on "InferNode 0.1", which matches an already-stamped
string, so a second run stamped the stamp. It now anchors on the
unstamped "InferNode 0.1 (".

Restore from a copy taken before stamping rather than from git, so a
developer's in-progress edit to version.h survives the build.
run-tests.sh globs all of tests/host/*_test.sh, so the version stamp test
ran on Linux CI jobs too. There, build-macos-sdl3.sh's BSD 'sed -i ""'
dies under GNU sed, set -e aborts, the EXIT trap restores a file that was
never stamped, and both assertions pass vacuously. Guard on uname like
build_test.sh does (exit 77, counted as SKIP).

Also correct the comment on why the build is expected to fail: the
pkg-config stub returning empty --cflags/--libs is the mechanism, not mk
being off PATH, since the script puts $ROOT/MacOSX/arm64/bin on PATH
itself.
…ed run

The idempotence assertion re-tested the restore, not the anchor: every
run starts from the restored file, so the stamp sed sees the same input
each time and the restored file cannot distinguish an anchored sed from
an unanchored one. A build script with the new copy/restore mechanism
but the old unanchored sed passed the test.

Assert on the build's echoed Version line instead: after the first run
it must show the anchored stamp with 'build ' exactly once. Then feed
in an already-stamped version.h -- the state a failed restore leaves --
and require the echoed line still shows 'build ' exactly once, which
an unanchored sed fails by stamping the stamp.
@Ticed
Ticed force-pushed the fix/macos-build-ndate-and-version-stamp branch from 542b1ae to 6951f78 Compare September 2, 2026 03:15
@Ticed

Ticed commented Sep 2, 2026

Copy link
Copy Markdown
Author

Rebased onto current master (df34b02). Force-pushed 542b1ae -> 6951f78.

git range-diff reports every commit unchanged — same content, same messages,
only the base moved. The five commits that landed underneath are #583, #582,
#566, #578 and #580; none of them touches this branch's files.

Re-verified on macOS after the rebase.

The host test passes on Darwin and skips with exit 77 off it.
include/version.h is byte-identical by sha256 before and after every run.
The idempotence assertion was re-checked against a hybrid carrying the old
unanchored sed: it goes red there with two build in the Version line, so
the assertion can still fail rather than being trivially true.

#578 fixed the ClusterFuzzLite link break, so Fuzz should now be green here
rather than red for a reason that was never this branch's.

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.

2 participants