feat: implement cross-compilation support for native addons and clean up non-target binaries
All checks were successful
Release Electron App / release-desktop (push) Successful in 11m5s

This commit is contained in:
2026-03-03 22:47:07 +01:00
parent 170e44a05a
commit f5d6978e0b

View File

@@ -69,6 +69,34 @@ const config: ForgeConfig = {
env: { ...process.env, npm_config_nodedir: '' },
});
// When cross-compiling, native addons (better-sqlite3, keytar) are built
// for the build machine (Linux). Re-download prebuilts for the target.
const targetKey = `${platform}-${arch}`;
const buildKey = `${process.platform}-${process.arch}`;
if (targetKey !== buildKey) {
console.log(`[forge] Cross-compiling: ${buildKey}${targetKey}`);
const electronVersion = JSON.parse(
fs.readFileSync(path.resolve(__dirname, 'node_modules', 'electron', 'package.json'), 'utf-8'),
).version;
// Use prebuild-install to fetch correct native binaries
const prebuildModules = ['better-sqlite3', 'keytar'];
for (const mod of prebuildModules) {
const modDir = path.join(buildPath, 'node_modules', mod);
if (fs.existsSync(modDir)) {
console.log(`[forge] Downloading ${mod} prebuilt for ${targetKey} (Electron ${electronVersion})...`);
try {
execSync(
`npx --yes prebuild-install -r electron -t ${electronVersion} --platform ${platform} --arch ${arch} --verbose`,
{ cwd: modDir, stdio: 'inherit' },
);
} catch (e) {
console.warn(`[forge] prebuild-install failed for ${mod}, trying node-gyp rebuild...`);
}
}
}
}
// vectordb uses platform-specific optional deps (@lancedb/vectordb-<platform>-<arch>-*).
// npm install on Linux only pulls the Linux variant. Force-install the target's.
const platformNativePackages: Record<string, Record<string, string>> = {
@@ -85,7 +113,6 @@ const config: ForgeConfig = {
'@lancedb/vectordb-darwin-arm64': '',
},
};
const targetKey = `${platform}-${arch}`;
const nativePkgs = platformNativePackages[targetKey];
if (nativePkgs) {
// Remove wrong-platform lancedb native packages
@@ -110,8 +137,7 @@ const config: ForgeConfig = {
// Remove cross-platform prebuilt binaries that don't match the target.
// Packages like @github/copilot ship prebuilds for all platforms;
// keeping foreign-arch .node files breaks rpmbuild's strip step.
const targetDir = `${platform}-${arch}`;
const nmPath = path.join(buildPath, 'node_modules');
const nodeModulesPath = path.join(buildPath, 'node_modules');
const findPrebuilds = (dir: string): string[] => {
const results: string[] = [];
if (!fs.existsSync(dir)) return results;
@@ -128,15 +154,36 @@ const config: ForgeConfig = {
return results;
};
for (const prebuildsDir of findPrebuilds(nmPath)) {
for (const prebuildsDir of findPrebuilds(nodeModulesPath)) {
for (const entry of fs.readdirSync(prebuildsDir)) {
if (entry !== targetDir) {
if (entry !== targetKey) {
const fullPath = path.join(prebuildsDir, entry);
fs.rmSync(fullPath, { recursive: true, force: true });
console.log(`[forge] Removed non-target prebuild: ${entry}`);
}
}
}
// @github/copilot ships @teddyzhu/clipboard-* platform packages outside
// of prebuilds/. Remove non-target variants to avoid bundling wrong binaries.
const clipboardDir = path.join(buildPath, 'node_modules', '@github', 'copilot', 'clipboard', 'node_modules', '@teddyzhu');
if (fs.existsSync(clipboardDir)) {
const targetClipboardMap: Record<string, string> = {
'win32-x64': 'clipboard-win32-x64-msvc',
'win32-arm64': 'clipboard-win32-arm64-msvc',
'linux-x64': 'clipboard-linux-x64-gnu',
'linux-arm64': 'clipboard-linux-arm64-gnu',
'darwin-x64': 'clipboard-darwin-x64',
'darwin-arm64': 'clipboard-darwin-arm64',
};
const wantedPkg = targetClipboardMap[targetKey];
for (const entry of fs.readdirSync(clipboardDir)) {
if (entry.startsWith('clipboard-') && entry !== wantedPkg) {
fs.rmSync(path.join(clipboardDir, entry), { recursive: true, force: true });
console.log(`[forge] Removed non-target clipboard package: @teddyzhu/${entry}`);
}
}
}
},
},
makers: [