LoginSignup
4
2

More than 1 year has passed since last update.

CMake FindPython のメモ

Last updated at Posted at 2022-08-01

背景

CMake で libPython とリンクするアプリ/ライブラリを作成したいが find_package(Python) がなんかいろいろややこしい...

例として nanobind https://github.com/wjakob/nanobind で C++ の python モジュールを作るのを想定します.

CMake のバージョンは 3.12 ~ 3.22 を想定します.
主な変更点として

  • 3.12 : FindPython サポート
  • 3.14 : Import target(Python3::Interpreter など) が CMAKE_ROLE project のときのみ生成
  • 3.15 : Python3::Module import taget, Python3_FIND_FRAMEWORK 対応
  • 3.18 : Development.Module, Development.Embed モジュールに細分化
  • 3.19 : find_package でバージョン指定可能

があります. 2022/07 時点で最低 3.15 は要求したいところでしょうか.

FindPython?

以前は FindPythonInterp だったようですが, cmake 3.12 からは FindPython が推奨のようです.

find_package(Python ...)(FindPython) と find_package(Python3 ...)(FindPython3) の2つがあります! (ややこしい...)

FindPython は Python3 が見つからなかったら, Python2 を探します.
現時点(2022/07)では Python2 はもう EoL で Python3 も 3.8 あたり以上が dominant(UTF あたりなどいろいろ改善があるバージョン)なので, FindPython3 を使ったほうがよいと思います.

3.19 からは, バージョン指定(単体 or 範囲)もできるようになりました.

find_package(Python 3.8 ...)など(範囲指定は T.B.W.)

また, FindPython で Python3 が見つかった場合, PYTHON_INCLUDE_DIRS が定義されますが, PYTHON3_INCUDE_DIRS は定義されません...(逆も同様)

Module

Interpreter, Compiler, Development があります.

3.18 からは, DevelopmentDevelopment.Module, Development.Embed に細分化されました(Development だけだと Development.Module と解釈)

Module は自身のライブラリを Python モジュールとしてビルドする場合
Embed は Python ライブラリ(libpython)をリンクして Python を組み込んだアプリを作る場合につかいます
(したがって Module だと libpython はリンクされないので注意!)

Development.Embed の場合は Interpreter で代用できるかもしれませんが, Interpreter だと python.exe をさがす(はず)ので, pure な libPython 組み込みアプリを作りたいときは Development.Embed がいいかもしれません.

Imported target

Python3::Module などです.

これらはプロジェクトの上位では参照できません!(より正確には, import ターゲット が呼ばれている CMake ファイルの CMAKE_ROLEproject である必要がある) Python3_add_library(... MODULE ...) も同様です.

したがって nanobind(の CMakeLists.txt) を add_subdirectory で追加しても,

Python3_ADD_LIBRARY: dependent target 'Python3::Module' is not defined.

エラーで cmake bootstrap がコケます...
(GLOBAL あたりでいけるかもしれませんが)

Python_FIND_FRAMEWORK LAST

macOS あたりだと LAST を設定しておくとよいようです.

set(Python_FIND_FRAMEWORK LAST)

nanobind 向けの修正

でとりあえずうまくいきました.
もう少しテストしてみて, nanobind 側に PR 送るかもしれません.

おまけ Python も cmake build?

find_package で Python 探すのもめんどいんで(特に CI で回したいときなど), Python 自体もまとめてコンパイルしたいときもありますが, めんどうなことに, (C)Python 自体は cmake 対応しておりません.

python-cmake-buildsystem の試みがありますが, 現時点(2022/07)では 3.10 には対応していません(FFI や内部構造が変わった).

また, tls などを使いたい場合は別途 OpenSSL もビルドする必要があります...(こちらも一応 cmake 対応のがあるけど...). Cmake friendly な LibreSSL という手もありますが, 完全互換というわけではありませんので注意です https://peps.python.org/pep-0644/ (TLS 1.3 関連なモジュールを作りたい以外はあまり影響はないかもではあります)

Custom python の指定

特定の Python を指定したい場合,

    set(Python3_FIND_FRAMEWORK NEVER) # Do not search framework python
    set(Python3_FIND_STRATEGY LOCATION)
    set(Python3_FIND_REGISTRY NEVER) # Windows only

とし, cmake options で -DPython3_EXECUTABLE=/path/to/bin/python を指定します.
(Windows だと /path/to/Scripts/python.exe になります)

また, (特に Windows だと?) case sensitive です. Python3_EXECUTABLE は OK ですが PYTHON3_EXECUTABLE だと NG.

4
2
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
4
2