Rustをまがりなりにも触れている身として、またGuix Systemを利用する身として、Guix System上でRustプロジェクト関連の諸々、たとえばビルドや実行を行いたいところだ。
Guix SystemはFilesystem Hierarchy Standard(以下FHS)に準拠しない上に ld がライブラリの場所をほぼ全く知らないため、Rustのプロジェクトがビルドできなかったり、ビルドできても実行できなかったりする。これはgcc系統のライブラリ、たとえば libgcc_s.so.1 がみつけられなかったり、自身でビルドしたsysライブラリ自体がみつけられなかったりするためだ。
これをどうにかするため、 guix shell には --emulate-fhs (-F)というオプションがある1。これは特定のパッケージのみを含むコンテナを作成した上で、それらのパッケージをFHSに従ったディレクトリ構成に配置する機能だ。これを利用することで、 cargo build や cargo run をなんなく実行することができる…ときもあるが、できないときもある。
これはRustのビルドプロセスにあまり詳しくない私には全く原因がわからないのだが、FHSに従って libgcc_s.so.1 を配置しても、 cargo はビルドの際にそれを見付けてくれないのだ。正確には、一部のパッケージ(serde、proc-macro2、icu_.*、libcなど)がビルド時にビルド用スクリプト build-script-build を走らせるようで、その実行時に以下のような「 libgcc_s.so.1 がみつからない」という旨のエラーが出る。
error: failed to run custom build command for `icu_normalizer_data v2.0.0`
Caused by:
process didn't exit successfully: `/path/to/your/project/target/debug/build/icu_normalizer_data-02b3286e562902a4/build-script-build` (exit status: 127)
--- stderr
/path/to/your/project/target/debug/build/icu_normalizer_data-02b3286e562902a4/build-script-build: error while loading shared libraries: libgcc_s.so.1: cannot open shared object file: No such file or directory
これをどう解決するか頭を抱えたが、とりあえず応急処置として LD_LIBRARY_PATH に /lib を追加することで解決できた。具体的には、 --emulate-fhs 影響下の guix shell 内で以下のコマンドを実行しておけばよい。
export LD_LIBRARY_PATH=/lib
原因についてはこれから調べ、わかり次第この記事に追記する予定だが、困る人もそれなりにいそうなので、応急処置のしかただけでもここに記しておく。
元々記載していたが後々微妙だとわかった方法
以下は最初記載していた方法だが、 cargo test などの際に結局 libgcc_s.so.1 が見つからないことがわかったため、別の方法を記載しなおした。
export RUSTFLAGS="-C link-args=-Wl,-rpath,/lib"
一応軽く中身に触れると、 -C は --codegen の略で、コード生成、すなわち rustc に渡るオプションたちのことを指す。そのなかでも link-args はリンカの呼び出しに利用される。Linuxではこのオプションは cc に渡る。直前でリンカとは言ったが、 cc は実際はリンカではなくコンパイラであり、 -Wl は本当のリンカ(きちんと調べてないけどたぶん ld)に渡すオプションを指定するための cc のオプションだ。ここまでの説明はRust公式のCodegen Options - The rustc bookを参考にした。
残りの -rpath,/lib がリンカ ld (たぶん)に渡る。これは RPATH 、すなわち実行時にリンカが動的ライブラリを探す場所として /lib を追加している。
-
実用上は
guix shell -CNFくらいでまとめて使うことが多い。 特に-Cは--emulate-fhsを利用する際には必須。-Nもネットワーク接続するなら必須だ。 ↩︎