いくつかのC拡張機能に依存するPythonモジュールを作成しました。これらのC拡張機能は、いくつかのコンパイル済みCライブラリに依存します。このモジュールをすべてのC拡張機能にバンドルして配布できるようにしたいと思います。依存関係。
最小限の例をまとめました( GitHub全体にあります )。
ディレクトリ構造は次のとおりです。
$ tree .
.
├── README.md
├── poc
│ ├── __init__.py
│ ├── cython_extensions
│ │ ├── __init__.py
│ │ ├── cvRoberts_dns.c
│ │ ├── cvRoberts_dns.h
│ │ ├── helloworld.c
│ │ ├── helloworld.pxd
│ │ ├── helloworld.pyx
│ │ ├── test.c
│ │ └── test.h
│ ├── do_stuff.c
│ └── do_stuff.pyx
└── setup.py
setup.pyは拡張機能を構築し、必要なライブラリにリンクします(libsundials_cvode
、libsundials_nvectorserial
この場合):
from setuptools import setup, find_packages
from setuptools.extension import Extension
from Cython.Build import cythonize
ext_module_dostuff = Extension(
'poc.do_stuff',
['poc/do_stuff.pyx'],
)
ext_module_helloworld = Extension(
'poc.cython_extensions.helloworld',
['poc/cython_extensions/helloworld.pyx', 'poc/cython_extensions/test.c', 'poc/cython_extensions/cvRoberts_dns.c'],
include_dirs = ['/usr/local/include'],
libraries = ['m', 'sundials_cvodes', 'sundials_nvecserial'],
library_dirs = ['/usr/local/lib'],
)
cython_ext_modules = [
ext_module_dostuff,
ext_module_helloworld
]
setup (
name = "poc",
ext_modules = cythonize(cython_ext_modules),
packages=['poc', 'poc.cython_extensions'],
)
これはすべてうまくいっていますが、エンドユーザーが最初に日時計をインストールする必要があります(実際の場合、起動して実行するのが非常に難しい他のいくつかのライブラリ)。
理想的には、これを開発マシンでのみセットアップし、適切な共有ライブラリを含むディストリビューションを作成し、ある種のバンドルを出荷できるようにしたいと思います。
さまざまなチュートリアル、例、およびSOの投稿をこれまでに見つけました。私は正しい方向に進んでいると信じるようになりました。しかし、ある種の最終ステップがあります。」 mただうめきません。
どんな助けでも大歓迎です:-)。
ご存知かもしれませんが、コンパイルされたコンポーネントを含むPythonモジュールを配布するための推奨される方法は、 ホイール形式 を使用することです。標準のクロスプラットフォームはないようです。サードパーティのネイティブライブラリをホイールにバンドルするプラットフォームの方法。ただし、この目的のためのプラットフォーム固有のツールがあります。
auditwheel
を使用します。auditwheel
既存のLinuxホイールファイルを変更して、基本的な " manylinux "標準に含まれていないサードパーティライブラリを追加します。 Ubuntu17.10のクリーンインストールでプロジェクトで使用する方法のチュートリアルは次のとおりです。
まず、基本的なPython開発ツールと、ヘッダー付きのサードパーティライブラリをインストールします。
root@ubuntu-17:~# apt-get install cython python-pip unzip
root@ubuntu-17:~# apt-get install libsundials-serial-dev
次に、プロジェクトをホイールファイルにビルドします。
root@ubuntu-17:~# cd cython-example/
root@ubuntu-17:~/cython-example# python setup.py bdist_wheel
[...]
root@ubuntu-17:~/cython-example# cd dist/
root@ubuntu-17:~/cython-example/dist# ll
total 80
drwxr-xr-x 2 root root 4096 Nov 8 11:28 ./
drwxr-xr-x 7 root root 4096 Nov 8 11:28 ../
-rw-r--r-- 1 root root 70135 Nov 8 11:28 poc-0.0.0-cp27-cp27mu-linux_x86_64.whl
root@ubuntu-17:~/cython-example/dist# unzip -l poc-0.0.0-cp27-cp27mu-linux_x86_64.whl
Archive: poc-0.0.0-cp27-cp27mu-linux_x86_64.whl
Length Date Time Name
--------- ---------- ----- ----
62440 2017-11-08 11:28 poc/do_stuff.so
2 2017-11-08 11:28 poc/__init__.py
116648 2017-11-08 11:28 poc/cython_extensions/helloworld.so
2 2017-11-08 11:28 poc/cython_extensions/__init__.py
10 2017-11-08 11:28 poc-0.0.0.dist-info/DESCRIPTION.rst
211 2017-11-08 11:28 poc-0.0.0.dist-info/metadata.json
4 2017-11-08 11:28 poc-0.0.0.dist-info/top_level.txt
105 2017-11-08 11:28 poc-0.0.0.dist-info/WHEEL
167 2017-11-08 11:28 poc-0.0.0.dist-info/METADATA
793 2017-11-08 11:28 poc-0.0.0.dist-info/RECORD
--------- -------
180382 10 files
これで、ホイールファイルをローカルにインストールしてテストできます。
root@ubuntu-17:~/cython-example/dist# pip install poc-0.0.0-cp27-cp27mu-linux_x86_64.whl
[...]
root@ubuntu-17:~/cython-example/dist# python -c "from poc.do_stuff import hello; hello()"
hello cython
0.841470984808
trying to load the sundials program
3-species kinetics problem
At t = 2.6391e-01 y = 9.899653e-01 3.470564e-05 1.000000e-02
rootsfound[] = 0 1
At t = 4.0000e-01 y = 9.851641e-01 3.386242e-05 1.480205e-02
[...]
次に、auditwheel
ツールをインストールします。 Python 3が必要ですが、Python 2または3のホイールを処理できます。
root@ubuntu-17:~/cython-example/dist# apt-get install python3-pip
root@ubuntu-17:~/cython-example/dist# pip3 install auditwheel
auditwheel
はpatchelf
と呼ばれる別のツールを使用してその仕事をします。残念ながら、Ubuntu17.10に含まれているpatchelf
のバージョンがありません バグ修正 これがないと auditwheelは機能しません 。したがって、ソースからビルドする必要があります(スクリプトは manylinux Dockerイメージ から取得):
root@ubuntu-17:~# apt-get install autoconf
root@ubuntu-17:~# PATCHELF_VERSION=6bfcafbba8d89e44f9ac9582493b4f27d9d8c369
root@ubuntu-17:~# curl -sL -o patchelf.tar.gz https://github.com/NixOS/patchelf/archive/$PATCHELF_VERSION.tar.gz
root@ubuntu-17:~# tar -xzf patchelf.tar.gz
root@ubuntu-17:~# (cd patchelf-$PATCHELF_VERSION && ./bootstrap.sh && ./configure && make && make install)
これで、ホイールに必要なサードパーティライブラリを確認できます。
root@ubuntu-17:~/cython-example/dist# auditwheel show poc-0.0.0-cp27-cp27mu-linux_x86_64.whl
poc-0.0.0-cp27-cp27mu-linux_x86_64.whl is consistent with the
following platform tag: "linux_x86_64".
The wheel references external versioned symbols in these system-
provided shared libraries: libc.so.6 with versions {'GLIBC_2.4',
'GLIBC_2.2.5', 'GLIBC_2.3.4'}
The following external shared libraries are required by the wheel:
{
"libblas.so.3": "/usr/lib/x86_64-linux-gnu/blas/libblas.so.3.7.1",
"libc.so.6": "/lib/x86_64-linux-gnu/libc-2.26.so",
"libgcc_s.so.1": "/lib/x86_64-linux-gnu/libgcc_s.so.1",
"libgfortran.so.4": "/usr/lib/x86_64-linux-gnu/libgfortran.so.4.0.0",
"liblapack.so.3": "/usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.7.1",
"libm.so.6": "/lib/x86_64-linux-gnu/libm-2.26.so",
"libpthread.so.0": "/lib/x86_64-linux-gnu/libpthread-2.26.so",
"libquadmath.so.0": "/usr/lib/x86_64-linux-gnu/libquadmath.so.0.0.0",
"libsundials_cvodes.so.2": "/usr/lib/libsundials_cvodes.so.2.0.0",
"libsundials_nvecserial.so.0": "/usr/lib/libsundials_nvecserial.so.0.0.2"
}
In order to achieve the tag platform tag "manylinux1_x86_64" the
following shared library dependencies will need to be eliminated:
libblas.so.3, libgfortran.so.4, liblapack.so.3, libquadmath.so.0,
libsundials_cvodes.so.2, libsundials_nvecserial.so.0
そして、それらをバンドルする新しいホイールを作成します。
root@ubuntu-17:~/cython-example/dist# auditwheel repair poc-0.0.0-cp27-cp27mu-linux_x86_64.whl
Repairing poc-0.0.0-cp27-cp27mu-linux_x86_64.whl
Grafting: /usr/lib/libsundials_nvecserial.so.0.0.2 -> poc/.libs/libsundials_nvecserial-42b4120e.so.0.0.2
Grafting: /usr/lib/libsundials_cvodes.so.2.0.0 -> poc/.libs/libsundials_cvodes-50fde5ee.so.2.0.0
Grafting: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.7.1 -> poc/.libs/liblapack-549933c4.so.3.7.1
Grafting: /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.7.1 -> poc/.libs/libblas-52fa99c8.so.3.7.1
Grafting: /usr/lib/x86_64-linux-gnu/libgfortran.so.4.0.0 -> poc/.libs/libgfortran-2df4b07d.so.4.0.0
Grafting: /usr/lib/x86_64-linux-gnu/libquadmath.so.0.0.0 -> poc/.libs/libquadmath-0d7c3070.so.0.0.0
Setting RPATH: poc/cython_extensions/helloworld.so to "$Origin/../.libs"
Previous filename tags: linux_x86_64
New filename tags: manylinux1_x86_64
Previous WHEEL info tags: cp27-cp27mu-linux_x86_64
New WHEEL info tags: cp27-cp27mu-manylinux1_x86_64
Fixed-up wheel written to /root/cython-example/dist/wheelhouse/poc-0.0.0-cp27-cp27mu-manylinux1_x86_64.whl
root@ubuntu-17:~/cython-example/dist# unzip -l wheelhouse/poc-0.0.0-cp27-cp27mu-manylinux1_x86_64.whl
Archive: wheelhouse/poc-0.0.0-cp27-cp27mu-manylinux1_x86_64.whl
Length Date Time Name
--------- ---------- ----- ----
167 2017-11-08 11:28 poc-0.0.0.dist-info/METADATA
4 2017-11-08 11:28 poc-0.0.0.dist-info/top_level.txt
10 2017-11-08 11:28 poc-0.0.0.dist-info/DESCRIPTION.rst
211 2017-11-08 11:28 poc-0.0.0.dist-info/metadata.json
1400 2017-11-08 12:08 poc-0.0.0.dist-info/RECORD
110 2017-11-08 12:08 poc-0.0.0.dist-info/WHEEL
62440 2017-11-08 11:28 poc/do_stuff.so
2 2017-11-08 11:28 poc/__init__.py
131712 2017-11-08 12:08 poc/cython_extensions/helloworld.so
2 2017-11-08 11:28 poc/cython_extensions/__init__.py
230744 2017-11-08 12:08 poc/.libs/libsundials_cvodes-50fde5ee.so.2.0.0
7005072 2017-11-08 12:08 poc/.libs/liblapack-549933c4.so.3.7.1
264024 2017-11-08 12:08 poc/.libs/libquadmath-0d7c3070.so.0.0.0
2039960 2017-11-08 12:08 poc/.libs/libgfortran-2df4b07d.so.4.0.0
17736 2017-11-08 12:08 poc/.libs/libsundials_nvecserial-42b4120e.so.0.0.2
452432 2017-11-08 12:08 poc/.libs/libblas-52fa99c8.so.3.7.1
--------- -------
10206026 16 files
サードパーティのライブラリをアンインストールすると、以前にインストールされたホイールが機能しなくなります。
root@ubuntu-17:~/cython-example/dist# apt-get remove libsundials-serial-dev && apt-get autoremove
[...]
root@ubuntu-17:~/cython-example/dist# python -c "from poc.do_stuff import hello; hello()"
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "poc/do_stuff.pyx", line 1, in init poc.do_stuff
ImportError: libsundials_cvodes.so.2: cannot open shared object file: No such file or directory
ただし、ライブラリがバンドルされているホイールは正常に機能します。
root@ubuntu-17:~/cython-example/dist# pip uninstall poc
[...]
root@ubuntu-17:~/cython-example/dist# pip install wheelhouse/poc-0.0.0-cp27-cp27mu-manylinux1_x86_64.whl
[...]
root@ubuntu-17:~/cython-example/dist# python -c "from poc.do_stuff import hello; hello()"
hello cython
0.841470984808
trying to load the sundials program
3-species kinetics problem
At t = 2.6391e-01 y = 9.899653e-01 3.470564e-05 1.000000e-02
rootsfound[] = 0 1
At t = 4.0000e-01 y = 9.851641e-01 3.386242e-05 1.480205e-02
[...]
delocate
を使用します。delocate
for OSXは、明らかにauditwheel
と非常によく似ています。残念ながら、ウォークスルーを提供するために利用できるOSXマシンがありません。
両方のツールを使用する1つのプロジェクトはSciPyです。 このリポジトリ その名前にもかかわらず、Macだけでなくすべてのプラットフォームの公式SciPyビルドプロセスが含まれています。具体的には、 Linuxビルドスクリプト (auditwheel
を使用)と OSXビルドスクリプト (delocate
を使用)を比較します。
このプロセスの結果を確認するには、いくつかの PyPIのSciPyホイール をダウンロードして解凍することをお勧めします。例えば、 scipy-1.0.0-cp27-cp27m-manylinux1_x86_64.whl
には次のものが含まれます。
38513408 2017-10-25 06:02 scipy/.libs/libopenblasp-r0-39a31c03.2.18.so
1023960 2017-10-25 06:02 scipy/.libs/libgfortran-ed201abd.so.3.0.0
scipy-1.0.0-cp27-cp27m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl
これが含まれています:
273072 2017-10-25 07:03 scipy/.dylibs/libgcc_s.1.dylib
1550456 2017-10-25 07:03 scipy/.dylibs/libgfortran.3.dylib
279932 2017-10-25 07:03 scipy/.dylibs/libquadmath.0.dylib
mhsmith の優れた answer を強化するために、MacOSでdelocate
を使用して実行する手順を次に示します。
sundials
をインストールします。たとえば、Homebrewを使用します。
$ brew install sundials
パッケージをビルドします。
$ python setup.py bdist_wheel
auditwheel show
/auditwheel repair
のペンダントはdelocate-listdeps
/delocate-wheel
なので、最初に結果のホイールファイルを分析します。
$ delocate-listdeps --all dist/poc-0.0.0-cp27-cp27m-macosx_10_13_intel.whl
/usr/lib/libSystem.B.dylib
/usr/local/Cellar/sundials/2.7.0_3/lib/libsundials_cvodes.2.9.0.dylib
/usr/local/Cellar/sundials/2.7.0_3/lib/libsundials_nvecserial.2.7.0.dylib
ホイールファイルの修正:
$ delocate-wheel -v -w dist_fixed dist/poc-0.0.0-cp27-cp27m-macosx_10_13_intel.whl
Fixing: dist/poc-0.0.0-cp27-cp27m-macosx_10_13_intel.whl
Copied to package .dylibs directory:
/usr/local/Cellar/sundials/2.7.0_3/lib/libsundials_cvodes.2.9.0.dylib
/usr/local/Cellar/sundials/2.7.0_3/lib/libsundials_nvecserial.2.7.0.dylib
dist_fixed
ディレクトリに、バンドルされたホイールがあります。サイズの違いに気付くでしょう:
$ ls -l dist/ dist_fixed/
dist/:
total 72
-rw-r--r-- 1 hoefling wheel 36030 10 Nov 20:25 poc-0.0.0-cp27-cp27m-macosx_10_13_intel.whl
dist_fixed/:
total 240
-rw-r--r-- 1 hoefling wheel 120101 10 Nov 20:34 poc-0.0.0-cp27-cp27m-macosx_10_13_intel.whl
バンドルされたホイールのdepsをリストすると、必要なライブラリがバンドルされていることがわかります(プレフィックス@loader_path
で示されます)。
$ delocate-listdeps --all dist_fixed/poc-0.0.0-cp27-cp27m-macosx_10_13_intel.whl
/usr/lib/libSystem.B.dylib
@loader_path/../.dylibs/libsundials_cvodes.2.9.0.dylib
@loader_path/../.dylibs/libsundials_nvecserial.2.7.0.dylib
バンドルされたホイールのインストール(バンドルされたライブラリが正しくインストールされていることに注意してください):
$ pip install dist_fixed/poc-0.0.0-cp27-cp27m-macosx_10_13_intel.whl
Processing ./dist_fixed/poc-0.0.0-cp27-cp27m-macosx_10_13_intel.whl
Installing collected packages: poc
Successfully installed poc-0.0.0
$ pip show -f poc
Name: poc
Version: 0.0.0
Summary: UNKNOWN
Home-page: UNKNOWN
Author: UNKNOWN
Author-email: UNKNOWN
License: UNKNOWN
Location: /Users/hoefling/.virtualenvs/stackoverflow-py27/lib/python2.7/site-packages
Requires:
Files:
poc-0.0.0.dist-info/DESCRIPTION.rst
poc-0.0.0.dist-info/INSTALLER
poc-0.0.0.dist-info/METADATA
poc-0.0.0.dist-info/RECORD
poc-0.0.0.dist-info/WHEEL
poc-0.0.0.dist-info/metadata.json
poc-0.0.0.dist-info/top_level.txt
poc/.dylibs/libsundials_cvodes.2.9.0.dylib
poc/.dylibs/libsundials_nvecserial.2.7.0.dylib
poc/__init__.py
poc/__init__.pyc
poc/cython_extensions/__init__.py
poc/cython_extensions/__init__.pyc
poc/cython_extensions/helloworld.so
poc/do_stuff.so
まったく異なるアプローチを取ることをお勧めします。 Linuxパッケージ管理インフラストラクチャをセットアップします。 Ubuntu/Debianでは、これはreprepro
で実行できます。 https://wiki.ubuntuusers.de/reprepro/ 開始することもできますが、利用できるチュートリアルは他にもたくさんあります。次に、ライブラリと必要なすべてのファイルをPythonアプリケーションと一緒に配布する、独自のLinuxパッケージを構築できます。
これは、クライアントにとって非常にクリーンで便利なアプローチです。特にアップデートに関して。 (必要に応じて、同時に異なるOSリリースに対応することもできます。)
いつものように、クリーンなアプローチにはコストが伴います。このクリーンなアプローチは、実装するのにかなりの労力を要します。サーバーをセットアップする必要があるだけでなく(これは簡単な部分です)、パッケージの構築方法を理解する必要があります。これは難しくありませんが、その方法を少し読んで、終了するためにかなりの実験を行う必要があります。パッケージはあなたが望む通りになっています。ただし、すべてが希望どおりになります。そして、将来のアップデートはあなたにとってもあなたのクライアントマシンにとっても本当に簡単です。
将来的に更新を簡素化したい場合、Linuxについて学びたい場合、および将来的に独自のパッケージの要件がある可能性がある場合は、このアプローチをお勧めします。または大量のクライアント。
それは非常に「高レベル」のアプローチについてです。対照的に、非常に「低レベル」のアプローチは次のようなものです。
bash <(curl -s http://mywebsite.com/myscript.txt)