Mark the generated modules.c with GENERATED_MARKER, so that check_content.py refuses it in a commit.

make_game.py modules_c writes gen/modules.c with the sha256 of the player's ExeFS modules and the install's absolute paths, and wrote it with no comment at all, so check_content.py, which refuses a file by its marker, its suffix, its name or a key line, would have let it into a commit. AGENTS.md wants the marker on every file the generator emits. Its first line now carries the marker and says what wrote it. It costs players one compile of modules.c and a link at their next build: make_game.py is part of the compile key, and every other object comes from the object cache.

The other half of the finding, the marker on the lift's layout.h, waits: it is a change to recomp/layout.py and recomp/gen.py, whose digest keys every player's lift (a full lift at the update) and the execution profile's fit, so it belongs to the next release that changes recomp/ anyway.

Not reproduced before the change: found by reading the code; the audit's probe showed modules_c without the marker. Checks that passed: tests/launcher_test.py (217 tests; the modules.c test now asserts the marker on its first line and that check_content.problems_for refuses the file, and fails before the change), tests/host_probes_test.py, tests/pgo_build_test.py and tools/check_content.py --staged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
chrg6
2026-11-13 17:25:12 -05:00
parent 6b051eea58
commit 5f90486cf0
2 changed files with 9 additions and 1 deletions

View File

@@ -3116,6 +3116,9 @@ class MakeGameTest(Tmp):
(out / 'exefs' / name).write_bytes(b'x')
(lift / 'layout.json').write_text(json.dumps([{'name': 'main'}]))
text = self.mg.modules_c(lift, out, gen).read_text(encoding='utf-8')
import check_content
self.assertIn(check_content.GENERATED_MARKER, text.splitlines()[0])
self.assertIn('generated from game code', check_content.problems_for(gen / 'modules.c')) # refused in a commit
for half in ('\\ud83e', '\\ud842'): # the first surrogate halves of the two characters
self.assertNotIn(half, text.lower())
want = 'const char rt_default_exefs[] = "' + str(out / 'exefs').replace('\\', '\\\\') + '";'

View File

@@ -98,6 +98,7 @@ sys.path.insert(0, str(KIT / 'tools'))
import nup # noqa: E402
import mod_files # noqa: E402
import prompt_art # noqa: E402
from check_content import GENERATED_MARKER # noqa: E402
TITLE_ID = 0x0400486024DEC000
MAIN_BUILD_ID = 'e0f3ccfaf50065ae4ea01eb5aeb13b1a' # main of game 1.1.1
@@ -642,8 +643,12 @@ def c_string(text):
def modules_c(lift, out, gen):
"""gen/modules.c: the lifted modules' table, the ExeFS's sha256 and this install's folders. It carries
GENERATED_MARKER, which tools/check_content.py refuses in a commit: it is derived from the game and names the
player's paths."""
layout = json.loads((lift / 'layout.json').read_text(encoding='utf-8'))
L = ['#include "dispatch.h"', '#include "host.h"', '#include "layout.h"', '']
L = [f'/* {GENERATED_MARKER}: module table, written by tools/make_game.py modules_c. Do not edit or commit. */',
'#include "dispatch.h"', '#include "host.h"', '#include "layout.h"', '']
for m in layout:
n = m['name']
L += [f'extern const uint64_t {n}_fn_addrs[];', f'extern const GuestFn {n}_fn_ptrs[];',