返回 CodeWhale
compile-host.mjs
根目录 / crates / tui / extension-host / compile-host.mjs
1 // Compile the committed canonical host with an explicitly supplied local Bun.
2 // --compile-executable-path forbids Bun's implicit runtime download. Target and
3 // architecture therefore follow that binary; cross targets need a matching
4 // verified build input, not a runtime fetched during host startup.
5 import { spawnSync } from 'node:child_process'
6 import { createHash } from 'node:crypto'
7 import { readFileSync, realpathSync } from 'node:fs'
8 import { dirname, isAbsolute, resolve } from 'node:path'
9 import { fileURLToPath } from 'node:url'
10
11 const here = dirname(fileURLToPath(import.meta.url))
12 const args = process.argv.slice(2)
13 const value = (flag) => {
14 const index = args.indexOf(flag)
15 if (index < 0 || !args[index + 1] || args[index + 1].startsWith('--')) throw new Error(`required: ${flag} PATH`)
16 return args[index + 1]
17 }
18 const bun = value('--bun')
19 if (!isAbsolute(bun)) throw new Error('--bun must name an absolute local Bun executable')
20 const binary = realpathSync(bun)
21 const output = resolve(value('--output'))
22 const bundle = resolve(here, 'dist/codewhale-extension-host.mjs')
23 const sourceSha = createHash('sha256').update(readFileSync(bundle)).digest('hex')
24 const cleanEnv = { ...process.env, NODE_OPTIONS: '', BUN_OPTIONS: '', BUN_BE_BUN: '0', BUN_JSC_useShadowRealm: '0' }
25 // Actual selected compiler process facts, including emulation. Never label a
26 // runtime/image using the architecture of the Node driver or Rust runner.
27 const facts = spawnSync(binary, ['--no-install', '--no-env-file', `--config=${process.platform === 'win32' ? 'NUL' : '/dev/null'}`, '-p',
28 'JSON.stringify({platform:process.platform,arch:process.arch})'],
29 { cwd: here, env: cleanEnv, encoding: 'utf8', timeout: 5000, maxBuffer: 16 * 1024 })
30 if (facts.error || facts.status !== 0) throw facts.error ?? new Error(`compiler runtime identity failed (${facts.status})`)
31 const runtimeInfo = JSON.parse(facts.stdout)
32 if (!['linux', 'darwin', 'win32'].includes(runtimeInfo.platform) || !['x64', 'arm64'].includes(runtimeInfo.arch)) throw new Error('unsupported compiler runtime identity')
33 const run = (argv) => {
34 const result = spawnSync(binary, argv, { cwd: here, env: cleanEnv, encoding: 'utf8', timeout: 120_000, maxBuffer: 4 * 1024 * 1024 })
35 if (result.stdout) process.stderr.write(result.stdout)
36 if (result.stderr) process.stderr.write(result.stderr)
37 if (result.error || result.status !== 0) throw result.error ?? new Error(`Bun failed (${result.status})`)
38 }
39 run([
40 '--no-install', '--no-env-file', `--config=${process.platform === 'win32' ? 'NUL' : '/dev/null'}`, 'build', '--compile', `--compile-executable-path=${binary}`,
41 // A Windows Native host runs in an LPAC, which cannot open the NUL device;
42 // --no-compile-autoload-bunfig below already keeps bunfig.toml unread there.
43 `--compile-exec-argv=--no-install --no-env-file${process.platform === 'win32' ? '' : ' --config=/dev/null'} --no-addons`,
44 '--no-compile-autoload-dotenv', '--no-compile-autoload-bunfig',
45 '--no-compile-autoload-tsconfig', '--no-compile-autoload-package-json',
46 '--define=CODEWHALE_COMPILED_HOST=true',
47 `--define=CODEWHALE_COMPILED_BUNDLE_SHA256=${JSON.stringify(sourceSha)}`,
48 resolve(here, 'src/compiled.mjs'), '--outfile', output,
49 ])
50 const probe = spawnSync(output, ['--codewhale-host-info'], { env: cleanEnv, encoding: 'utf8', timeout: 5000, maxBuffer: 16 * 1024 })
51 if (probe.error || probe.status !== 0) throw probe.error ?? new Error(`compiled host probe failed (${probe.status})`)
52 const info = JSON.parse(probe.stdout)
53 if (info.kind !== 'codewhale-extension-host' || info.runtime !== 'bun' || info.bundle_sha256 !== sourceSha || typeof info.version !== 'string' || info.platform !== runtimeInfo.platform || info.arch !== runtimeInfo.arch) {
54 throw new Error('compiled host identity does not match the canonical bundle')
55 }
56 console.log(JSON.stringify({ output, ...info, compiler: runtimeInfo }))
57
57 lines Plain Text