iTranslated by AI

The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
🫥

Bun.build --compile artifacts "transform" when using stdenv.mkDerivation

に公開

tl;dr

When using Bun.build --compile, use stdenvNoCC.mkDerivation instead of stdenv, or use dontStrip.

Phenomenon

When packaging the output of Bun.build --compile using stdenv.mkDerivation, the files under bin/ end up becoming the Bun binary itself.

Reproduction Steps

I have created a minimal reproduction. Please clone it and give it a try.
(Note: I have only tested this on aarch64-darwin, so please change the system as appropriate. It is unclear whether it can be reproduced on other architectures.)

https://gist.github.com/gw31415/96cb3919f0eb4ebaa5eeb40bf7206552

The flake.nix is as follows. It simply runs index.ts through Bun.build --compile and copies the resulting artifact to two locations: ① directly under $out/, and ② under $out/bin/. index.ts just contains console.log("Hello via Bun!");.

default is the package where the problem occurs.

  1. Build it using nix build ..
$ git clone https://gist.github.com/gw31415/96cb3919f0eb4ebaa5eeb40bf7206552 example
$ cd example
$ nix build .
  1. There are two files under ./result/, so please try running each of them.
$ tree ./result/
result
├── bin
   └── example
└── example
$ ./result/example
Hello via Bun!

$ ./result/bin/example
Bun is a fast JavaScript runtime, package manager, bundler, and test runner. (rest omitted)

What Happened

As you can see by running them, the files under bin/ in the artifacts have become the Bun binary itself.
While stdenv.mkDerivation provides convenient defaults for C/C++ packages, I suspect that the files under bin/ underwent some form of preprocessing (the Strip process), causing the Bun binary embedded within the artifact to be exposed.

I am not deeply familiar with the specifications of Bun or stdenv.mkDerivation, so the specific reason is unknown. Experts, please let me know!

As comamoka🦊 pointed out to me, because stdenv.mkDerivation strips build artifacts, the stripping process was applied to the binary files. Through this stripping, information other than the Bun binary itself was removed, leaving only the Bun binary behind.

Workaround

Using stdenvNoCC.mkDerivation instead of stdenv.mkDerivation avoids this issue. In the aforementioned package, it is packaged under the name noCC, so please give it a try.

$ nix build .#noCC

$ ./result/example
Hello via Bun!

$ ./result/bin/example
Hello via Bun!

(Added 2024-01-06)

It seems that the problem can also be solved by using dontStrip even when using stdenv.mkDerivation. Thanks to comamoka🦊 for letting me know!

$ nix build .#dontStrip

$ ./result/example
Hello via Bun!

$ ./result/bin/example
Hello via Bun!

Summary

When packaging artifacts from Bun.build --compile, use stdenvNoCC or dontStrip.

Thoughts

Since Nix is a long-standing system, it's possible that defaults that were convenient for previous generations have poor compatibility with modern environments. These days, tools not built with languages like C/C++ are often used... On the other hand, Bun's output might also be structured in a way that conflicts with traditional C/C++ build mechanisms.

It was interesting to learn that there are binaries where the strip process causes problems. However, since this was the first time I had encountered this, I had a hard time identifying the cause. While it's certainly more convenient for stripping to be the default, I learned a lot because these kinds of things do happen, even if not often.

It was quite a hassle as it took considerable time to debug exactly what was going wrong.

GitHubで編集を提案

Discussion