Revert "Convert build scripts to CMake (#13427)"

This reverts commit 354df17d16.
This commit is contained in:
Dylan Conway
2024-09-10 19:57:19 -07:00
parent a832954c94
commit 374bb15db6
223 changed files with 44769 additions and 4467 deletions

View File

@@ -1,251 +0,0 @@
#!/usr/bin/env node
import { spawn as nodeSpawn } from "node:child_process";
import { existsSync, readFileSync, readdirSync } from "node:fs";
import { join, relative, resolve } from "node:path";
// https://cmake.org/cmake/help/latest/manual/cmake.1.html#generate-a-project-buildsystem
const generateFlags = [
["-S", "string", "path to source directory"],
["-B", "string", "path to build directory"],
["-D", "string", "define a build option (e.g. -DCMAKE_BUILD_TYPE=Release)"],
["-G", "string", "build generator (e.g. -GNinja)"],
["-W", "string", "enable warnings (e.g. -Wno-dev)"],
["--fresh", "boolean", "force a fresh build"],
["--log-level", "string", "set the log level"],
["--debug-output", "boolean", "print debug output"],
["--toolchain", "string", "the toolchain to use"],
];
// https://cmake.org/cmake/help/latest/manual/cmake.1.html#generate-a-project-buildsystem
const buildFlags = [
["--config", "string", "build configuration (e.g. --config Release)"],
["--target", "string", "build target"],
["-t", "string", "same as --target"],
["--parallel", "number", "number of parallel jobs"],
["-j", "number", "same as --parallel"],
["--verbose", "boolean", "enable verbose output"],
["-v", "boolean", "same as --verbose"],
];
async function build(args) {
if (process.platform === "win32" && !process.env["VSINSTALLDIR"]) {
const shellPath = join(import.meta.dirname, "vs-shell.ps1");
const scriptPath = import.meta.filename;
return spawn("pwsh", ["-NoProfile", "-NoLogo", "-File", shellPath, process.argv0, scriptPath, ...args]);
}
const env = {
...process.env,
FORCE_COLOR: "1",
CLICOLOR_FORCE: "1",
};
const generateOptions = parseOptions(args, generateFlags);
const buildOptions = parseOptions(args, buildFlags);
const buildPath = resolve(generateOptions["-B"] || buildOptions["--build"] || "build");
generateOptions["-B"] = buildPath;
buildOptions["--build"] = buildPath;
if (!generateOptions["-S"]) {
generateOptions["-S"] = process.cwd();
}
const cacheRead = isCacheReadEnabled();
const cacheWrite = isCacheWriteEnabled();
if (cacheRead || cacheWrite) {
const cachePath = getCachePath();
if (cacheRead && !existsSync(cachePath)) {
const mainCachePath = getCachePath(getDefaultBranch());
if (existsSync(mainCachePath)) {
mkdirSync(cachePath, { recursive: true });
try {
cpSync(mainCachePath, cachePath, { recursive: true, force: true });
} catch (err) {
switch (err?.code) {
case "EPERM":
case "EACCES":
try {
chmodSync(mainCachePath, 0o777);
} catch (e2) {}
cpSync(mainCachePath, cachePath, { recursive: true, force: true });
break;
default:
throw err;
}
}
}
}
generateOptions["-DCACHE_PATH"] = cmakePath(cachePath);
generateOptions["--fresh"] = undefined;
if (cacheRead && cacheWrite) {
generateOptions["-DCACHE_STRATEGY"] = "read-write";
} else if (cacheRead) {
generateOptions["-DCACHE_STRATEGY"] = "read-only";
} else if (cacheWrite) {
generateOptions["-DCACHE_STRATEGY"] = "write-only";
}
}
const toolchain = generateOptions["--toolchain"];
if (toolchain) {
const toolchainPath = resolve(import.meta.dirname, "..", "cmake", "toolchains", `${toolchain}.cmake`);
generateOptions["--toolchain"] = toolchainPath;
}
const generateArgs = Object.entries(generateOptions).flatMap(([flag, value]) =>
flag.startsWith("-D") ? [`${flag}=${value}`] : [flag, value],
);
await spawn("cmake", generateArgs, { env });
const envPath = resolve(buildPath, ".env");
if (existsSync(envPath)) {
const envFile = readFileSync(envPath, "utf8");
for (const line of envFile.split(/\r\n|\n|\r/)) {
const [key, value] = line.split("=");
env[key] = value;
}
}
const buildArgs = Object.entries(buildOptions)
.sort(([a], [b]) => (a === "--build" ? -1 : a.localeCompare(b)))
.flatMap(([flag, value]) => [flag, value]);
await spawn("cmake", buildArgs, { env });
const buildFiles = ["ccache.log", "compile_commands.json"];
const buildPaths = [buildPath, ...readdirSync(buildPath).map(path => join(buildPath, path))];
const buildArtifacts = [];
for (const buildPath of buildPaths) {
for (const buildFile of buildFiles) {
const path = join(buildPath, buildFile);
if (existsSync(path)) {
buildArtifacts.push(path);
}
}
}
if (isBuildkite()) {
await Promise.all(buildArtifacts.map(path => spawn("buildkite-agent", ["artifact", "upload", relative(buildPath, path)], { cwd: buildPath, env })));
}
}
function cmakePath(path) {
return path.replace(/\\/g, "/");
}
function getCachePath(branch) {
const buildPath = process.env.BUILDKITE_BUILD_PATH;
const repository = process.env.BUILDKITE_REPO;
const fork = process.env.BUILDKITE_PULL_REQUEST_REPO;
const repositoryKey = (fork || repository).replace(/[^a-z0-9]/gi, "-");
const branchKey = (branch || process.env.BUILDKITE_BRANCH).replace(/[^a-z0-9]/gi, "-");
const stepKey = process.env.BUILDKITE_STEP_KEY.replace(/[^a-z0-9]/gi, "-");
return resolve(buildPath, "..", "cache", repositoryKey, branchKey, stepKey);
}
function isCacheReadEnabled() {
return (
isBuildkite() &&
process.env.BUILDKITE_CLEAN_CHECKOUT !== "true" &&
process.env.BUILDKITE_BRANCH !== getDefaultBranch()
);
}
function isCacheWriteEnabled() {
return isBuildkite();
}
function isBuildkite() {
return process.env.BUILDKITE === "true";
}
function getDefaultBranch() {
return process.env.BUILDKITE_PIPELINE_DEFAULT_BRANCH || "main";
}
function parseOptions(args, flags = []) {
const options = {};
for (let i = 0; i < args.length; i++) {
const arg = args[i];
for (const [flag, type] of flags) {
if (arg === flag) {
if (type === "boolean") {
options[arg] = undefined;
} else {
options[arg] = args[++i];
}
} else if (arg.startsWith(flag)) {
const delim = arg.indexOf("=");
if (delim === -1) {
options[flag] = arg.slice(flag.length);
} else {
options[arg.slice(0, delim)] = arg.slice(delim + 1);
}
}
}
}
return options;
}
async function spawn(command, args, options) {
const effectiveArgs = args.filter(Boolean);
const description = [command, ...effectiveArgs].map(arg => (arg.includes(" ") ? JSON.stringify(arg) : arg)).join(" ");
console.log("$", description);
const subprocess = nodeSpawn(command, effectiveArgs, {
stdio: "pipe",
...options,
});
let timestamp;
subprocess.on("spawn", () => {
timestamp = Date.now();
});
const stdout = new Promise(resolve => {
subprocess.stdout.on("end", resolve);
subprocess.stdout.on("data", data => process.stdout.write(data));
});
const stderr = new Promise(resolve => {
subprocess.stderr.on("end", resolve);
subprocess.stderr.on("data", data => process.stderr.write(data));
});
const done = Promise.all([stdout, stderr]);
const { error, exitCode, signalCode } = await new Promise(resolve => {
subprocess.on("error", error => resolve({ error }));
subprocess.on("exit", (exitCode, signalCode) => resolve({ exitCode, signalCode }));
});
await done;
const duration = Date.now() - timestamp;
if (duration > 60000) {
console.log(`Took ${(duration / 60000).toFixed(2)} minutes`);
} else {
console.log(`Took ${(duration / 1000).toFixed(2)} seconds`);
}
if (exitCode === 0) {
return;
}
if (error) {
console.error(error);
} else if (signalCode) {
console.error(`Command killed: ${signalCode}`);
} else {
console.error(`Command exited: code ${exitCode}`);
}
process.exit(exitCode ?? 1);
}
build(process.argv.slice(2));