Files
bun-src/scripts/build/depVersionsHeader.ts
T

122 lines
4.6 KiB
TypeScript
Raw Normal View History

2026-08-27 21:09:14 +00:00
/**
* Generates bun_dependency_versions.h — a header with dep version strings
* for `process.versions` and similar runtime introspection.
*
* Version values are DERIVED from `allDeps` — each dep's `source(cfg)`
* provides its commit/identity. Bumping a dep in `deps/<name>.ts`
* automatically updates this header. Single source of truth.
*
* Written at configure time. writeIfChanged semantics so changing an
* unrelated dep doesn't recompile everything via this header's mtime.
*
* Source: cmake/tools/GenerateDependencyVersions.cmake
*/
import { mkdirSync } from "node:fs";
import { resolve } from "node:path";
import type { Config } from "./config.ts";
import { allDeps } from "./deps/index.ts";
import { writeIfChanged } from "./fs.ts";
import type { Source } from "./source.ts";
/**
* Pull a version identifier from a Source. The shape depends on the kind:
* github-archive → commit hash, prebuilt → identity string. Local/in-tree
* don't have a pinned identifier.
*/
function sourceIdentifier(source: Source): string | undefined {
switch (source.kind) {
case "github-archive":
return source.commit;
case "prebuilt":
return source.identity;
case "local":
case "in-tree":
// User-managed / in-tree — no pinned identifier independent of the
// bun commit. Callers that need a value use cfg.revision.
return undefined;
}
}
/**
* (macro_name, value) pairs. Values that can't be determined are omitted
* from output (CMake behavior — consumers check #ifdef).
*/
function computeVersions(cfg: Config): [string, string][] {
const versions: [string, string][] = [];
// ─── Deps: derived from allDeps source definitions ───
// Single source of truth — bumping deps/<name>.ts updates this.
for (const dep of allDeps) {
if (dep.versionMacro === undefined) continue;
const source = dep.source(cfg);
const id = sourceIdentifier(source);
// WebKit special case: prebuilt.identity carries the artifact suffix, but
// process.versions wants the version. Strip the autobuild- prefix so tags
// report the clean sha and previews report preview-pr-<N>-<sha8>.
if (dep.name === "WebKit") {
const v = cfg.webkitVersion;
versions.push([dep.versionMacro, v.startsWith("autobuild-") ? v.slice("autobuild-".length) : v]);
} else if (id !== undefined) {
versions.push([dep.versionMacro, id]);
}
// local/in-tree with no identifier: omit (consumer does #ifdef)
}
// ─── Non-dep versions ───
// UWS/USOCKETS are vendored at packages/bun-usockets — the bun commit
// IS their version.
versions.push(["UWS", cfg.revision]);
versions.push(["USOCKETS", cfg.revision]);
// The runtime was ported from Zig; `process.versions.zig` records the
// upstream Zig commit it derives from. The build no longer uses a Zig
// toolchain, so this is a fixed historical reference rather than a live pin.
versions.push(["ZIG", "04e7f6ac1e009525bc00934f20199c68f04e0a24"]);
// NOTE: cmake's GenerateDependencyVersions.cmake also extracted semantic
// versions (LIBDEFLATE_VERSION="1.19", ZLIB_VERSION="1.2.8") from vendor
// headers. Those macros were never consumed — BunProcess.cpp only reads
// the _HASH (commit) macros for process.versions. The extraction is also
// a chicken-and-egg: it runs at configure time but vendor headers exist
// only after fetch, so on a clean checkout the header content flips on
// the second configure → spurious rebuild. Dropping the dead code.
return versions;
}
/**
* Generate bun_dependency_versions.h at buildDir/. Returns the absolute path.
*/
export function generateDepVersionsHeader(cfg: Config): string {
const outPath = resolve(cfg.buildDir, "bun_dependency_versions.h");
const versions = computeVersions(cfg).filter(([, v]) => v !== "" && v !== "unknown");
const lines: string[] = [
"// Auto-generated by scripts/build/depVersionsHeader.ts. Do not edit.",
"// Version values derived from scripts/build/deps/*.ts source definitions.",
"#ifndef BUN_DEPENDENCY_VERSIONS_H",
"#define BUN_DEPENDENCY_VERSIONS_H",
"",
"#ifdef __cplusplus",
'extern "C" {',
"#endif",
"",
"// Dependency versions",
...versions.map(([name, val]) => `#define BUN_DEP_${name} "${val}"`),
"",
"// C string constants for easy access",
...versions.map(([name, val]) => `static const char* const BUN_VERSION_${name} = "${val}";`),
"",
"#ifdef __cplusplus",
"}",
"#endif",
"",
"#endif // BUN_DEPENDENCY_VERSIONS_H",
"",
];
mkdirSync(cfg.buildDir, { recursive: true });
writeIfChanged(outPath, lines.join("\n"));
return outPath;
}