Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sharp is not working with "Bun build --compile" #4283

Open
buzzy opened this issue Nov 23, 2024 · 7 comments
Open

Sharp is not working with "Bun build --compile" #4283

buzzy opened this issue Nov 23, 2024 · 7 comments
Labels

Comments

@buzzy
Copy link

buzzy commented Nov 23, 2024

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.

@buzzy buzzy added the triage label Nov 23, 2024
@buzzy buzzy changed the title Sharp is not working with "Bun build" Sharp is not working with "Bun build --compile" Nov 23, 2024
@lovell lovell added question and removed triage labels Nov 23, 2024
@lovell
Copy link
Owner

lovell commented Nov 23, 2024

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.

@buzzy
Copy link
Author

buzzy commented Nov 24, 2024

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.

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

@lovell
Copy link
Owner

lovell commented Nov 24, 2024

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 #3912 (comment)

@buzzy
Copy link
Author

buzzy commented Nov 24, 2024

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 #3912 (comment)

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!

@LetrixZ
Copy link

LetrixZ commented Dec 4, 2024

My previous advice to people attempting to do something similar with deno compile is 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.

@infrahead
Copy link

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 #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.

@LetrixZ
Copy link

LetrixZ commented Dec 24, 2024

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants