ReviewOS

also looking at this

craft-native/craft

fix(build): select the core Zig project explicitly

#383
Merged chris wants to merge codex/zig-core-build-root into main
4 files +44 -2

Review threads live on the whole diff, not on one commit, so none are shown here - a thread's line means something in the branch's final form, and painting it into an intermediate step would put it on code it is not about.

.github/workflows/ci.ymlmodified+3-0
Changes to .github/workflows/ci.yml
@@ -187,6 +187,9 @@ jobs:
187187 - name: First-party Zig dependencies
188188 uses: ./.github/actions/first-party-zig-deps
189189
190 - name: Verify pinned compiler core project selection
191 run: bun scripts/verify-zig-core-project.ts
192
190193 - name: Build Windows CLI
191194 # scripts/zig.ts resolves the actual managed binary from pantry.lock,
192195 # including its adjacent standard library on Windows.
scripts/verify-zig-core-project.tsadded+36-0
Changes to scripts/verify-zig-core-project.ts
@@ -0,0 +1,36 @@
1import { mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
2import { tmpdir } from 'node:os'
3import { join, resolve } from 'node:path'
4import { resolveZig } from './zig'
5
6const source = resolve(import.meta.dir, '..')
7const zig = resolveZig(source)
8const root = mkdtempSync(join(tmpdir(), 'craft-core-project-'))
9const core = join(root, 'packages', 'zig')
10try {
11 mkdirSync(core, { recursive: true })
12 writeFileSync(join(root, 'pantry.lock'), readFileSync(join(source, 'pantry.lock')))
13 writeFileSync(join(root, 'package.json'), JSON.stringify({ version: '1.2.3' }))
14 writeFileSync(join(root, 'build.zig'), 'const std=; pub fn build(b:*std.Build) void {_=b.standardOptimizeOption(.{});}\n')
15 writeFileSync(join(core, 'build.zig'), 'const std=; pub fn build(b:*std.Build) void {_=b.standardOptimizeOption(.{}); const version=b.option([]const u8,"version","version") orelse "missing"; std.debug.print("PROJECT_VERSION={s}\\n",.{version});}\n')
16 const env = { ...process.env, CRAFT_ZIG: zig.path }
17 const child = Bun.spawnSync([process.execPath, '-p', 'process.cwd()'], { cwd: core, env, stdout: 'pipe', stderr: 'pipe' })
18 console.log('Requested/observed child cwd:', JSON.stringify({ requested: core, observed: child.stdout.toString().trim(), status: child.exitCode }))
19 for (const mode of ['default', 'absolute', 'relative'] as const) {
20 const cwd = mode === 'relative' ? root : core
21 const args = mode === 'default' ? [] : ['--build-file', mode === 'absolute' ? join(core, 'build.zig') : 'packages/zig/build.zig']
22 const result = Bun.spawnSync([zig.path, 'build', ...args, '-Dversion=1.2.3'], { cwd, env, stdout: 'pipe', stderr: 'pipe' })
23 console.log(JSON.stringify({ mode, cwd, status: result.exitCode, stdout: result.stdout.toString(), stderr: result.stderr.toString() }))
24 }
25 const runner = join(root, 'runner.ts')
26 writeFileSync(runner, `import {runZig} from ${JSON.stringify(join(source, 'scripts/zig.ts'))};process.exitCode=runZig(${JSON.stringify(root)},['--core','--versioned','build']);\n`)
27 const result = Bun.spawnSync([process.execPath, runner], { cwd: root, env, stdout: 'pipe', stderr: 'pipe' })
28 console.log(result.stdout.toString(), result.stderr.toString())
29 // The root wrapper rejects -Dversion. A successful configure therefore
30 // proves core selection even when Zig reuses its cached configuration.
31 if (result.exitCode !== 0)
32 throw new Error('The actual pinned compiler did not configure the selected core project with its package version.')
33}
34finally {
35 rmSync(root, { recursive: true, force: true })
36}