Skip to content

build/flags.stamp invalidation is target-independent: a maintenance target that builds no PRG deletes every object and the PRG, and leaves a stale .map behind #220

Description

@JC-000

build/flags.stamp invalidation is target-independent: a maintenance target that builds no PRG still deletes every object and the PRG, and leaves the stale .map behind

Summary

#159's stamp compare runs at Makefile parse time, which is the whole point of the design and is correct. The consequence that is not written down anywhere: it runs whatever target you asked for. make ip65-libs and make ip65-blob — neither of which produces a PRG — will delete every .o and build/c64-https.prg if their (flagless) command line expands differently from the stamped one.

Worse, and this is the part that actually costs you: build/c64-https.map is NOT deleted. You are left with a map file that corresponds to no artifact in the tree, in a repo where every memory-margin figure is measured off exactly that file.

This is not a bug report against #159's behaviour, which is sound and enforced by tools/test_build_flags_stamp.py. It is a request to (a) document the target-independence and (b) decide whether the surviving .map is acceptable.

Measured

All from a clean checkout at master 02e5662, libs/nistcurves v0.14.0.

Baselinemake BACKEND=uci USE_NISTCURVES_ONCHIP_COMB=1: 24 objects, PRG 00e4370ce3086e8b30df243861e56725a09797f08d8e668535c5166c62882152.

invocation after that build objects PRG map
make -n ip65-libs 24 present present
make ip65-libs 0 gone present (stale)
make ip65-blob 0 gone present (stale)
make BACKEND=uci USE_NISTCURVES_ONCHIP_COMB=1 ip65-libs 24 present present

So:

  1. It is not ip65-libs-specific. ip65-blob does it too. It is any real invocation whose expanded CA65FLAGS/LD65FLAGS differ from the stamp — the target is irrelevant, because the compare happens before target selection.
  2. Carrying the same flags through preserves everything (row 4). That is the workaround, and it is not obvious: you have to know to repeat build flags on a target that does not use them.
  3. -n is correctly exempt and even says so, which is make -n deletes all objects and the PRG: the flag-stamp compare runs at parse time #174 working exactly as designed:
    Makefile:781: A real build would rewrite the stamp and delete every object and build/c64-https.prg
    Makefile:782: at parse time. NOTHING was deleted; the tree is untouched.
    

Why it matters here specifically

CLAUDE.md's Memory-layout section demands that margin figures be re-measured in all five profiles off build/c64-https.map, and names "corrected in one profile, left stale in the other four" as the recurring failure. The natural way to do that is: build a profile, read the map, build the next. If anything in that loop shells out to a maintenance target without repeating the flags, the map silently stops matching the PRG — and a .map that survives its .os gives no signal that it has gone stale. Every number in it still parses fine.

This was hit for real while measuring the uci-comb CRYPTO_OVERLAY tail for #193 (the 153 B → 126 B correction on fix/triage-quickwins); the measurement was saved first, by luck rather than by rule.

Suggested resolution

Pick one or more:

  • Docs (cheapest). CLAUDE.md's Build section describes flags.stamp at length but frames it entirely as protecting builds. Add that the compare is target-independent, that a flagless maintenance target therefore invalidates, and that repeating the flags is the way to avoid it. The make ip65-libs / make ip65-blob bullets are the place a reader would look.
  • Delete the .map alongside the PRG. One line in the invalidation, and it converts a silently-stale measurement source into an absent one — the same argument $(PRG)'s recipe already makes for rm -fing the target ("an absent PRG is the honest state after a failed link"). The map deserves the same treatment for the same reason.
  • Exempt the maintenance targets. Probably wrong — it reintroduces exactly the "make skipped an invalidation it needed" hazard make -n deletes all objects and the PRG: the flag-stamp compare runs at parse time #174 fought, and the exemption logic is already the subtlest part of the Makefile. Recorded so it is visibly considered and declined.

My preference is docs + deleting the map; the third option is noted only to be rejected.

Not claimed

I have not checked whether make package / package-verify are exposed to this, nor whether any test suite or rig shells out to a maintenance target mid-measurement. Both are worth a look and neither is in evidence above.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions