import { createHash } from 'node:crypto' import { mkdir, readFile, writeFile } from 'node:fs/promises' import * as path from 'node:path' import { fileURLToPath } from 'node:url' const __dirname = fileURLToPath(new URL('.', import.meta.url)) // Workaround for Bun binary downloads failing on Windows CI when // USERPROFILE is passed through by Turborepo. // // Unfortunately, setting this at runtime doesn't appear to work so we have to // spawn a new process without the env var. if (process.env.NESTED_BUILD !== '1' && process.env.USERPROFILE && process.env.USERPROFILE !== '') { let result = await Bun.$`bun ${fileURLToPath(import.meta.url)}`.env({ USERPROFILE: '', NESTED_BUILD: '1', }) process.exit(result.exitCode) } // We use baseline builds for all x64 platforms to ensure compatibility with // older hardware. let builds: { target: Bun.Build.Target; name: string }[] = [ { name: 'tailwindcss-linux-arm64', target: 'bun-linux-arm64' }, { name: 'tailwindcss-linux-arm64-musl', target: 'bun-linux-arm64-musl' }, // @ts-expect-error: Either the types are wrong or the runtime needs to be updated // to accept a `-glibc` at the end like the types suggest. { name: 'tailwindcss-linux-x64', target: 'bun-linux-x64-baseline' }, { name: 'tailwindcss-linux-x64-musl', target: 'bun-linux-x64-baseline-musl' }, { name: 'tailwindcss-macos-arm64', target: 'bun-darwin-arm64' }, { name: 'tailwindcss-macos-x64', target: 'bun-darwin-x64-baseline' }, { name: 'tailwindcss-windows-x64.exe', target: 'bun-windows-x64-baseline' }, ] let summary: { target: Bun.Build.Target; name: string; sum: string }[] = [] // Build platform binaries and checksum them. let start = process.hrtime.bigint() for (let { target, name } of builds) { let outfile = path.resolve(__dirname, `../dist/${name}`) let result = await Bun.build({ entrypoints: ['./src/index.ts'], target: 'node', minify: { whitespace: false, syntax: true, identifiers: false, keepNames: true, }, define: { // This ensures only necessary binaries are bundled for linux targets // It reduces binary size since no runtime selection is necessary 'process.env.PLATFORM_LIBC': JSON.stringify(target.includes('-musl') ? 'musl' : 'glibc'), // This prevents the WASI build from being bundled with the binary 'process.env.NAPI_RS_FORCE_WASI': JSON.stringify(''), // This simplifies the Oxide loading code a small amount 'process.env.NAPI_RS_NATIVE_LIBRARY_PATH': JSON.stringify(''), // No need to support additional NODE_PATHs in the standalone build 'process.env.NODE_PATH': JSON.stringify(''), }, compile: { target, outfile, // Disable .env loading autoloadDotenv: false, // Disable bunfig.toml loading autoloadBunfig: false, }, plugins: [ { name: 'tailwindcss-plugin', setup(build) { build.onLoad({ filter: /tailwindcss-oxide\.wasi\.cjs$/ }, async (args) => { return { contents: '' } }) }, }, ], }) let entry = result.outputs.find((output) => output.kind === 'entry-point') if (!entry) throw new Error(`Build failed for ${target}`) let content = await readFile(outfile) summary.push({ target, name, sum: createHash('sha256').update(content).digest('hex'), }) } await mkdir(path.resolve(__dirname, '../dist'), { recursive: true }) // Write the checksums to a file let sumsFile = path.resolve(__dirname, '../dist/sha256sums.txt') let sums = summary.map(({ name, sum }) => `${sum} ./${name}`) await writeFile(sumsFile, sums.join('\n') + '\n') console.table(summary.map(({ target, sum }) => ({ target, sum }))) let elapsed = process.hrtime.bigint() - start console.log(`Build completed in ${(Number(elapsed) / 1e6).toFixed(0)}ms`)