element-desktop/scripts/hak/hakEnv.ts

148 lines
4.5 KiB
TypeScript
Raw Permalink Normal View History

/*
2024-09-06 18:56:18 +02:00
Copyright 2024 New Vector Ltd.
Copyright 2020, 2021 The Matrix.org Foundation C.I.C.
2024-09-06 18:56:18 +02:00
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/
import path from "node:path";
import os from "node:os";
import nodePreGypVersioning from "@mapbox/node-pre-gyp/lib/util/versioning";
import { getElectronVersionFromInstalled } from "app-builder-lib/out/electron/electronVersion.js";
import childProcess, { SpawnOptions } from "node:child_process";
import { Arch, Target, TARGETS, getHost, isHostId, TargetId } from "./target.js";
async function getRuntime(projectRoot: string): Promise<string> {
const electronVersion = await getElectronVersionFromInstalled(projectRoot);
2022-12-15 12:00:58 +01:00
return electronVersion ? "electron" : "node-webkit";
}
async function getRuntimeVersion(projectRoot: string): Promise<string> {
const electronVersion = await getElectronVersionFromInstalled(projectRoot);
if (electronVersion) {
return electronVersion;
} else {
return process.version.substr(1);
}
}
export type Tool = [cmd: string, ...args: string[]];
export default class HakEnv {
public readonly target: Target;
public runtime?: string;
public runtimeVersion?: string;
public dotHakDir: string;
public constructor(
public readonly projectRoot: string,
targetId: TargetId | null,
) {
const target = targetId ? TARGETS[targetId] : getHost();
if (!target) {
throw new Error(`Unknown target ${targetId}!`);
}
this.target = target;
2022-12-15 12:00:58 +01:00
this.dotHakDir = path.join(this.projectRoot, ".hak");
}
public async init(): Promise<void> {
this.runtime = await getRuntime(this.projectRoot);
this.runtimeVersion = await getRuntimeVersion(this.projectRoot);
}
public getRuntimeAbi(): string {
return nodePreGypVersioning.get_runtime_abi(this.runtime!, this.runtimeVersion!);
}
// {node_abi}-{platform}-{arch}
public getNodeTriple(): string {
2022-12-15 12:00:58 +01:00
return this.getRuntimeAbi() + "-" + this.target.platform + "-" + this.target.arch;
}
public getTargetId(): TargetId {
2021-06-22 14:37:33 +02:00
return this.target.id;
}
public isWin(): boolean {
2022-12-15 12:00:58 +01:00
return this.target.platform === "win32";
}
public isMac(): boolean {
2022-12-15 12:00:58 +01:00
return this.target.platform === "darwin";
}
public isLinux(): boolean {
2022-12-15 12:00:58 +01:00
return this.target.platform === "linux";
}
public isFreeBSD(): boolean {
return this.target.platform === "freebsd";
}
public getTargetArch(): Arch {
return this.target.arch;
}
public isHost(): boolean {
return isHostId(this.target.id);
}
public makeGypEnv(): Record<string, string | undefined> {
2024-07-31 16:08:06 +02:00
return {
...process.env,
npm_config_arch: this.target.arch,
npm_config_target_arch: this.target.arch,
2022-12-15 12:00:58 +01:00
npm_config_disturl: "https://electronjs.org/headers",
npm_config_runtime: this.runtime,
npm_config_target: this.runtimeVersion,
2024-07-31 16:08:06 +02:00
npm_config_build_from_source: "true",
npm_config_devdir: path.join(os.homedir(), ".electron-gyp"),
2024-07-31 16:08:06 +02:00
};
}
public wantsStaticSqlCipher(): boolean {
return !(this.isLinux() || this.isFreeBSD()) || process.env.SQLCIPHER_BUNDLED == "1";
}
public spawn(
cmd: string,
args: string[],
{ ignoreWinCmdlet, ...options }: SpawnOptions & { ignoreWinCmdlet?: boolean } = {},
): Promise<void> {
return new Promise((resolve, reject) => {
const proc = childProcess.spawn(cmd + (!ignoreWinCmdlet && this.isWin() ? ".cmd" : ""), args, {
stdio: "inherit",
// We need shell mode on Windows to be able to launch `.cmd` executables
// See https://nodejs.org/en/blog/vulnerability/april-2024-security-releases-2
shell: this.isWin(),
...options,
});
proc.on("exit", (code) => {
if (code) {
reject(code);
} else {
resolve();
}
});
});
}
public async checkTools(tools: Tool[]): Promise<void> {
for (const [tool, ...args] of tools) {
try {
await this.spawn(tool, args, {
ignoreWinCmdlet: true,
stdio: ["ignore"],
shell: false,
});
} catch {
throw new Error(`Can't find ${tool}`);
}
}
}
}