前回のscikit-buildの続きです。
Pythonのwheelとして配布する場合、拡張モジュールは共有ライブラリとして配布されますが、この時外部の共有ライブラリ(今回はlibboost_python.so)に依存していると、実行時にこの共有ライブラリが必要になります。しかしwheelにはこの共有ライブラリが含まれていないので、import
時に失敗することになります。
それを避けるために今回はBoost.Pythonを静的にリンクして配布する方法をまとめます。
この内容は以下のリポジトリに含まれています
Boostのビルド
aptで入れたlibboost-python-dev
に含まれる静的ライブラリをリンクしようとすると-fPIC
をつけて再コンパイルしろとリンカーに言われるので、おとなしくBoostの再コンパイルから行います。
を参考に作業していきます。今回必要なのはBoost.Pythonだけなので、他のモジュールについてはビルドしません。
curl -LO https://dl.bintray.com/boostorg/release/1.70.0/source/boost_1_70_0.tar.gz
tar xf boost_1_70_0.tar.gz
cd boost_1_70_0
./bootstrap.sh --with-python=/usr/bin/python3 --with-python-version=3.7
./b2 cxxflags=-fPIC link=static --with-python --prefix=/usr install -j 12
- Boost 1.70とPython3.7に対して行います
- 普通ビルドしようとするとPython2を探してきてしまうので、所々にPythonのパスの指定があります
- コンテナ上で行う予定なので
--prefix=/usr
にしています -
link=static
で静的ライブラリをビルドするように設定します -
cxxflags=-fPIC
をつけることによって静的ライブラリ作成時にも強制的にPosition-Independentなコードを生成させることができます。
これでBoost.PythonなC++拡張をビルドしてwheelで配布するための作業コンテナが出来上がります
FROM debian:buster
LABEL maintainer "Toshiki Teramura <toshiki.teramura@gmail.com>"
RUN apt-get update \
&& apt-get install -y \
curl \
g++ \
make \
cmake \
ninja-build \
python3 \
python3-pip \
python3-numpy \
libpython3-dev \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
RUN pip3 install --upgrade pip scikit-build
RUN curl -LO https://dl.bintray.com/boostorg/release/1.70.0/source/boost_1_70_0.tar.gz \
&& tar xf boost_1_70_0.tar.gz \
&& cd boost_1_70_0 \
&& ./bootstrap.sh --with-python=/usr/bin/python3 --with-python-version=3.7 \
&& ./b2 cxxflags=-fPIC link=static --with-python --prefix=/usr install -j 12 \
&& cd .. \
&& rm -rf boost_1_70_0*
これは一応
docker pull registry.gitlab.com/termoshtt/flat_ffi_example/boost_python:latest
で取得できるようにGitLabでホストされていますが、今後も使えるかは保障しかねるので何かで使うときは独自にビルドしてください。
cmake
Boostを静的にリンクしたい場合はfind_package
する前に Boost_USE_STATIC_LIBS
を指定してあげます
set(Boost_USE_STATIC_LIBS ON)
find_package(Boost COMPONENTS python numpy REQUIRED)
いまいちよく理解していないのですが、上のようにPythonを指定してビルドすると、python
, numpy
のコンポーネント名でPython3が指定できます(aptで入れるとpython3
等にする必要がある)。
GitLab CI
このコンテナを使えば以下のようにして、Boost.Pythonを静的にリンクしたwheelをartifactにできます。
build_cpp_wheel:
image: registry.gitlab.com/termoshtt/flat_ffi_example/boost_python
script:
- python3 setup.py bdist_wheel
- mv dist/*.whl ..
artifacts:
paths:
- ./*.whl
あとは後段のstepで使うなり、GitLab Pagesで公開するなり、PyPIに公開するなり自由です。