MicroPython manifest dosyaları

Özet

MicroPython, Python kodunun dosya sisteminden yüklenmesine alternatif olarak aygıt yazılımına (firmware) “dondurulmasına” olanak tanıyan bir özelliğe sahiptir.

Bunun aşağıdaki faydaları vardır:

  • kod, bayt koduna önceden derlenir; böylece Python kaynağının yükleme anında derlenmesine gerek kalmaz.

  • bayt kodu RAM’e kopyalanmak yerine doğrudan ROM’dan (yani flash bellekten) çalıştırılabilir. Benzer şekilde, herhangi bir sabit nesne (dizeler, demetler vb.) de ROM’dan yüklenir. Bu, uygulamanız için önemli ölçüde daha fazla belleğin kullanılabilir olmasını sağlayabilir.

  • dosya sistemi olmayan cihazlarda, Python kodunu yüklemenin tek yolu budur.

Geliştirme sırasında dondurma genellikle önerilmez, çünkü her güncelleme tüm aygıt yazılımının yeniden flaşlanmasını gerektireceğinden geliştirme döngünüzü önemli ölçüde yavaşlatır. Bununla birlikte, nadiren değişen bazı bağımlılıkları (örneğin üçüncü taraf kütüphaneleri) seçici olarak dondurmak yine de faydalı olabilir.

Aygıt yazılımına dondurulacak Python dosyalarını listelemenin yolu, derleme süreci tarafından yorumlanacak bir Python dosyası olan bir “manifest” aracılığıyladır. Tipik olarak bir manifest dosyasını bir kart tanımının parçası olarak yazarsınız, ancak bağımsız bir manifest dosyası yazıp mevcut bir kart tanımıyla da kullanabilirsiniz.

Manifest dosyaları, micropython-lib içindeki kütüphanelere olan bağımlılıkların yanı sıra dosya sistemindeki Python dosyalarına ve ayrıca diğer manifest dosyalarına olan bağımlılıkları da tanımlayabilir.

Manifest dosyaları yazma

Bir manifest dosyası, bir dizi işlev çağrısı içeren bir Python dosyasıdır. Aşağıda tanımlanan kullanılabilir işlevlere bakın.

Manifest dosyalarında kullanılan herhangi bir yol aşağıdaki değişkenleri içerebilir. Bunların tümü mutlak yollara çözümlenir.

  • $(MPY_DIR) – micropython deposunun yolu.

  • $(MPY_LIB_DIR) – micropython-lib alt modülünün yolu. require() kullanmayı tercih edin.

  • $(PORT_DIR) – mevcut portun yolu (örneğin ports/stm32)

  • $(BOARD_DIR) – mevcut kartın yolu (örneğin ports/stm32/boards/OPENMV4)

Özel manifest dosyaları ana MicroPython deposunda bulunmamalıdır. Bunları projenizin geri kalanıyla birlikte sürüm kontrolünde tutmalısınız.

Tipik olarak, aygıt yazılımı derlemek için kullanılan bir manifest, kartın çalışması için gereken dondurulmuş modülleri içerebilen port manifest’ini dahil etmesi gerekir. Yalnızca mevcut bir karta ek modüller eklemek istiyorsanız, kart manifest’ini dahil edin (bu da port manifest’ini dahil edecektir).

Özel bir manifest ile derleme

Manifest’iniz make komut satırında şu şekilde belirtilebilir:

$ make BOARD=MYBOARD FROZEN_MANIFEST=/path/to/my/project/manifest.py

Bu, Makefile sarmalayıcısı bunu CMake derlemesine ileteceğinden, CMake tabanlı olanlar (örneğin rp2) da dahil olmak üzere tüm portlar için geçerlidir.

Bir kart tanımına manifest ekleme

Özel bir kart tanımınız varsa, özel manifest’inizi otomatik olarak dahil etmesini sağlayabilirsiniz. make tabanlı portlarda (çoğu port), mpconfigboard.mk dosyanızda FROZEN_MANIFEST değişkenini ayarlayın.

FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py

CMake tabanlı portlarda (örneğin rp2), bunun yerine mpconfigboard.cmake kullanın

set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py)

Üst düzey işlevler

Bunlar normalde kullanacağınız işlevlerdir. Bayt koduna önceden derlenen ve aygıt yazılımı imajına dondurulan kümeye kod eklerler:

  • module ve package, kendi yerel kaynağınızı dondurur — sırasıyla tek bir dosya veya bütün bir paket dizini.

  • require, micropython-lib içinden yayımlanmış bir paketi (ve bağımlılıklarını) ada göre dondurur.

  • include, başka bir manifest’i çeker; böylece onun dondurulmuş modülleri de eklenir.

  • add_library ve metadata destek işlevleridir (require için ek arama yolları kaydetme ve paket meta verilerini bildirme).

Tipik bir aygıt yazılımı manifest’i önce port veya kart manifest’ini include eder (böylece kartın ihtiyaç duyduğu modüller dondurulmuş kalır), ardından kendi module/package/require satırlarını ekler.

Not: opt anahtar sözcüğü argümanı çeşitli işlevlerde ayarlanabilir; bu, çapraz derleyici tarafından kullanılan optimizasyon seviyesini kontrol eder. Bkz. micropython.opt_level().

add_library(library, library_path, prepend=False)

Harici adlandırılmış bir library yolunu kaydeder.

require‘ın paketleri micropython-lib dışındaki bir dizinden çözümlemesini istediğinizde bunu kullanın — örneğin kendi sürücü koleksiyonunuz veya bir üçüncü taraf kütüphane checkout’u.

library_path yolu, require kullanılırken otomatik olarak aranacaktır. Varsayılan olarak, eklenen kütüphane aranacak kütüphaneler listesinin sonuna eklenir. Listenin başına eklemek için True geçirerek başa ekleyin.

Ek olarak, eklenen kütüphane require("name", library="library") kullanılarak açıkça istenebilir.

package(package_path, files=None, base_path='.', opt=None)

Bütün bir paketi.py dosyalarından oluşan bir dizini (isteğe bağlı olarak alt paketlerle birlikte) — import <package> olarak içe aktarılabilmesi için dondurun. Tek bir bağımsız dosya için bunun yerine module kullanın.

Bu, “package_path” dizinini cihaza kopyalamaya eşdeğerdir (dondurulmuş kod olması dışında).

En basit durumda, mevcut dizindeki bir “foo” paketini dondurmak için:

package("foo")

foo içindeki tüm .py dosyalarını özyinelemeli olarak dahil eder ve foo/**/*.py olarak dondurur.

Paket, manifest dosyasıyla aynı dizinde değilse base_path kullanın:

package("foo", base_path="path/to/libraries")

Yukarıdaki değişkenleri, örneğin $(PORT_DIR) değişkenini base_path içinde kullanabilirsiniz.

Paketteki belirli dosyalarla sınırlamak için files kullanın (not: yollar pakete göreceli olmalıdır): package("foo", files=["bar/baz.py"]).

module(module_path, base_path='.', opt=None)

Tek bir bağımsız .py dosyasını adıyla içe aktarılabilmesi için dondurun (module("foo.py"), import foo ifadesinin çalışmasını sağlar). Bir dizin/paket için package kullanın.

Dosya mevcut dizindeyse:

module("foo.py")

Aksi takdirde dosyayı bulmak için base_path kullanın:

module("foo.py", base_path="src/drivers")

Yukarıdaki değişkenleri, örneğin $(PORT_DIR) değişkenini base_path içinde kullanabilirsiniz.

require(name, library=None)

micropython-lib içinden bir paketi (ve bağımlılıklarını) ada göre talep edin.

Standart kütüphane uzantıları ve topluluk sürücüleri bu şekilde dondurulur: adlandırılan paket micropython-lib alt modülünden alınır ve bağımlı olduğu her şeyle birlikte dondurulur. Yayımlanmış bir paket yerine kendi kaynağınızı dondurmak için bunun yerine module veya package kullanın.

İsteğe bağlı olarak, daha önce add_library ile kaydedilmiş bir kütüphaneden bir pakete başvurmak için library (bir dize) belirtin. Aksi takdirde kütüphane yolları listesi kullanılacaktır.

include(manifest_path)

Başka bir manifest’i dahil edin. Manifest’ler bu şekilde oluşturulur: özel bir aygıt yazılımı manifest’i, kartın ihtiyaç duyduğu modüllerin dondurulmuş kalması için port (veya kart) manifest’ini include etmeli ve ardından kendi girdilerini eklemelidir.

Tipik olarak, aygıt yazılımı derlemek için kullanılan bir manifest, kartın çalışması için gereken dondurulmuş modülleri içerebilen port manifest’ini dahil etmesi gerekir.

manifest argümanı bir dize (dosya adı) veya bir dizeler yinelenebiliri olabilir.

Göreceli yollar, mevcut manifest dosyasına göre çözümlenir.

Yol bir dizine işaret ediyorsa, o dizinin içindeki manifest.py dosyasını dolaylı olarak dahil eder.

Yukarıdaki değişkenleri, örneğin $(PORT_DIR) değişkenini manifest_path içinde kullanabilirsiniz.

metadata(description=None, version=None, license=None, author=None)

Bu manifest dosyası için meta veri tanımlayın. Bu, micropython-lib paketleri için manifest’lerde kullanışlıdır.

Bu alanlar, bir paket mip aracılığıyla micropython-lib‘e yayımlandığında / oradan kurulduğunda tüketilir; bir kart aygıt yazılımı manifest’inde gerekli değildirler.

Düşük düzey işlevler

Bu işlevler bütünlük açısından belgelenmiştir, ancak freeze_as_str dışında tüm işlevselliğe üst düzey işlevler aracılığıyla erişilebilir.

freeze* işlevleri yalnızca kodun nasıl depolandığı bakımından farklılık gösterir:

  • freeze_as_mpy / freeze_mpy, önceden derlenmiş bayt kodunu (.mpy) flash bellekte depolar. Kod doğrudan flash bellekten çalışır, minimum RAM kullanır ve hızlı içe aktarılır. module, package ve require dahili olarak bunu kullanır.

  • freeze_as_str ise bunun yerine Python kaynağını dondurur ve bu kaynak içe aktarma zamanında bayt koduna derlenir (RAM kullanarak ve cihaz üzerindeki derleyiciyi gerektirerek). Bu, üst düzey işlevler tarafından açığa çıkarılmayan tek yetenektir; yukarıda belirtilen istisnanın nedeni budur.

freeze(path, script=None, opt=0)

Üst düzey işlevlerin üzerine kurulduğu temel ilkel; onları tercih edin. path ile belirtilen girdiyi, türünü otomatik olarak belirleyerek dondurun. Bir .py betiği önce bir .mpy dosyasına derlenip ardından dondurulur, bir .mpy dosyası ise doğrudan dondurulur.

path bir dizin olmalıdır; bu, dosyaları aramaya başlamak için kullanılan temel dizindir. Ortaya çıkan dondurulmuş modülleri içe aktarırken, modülün adı path‘ten sonra başlar, yani path modül adından hariç tutulur.

path göreceliyse, mevcut manifest.py dosyasına göre çözümlenir.

script None ise, path içindeki tüm dosyalar dondurulur.

script bir yinelenebilir ise, yinelenebilirin tüm öğeleri üzerinde freeze() çağrılır (aynı path ve opt iletilerek).

script bir dize ise, dondurulacak dosyayı veya dizini belirtir ve dosya ya da son dizinden önce ek dizinler içerebilir. Dosya veya dizin path içinde aranır. script bir dizin ise, o dizindeki tüm dosyalar dondurulur.

opt, .py dosyalarını .mpy dosyalarına derlerken mpy-cross’a geçirilecek optimizasyon seviyesidir. Bu seviyeler micropython.opt_level() içinde açıklanmıştır.

freeze_as_str(path)

Verilen path yolunu ve içindeki tüm .py betiklerini, içe aktarma sırasında derlenecek bir dize olarak dondurun. Bunu yalnızca dondurulmuş kodun Python kaynağı olarak kalması gerektiğinde kullanın; .mpy türevlerine kıyasla içe aktarma zamanında RAM maliyeti vardır.

freeze_as_mpy(path, script=None, opt=0)

Girdiyi önce .py betiklerini .mpy dosyalarına derleyerek, ardından ortaya çıkan .mpy dosyalarını dondurarak dondurun. module ve package perde arkasında bunu yapar. Argümanlarla ilgili ayrıntılar için freeze() öğesine bakın.

freeze_mpy(path, script=None, opt=0)

Doğrudan dondurulan (derleme adımı olmadan) .mpy dosyaları olması gereken girdiyi dondurun. Argümanlarla ilgili ayrıntılar için freeze() öğesine bakın.

Örnekler

Mevcut dizindeki tek bir dosyayı import mydriver olarak kullanılabilecek şekilde dondurmak için şunu kullanın:

module("mydriver.py")

Mevcut dizinin “mydriver” alt dizinindeki bir dosya dizinini import mydriver olarak kullanılabilecek şekilde dondurmak için şunu kullanın:

package("mydriver")

micropython-lib içinden “hmac” kütüphanesini dondurmak için şunu kullanın:

require("hmac")

Özel bir manifest.py dosyasının (kendi varsayılan manifest’ine sahip bir kart için) daha eksiksiz bir örneği:

# Include the board's default manifest.
include("$(BOARD_DIR)/manifest.py")
# Add a custom driver
module("mydriver.py")
# Add aiorepl from micropython-lib
require("aiorepl")

Ardından kart şununla derlenebilir

$ cd ports/stm32
$ make BOARD=MYBOARD FROZEN_MANIFEST=~/src/myproject/manifest.py

Çoğu kartın kendi manifest.py dosyasının olmadığını, bunun yerine port’unkini doğrudan kullandığını unutmayın; bu durumda manifest’inizin yalnızca include("$(PORT_DIR)/boards/manifest.py") ifadesini kullanması yeterlidir.