PythonにはmanylinuxというLinux用にビルドした,C/C++で書かれたPythonの拡張ライブラリを様々な環境(異なるディストリビューション)で動作させるための仕組みがあります。仕組みを調べたのでここにメモをしておきます。
参考文献#
- https://cibuildwheel.pypa.io/en/stable/ cibuildwheel というツールの文書。ここのドキュメントが一番有用だと思われる
- https://www.python.org/dev/peps/pep-0600/ 仕様や思想を説明した文書。
目標#
目標は上に書いた通りLinux用にビルドしたC/C++によるPythonの拡張ライブラリを様々な環境(異なるディストリビューション)で動作させることです。
問題と解決策#
1. カーネルとlibcの互換性#
まずはLinuxカーネルとlibcの互換性の問題について考えます。これらはLinuxで動作する殆どのソフトウェアで必要とされる部品で,これの互換性がないとソフトウェアはまともに動作しません。ありがたいことにLinuxカーネルとlibc (glibc) は開発者の努力により高い後方互換性があり,古いバージョン用にビルドしたバイナリは新しいカーネル&libcでもちゃんと動作します。
そこでこの互換性の問題は「適当に古いバージョンのLinuxカーネルとlibcの下でソフトウェアをビルドする」となります。あまり古すぎてサポートの問題があっても困るので,「適当に古く」「メンテナンスが続いているディストリビューション」を使うことになります。いくつか利用可能な環境があり,manylinux2014 (CentOS 7 ベース),manylinux_2_28 (AlmaLinux 8 ベース)などがあります。
2. 共有ライブラリの互換性#
次に共有ライブラリの問題について考えましょう。これはこの手のバイナリのポータビリティに関して常に問題になることです。ある環境でビルド&リンクした共有ライブラリを別の環境に持っていくとその共有ライブラリが存在しない,もしくはバージョンが異なり互換性がない,という問題です。この問題のmanylinuxにおける解決は以下の通りです。
ビルドしたバイナリに動的リンクされる共有ライブラリをそのバイナリを解析して列挙する それらの共有ライブラリをシステムから抽出して拡張ライブラリを配布するパッケージに含める 実際にこれらの処理を実行するのは auditwheel というツールです。このツールは共有ライブラリの内容から計算したハッシュ値をファイル名に付け足すなどして共有ライブラリ名の不用意な衝突を避ける仕組みもあります。
このアプローチには限界があり,dlopenを使って動的に共有ライブラリをリンクする場合には対応できません。これの対策としてはdlopenを使わないことです。dlopenとmanylinuxの組み合わせをどうしても使いたいなら開発者が頑張るしかありません。
3. 共有ライブラリの衝突#
3つ目の問題は複数の拡張ライブラリを同時に使うときに生じる問題です。拡張ライブラリAと拡張ライブラリBが同時に同じ共有ライブラリXを使っている,ただし利用するXのバージョンが異なる,というときに生じる問題です。一般的に異なるバージョンの共有ライブラリを同時に読み込ませることはできません(まったく不可能というわけではないと思いますがそういう無理をすると大概トラブルの原因となります)。一方で上で説明したようにパッケージに共有ライブラリを含める仕組みにするとこういう問題が生じがちです。
これの対策ですが,明示された文章が見付からなかったのですがおそらく以下のような方法で対応することが想定されているものと思われます。
- 環境はDockerなどを使って世界中の開発者の間で共有する
- 共有ライブラリはそのDocker imageの中から正当な方法でインストールするものに限る(デフォルトのディストリビューションのパッケージリポジトリだけを使って yum や apt でインストール)
こうすれば同じ共有ライブラリの異なるバージョンが同時に利用される,ということはなくなるはずです。
まあこれは開発者が共通の認識を持って運用する必要があるので本当にうまくいっているのかは不明です。
ツール#
こういった処理を一通り自動化するツールとして上に挙げた cibuildwheel があります。自分の使っているCIにcibuildwheelを組み込んでビルドする,という感じです。
Linux以外は?#
OSXやWindowsでも同様の問題があるはずですがmanylinuxのような仕組みはないようです。cibuildwheel自体はOSXやWindowsでもビルドもできるのですが,auditwheelはOSXも対応しているようですが,実際これをどのように使うべきなのか,という方針があまりないようです。つまり何となく動いてる,というような感じでしょうか。
現状はどのmanylinuxが使われているのか#
Numpyは manylinux2014 を使っているのでこれが一番普及しているのではないか,という気がします。しかしこれの元となっているCentOS 7は最近(2024/6/30)EOLになったので次に移行しようとする動きになると予想されます。とはいえこういった移行は時間がかかるのでしばらくこのままでしょう。
追記#
NumPy 2.3.0 (2025/06 リリース) で manylinux2014 から manylinux_2_28 に更新されました。