/usr/bin/ld: cannot find -lpython3.9: No such file or directory の対処法メモ
自分用のメモです。間違えたこと言ってたら教えてください。
経緯
rye で用意した python 環境で、pola-rs/pyo3-polars の example を build しようとしたら、
> make install
...
= note: /usr/bin/ld: cannot find -lpython3.9: No such file or directory
collect2: error: ld returned 1 exit status
error: could not compile `expression_lib` (lib) due to previous error
💥 maturin failed
Caused by: Failed to build a native library through cargo
...
と怒られれ、build できなかった。
環境
❯ cat /etc/os-release
PRETTY_NAME="Ubuntu 22.04.3 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.3 LTS (Jammy Jellyfish)"
...
❯ python --version
Python 3.9.16
❯ venv/bin/pip list
Package Version
-------------- -------
expression_lib 0.1.0
maturin 1.3.1
pip 22.0.4
polars 0.19.12
setuptools 58.1.0
tomli 2.0.1
解決法
以下のコマンドで build する。
> RUSTFLAGS='-L <PATH_TO>/.rye/py/cpython@3.9.16/install/lib' make run
原因
maturin(というか Rust)は、使用している python を dynamic リンクする際に(linux 環境だと)、 /usr/lib/
を見にいく。しかし、rye を使って環境を管理していると、そこにライブラリは存在せず、(自分でカスタマイズしない限りは)~/.rye
の中に持っている。そのため、maturin がライブラリを見つけることができずに上記のエラーになっていたと考えられる。
その場所を maturin に明示的に教えてあげればよい。Rust では RUSTFLAGS='-L <PATH_TO_LD_LIBRARY_PATH>
とすることで、それが可能。もちろん、LD_LIBRARY_PATH
を設定してあげることでも可能である。
ちなみに、static リンクしてる場合は、LIBRARY_PATH
を設定する必要がある(気がする)。どちらが必要かは、build してみて必要だと言われている file が dynamic なのか static なのかを判断した上で決める感じで現状は対処している。
補足
polars を test する際に、RUSTFLAGS='-L ...
を設定するだけでは fail し、LIBRARY_PATH
も設定しないといけない場面があった。つまり、
RUSTFLAGS='-L <PATH_TO>/.rye/py/cpython@3.9.16/install/lib' make test
ではエラーになるが、
LIBRARY_PATH=<PATH_TO>/.rye/py/cpython@3.9.16/install/lib/ RUSTFLAGS='-L <PATH_TO>/.rye/py/cpython@3.9.16/install/lib' make test
だと問題ないということがあった。詳しい理由はまだ追えてないので、ご存じの方いたら教えてください。
memo
内容とは全く関係ないですが、LD_PRELOAD
という環境変数を使ってコンパイルなしに動的ライブラリを書き換えることができるようです
Discussion