LoginSignup
15
13

More than 3 years have passed since last update.

Boost.Pythonを使って書いたC++拡張をwheelで配布する

Last updated at Posted at 2019-07-18

前回の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 を指定してあげます

CMakeLists.txt
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にできます。

.gitlab-ci.yml
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に公開するなり自由です。

15
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
13