<p>如您所知,使用编译组件分发Python模块的推荐方法是使用<a href="https://pypi.python.org/pypi/wheel" rel="noreferrer">wheel format</a>。似乎没有任何标准的跨平台方式将第三方本机库捆绑到一个轮子中。但是,有一些特定于平台的工具可用于此目的。在</p>
<h2>在Linux上,使用<code>auditwheel</code></h2>
<p><a href="https://github.com/pypa/auditwheel" rel="noreferrer">^{<cd1>}</a>修改现有的LinuxWheel文件,以添加基本“<a href="https://github.com/pypa/manylinux" rel="noreferrer">manylinux</a>”标准中未包含的任何第三方库。下面是如何在Ubuntu 17.10干净安装的项目中使用它的演练:</p>
<p>首先,安装基本的Python开发工具和第三方库及其头:</p>
<pre class="lang-none prettyprint-override"><code>root@ubuntu-17:~# apt-get install cython python-pip unzip
root@ubuntu-17:~# apt-get install libsundials-serial-dev
</code></pre>
<p>然后将项目构建到控制盘文件中:</p>
^{pr2}$
<p>现在可以在本地安装和测试wheel文件:</p>
<pre class="lang-none prettyprint-override"><code>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
[...]
</code></pre>
<p>现在我们安装<code>auditwheel</code>工具。它需要Python3,但它能够处理Python2或3的轮子。在</p>
<pre class="lang-none prettyprint-override"><code>root@ubuntu-17:~/cython-example/dist# apt-get install python3-pip
root@ubuntu-17:~/cython-example/dist# pip3 install auditwheel
</code></pre>
<p><code>auditwheel</code>使用另一个名为<code>patchelf</code>的工具来完成它的工作。不幸的是,ubuntu17.10中包含的<code>patchelf</code>版本丢失了<a href="https://github.com/NixOS/patchelf/issues/84" rel="noreferrer">a bugfix</a>,没有了{a5}。所以我们必须从源代码构建它(脚本取自<a href="https://github.com/pypa/manylinux/blob/6eae41b6988f34401d87d22fcb78970df2c3a06d/docker/build_scripts/build.sh#L114" rel="noreferrer">the manylinux Docker image</a>):</p>
<pre class="lang-none prettyprint-override"><code>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)
</code></pre>
<p>现在,我们可以检查wheel需要哪些第三方库:</p>
<pre class="lang-none prettyprint-override"><code>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
</code></pre>
<p>并创建一个新的轮子来捆绑它们:</p>
<pre class="lang-none prettyprint-override"><code>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
</code></pre>
<p>如果卸载第三方库,以前安装的控制盘将停止工作:</p>
<pre class="lang-none prettyprint-override"><code>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
</code></pre>
<p>但是,带有捆绑库的轮子可以正常工作:</p>
<pre class="lang-none prettyprint-override"><code>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
[...]
</code></pre>
<h2>在OSX上,使用<code>delocate</code></h2>
<p>OSX的<a href="https://github.com/matthew-brett/delocate" rel="noreferrer">^{<cd7>}</a>显然与<code>auditwheel</code>非常相似。不幸的是,我没有一台OSX机器来提供演练。在</p>
<h2>组合示例:</h2>
<p>一个同时使用这两种工具的项目是SciPy。<a href="https://github.com/MacPython/scipy-wheels" rel="noreferrer">This repository</a>,尽管它的名字,包含了所有平台的官方SciPy构建过程,而不仅仅是Mac。具体来说,将<a href="https://github.com/matthew-brett/multibuild/blob/e6ebbfa42588c26579eff99c50e84326dd9f6b3e/manylinux_utils.sh" rel="noreferrer">Linux build script</a>(使用<code>auditwheel</code>)与{a10}(使用<code>delocate</code>)进行比较。在</p>
<p>要查看此过程的结果,您可能需要下载并解压一些<a href="https://pypi.python.org/pypi/scipy" rel="noreferrer">SciPy wheels from PyPI</a>。例如,<code>scipy-1.0.0-cp27-cp27m-manylinux1_x86_64.whl</code>包含以下内容:</p>
<pre class="lang-none prettyprint-override"><code> 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
</code></pre>
<p>而<code>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</code>包含以下内容:</p>
<pre class="lang-none prettyprint-override"><code> 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
</code></pre>