Sharp is not working with "Bun build --compile"
When compiling a binary using "Bun build --compile", it seems that the resulting binary does not contain the "binary" of Sharp. It still tries to load it from ./node_modules. If I copy the node_modules directory together with the resulting binary from "Bun build", it runs without issues. I am not sure if this is an issue with "Bun build" or with Sharp, but other node-related binaries from node_modules are working for me.
It's very unlikely that bun build --compile will work with sharp as it attempts to create a single executable, however sharp and libvips are provided as shared dynamic libraries.
It's very unlikely that
bun build --compilewill work with sharp as it attempts to create a single executable, however sharp and libvips are provided as shared dynamic libraries.
Well, so does sqlite, but that works with Bun. I am not talking about the built in version, but the node module. Bun embeds the lib into the binary on --compile
Bun provides its own sqlite implementation that does not depend on 3rd party shared libraries so it's not quite the same thing.
My previous advice to people attempting to do something similar with deno compile is to experiment with WebAssembly - please see https://github.com/lovell/sharp/issues/3912#issuecomment-1866214392
Bun provides its own sqlite implementation that does not depend on 3rd party shared libraries so it's not quite the same thing.
My previous advice to people attempting to do something similar with
deno compileis to experiment with WebAssembly - please see https://github.com/lovell/sharp/issues/3912#issuecomment-1866214392
Like I wrote in the earlier post; I am not talking about the built-in sqlite library. I am talking about the node-lib of sqlite that also works with Bun. Any case, I now understand the issue. I have opened an issue with the Bun team so that they can include the dynamic lib inside the binary. Thanks!
My previous advice to people attempting to do something similar with
deno compileis to experiment with WebAssembly - please see #3912 (comment)
I patched sharp.js to force the Wasm library to load but, upon invocation, my program froze.
'use strict';
module.exports = require('@img/sharp-wasm32/sharp.node')
Do you know how should I debug this?
Thanks.
I got this working as a sort of experiment previously and can probably be done even easier now, with very recent improvements in https://bun.sh/docs/bundler/executables#embed-assets-files. As the sharp .node addon builds fine, the snag is in the libvips dll/so library. After @lovell answered https://github.com/lovell/sharp/issues/4023 it was clear the path for now was doing some imports/scripting to make those files embedded in the binary, and then update the reference from sharp.
After experimenting I managed to get it working with this:
I use this script to make a file which basically is an import line for the Node module with { type: 'file' }.
// embed-sharp.ts
import { runtimePlatformArch } from './node_modules/sharp/lib/libvips';
const runtimePlatform = runtimePlatformArch();
const path = `./node_modules/sharp/src/build/Release/sharp-${runtimePlatform}.node`;
// eslint-disable-next-line @typescript-eslint/no-require-imports
require(path);
Bun.write('./compile/sharp.ts', `import '${path.replace('./', '../')}' with { type: 'file' }`);
// compile/sharp.ts
import '../node_modules/sharp/src/build/Release/sharp-darwin-arm64.node' with { type: 'file' }
I then import the generated file in my entrypoint:
// entrypoint.ts
...
import './compile/sharp';
...
I needed to patch the Sharp package so it gets the module from the embeded files:
diff --git a/lib/sharp.js b/lib/sharp.js
index 3428c5fefae5c7fc02f18a6a9026ac6a7df190e4..fd8dbff27768dae8242f77eeeb53f4dc910fd0c3 100644
--- a/lib/sharp.js
+++ b/lib/sharp.js
@@ -6,6 +6,7 @@
// Inspects the runtime environment and exports the relevant sharp.node binary
const { familySync, versionSync } = require('detect-libc');
+const { join } = require('node:path');
const { runtimePlatformArch, isUnsupportedNodeRuntime, prebuiltPlatforms, minimumLibvipsVersion } = require('./libvips');
const runtimePlatform = runtimePlatformArch();
@@ -29,6 +30,11 @@ for (const path of paths) {
}
}
+if (!sharp && Bun.embeddedFiles.length) {
+ const sharpModule = Bun.embeddedFiles.find(file => /sharp-(.*).node$/.test(file.name))
+ sharp = require(join(import.meta.dirname, sharpModule.name));
+}
+
/* istanbul ignore next */
if (sharp) {
module.exports = sharp;
This is my build script:
# build.sh
bun ./embed-sharp.ts &&
bun build --outfile my_binary --minify --sourcemap --compile ./entrypoint.ts
Importing the package @img/sharp-${runtimePlatform}/sharp.node didn't work as then the lib files wouldn't be included.
I need to build the module from source else it won't work.
I only tried on macOS ARM64 and Linux x64
This might not work. It complains that libvips-cpp.so.42 is missing when trying on a fresh system.
i dont think this is exclusively related to bun. i tried with node js pkg and same/similar error messages.
So, no go with bun for now I guess?
Seems I have to run my app directly now instead of the built version, just to get sharp to work, no idea if they intend to address this? Not much performance impact I assume?
Sorry to revive a closed thread, potential fix described here https://github.com/lovell/sharp/issues/4377#issuecomment-2819585265
Just a quick update. Found a solution. I was missing
--config package.jsonin thenpxcommand:npx pkg index.js --config package.json --targets node20-macos-arm64 --output indexAnd added assets to
package.json:"pkg": { "assets": [ "node_modules/@img/sharp-darwin-arm64/**/*", "node_modules/@img/sharp-libvips-darwin-arm64/**/*" ] }
Sorry to revive a closed thread, potential fix described here #4377 (comment)
Just a quick update. Found a solution. I was missing
--config package.jsonin thenpxcommand:npx pkg index.js --config package.json --targets node20-macos-arm64 --output indexAnd added assets to
package.json:"pkg": { "assets": [ "node_modules/@img/sharp-darwin-arm64/**/*", "node_modules/@img/sharp-libvips-darwin-arm64/**/*" ] }
Does this works if the user doesn't have libvips installed in their system?
UPDATE: Checked @yao-pkg/pkg and it works by bundling the files and extracting them at runtime to $HOME/.cache and I could only get it working with the prebuilt binaries and not with custom Vips because it can't load libvips-cpp.so.42.