mirror of
https://github.com/amitwh/markdown-converter.git
synced 2026-08-23 23:10:17 +05:30
fix(packaging): unpack @img prebuilt sharp binaries so deb ships bundled libvips
build.asarUnpack only claimed node_modules/sharp/**, so electron-builder pruned the @img/sharp-* optionalDependencies: the asar kept 34 pure-JS @img entries while the bundled libvips shared libraries never shipped. At boot sharp's loader fell back to a system-libvips-linked binding and dlopen failed, crashing the main process. Claim the prebuilt packages explicitly (@img/** and @napi-rs/**) per the sharp+electron-builder recipe, and guard the built output with a packaging regression test. Amit Haridas
This commit is contained in:
@@ -116,6 +116,8 @@
|
||||
"asarUnpack": [
|
||||
"node_modules/ffmpeg-static/**",
|
||||
"node_modules/sharp/**",
|
||||
"node_modules/@img/**",
|
||||
"node_modules/@napi-rs/**",
|
||||
"assets/fonts/**"
|
||||
],
|
||||
"extraFiles": [],
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// Regression guard for the deb startup crash (2026-08-23): the packaged build
|
||||
// pruned the @img/sharp-* native bindings (only the pure-JS @img/colour entries
|
||||
// landed in the asar), so sharp's loader fell back to a binding that links
|
||||
// against system libvips and the main process died on ERR_DLOPEN_FAILED before
|
||||
// any window opened. When a linux build is present, the prebuilt sharp packages
|
||||
// — including the bundled libvips shared libraries — must be unpacked next to
|
||||
// the asar (build.asarUnpack claims node_modules/@img/** and node_modules/@napi-rs/**).
|
||||
const UNPACKED_IMG_DIR = path.join(
|
||||
__dirname,
|
||||
'..',
|
||||
'dist',
|
||||
'linux-unpacked',
|
||||
'resources',
|
||||
'app.asar.unpacked',
|
||||
'node_modules',
|
||||
'@img'
|
||||
);
|
||||
|
||||
const buildOutputExists = fs.existsSync(UNPACKED_IMG_DIR);
|
||||
|
||||
function listFilesRecursively(dir) {
|
||||
const files = [];
|
||||
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
||||
const full = path.join(dir, entry.name);
|
||||
if (entry.isDirectory()) {
|
||||
files.push(...listFilesRecursively(full));
|
||||
} else {
|
||||
files.push(full);
|
||||
}
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
(buildOutputExists ? describe : describe.skip)('packaged @img sharp prebuilt binaries', () => {
|
||||
test('unpacked @img directory exists and is non-empty', () => {
|
||||
const entries = fs.readdirSync(UNPACKED_IMG_DIR);
|
||||
expect(entries.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
test.each(['sharp-linux-x64', 'sharp-libvips-linux-x64'])(
|
||||
'%s package is unpacked with contents',
|
||||
(pkg) => {
|
||||
const pkgDir = path.join(UNPACKED_IMG_DIR, pkg);
|
||||
expect(fs.existsSync(pkgDir)).toBe(true);
|
||||
expect(listFilesRecursively(pkgDir).length).toBeGreaterThan(0);
|
||||
}
|
||||
);
|
||||
|
||||
test('sharp-linux-x64 ships its native binding', () => {
|
||||
const binding = path.join(UNPACKED_IMG_DIR, 'sharp-linux-x64', 'lib', 'sharp-linux-x64.node');
|
||||
expect(fs.existsSync(binding)).toBe(true);
|
||||
});
|
||||
|
||||
test('sharp-libvips-linux-x64 ships the bundled libvips shared libraries', () => {
|
||||
const libvipsLibDir = path.join(UNPACKED_IMG_DIR, 'sharp-libvips-linux-x64', 'lib');
|
||||
const sharedLibs = fs.readdirSync(libvipsLibDir).filter((f) => /^libvips.*\.so/.test(f));
|
||||
expect(sharedLibs.length).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user