MicroPython マニフェストファイル¶
概要¶
MicroPythonには、ファイルシステムからのコードの読み込みに代わる方法として、Pythonコードをファームウェアに「凍結」する機能があります。
これには以下の利点があります:
コードはバイトコードに事前コンパイルされているため、ロード時に Python ソースをコンパイルする無駄がなくなります。
バイトコードは ROM (フラッシュメモリ)から直接実行できるため、RAM にコピーしなくて済みます。同様に、定数オブジェクト(文字列、タプルなど)も ROM から読み込まれます。これにより、アプリケーションでより多くのメモリが利用できるようになります。
ファイルシステムを持たないデバイスでは、これが Python コードをロードする唯一の方法となります。
開発中は、更新のたびにファームウェア全体の再フラッシュが必要になるため、凍結は一般的に推奨されません。ただしそれでも、サードパーティのライブラリなど、あまり変更されない依存関係にあるものを選択的に凍結するのは役立つことがあります。
ファームウェアに凍結する Python ファイル一覧を指定する方法は、「マニフェスト」というもので、ビルドプロセスによって解釈される Python ファイルです。通常、ボード定義の一部としてマニフェストファイルを書きますが、既存のボード定義を取り込んで、スタンドアロンのマニフェストファイルを書くこともできます。
マニフェストファイルは micropython-lib のライブラリ、ファイルシステム上の Python ファイル、他のマニフェストファイルに対する依存関係を定義できます。
マニフェストファイルの書き方¶
マニフェストファイルは、関数呼び出しの並びを含む Python ファイルです。後述の利用可能な関数を参照してください。
マニフェストファイルで使用されるパスには、次の変数を含められます。これらはすべて絶対パスに解決されます。
$(MPY_DIR)
-- micropython リポジトリへのパス。$(MPY_LIB_DIR)
-- micropython-lib のサブモジュールへのパス。require()
の利用を推奨します。$(PORT_DIR)
-- 現在のポートへのパス(例:ports/stm32
)$(BOARD_DIR)
-- 現在のボードへのパス(例:ports/stm32/boards/PYBV11
)
カスタムマニフェストファイルは、メインの MicroPython リポジトリに置かないでください。プロジェクトの他の部分と一緒にバージョン管理してください。
通常、ファームウェアをコンパイルするのに使うマニフェストには、ボードが動作するために必要な凍結モジュールを含むポートマニフェストを含める必要があります。既存のボードに追加のモジュールを追加するだけであれば、ボードマニフェストを含めます(これはポートマニフェストを含みます)。
カスタムマニフェストを使ってビルドする方法¶
カスタムマニフェストは、次のように make
コマンドラインで指定できます。
$ make BOARD=MYBOARD FROZEN_MANIFEST=/path/to/my/project/manifest.py
これは、CMake をベースにしたポート(例: esp32、rp2)を含むすべてのポートに適用されます。なぜなら Makefile のラッパーがこれを CMake ビルドに渡すためです。
ボード定義にマニフェストを追加する方法¶
カスタムボード定義がある場合、カスタムマニフェストを自動的に含められます。ほとんどのポートでは make を使っているため、 mpconfigboard.mk
で FROZEN_MANIFEST
変数を設定します。
FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py
CMake をベースにしたポート(例: esp32、rp2)の場合、代わりに mpconfigboard.cmake
を使います。
set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py)
高レベル関数¶
注記: さまざまな関数で opt
キーワード引数を設定できます。これはクロスコンパイラで使う最適化レベルを制御します。micropython.opt_level()
を参照してください。
- package(package_path, files=None, base_path='.', opt=None)¶
これは "package_path" ディレクトリをデバイスにコピーするのと同等です(ただし、凍結されたコードになります)。
最も単純な場合で、現在のディレクトリにあるパッケージ "foo" を凍結するには次のようにします。
package("foo")
これにより foo 内のすべての .py ファイルが再帰的に含まれ、
foo/**/*.py
として凍結されます。マニフェストファイルと同じディレクトリにパッケージがない場合は
base_path
を使ってください:package("foo", base_path="path/to/libraries")
base_path
では$(PORT_DIR)
などの変数を使えます。パッケージ内の特定のファイルに制限するには
files
を使います(注記: パスはパッケージに対して相対的である必要があります)。たとえばpackage("foo", files=["bar/baz.py"])
のように指定します。
- module(module_path, base_path='.', opt=None)¶
単一の Python ファイルをモジュールとして取り込みます。
ファイルが現在のディレクトリにある場合:
module("foo.py")
それ以外の場合は base_path を指定してファイルを検索します。
module("foo.py", base_path="src/drivers")
base_path
では$(PORT_DIR)
などの変数を使えます。
- require(name, unix_ffi=False)¶
micropython-lib から名前(およびその依存関係)によってパッケージを要求します。
オプションで unix_ffi=True を指定して、unix-ffi ディレクトリからモジュールを使えるようにできます。
- include(manifest_path)¶
別のマニフェストを取り込みます。
通常、ファームウェアのコンパイルに使うマニフェストでは、ポートマニフェストを取り込む必要があります。ポートマニフェストには、ボードの動作に必要な凍結モジュールを定義しています。
manifest 引数には文字列(ファイル名)または文字列のイテラブルを指定します。
相対パスは、現在のマニフェストファイルを基準に解決されます。
パスがディレクトリである場合、そのディレクトリ内の manifest.py ファイルを暗黙的に取り込みます。
manifest_path
内では$(PORT_DIR)
などの変数を使えます。
- metadata(description=None, version=None, license=None, author=None)¶
Define metadata for this manifest file. This is useful for manifests for micropython-lib packages.
低レベル関数¶
これらの関数は完全性のためにドキュメント化してますが、 freeze_as_str
を除くすべての機能は高レベル関数を介してアクセスできます。
- freeze(path, script=None, opt=0)¶
path で指定された入力を凍結します。凍結対象の種別は自動的に判定します。
.py
スクリプトは最初に.mpy
にコンパイルしてから凍結し、.mpy
ファイルは直接凍結します。path はディレクトリでなければなりません。これは、ファイルを検索するベースとなるディレクトリです。凍結されたモジュールをインポートする際、モジュール名は path の後から始まります。つまり、モジュール名には path が含まれません。
path が相対パスの場合、現在の
manifest.py
を基準に解決されます。script が None の場合、 path 内のすべてのファイルを凍結します。
script がイテラブルなオブジェクトである場合、イテラブルのすべての項目について
freeze()
を呼び出します(path と opt が渡されます)。script が文字列である場合、それは凍結するファイルまたはディレクトリを指定します。ファイルまたは最後のディレクトリの前には追加のディレクトリを含められます。凍結するファイルまたはディレクトリは path 内で検索されます。script がディレクトリである場合、そのディレクトリ内のすべてのファイルを凍結します。
opt は
.py
から.mpy
へのコンパイル時に mpy-cross に渡す最適化レベルです。レベルについての説明はmicropython.opt_level()
にあります。
- freeze_as_str(path)¶
指定した path とその中にあるすべての
.py
スクリプトを文字列として凍結します。この文字列として凍結したものはインポート時にコンパイルされます。
- freeze_as_mpy(path, script=None, opt=0)¶
最初に
.py
スクリプトを.mpy
ファイルにコンパイルしてから、結果の.mpy
ファイルを凍結することで、入力を凍結します。引数に関する詳細はfreeze()
を参照してください。
- freeze_mpy(path, script=None, opt=0)¶
コンパイル済の
.mpy
ファイルでなければならない入力を凍結します。引数に関する詳細はfreeze()
を参照してください。
サンプル¶
現在のディレクトリから単一のファイルをインポート可能なモジュールとして凍結するには次のようにします:
module("mydriver.py")
現在のディレクトリのサブディレクトリ "mydriver" のファイルをインポート可能なモジュールとして凍結するには次のようにします:
package("mydriver")
micropython-lib の "hmac" ライブラリを凍結するには次のようにします:
require("hmac")
PYBD_SF2
ボードのカスタム manifest.py
ファイルの例を次に示します:
# ボードのデフォルトのマニフェストを取り込む。
include("$(BOARD_DIR)/manifest.py")
# カスタムドライバを追加
module("mydriver.py")
# micropython-lib から aiorepl を追加
require("aiorepl")
このファイルを使って、次のようにしてボードをビルドできます。
$ cd ports/stm32
$ make BOARD=PYBD_SF2 FROZEN_MANIFEST=~/src/myproject/manifest.py
なお、多くのボードには独自の manifest.py
がありません。その場合は、マニフェストが include("$(PORT_DIR)/boards/manifest.py")
だけであるようなマニフェストファイルを作成する必要があります。