🫥

Bun.build --compile 成果物は stdenv.mkDerivation すると「変身」する

2025/01/06に公開

tl;dr

Bun.build --compile する時は stdenv ではなく stdenvNoCC の mkDerivation を使うか dontStrip を使おう。

現象

Bun.build --compile した成果物を stdenv.mkDerivation でパッケージ化すると、 bin/ 以下のファイルが bun 本体に なってしまいます。

再現手順

最小構成を作成しました。クローンしてお試しください。
(自分は aarch64-darwin でしか試していないため、適宜 system を変更してください。別アーキテクチャで再現できるかどうかは不明です)

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

flake.nix は以下のようになっています。
index.ts を Bun.build --compile にかけ、① $out/ 直下, ② $out/bin/ 以下 の2箇所に成果物をコピーするだけです。
index.ts はただ console.log("Hello via Bun!"); とだけ書かれています。

default が問題の起こるパッケージです。

  1. nix build . でビルドします。
$ git clone https://gist.github.com/gw31415/96cb3919f0eb4ebaa5eeb40bf7206552 example
$ cd example
$ nix build .
  1. ./result/ 以下に2つのファイルがあるのでそれぞれ実行してみてください。
$ 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. (以下省略)

何が起こったのか

実行してみたら分かると思いますが、成果物のうち bin/ 以下のファイルは bun 本体になってしまっています。
stdenv.mkDerivation は C/C++ によるパッケージに便利なデフォルトを提供していますが、恐らく bin/ 以下のファイルが 何らかの前処理 (Stripの処理) を受け、成果物の中に埋めこまれた bun 本体が放り出されたのだと思います。

bun や stdenv.mkDerivation の仕様に詳しくないので、具体的な理由は不明です。有識者の方々教えてください!

こまもか🦊 さんに教えていただきましたが、stdenv.mkDerivation はビルド成果物を Strip するため、バイナリファイルに対して Strip が行われてしまったということです。Stripによって bun 本体以外の情報が削除され、bun 本体だけが残ったという訳です。

回避策

stdenv.mkDerivation ではなく stdenvNoCC.mkDerivation を使うとこの問題を回避できます。前述のパッケージ内では noCC という名前でパッケージ化しているので試してみてください。

$ nix build .#noCC

$ ./result/example
Hello via Bun!

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

(2024-01-06追記)

stdenv.mkDerivation の時も、 dontStrip を用いると問題を解決できるようです。 こまもか🦊 さんに教えていただきました。ありがとうございます!

$ nix build .#dontStrip

$ ./result/example
Hello via Bun!

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

まとめ

Bun.build --compile した成果物をパッケージ化する時は stdenvNoCCdontStrip を使おう。

感想

Nix は古くからあるシステムなので、旧世代に便利だったデフォルトが新しい環境と相性が悪いことがあるのかもしれません。今では C/C++ 等で作成されていないツールが用いられることも多いので……。一方、BunもC/C++のビルドの仕組みに競合するような成果物になっているのかもしれません。

Strip処理が行われるとマズいバイナリがあるというのはなるほどと思いました。ただ、この問題は初めて遭遇したので、なかなか原因が分からず苦労しました。Strip処理はもちろんデフォルトで行われた方が便利ですが、こういうことも確かに多くはないですがあるので、とても勉強になりました。

結構どこがマズいのかデバッグするのに時間がかかって厄介でした。

GitHubで編集を提案

Discussion