漢なら Python pip で Windows, macOS, Linux で C++ モジュール含んだ prebuilt wheel インストールしたいですね!
cibuildwheel でやりましょう!
いろんな環境と python バージョンでビルドしてくれるスクリプトです. 素晴らしいですね.
これを自前プロジェクトの CI(travis, GitHub Actions, etc)に取り込めばいいです.
ちょっとわかりずらいですが,
$ python3 -m cibuildwheel --output-dir wheelhouse
を実行することで, python setup.py bdist_wheel
相当を, それぞれの python バージョンの環境を構築して実行してくれます
(Linux, macOS の場合は Docker 利用).
ビルド前にスクリプトを実行する
cibuildwheel では, Linux, macOS ですと Docker コンテナで実行されるため, Travis などで CI ビルドを行う場合は, git submodule update
みたいなのは docker コンテナの内部で実行しないといけません.
cibuildwheel の環境変数で, いくつか設定することができます.
ARM64 対応
ありがとうございます.
Github Actions ですと, Linux での arm64 ビルドは qemu になり遅いです.
Cirrus CI を使うとよいでしょう.
Windows ですと, cross-compile での対応になります(test は走らせられない).
また, x86 のビルドと混在すると, x86 ビルドで残っている .obj キャッシュを参照するようになりビルド(リンク)がこけます.
ビルドごとに毎回ビルドキャッシュを clean するのがよいでしょうが, とりあえずは job を分けるのがよいでしょうか.
TinyUSDZ での例を参照ください.
pypi にアップロードする
PyPI に Linux バイナリでパッケージをアップロードするメモ
https://qiita.com/syoyo/items/6185380b8d9950b25561
あたりを参照ください
Github Actions では trusted publisher 推奨っぽい.
2023/12 月時点では, Github Actions で pypi にアップロードする場合, アクセストークン(Encrypted environment variable)ではなく, Trusted Publisher を使うのが推奨のようです.
要はアクセストークンだと無限期間有効でセキュリティの懸念があるので, 短期でのみ有効なトークン(15 分間だけ)を CI での upload 時に作成してセキュリティ高めましょうという感じです. 2023/12 時点では CI サービスは Github Actions のみの対応になっています.
Azure pipeline は...?
Azure pipeline だと, twine などでビルド後アップロード自動化は現状めんどそうですが, vispy の設定が参考になるでしょうか.
一応 template が提案されていたりしますが, いくつか制約などがある感じです.
実際 tinyobjloader で使ってみましたが, オンラインドキュメントがわかりづらく, Travis に比べて面倒な感じでした.
(yaml 記述はオンラインエディタで構文チェックできるのがよいですが)
Travis が使えるなら travis を使う(or Github actions)を推奨します.
ビルド and publish の流れ
- OS ごとに cibuildwheel で whl ビルド
-
CopyFiles@2
で staging folder(ジョブが終わっても残っているディスク領域?)にビルド物をコピー-
$(Build.ArtifactStagingDirectory)
がステージングフォルダ
-
-
PublishBuildArtifacsts@0
で, artifact のフォルダに名前をつける
- task: PublishBuildArtifacts@1
inputs:
path: $(Build.ArtifactStagingDirectory)
artifactName: tinyobjDeployWindows
デプロイ(e.g. PyPI へのアップロード)では,
まず依存するタスクが完了しているか(dependsOn
)と, tag コミットであることをチェックします.
- job: deployPyPI
# Based on vispy: https://github.com/vispy/vispy/blob/master/azure-pipelines.yml
pool: {vmImage: 'Ubuntu-16.04'}
condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/v'))
dependsOn:
- linux
- macos
- windows
その後, DownloadBuildArtifacts
で, job のアーティファクト(実態としてはフォルダ群)をダウンロードします.
- task: DownloadBuildArtifacts@0
inputs:
artifactName: 'tinyobjDeployWindows'
downloadPath: $(Pipeline.Workspace)
このとき, artifactName
でフォルダが作られ($(Pipeline.Workspace)/tinyobjDepoloyWinwdows
), その中にビルド物が配置されます.
デバッグでは, ls などでログに出力して確認できるようにしておくとよさそうです.
あとは twine で publish して完成です!
# Publish to PyPI through twine
- bash: |
cd $(Pipeline.Workspace)
find .
python -m pip install --upgrade pip
pip install twine
echo tinyobjDeployLinux/python/dist/*
echo tinyobjDeployLinux/python/wheelhouse/* tinyobjDeployMacOS/python/wheelhouse/* tinyobjDeployWindows/python/wheelhouse/*
twine upload -u "__token__" --skip-existing tinyobjDeployLinux/python/dist/* tinyobjDeployLinux/python/wheelhouse/* tinyobjDeployMacOS/python/wheelhouse/* tinyobjDeployWindows/python/wheelhouse/*
env:
TWINE_PASSWORD: $(pypiToken2)
TWINE のパスワード(シークレットトークン)は, pypiToken2
の名前で Azure Pipeline の website でシークレットトークンを variable で登録しておきます.
感想
毎回 git push してビルドトリガーして 10 分くらい待ち, エラーが出ると修正 & 再度 tag つけて push がめんどいので, 手元で試せる環境がほしいところです.
Twine token
Azure Pipeline でも, Twine(PyPi)のシークレットトークンを扱える secret variables の機能がありますので, そちらを利用できます.
Secret variable は, ビルドスクリプト内では環境変数経由で指定します.
PublishBuildArtifacts を使いましょう
PublishPipelineArtifact
は One or more errors occurred
というエラーメッセージにもなっていないログだけ出して(エラー理由がまったく表示されない)てうまくうごきません.
PublishBuildArtifacts
を使いましょう.
C++ コードを含んだ実際のサンプル
cibuildwheel して, pypi アップロード,
pytinyexr(PyEXR) では Travis を使っています.
tinyobjloader では Azure Pipeline を使っています.
Py2.7(or pypy) + Windows + pybind11
少なくとも pypy はビルドエラーになるので, pp27-win32, pp36-win32 あたりは CIBW_SKIP
に含めてビルドしないようにしておきましょう
(pypy 使っている人いるのだろうか?)
また, python2.7 + C++11 も基本は非推奨です.
py27 を使わなければならない強い理由がなければ, python 2.7 サポートはしないほうがいいでしょう.
TODO
- GitHub Actions でのサンプルを作る