PyAlembicをWindows環境でビルドする

Windows環境のPythonからAlembicファイル (.abc) を扱えるようにするため、PyAlembicをビルドしてみます。

(2023/01/22追記)
ビルドスクリプトを作りました
(2024/02/03追記)
PythonパッケージをGitHub Actionsで作るようにして、
Releasesにバイナリパッケージを置きました

https://github.com/ugai/pyalembic-windows-buildscript

## Alembicとは

[Alembic](http://www.alembic.io/) は複雑なCGアニメーションをベイクする等の用途で使われるC++ライブラリです。このライブラリで生成できる.abcファイルは多くの主要なDCCツールでサポートされており、手軽に扱えると何かと便利です。

PyAlembicはそのAlembicライブラリのPythonバインディングで、これを使うことでPythonから簡単に.abcファイルを読み書きできるようになります。[Alembicのリポジトリ](https://github.com/alembic/alembic) にソースが同梱されていますが、公式のビルド済みファイルがないため自力でビルドする必要があります。

:::note warn
[PyPIにあるAlembic](https://pypi.org/project/alembic/) は同名の別ツールなので注意
:::

## 必要なツールの用意

事前に下記のツールをインストールしておきます。
ツールのバージョンは今回使ったものを載せています。

- Visual Studio 2022 (Community版)
- CMake 3.25
- Python 3.10
- Git

CMakeはパスを通しておいたほうが楽です。

## 依存関係のビルド

Alembicの依存ライブラリは下記の2つです。

- [Boost.Python](https://www.boost.org/doc/libs/release/libs/python/doc/html/index.html)
- [Imath](https://github.com/AcademySoftwareFoundation/Imath)

古い.abcファイルに対応する場合は [HDF5](https://www.hdfgroup.org/downloads/hdf5) も必要なようですが今回は省きます。

それぞれ個別にビルドしていきます。

### Boost.Python

[Boost公式のダウンロードページ](https://www.boost.org/users/download/) からWindows用のソースコード一式（例: `boost_1_81_0.zip` のようなファイル）を入手、展開し、下記のようにしてBoost.Pythonだけをビルドします。

```powershell
cd boost_1_81_0
.\booststrap.bat
echo "using python : : C:/Python/Python310 ;" > user-config.jam
.\b2 --build-type=complete --with-python --user-config=user-config.jam
```

:::note warn
コマンド中のBoostのフォルダ名 (`boost_1_81_0`) やPythonのパス (`C:/Python/Python310`) は適宜置き換えて実行してください
:::

ビルドしたファイルは `boost_1_81_0/stage/lib` フォルダに出力されます。

### Imath

ソースコードをgitリポジトリから入手します。
CMakeでビルドするので `build` フォルダを作ってその中で作業します。

```powershell
git clone https://github.com/AcademySoftwareFoundation/Imath
cd Imath
mkdir build
cd build
```

`cmake` コマンドを実行します。`-DPYTHON=ON` オプションでPythonモジュールのビルドを有効にしています。

```powershell
cmake .. -DPython_EXECUTABLE="C:/Python/Python310/Python.exe" -DPython3_EXECUTABLE="C:/Python/Python310/Python.exe" -DPYTHON=ON -DBoost_ROOT="../../boost_1_81_0" -DCMAKE_INSTALL_PREFIX="../_installed"
cmake --build . --config Release
cmake --install .
```

ビルドしたファイルは `Imath/_installed` フォルダに出力されます。

出力されたファイルのうち、`*.pyd` ファイルをPythonから見えるところにコピーしておきます。

```powershell
cp "Imath/_installed/lib/site-packages/*.pyd" "C:/Python/Python310/Lib/site-packages"
```

## Alembicのビルド

ソースコードをgitリポジトリから入手します。
CMakeでビルドするので `build` フォルダを作ってその中で作業します。

```powershell
git clone https://github.com/alembic/alembic
cd alembic
mkdir build
cd build
```

`cmake` コマンドを実行します。

```powershell
cmake .. -DUSE_PYALEMBIC=ON -DImath_DIR="../Imath/_installed/lib/cmake/Imath" -DPython3_EXECUTABLE="C:/Python/Python310/Python.exe" -DBoost_ROOT="../../boost_1_81_0" -DCMAKE_INSTALL_PREFIX="../_installed" -DALEMBIC_PYTHON_INSTALL_DIR="../_installed/lib/site-packages"
cmake --build . --config Release
cmake --install .
```

ビルドしたファイルは `alembic/_installed` フォルダに出力されます。

出力されたファイルのうち、`*.pyd` ファイルをPythonから見えるところにコピーしておきます。

```powershell
cp "alembic/_installed/lib/site-packages/*.pyd" "C:/Python/Python310/Lib/site-packages"
```

## 動作確認

Pythonインタプリタから `alembic` モジュールを読み込んでみます。おそらくエラーになります。

```python
>>> import alembic
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: DLL load failed while importing alembic: 指定されたモジュールが見つかりません。
```

`alembic.pyd` ファイルが依存しているDLLのうち、いずれかが見つからないためエラーになっているので、
下記のようにPythonのDLL探索パスにBoost、Imath、Alembicのフォルダを追加します。パスは適宜書き換えてください。

```python
import os
os.add_dll_directory(r"D:\_alembic-build\boost\stage\lib")
os.add_dll_directory(r"D:\_alembic-build\Imath\_installed\bin")
os.add_dll_directory(r"D:\_alembic-build\alembic\_installed\lib")
```

:::note warn
Python <= 3.7の場合は上記コマンドの代わりに、環境変数 `PATH` へ上記の3つのパスを追加します
:::

再度インポートしてみます。

```python
>>> import alembic
>>> alembic
<module 'alembic' from 'C:\\Python\\Python310\\lib\\site-packages\\alembic.pyd'>
```

うまくいったようです。

.abcファイルを読み込んでみます。

```python
>>> arch = alembic.Abc.IArchive(r"C:\abctest.abc")
>>> arch
<alembic.Abc.IArchive object at 0x0000026462464180>
```

## PyAlembicの使い方

PyAlembicの使い方は公式のドキュメントとPyAlembicのテストコードが参考になります。
というかそれしか情報が見当たりません :cry:

- [Introduction to PyAlembic](http://docs.alembic.io/python/examples.html)
- [testPolyMesh.py](https://github.com/alembic/alembic/blob/master/python/PyAlembic/Tests/testPolyMesh.py)