prebuild / prebuildify

Create and package prebuilds for native modules
MIT License
200 stars 37 forks source link

Prebuilding binaries for multiple version of the same OS #44

Closed gonzus closed 3 years ago

gonzus commented 4 years ago

We run our module on CentOS in production, and would like our developers (who mostly have mac and Ubuntu laptops) to be able to use it locally on their boxes.

Is there any way to have the prebuilds directory contain two different versions of a shared object for the same OS, one for CentOS and one for Ubuntu? Or somehow ignoring the pre-built version from the package (which was created for CentOS) and forcing the compilation of a local one (for the case of Ubuntu)?

Or perhaps we are going about this the wrong way, and you guys have better suggestions?

vweevers commented 4 years ago

Not sure if it answers you question, but with prebuildify-cross you can compile a prebuild that's compatible with both CentOS and Ubuntu (and others).

gonzus commented 4 years ago

I guess that is one way to go about this: having a single version for linux that works on many different versions of the OS. But I also see room for the case where you would want to take advantage of differences between linux versions, or where it is just not possible to have a least common denominator.

I guess the real problem here is that node-gyp-build doesn't (currently) have the smarts to add differentiators when it is determining the name of the module it will try to load. I was curious how others were managing such a case. For us, we would like just to differentiate between linux OS flavor (CentOS, Ubuntu, Alpine), but I can totally see how it might be interesting to differentiate, for example, between versions of a single flavor (Ubuntu 16 v Ubuntu 20), or between C compilers (gcc v clang) or even versions of the C library. You might end up with a larger prebuilds directory, but one that might match better your use case.

vweevers commented 4 years ago

There are a few challenges with that approach:

As for:

and forcing the compilation of a local one (for the case of Ubuntu)?

That can be done with npm i --build-from-source

yisibl commented 3 years ago

This seems to be what napi-rs is doing. Build binaries for different platforms.

todbot commented 3 years ago

Hi! How does one tell if a prebuild is universal (fat) binary on MacOS?

In regular shared libraries, you can use file <libname>, and you'll get output like:

% file helloworld
helloworld: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64] [arm64:Mach-O 64-bit executable arm64]
helloworld (for architecture x86_64):   Mach-O 64-bit executable x86_64
helloworld (for architecture arm64):    Mach-O 64-bit executable arm64

but these .node files are just reported as:

# prebuildify --napi --strip
% file prebuilds/darwin-arm64/node.napi.node
prebuilds/darwin-arm64/node.napi.node: Mach-O 64-bit bundle arm64

# prebuildify --napi --arch x64+arm64
% file prebuilds/darwin-x64+arm64/node.napi.node
prebuilds/darwin-x64+arm64/node.napi.node: Mach-O 64-bit bundle x86_64

In my test, the multi-arch build seems to have both archs in them, but it would be nice to be able to inspect them like one can do with file.

vweevers commented 3 years ago

@todbot When universal binaries are correctly configured via binding.gyp (https://github.com/prebuild/prebuildify/issues/56#issuecomment-978935860), the output of file will look like:


$ file prebuilds/darwin-x64+arm64/node.napi.node
prebuilds/darwin-x64+arm64/node.napi.node: Mach-O universal binary with 2 architectures:
[x86_64:Mach-O 64-bit x86_64 bundle, flags:<NOUNDEFS|DYLDLINK|TWOLEVEL|WEAK_DEFINES|BINDS_TO_WEAK>]
[arm64:Mach-O 64-bit arm64 bundle, flags:<NOUNDEFS|DYLDLINK|TWOLEVEL|WEAK_DEFINES|BINDS_TO_WEAK>]