31 lines
1.8 KiB
JavaScript
31 lines
1.8 KiB
JavaScript
/** Build the Windows artifact from source on Windows or the Linux/Wine CI host. */
|
|
import { execFileSync } from 'node:child_process'
|
|
import { rmSync, readFileSync } from 'node:fs'
|
|
import path from 'node:path'
|
|
import { fileURLToPath } from 'node:url'
|
|
|
|
const sourceHome = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../assets/codex-bridge')
|
|
export function compilerCommand({ platform = process.platform, env = process.env, source, output }) {
|
|
const args = ['/nologo', '/target:exe', '/platform:anycpu', '/reference:System.Web.Extensions.dll', `/out:${output}`, source]
|
|
if (platform === 'win32') {
|
|
return { command: path.win32.join(env.SystemRoot || 'C:/Windows', 'Microsoft.NET/Framework64/v4.0.30319/csc.exe'), args }
|
|
}
|
|
if (platform === 'linux') return { command: 'mcs', args }
|
|
throw new Error(`Windows launcher compilation is not configured on ${platform}`)
|
|
}
|
|
|
|
export function buildNativeWatchLauncher({ home = sourceHome, ...options } = {}) {
|
|
const output = path.join(home, 'native-watch.exe')
|
|
const invocation = compilerCommand({ ...options, source: path.join(home, 'NativeWatchBootstrap.cs'), output })
|
|
// A missing compiler or broken source must fail packaging, never reuse an old EXE.
|
|
rmSync(output, { force: true })
|
|
execFileSync(invocation.command, invocation.args, { windowsHide: true, stdio: 'inherit' })
|
|
const bytes = readFileSync(output)
|
|
if (bytes.length < 64 || bytes.toString('ascii', 0, 2) !== 'MZ' || bytes.toString('ascii', bytes.readUInt32LE(60), bytes.readUInt32LE(60) + 4) !== 'PE\0\0') {
|
|
rmSync(output, { force: true })
|
|
throw new Error('Native watch compiler did not produce a Windows PE executable')
|
|
}
|
|
return output
|
|
}
|
|
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) buildNativeWatchLauncher()
|