Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
183 lines
5.8 KiB
JavaScript
183 lines
5.8 KiB
JavaScript
const fs = require("node:fs");
|
|
const path = require("node:path");
|
|
const { execFileSync } = require("node:child_process");
|
|
|
|
function findCompiler(env = process.env) {
|
|
if (env.CXX) return env.CXX;
|
|
if (env.CL) return "cl.exe";
|
|
return "cl.exe";
|
|
}
|
|
|
|
function quoteCmdArg(value) {
|
|
return `"${String(value).replace(/"/g, '\\"')}"`;
|
|
}
|
|
|
|
function makeCmdScriptPath(tmpdir, targetArch) {
|
|
return path.win32.join(tmpdir(), `build-netcatty-windows-hello-${targetArch}.cmd`);
|
|
}
|
|
|
|
function visualStudioDevCmdCandidates(env = process.env) {
|
|
const candidates = [];
|
|
if (env.VSINSTALLDIR) {
|
|
candidates.push(path.win32.join(env.VSINSTALLDIR, "Common7", "Tools", "VsDevCmd.bat"));
|
|
}
|
|
|
|
const programFilesRoots = [
|
|
env.ProgramFiles,
|
|
env["ProgramFiles(x86)"],
|
|
"C:\\Program Files",
|
|
"C:\\Program Files (x86)",
|
|
].filter(Boolean);
|
|
const versions = ["2026", "2022", "2019"];
|
|
const editions = ["Enterprise", "Professional", "Community", "BuildTools", "Preview"];
|
|
for (const root of programFilesRoots) {
|
|
for (const version of versions) {
|
|
for (const edition of editions) {
|
|
candidates.push(
|
|
path.win32.join(root, "Microsoft Visual Studio", version, edition, "Common7", "Tools", "VsDevCmd.bat"),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
return [...new Set(candidates)];
|
|
}
|
|
|
|
function findVisualStudioDevCmd(env = process.env, existsSync = fs.existsSync) {
|
|
return visualStudioDevCmdCandidates(env).find((candidate) => existsSync(candidate)) || null;
|
|
}
|
|
|
|
function hasInitializedMsvcEnvironment(env = process.env, targetArch) {
|
|
const initializedArch = String(env.VSCMD_ARG_TGT_ARCH || "").toLowerCase();
|
|
if (initializedArch) return initializedArch === targetArch;
|
|
return Boolean(env.VSCMD_VER && env.INCLUDE && env.LIB);
|
|
}
|
|
|
|
function normalizeWindowsHelperArch(arch) {
|
|
if (arch === "x64" || arch === "arm64") return arch;
|
|
if (arch === 1 || arch === "1") return "x64";
|
|
if (arch === 3 || arch === "3") return "arm64";
|
|
return null;
|
|
}
|
|
|
|
function getExpectedPeMachine(arch) {
|
|
if (arch === "x64") return 0x8664;
|
|
if (arch === "arm64") return 0xaa64;
|
|
return null;
|
|
}
|
|
|
|
function readPeMachine(input) {
|
|
const buffer = Buffer.isBuffer(input) ? input : fs.readFileSync(input);
|
|
if (buffer.length < 0x40 || buffer.toString("ascii", 0, 2) !== "MZ") return null;
|
|
const peOffset = buffer.readUInt32LE(0x3c);
|
|
if (peOffset + 6 > buffer.length) return null;
|
|
if (buffer.toString("ascii", peOffset, peOffset + 4) !== "PE\0\0") return null;
|
|
return buffer.readUInt16LE(peOffset + 4);
|
|
}
|
|
|
|
function buildWindowsHelloHelper({
|
|
projectDir = process.cwd(),
|
|
platform = process.platform,
|
|
arch = process.env.npm_config_arch || process.arch,
|
|
env = process.env,
|
|
run = execFileSync,
|
|
mkdir = fs.mkdirSync,
|
|
writeFile = fs.writeFileSync,
|
|
rm = fs.rmSync,
|
|
tmpdir = require("node:os").tmpdir,
|
|
existsSync = fs.existsSync,
|
|
readMachine = readPeMachine,
|
|
logger = console,
|
|
} = {}) {
|
|
if (platform !== "win32") return { skipped: true, reason: "non-windows" };
|
|
const targetArch = normalizeWindowsHelperArch(arch);
|
|
if (!targetArch) return { skipped: true, reason: "unsupported-arch" };
|
|
|
|
const pathApi = platform === "win32" ? path.win32 : path;
|
|
const sourcePath = pathApi.join(projectDir, "electron", "bridges", "windowsHelloHelper", "NetcattyWindowsHello.cpp");
|
|
const outputDir = pathApi.join(projectDir, "electron", "bridges", "windowsHelloHelper", "build", targetArch);
|
|
const outputPath = pathApi.join(outputDir, "NetcattyWindowsHello.exe");
|
|
mkdir(outputDir, { recursive: true });
|
|
|
|
const compiler = findCompiler(env);
|
|
const machine = targetArch === "arm64" ? "ARM64" : "X64";
|
|
const compilerArgs = [
|
|
"/nologo",
|
|
"/EHsc",
|
|
"/std:c++17",
|
|
"/D_SILENCE_EXPERIMENTAL_COROUTINE_DEPRECATION_WARNINGS",
|
|
sourcePath,
|
|
"/Fe:" + outputPath,
|
|
"/link",
|
|
"/MACHINE:" + machine,
|
|
"runtimeobject.lib",
|
|
"windowsapp.lib",
|
|
];
|
|
try {
|
|
const shouldInitializeMsvc = compiler === "cl.exe" && !hasInitializedMsvcEnvironment(env, targetArch);
|
|
const vsDevCmd = shouldInitializeMsvc ? findVisualStudioDevCmd(env, existsSync) : null;
|
|
if (vsDevCmd) {
|
|
const devArch = targetArch === "arm64" ? "arm64" : "x64";
|
|
const compileCommand = [
|
|
"call",
|
|
quoteCmdArg(vsDevCmd),
|
|
`-arch=${devArch}`,
|
|
"-host_arch=x64",
|
|
"&&",
|
|
quoteCmdArg(compiler),
|
|
...compilerArgs.map(quoteCmdArg),
|
|
].join(" ");
|
|
const scriptPath = makeCmdScriptPath(tmpdir, targetArch);
|
|
writeFile(scriptPath, `@echo off\r\n${compileCommand}\r\n`, "utf8");
|
|
try {
|
|
run("cmd.exe", ["/d", "/c", scriptPath], {
|
|
cwd: projectDir,
|
|
stdio: "inherit",
|
|
env,
|
|
});
|
|
} finally {
|
|
rm(scriptPath, { force: true });
|
|
}
|
|
} else {
|
|
run(compiler, compilerArgs, {
|
|
cwd: projectDir,
|
|
stdio: "inherit",
|
|
env,
|
|
});
|
|
}
|
|
} catch (err) {
|
|
logger.warn?.(`[windowsHelloHelper] Failed to build Windows Hello helper: ${err?.message || err}`);
|
|
return { skipped: true, reason: "compiler-unavailable" };
|
|
}
|
|
|
|
const expectedMachine = getExpectedPeMachine(targetArch);
|
|
const actualMachine = readMachine(outputPath);
|
|
if (actualMachine !== expectedMachine) {
|
|
logger.warn?.(`[windowsHelloHelper] Built helper machine ${actualMachine} does not match ${targetArch}`);
|
|
return { skipped: true, reason: "wrong-arch" };
|
|
}
|
|
|
|
return { skipped: false, outputPath };
|
|
}
|
|
|
|
if (require.main === module) {
|
|
const result = buildWindowsHelloHelper();
|
|
if (result.skipped) {
|
|
console.log(`[windowsHelloHelper] skipped: ${result.reason}`);
|
|
} else {
|
|
console.log(`[windowsHelloHelper] built: ${result.outputPath}`);
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
buildWindowsHelloHelper,
|
|
findCompiler,
|
|
findVisualStudioDevCmd,
|
|
getExpectedPeMachine,
|
|
hasInitializedMsvcEnvironment,
|
|
makeCmdScriptPath,
|
|
normalizeWindowsHelperArch,
|
|
readPeMachine,
|
|
visualStudioDevCmdCandidates,
|
|
};
|