pybind11を使ったC++製のPythonライブラリをGithub上にサクッと公開する手順書

pybind11を使ってC++で書いたライブラリをPythonから使えるようにする記事は沢山あるが、
作ったものをどうやって公開するかという話はあまりされていないように感じた。

この記事ではpybindが公式提供している`cmake_example`というテンプレートをベースに、公開できる状態のGithubリポジトリをちゃちゃっと作成する手順を述べる。この手順を最後まで踏むと、ユーザーが2,3コマンドを打つだけでインストールして使い始めることができる状態のリポジトリが出来上がる。

## 1. cmake_exampleをクローンする

[cmake_example](https://github.com/pybind/cmake_example)はCMakeを使ってビルドを行うようにセットアップされた公式のテンプレートである。まずはこれを入手する。

```
cd work  # なんか適当な作業ディレクトリに入る
git clone https://github.com/pybind/cmake_example.git
```

## 2. 自分のGithubリポジトリを作成してクローンする

リポジトリの作り方は省略する。仮にリポジトリ名は`mylib`とする。.gitignoreは自由に作って構わないが、あとでcmake_exampleのものと合成する必要があるので注意。public・privateも好きに設定してよい。出来たらクローンしておく。

```
git clone https://github.com/*****/mylib.git
```

## 3. 自分のGithubリポジトリにpybind11をサブモジュールとして追加する

```
cd mylib
git submodule add -b master https://github.com/pybind/pybind11.git pybind11
```

`pybind11/`ディレクトリ以下にいろいろダウンロードされ、また`.gitmodules`が生成される。

## 4. 最低限必要なファイルをコピーする

`cmake_example/`ディレクトリから必要なファイル&ディレクトリを`mylib/`にコピーしてくる。最低限必要なものは以下の通り。

- .gitignore
- CMakeLists.txt
- MANIFEST.in
- LICENSE
- setup.py
- src/

`LICENSE`は`LICENSE.pybind`のように改名して、別途自分のプロジェクト用の`LICENSE`を用意する。前述したとおり、`.gitignore`についてはcmake_exampleのものと自分のものをうまくマージする。

## 5. CMakeLists.txtを編集する

`cmake_example`と記載されている箇所を自分のライブラリ名に変更する。

```cmake:CMakeLists.txt
cmake_minimum_required(VERSION 2.8.12)
project(mylib) <--

add_subdirectory(pybind11)
pybind11_add_module(mylib src/main.cpp) <--
```

## 6. setup.pyを編集する

一番下の`setup`呼び出し部分を自分の情報に書き換える。

```python:setup.py
setup(
    name='mylib', <-
    version='1.0.0', <-
    author='oreore', <-
    author_email='oreore@example.com', <-
    description='HogeHoge', <-
    long_description='', <-
    ext_modules=[CMakeExtension('mylib')], <-
    cmdclass=dict(build_ext=CMakeBuild),
    zip_safe=False,
)
```

必要に応じて以下のように外部ライブラリの要件を記述に加える。

```
    ...
    zip_safe=False,
    packages=find_packages(),
    install_requires=['pillow']
```

## 7. ソースコードを編集する

`main.cpp`の`PYBIND11_MODULE`の指定のところで、ライブラリ名を`mylib`に書き換える。

```
PYBIND11_MODULE(mylib, m) {
```

あとは好きにコードを作成し、必要に応じて`CMakeLists.txt`に書き足していく。

## 8. ビルドする

```
python setup.py build
```

エラーがでなければOK

## 9. インストールする

```
python setup.py install
```

## 10. 動作確認する

`mylib/`ディレクトリの外に出てpythonを起動し、ライブラリをimportして動作を確認してみる。`mylib/`の中で確認すると、ファイル検索順序の影響でインストールしたファイルではなくカレントディレクトリ以下のファイルが使われる可能性があるので、外で行う。

```
>>> import mylib
>>> mylib.add(1, 2)
>>> 3
```

## 11. コミットして公開する

作ったものをユーザーに使用してもらうには、以下の3ステップを踏んでもらう。

### 11.1. コンパイラとCMakeを用意してもらう

Ubuntuなどの場合は

```
sudo apt install build-essential cmake
```

など打ってもらえばいい。Windowsユーザーの場合は……、頑張ってVisual Studio 2019とCMakeを個別にインストールしてもらおう(ついでにCMakeにはパスを通してもらう必要もある。つらい)。

### 11.2. リポジトリをクローンしてもらう

ユーザーにリポジトリをクローンしてもらう際は以下のコマンドを実行してもらうようにする。

```
git clone --recursive https://github.com/******/mylib.git
```

`--recursive`を付けないと`pybind11`がダウンロードされずにビルドできないのでちゃんと記載する。

### 11.3. setup.pyを実行してもらう

```sh
python setup.py install
```

と打ってもらう。以上。

## 補足1. Pythonのコードも含めたい場合

C++のライブラリだけでなく、Pythonのコードも合わせて提供したい場合は、C++のライブラリ名を`_mylib`のように変えて、`mylib/__init__.py`からimportとして読み込むようにする。

具体的にはまず、`CMakeLists.txt`を以下のようにする。

```cmake:CMakeLists.txt
project(_mylib)
...
pybind11_add_module(_mylib src/main.cpp)
```

次に`setup.py`

```python:setup.py
ext_modules=[CMakeExtension('mylib._mylib')],
```

これはビルドの成果物を`mylib/_mylib****`(.soあるいは.pyd)に置くことを意味している。

次に`src/main.cpp`

```cpp:src/main.cpp
PYBIND11_MODULE(_mylib, m) {
```

最後にPythonのソースコードを置く`mylib/`ディレクトリを用意して`__init__.py`を書く。

```python:mylib/__init__.py
from ._mylib import *
```

あとはPythonコードを好きなように書き足す。

## 補足2. Visual Studio 2019で開発する場合

せっかくCMakeを使っているので、Visual Studio用のソリューションファイルを生成する。

`build/`ディレクトリを作り、その中でcmakeを実行する。

```cmd
mkdir build
cd build
cmake .. -G "Visual Studio 16 2019"
```

`build/mylib.sln`が生成されるので、これを使って開発する。なお、`build/`ディレクトリは`.gitignore`に含まれているので、ソリューションファイル等をリポジトリに登録したい場合は`build`ではなく違うディレクトリを使おう。