組み込みLinuxでエッジAIの開発をしようと思い立った際に、そういえばYoctoってしばらくビルドしてないなぁ...と思ったので、安価に入手できる 「Raspberry Pi 5」に合わせたLinuxディストリビューションをYocto Projectを使ってビルドする 手順をまとめてみました。今回ターゲットに選択したのは、Raspberry Pi 5の8GBモデルです。
参考にさせていただきました記事
今回は下記の記事を参考にさせていただきました。ありがとうございます。
関連記事
本記事はYocto 4.0.23(kirkstone) × Raspberry Pi 5の組み合わせが非推奨であったことに対する、下記の記事へ向けた対策記事ともなっています。
Yocto 5.0 (scarthgap) on Raspberry Pi 5
本記事ではビルド環境となるOSのセットアップから、ビルド環境の構築、ビルド用コンフィグファイルの設定、実際のビルドと実行結果までをまとめました。 Yocto Project 5.0 (scarthgap) で生成できるRaspberry Pi 5向けLinuxディストリビューションのGUI版のビルドと実行方法、構築したLinuxディストリビューション向けのアプリケーションやカーネルモジュールを作成するためのSDKをインストールする方法を解説します。
※Yoctoは Yocto 5.1(styhead)が最新ですが、2024/12/30時点ではBSPである「meta-raspberrypi」に「Yocto 5.1(styhead)」のブランチがなく、「Yocto 5.0(scarthgap)」のブランチのみが存在したため今回はscarthgapを選択しました。
組み込みAI向けLinuxディストリビューション
今回はGUIに加えて、以下の機能を備え、組み込みプラットフォームである Raspberry Pi 5上で組み込みAIのベースとして動作できる組み込みAI向けLinuxディストリビューションを構築してみます。試してみたのは以下のLayerですが、 今回の記事では以下でNGとしているレイヤーは、ビルドエラーが発生したため除外しました。Yocto 4.0.23(kirkstone)ではビルドできていたRaspberry Pi 5 AI Kitを組み込めないのは残念ですね...(meta-hailoはi.MX向けにメンテされているようなので仕方ないのですが)
- Yocto 5.0.5(scarthgap) + meta-raspberrypi
- Networking (OK)
- meta-networking
- Docker (OK)
- meta-virtualization
- Python3 (OK)
- meta-python
- OpenCV (OK)
- opencv, python3-opencv
- imshowも機能する
- Tensorflow (NG)
- meta-tensorflow
- scarthgap向けのブランチなし
- Tensorflow Lite (OK)
- meta-tensorflow-lite
- ONNX runtime (OK)
- meta-onnxruntime
- Raspberry Pi 5 AI Kit (NG)
- meta-hailo
- i.MXにのみ対応している状態
- scarthgap非対応(yocto 4.x系まで対応)
- SDKによるカーネルモジュールのビルド (OK)
- Networking (OK)
さて、はじめていきましょう。
ビルド環境を構築する
まず、Ubuntu 22.04 LTSをベースとしたビルド環境を構築します。
Ubuntu 22.04 LTSをインストールする
Yocto 5.0のSystem Requirementに示されているビルド環境を整備します。今回はUbuntu 22.04 LTSを選択しました。USBメモリにインストールイメージを書き込み、標準構成でOSをセットアップします。
OSを最新の状態にし、必要なパッケージをインストールする
OSをセットアップした後、下記のコマンドを実行して環境を整備します。
# 英語(LANG=C)でホームに含まれるディレクトリを再構築する
$ LANG=C xdg-user-dirs-gtk-update
# 再起動後から利用されるようになる
$ reboot
# すべてのパッケージを最新に更新する
$ sudo apt update
$ sudo apt upgrade
# 日本語入力機能とエディタをインストールする
$ sudo apt install ibus-mozc vim
$ im-config -n ibus
# sshサーバーをインストールする
$ sudo apt install openssh-server
$ sudo systemctl start ssh
$ sudo systemctl enable ssh
ビルドに必要な依存パッケージをインストールする
Ubuntu 22.04 LTSへYocto Projectのビルドに必要とされるパッケージをインストールします。Yocto Projectのサイトに書かれている内容をそのまま実行すれば問題ありません。
# System Requirementsで指定されたパッケージをインストールする
$ sudo apt install build-essential chrpath cpio debianutils diffstat file gawk gcc git iputils-ping libacl1 liblz4-tool locales python3 python3-git python3-jinja2 python3-pexpect python3-pip python3-subunit socat texinfo unzip wget xz-utils zstd
# localeにen_US.utf8を追加する
$ locale --all-locales | grep en_US.utf8
# en_US.utf8
$ sudo locale-gen en_US.UTF-8
# Generating locales (this might take a while)...
# en_US.UTF-8... done
# Generation complete.
Raspberry Pi 5向けのLinuxディストリビューションをビルドするために必要なソースコードを入手する
以上でビルド環境は整いました。次に、Yocto ProjectでLinuxディストリビューションをビルドするために必要なソースコードとビルド用スクリプトを入手しましょう。
Yocto Project 5.0 をビルドするディレクトリを作成する
今回はYocto Projectの安定版でありRaspberry Pi 5にも対応している Yocto 5.0.5(scarthgap) を利用します。まずビルドに備えて作業ディレクトリを作成してください。
####
# 作業ディレクトリを作成して、移動する
$ mkdir -p ~/scarthgap-work-2024_v1
$ cd ~/scarthgap-work-2024_v1
poky
Yoctoのフレームワークとなるpokyを入手します。 pokyにはLinuxの基礎となる機能に加えて、ビルド用スクリプトが含まれています。 git clone
でリポジトリを入手した後にgit checkout
で scarthgap-5.0.5タグへ切り替え 、ビルドに必要なリソースを入手します。
$ cd ~/scarthgap-work-2024_v1/
$ pwd
# /home/shino/scarthgap-work-2024_v1
$ git clone git://git.yoctoproject.org/poky
$ cd ./poky
$ git checkout -b scarthgap refs/tags/scarthgap-5.0.5
meta-raspberrypi
「meta-raspberrypi」は Raspberry Pi向けのBSP(Board Support Package) を含むLayerです。git clone
でリポジトリを取得した後にgit checkout
でscarthgap向けのリソースに切り替えます。
$ cd ~/scarthgap-work-2024_v1/poky
$ git clone git://git.yoctoproject.org/meta-raspberrypi
$ cd ./meta-raspberrypi
$ git checkout -b scarthgap origin/scarthgap
meta-openembedded
「meta-openembedded」は Linuxでよく利用されるアプリケーションやミドルウェア、ライブラリなどが集約されたLayer です。いくつかのSub-Layerから構成されます。git clone
でリポジトリを取得した後にgit checkout
でscarthgap向けのリソースに切り替えます。
$ cd ~/scarthgap-work-2024_v1/poky
$ git clone git://git.openembedded.org/meta-openembedded
$ cd meta-openembedded
$ git checkout -b scarthgap origin/scarthgap
meta-virtualization
「meta-virtualization」は仮想化機能を含むLayerです。近年の開発で広く利用されるDockerもこのLayerに含まれています。 Dockerを利用することにより、異なるPythonのバージョンのプログラムをカプセル化してシームレスに統合したり、複数のバージョンの依存関係を保持したままシステムに組み上げることなどが可能 になります。git clone
でリポジトリを取得した後にgit checkout
でscarthgap向けのリソースに切り替えます。
$ cd ~/scarthgap-work-2024_v1/poky
$ git clone git://git.yoctoproject.org/meta-virtualization
$ cd meta-virtualization
$ git checkout -b scarthgap origin/scarthgap
meta-tensorflow 【Yocto 5.x向けのbranch無し】
ビルドしたところ下記のエラーで停止してしまうことを確認しました。
今回ビルドは対象から外します
# ERROR: bazel-native-6.0.0-r0 do_patch: Applying patch '0001-HttpDownloader-save-download-tarball-to-distdir.patch' on target directory '/home/shino/scarthgap-work-2024_v1/poky/aiot-build/tmp/work/x86_64-linux/bazel-native/6.0.0/sources'
# CmdError('quilt --quiltrc /home/shino/scarthgap-work-2024_v1/poky/aiot-build/tmp/work/x86_64-linux/bazel-native/6.0.0/recipe-sysroot-native/etc/quiltrc push', 0, "stdout: Applying patch 0001-HttpDownloader-save-download-tarball-to-distdir.patch
「meta-tensorflow」は組み込みAIで広く利用されているTensorflowを利用可能とするLayerです。このTensorflow Layerは、Tensorflowの軽量版であるTensorflow Lite Layerよりも大きいため、本番運用ではTensorflowかTensorflow Liteのいずれかに絞ったほうが良いでしょう。 なお、meta-tensorflowはmasterがscarthgap/styhead向けですが、変動しておりpatchを当てられないようなので、2024/12/30現在は一旦見送ります。
$ cd ~/scarthgap-work-2024_v1/poky
$ git clone git://git.yoctoproject.org/meta-tensorflow
$ cd meta-tensorflow
### masterがscarthgap向けなので、checkoutはしない
### -->> branchが切られるまでビルドに含めない
# $ git checkout -b XXX origin/XXX
# COMPATを確認する
$ grep scarthgap ./conf/layer.conf
# LAYERSERIES_COMPAT_meta-tensorflow = "scarthgap styhead"
下記のようにpatch適用失敗のメッセージが出る
meta-tensorflowをビルドしようとしたところ、下記のエラーが発生しビルドできませんでした。bazelにあてているパッチが対象外となっているようなので、patchだけ外そうかとも思いましたが meta-tensorflow
ごとビルドから除外します。
# ERROR: bazel-native-6.0.0-r0 do_patch: Applying patch '0001-HttpDownloader-save-download-tarball-to-distdir.patch' on target directory '/home/shino/scarthgap-work-2024_v1/poky/aiot-build/tmp/work/x86_64-linux/bazel-native/6.0.0/sources'
# CmdError('quilt --quiltrc /home/shino/scarthgap-work-2024_v1/poky/aiot-build/tmp/work/x86_64-linux/bazel-native/6.0.0/recipe-sysroot-native/etc/quiltrc push', 0, "stdout: Applying patch 0001-HttpDownloader-save-download-tarball-to-distdir.patch
# can't find file to patch at input line 19
# Perhaps you used the wrong -p or --strip option?
# The text leading up to this was:
# --------------------------
# |From 28acb4a213938bcb7e55ef3859699091c1f434c0 Mon Sep 17 00:00:00 2001
# |From: Hongxu Jia <hongxu.jia@eng.windriver.com>
# |Date: Thu, 1 Dec 2022 19:32:33 +0800
# |Subject: [PATCH] HttpDownloader: save download tarball to distdir
# |
# |It is helpful for collecting tarball url which supports offline build.
# |
# |Upstream-Status: Inappropriate [oe specific]
# |
# |Signed-off-by: Hongxu Jia <hongxu.jia@eng.windriver.com>
# |---
# | .../bazel/repository/downloader/DownloadManager.java | 12 ++++++++++++
# | 1 file changed, 12 insertions(+)
# |
# |diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/downloader/DownloadManager.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/downloader/DownloadManager.java
# |index bf65090..ee30dde 100755
# |--- a/src/main/java/com/google/devtools/build/lib/bazel/repository/downloader/DownloadManager.java
# |+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/downloader/DownloadManager.java
# --------------------------
meta-tensorflow-lite
「meta-tensorflow-lite」は Tensorflowのうち推論に特化した機能のみを抜き出したミドルウェアTensorflow Liteを利用可能とするLayer です。git clone
でリポジトリを取得した後にgit checkout
でscarthgap向けのリソースに切り替えます。
$ cd ~/scarthgap-work-2024_v1/poky
$ git clone https://github.com/NobuoTsukamoto/meta-tensorflow-lite.git
$ cd meta-tensorflow-lite/
$ git checkout -b scarthgap origin/scarthgap
meta-onnxruntime
「meta-onnxruntime」は ONNX形式のネットワークで推論を実行するためのLayer です。git clone
でリポジトリを取得した後にgit checkout
でscarthgap向けのリソースに切り替えます。
$ cd ~/scarthgap-work-2024_v1/poky
$ git clone https://github.com/NobuoTsukamoto/meta-onnxruntime.git
$ cd meta-onnxruntime/
$ git checkout -b scarthgap origin/scarthgap
meta-hailo 【yocto 5.0非対応】
meta-hailoはYocto 5.x(scarthgap)をサポートしておらず、ビルドしたところ下記のエラーで停止してしまうことを確認しました。今回ビルドは対象から外します
「meta-hailo」はRaspberry Pi 5 AI Kit向けのLayer群です。以下の機能を提供します。meta-hailoはSub-Layerである「meta-hailo-accelerator」「meta-hailo-libhailort」「meta-hailo-tappas」「meta-hailo-vpu」から構成されています。 Raspberry Pi向けには「meta-hailo-accelerator」「meta-hailo-libhailort」「meta-hailo-tappas」 を利用します。
- HailoRT library
- HailoRT drivers
- Firmware for Hailo devices
- pyHailoRT - HailoRT Python API (wraps the run-time library)
なお、meta-hailoはscarthgap向けのブランチを持っていませんので、今回は最新となるYocto 4.0.23(kirkstone)向けのブランチを使います。 git clone
でリポジトリを取得した後にgit checkout
でkirkstone向けのリソースに切り替えます。
# Layerの入手は下記のコマンドでできるように思えます
$ cd ~/scarthgap-work-2024_v1/poky
$ git clone https://github.com/hailo-ai/meta-hailo.git
$ cd meta-hailo
$ git checkout -b kirkstone origin/kirkstone
######
### Layerがkirkstone版のため設定ファイルのCOMPATに加筆
######
$ vi ./meta-hailo-accelerator/conf/layer.conf
### LAYERの対応バージョンを切り替える
# LAYERSERIES_COMPAT_meta-hailo-accelerator = "kirkstone"
LAYERSERIES_COMPAT_meta-hailo-accelerator = "scarthgap"
$ vi ./meta-hailo-libhailort/conf/layer.conf
### LAYERの対応バージョンを切り替える
# LAYERSERIES_COMPAT_meta-hailo-libhailort = "kirkstone"
LAYERSERIES_COMPAT_meta-hailo-libhailort = "scarthgap"
$ vi ./meta-hailo-tappas/conf/layer.conf
### LAYERの対応バージョンを切り替える
# LAYERSERIES_COMPAT_meta-hailo-tappas = "kirkstone"
LAYERSERIES_COMPAT_meta-hailo-tappas = "scarthgap"
また、このビルドスクリプトはi.MX用でありRapsbery Pi 5に対応していないため、以下の手順で常にHailo-8向けバイナリを生成するように(Raspberry Pi 5の構成向けに)ビルドスクリプトを書き足してください。
meta-hailo-tappasをRaspberry Pi 5 (Hailo-8)向けにする
「meta-hailo」はi.MX向けのLayerらしく、Raspberry Pi 5でビルドするとHailo-15のバイナリが生成されてしまうようです。そのため、下記の記事を参考に ソースコードが常にHailo-8向けにビルドされるようビルドスクリプトを修正 しました。
# bitbake時にtappas-appsをビルドするレシピに移動
$ cd ../meta-hailo/meta-hailo-tappas/recipes-gstreamer/tappas-apps
# tappas-appを変更する
$ vi tappas-apps_3.30.0.bb
# ...
# i.MX8の場合のみhailo8に切り替える箇所を変更
python () {
# if 'imx8' in d.getVar('MACHINE'):
d.setVar('REQS_FILE', d.getVar('REQS_IMX8_FILE'))
d.setVar('ARM_APPS_DIR', d.getVar('IMX8_DIR'))
# else:
# d.setVar('REQS_FILE', d.getVar('REQS_HAILO15_FILE'))
# d.setVar('ARM_APPS_DIR', d.getVar('HAILO15_DIR'))
# d.appendVar('DEPENDS', " libmedialib-api xtensor")
}
# ...
またビルド時に 生成物が予定外の箇所に生成されることにより do_install
が失敗する問題 については下記の対策を行いました。
# birbake時にlibhailrtを構成するスクリプトを変更
$ cd ~/scarthgap-work-2024_v1/poky/aiot-build/
$ vi ../meta-hailo/meta-hailo-libhailort/recipes-hailo/libhailort/libhailort_4.19.0.bb
do_install:append() {
# ...
# ビルド生成物が格納されるパスが変わっているので修正
# install -m 0644 ${WORKDIR}/build/hailort/libhailort/src/CMakeFiles/Export/lib/cmake/HailoRT/*.cmake ${HAILORT_EXPORT_DIR}
install -m 0644 ${WORKDIR}/build/hailort/libhailort/src/CMakeFiles/Export/*/*.cmake ${HAILORT_EXPORT_DIR}
# ...
###
# 本箇所によるエラーメッセージ
# install: cannot stat '/home/shino/scarthgap-work-2024_v1/poky/aiot-build/tmp/work/cortexa76-poky-linux/libhailort/4.19.0/build/hailort/libhailort/src/CMakeFiles/Export/lib/cmake/HailoRT/*.cmake': No such file or directory
# 以下のディレクトリが生成されてしまっている
# -->> ~/scarthgap-work-2024_v1/poky/aiot-build/tmp/work/cortexa76-poky-linux/libhailort/4.19.0/build/hailort/libhailort/src/CMakeFiles/Export/2889dedff7f789699a09a5260145dc0f/
###
ビルド中の do_fetchでWANINGが発生する 箇所にも修正を入れておきます。
# 作業ディレクトリへ移動
$ cd ~/scarthgap-work-2024_v1/poky/aiot-build/
# git:// でアクセスしている箇所に ;protocol=https を追加する
## -->> WARNING対策
$ vi ../meta-hailo//meta-hailo-tappas/recipes-gstreamer/xtl/xtl_0.7.3.bb
# SRC_URI = "git://github.com/xtensor-stack/xtl.git;name=xtl"
SRC_URI = "git://github.com/xtensor-stack/xtl.git;name=xtl;protocol=https"
設定ファイルを更新してビルドする
bitbake-layersでレイヤーを統合する
ここまでの手順で収集した 「meta-*」の各LayerをYoctoのビルド対象に追加 します。bitbake-layersコマンドで各ディレクトリを指定することにより「./conf/bblayers.conf」が更新されます。bitbake-layers add-layer
を実行後「./conf/bblayers.conf」ファイルにLayerが追加されていることを確認できます。
####
# ビルドディレクトリと設定ファイルの生成
####
$ cd ~/scarthgap-work-2024_v1/poky
$ pwd
# /home/shino/scarthgap-work-2024_v1/poky
$ source oe-init-build-env aiot-build
# 直前のコマンドにより作業ディレクトリがビルド用に切り替わる
$ pwd
# /home/shino/scarthgap-work-2024_v1/poky/aiot-build
$ ls conf/
# bblayers.conf
# conf-notes.txt
# conf-summary.txt
# local.conf
# templateconf.cfg
####
# Layerを追加する
####
# ビルド対象にRaspberry Pi 5 GUI向けのレイヤーを追加する
$ bitbake-layers add-layer ../meta-raspberrypi/
$ bitbake-layers add-layer ../meta-openembedded/meta-oe/
$ bitbake-layers add-layer ../meta-openembedded/meta-python/
$ bitbake-layers add-layer ../meta-openembedded/meta-multimedia/
$ bitbake-layers add-layer ../meta-openembedded/meta-networking/
$ bitbake-layers add-layer ../meta-openembedded/meta-filesystems/
# Docker向けのLayer
$ bitbake-layers add-layer ../meta-virtualization/
# 推論向けのLayer
$ bitbake-layers add-layer ../meta-tensorflow-lite/
$ bitbake-layers add-layer ../meta-onnxruntime/
# AI向けのLayer
### 今回のビルドには含めない
# $ bitbake-layers add-layer ../meta-tensorflow/
# Raspberry Pi 5 AI Kit向けのLayer (kirkstone版)
### 今回のビルドには含めない
# $ bitbake-layers add-layer ../meta-hailo/meta-hailo-accelerator/
# $ bitbake-layers add-layer ../meta-hailo/meta-hailo-libhailort/
# $ bitbake-layers add-layer ../meta-hailo/meta-hailo-tappas/
### 今回のビルドには含めない
# $ bitbake-layers add-layer ../meta-hailo/meta-hailo-vpu/
####
# Layerを確認する
####
$ grep /home/shino ./conf/bblayers.conf
/home/shino/scarthgap-work-2024_v1/poky/meta \
/home/shino/scarthgap-work-2024_v1/poky/meta-poky \
/home/shino/scarthgap-work-2024_v1/poky/meta-yocto-bsp \
/home/shino/scarthgap-work-2024_v1/poky/meta-raspberrypi \
/home/shino/scarthgap-work-2024_v1/poky/meta-openembedded/meta-oe \
/home/shino/scarthgap-work-2024_v1/poky/meta-openembedded/meta-python \
/home/shino/scarthgap-work-2024_v1/poky/meta-openembedded/meta-multimedia \
/home/shino/scarthgap-work-2024_v1/poky/meta-openembedded/meta-networking \
/home/shino/scarthgap-work-2024_v1/poky/meta-openembedded/meta-filesystems \
/home/shino/scarthgap-work-2024_v1/poky/meta-virtualization \
/home/shino/scarthgap-work-2024_v1/poky/meta-tensorflow-lite \
/home/shino/scarthgap-work-2024_v1/poky/meta-onnxruntime \
ライセンス "MINPACK" に対応する 【Workaround】
bitbakeすると下記のエラーメッセージが発生しビルドに失敗してしまうことがわかりました。これはYocto 5.0のビルド環境が「MINPACK」のLICENSEファイルを含んでいないためと思われます。
# ERROR: libeigen-3.4.0-r0 do_create_spdx: Cannot find any text for license MINPACK
# ERROR: Logfile of failure stored in: /home/shino/scarthgap-work-2024_v1/poky/aiot-build/tmp/work/cortexa76-poky-linux/libeigen/3.4.0/temp/log.do_create_spdx.474996
# ERROR: Task (/home/shino/scarthgap-work-2024_v1/poky/meta-openembedded/meta-oe/recipes-support/libeigen/libeigen_3.4.0.bb:do_create_spdx) failed with exit code '1'
そこで YoctoのビルドシステムにMINIPACKのライセンスファイルを準備します。 MINPACKのライセンスファイルを meta/files/common-licenses
以下に MINPACK
として保存します。ライセンスファイルはgitにあるものを利用しました。
# ライセンスファイルの格納先ディレクトリへ移動する
$ cd ~/scarthgap-work-2024_v1/poky/
$ cd meta/files/common-licenses/
# curlでライセンスファイルを取得する
$ sudo apt install curl
# ライセンスファイルをライセンス名で保存する
$ curl https://baltig.cnr.it/ectoplasm/spece/-/raw/feature/IMAS_adaptation/minpack-LICENSE.txt -o MINPACK
conf/local.confでビルドの設定をする
各機能のリポジトリのREADMEや各種記事を参考に、 Linuxディストリビューションに組み込みたいアプリケーション名や、それらのオプションを「./conf/local.conf」に指定 します。
westonをLinuxディストリビューションへ組み込む方法
rootのパスワードを設定する
# パスワード文字列 "testtest" をMD5-base passwordに変換する
$ openssl passwd -1 testtest
$1$YtdVyrZC$RBCUL//XC5pwkqOMo3TIn0
# この文字列を conf/local.conf に設定する
$ vi conf/local.conf
# ...
INHERIT += "extrausers"
EXTRA_USERS_PARAMS = "usermod -p '\$1\$YtdVyrZC\$RBCUL//XC5pwkqOMo3TIn0' root;"
# ...
以上をまとめると「./conf/local.conf」は以下のようになります。
$ vi ./conf/local.conf
# ...
BB_NUMBER_THREADS = "8"
PARALLEL_MAKE = "-j 8"
# ...
# ...
# MACHINEにはRaspberry Pi 5を指定する
MACHINE ??= "raspberrypi5"
####
# 以下の設定を追記する
####
UBOOT_EXTRA_CONFIGS = "LPDDR4_8GB"
# ...
# ...
DISTRO ?= "poky"
# ...
# ...
####
# 以下の設定を追記する
####
DISTRO_FEATURES:append = " wayland"
CORE_IMAGE_EXTRA_INSTALL += "wayland weston"
# rootのパスワードを設定する ("openssl passwd -1"で生成)
INHERIT += "extrausers"
EXTRA_USERS_PARAMS = "usermod -p '\$1\$YtdVyrZC\$RBCUL//XC5pwkqOMo3TIn0' root;"
# option for systemd
DISTRO_FEATURES:append = " systemd pam"
VIRTUAL-RUNTIME_init_manager = "systemd"
DISTRO_FEATURES_BACKFILL_CONSIDERED = "sysvinit"
VIRTUAL-RUNTIME_initscripts = "systemd-compat-units"
INIT_MANAGER ?= "systemd"
EXTRA_IMAGE_FEATURES += "ssh-server-openssh"
DISTRO_FEATURES:append = " virtualization"
IMAGE_INSTALL:append = " packagegroup-docker"
### meta-hailoのビルドエラーにより除外
# IMAGE_INSTALL:append = " hailo-firmware hailortcli hailo-pci libgsthailo libgsthailotools tappas-apps hailo-post-processes tappas-tracers"
### meta-tensorflowのビルドエラーにより除外
# IMAGE_INSTALL:append = " tensorflow"
IMAGE_INSTALL:append = " python3 python3-numpy python3-opencv opencv"
IMAGE_INSTALL:append = " python3-tensorflow-lite libtensorflow-lite"
IMAGE_INSTALL:append = " onnxruntime"
IMAGE_INSTALL:append = " curl"
IMAGE_INSTALL:append = " v4l-utils"
IMAGE_INSTALL:append = " sudo"
# build option
FORTRAN:forcevariable = ",fortran"
LICENSE_FLAGS_ACCEPTED = "synaptics-killswitch"
# ...
####
# 変更を加えて保存する
####
bitbakeでLinuxディストリビューションをビルドする
「bitbake」コマンドにGUI付きビルドである「core-image-weston」を指定して、GUI付きのLinuxディストリビューションをビルドします。8000〜10000パッケージ程度のビルドが実行されます。しばらくお待ちください。
######
### Linuxディストリビューションをビルドする
$ bitbake core-image-weston
# ...
# NOTE: Executing Tasks
# WARNING: core-image-weston-1.0-r0 do_populate_lic_deploy: QA Issue: The license listed Broadcom-RPi was not in the licenses collected for recipe rpi-bootfiles [license-file-missing]
# NOTE: Tasks Summary: Attempted 8546 tasks of which 8520 didn't need to be rerun and all succeeded.
# Summary: There was 1 WARNING message.
ビルド中にリソースを使い切れているか確認する
ビルド時間の長いYoctoでは、十分にリソースを使い切れているかがビルド時間に直結します。そのため、Activity Monitor等を利用して、すべてのリソースが予定通りに使用できているのを確認しておきましょう。今回ビルド環境にCore i7-6700とRAM32GB搭載していますのでCPUの使用率が高ければ十分と言えるでしょう。
Linuxディストリビューションをインストールする
ビルドしたLinuxディストリビューションをRaspberry Pi 5起動用のmicro-SDカードへ書き込みます。書き込みは下記の手順で実施してください。
# イメージをmicro-SDカードへインストールする
$ ls ./tmp/deploy/images/raspberrypi5/*.wic.bz2
# ./tmp/deploy/images/raspberrypi5/core-image-weston-raspberrypi5.rootfs-20241231035454.wic.bz2
# ./tmp/deploy/images/raspberrypi5/core-image-weston-raspberrypi5.rootfs.wic.bz2
$ sudo umount /dev/sdX1
$ sudo umount /dev/sdX2
$ sudo bmaptool copy ./tmp/deploy/images/raspberrypi5/core-image-weston-raspberrypi5.rootfs-20241231035454.wic.bz2 /dev/sdX
####
# micro-SDカードをRaspberry Pi 5に挿入して起動する
####
Linuxディストリビューションの動作を確認する
以下のスクリーンショットのように各機能の動作を確認することができます。
Python3 / Tensorflow Lite / ONNX runtime の動作確認
起動画面は以下の通りです。Networkが機能しており、Python3上でTensorflow LiteとONNX runtimeを呼び出すことに成功しています。
sudo / Docker / Networking の動作確認
Dockerdを起動して、docker run hello-world
に成功することも確認できます。
Python3 / OpenCV の動作確認
v4l2-ctl
コマンドによりWEBカメラのリストを確認し、Python3からOpenCVを呼び出し、WEBカメラの画像を撮影、imshow
+ waitKey
により表示させることも可能です。
Linuxディストリビューション向けSDKを準備する
続いて、アプリケーション開発用のSDKを準備していきましょう。
SDKを生成するためにlocal.confを修正する
local.conf
に TOOLCHAIN_TARGET_TASK
と TOOLCHAIN_HOST_TASK
を指定してSDKに含まれるリソースを選択します。TOOLCHAIN_TARGET_TASK
に指定するのはクロスプラットフォームビルドに必要となるターゲットに関するリソースであり、TOOLCHAIN_HOST_TASK
に指定するのはビルドに必要なホスト(開発環境)が必要とするツールです。
# 作業ディレクトリは前回記事と同様
$ pwd
# /home/shino/yocto-work-2024_v1/poky/aiot-build
# 設定ファイルを更新する
$ vi conf/local.conf
# 以下の行を追加する
# ...
# for development
TOOLCHAIN_TARGET_TASK:append = " kernel-dev kernel-devsrc"
TOOLCHAIN_HOST_TASK:append = " nativesdk-openssl-dev nativesdk-bison nativesdk-flex nativesdk-cmake"
# ...
TOOLCHAIN_HOST_TASKに指定可能なパッケージ
TOOLCHAIN_HOST_TASK
に指定できるパッケージは以下をご参照ください。
Bison
Flex
CMake
LinuxディストリビューションとそのSDKをビルドする
ソースコードと設定ファイルの準備ができたら bitbake
します。 bitbake [target] -c populate_sdk
を実行することによりSDKを生成することができます。
# Linuxディストリビューションをビルドする
$ bitbake core-image-weston
# ...
# NOTE: Executing Tasks
# NOTE: Tasks Summary: Attempted 7688 tasks of which 7677 didn't need to be rerun and all succeeded.
####
# イメージをmicro-SDカードへインストールする
$ ls ./tmp/deploy/images/raspberrypi5/*.wic.bz2
# ./tmp/deploy/images/raspberrypi5/core-image-weston-raspberrypi5.rootfs-20241231035454.wic.bz2
# ./tmp/deploy/images/raspberrypi5/core-image-weston-raspberrypi5.rootfs.wic.bz2
$ sudo umount /dev/sdX1
$ sudo umount /dev/sdX2
$ sudo bmaptool copy ./tmp/deploy/images/raspberrypi5/core-image-weston-raspberrypi5.rootfs-20241231035454.wic.bz2 /dev/sdX
####
# 開発ツールと依存するヘッダー等をビルドする
$ bitbake core-image-weston -c populate_sdk
# ...https://note.com/yamblue/n/n1741975068c1
# NOTE: Executing Tasks
# NOTE: Tasks Summary: Attempted 7949 tasks of which 7899 didn't need to be rerun and all succeeded.
# 生成された開発ツールを確認する
$ ls ./tmp/deploy/sdk/*.sh
# ./tmp/deploy/sdk/poky-glibc-x86_64-core-image-weston-cortexa76-raspberrypi5-toolchain-5.0.5.sh
yoctoで生成したLinuxディストリビューションに対応するアプリケーション開発用のSDKをインストールする
yoctoで生成したLinuxディストリビューションに対応するSDKを作成できましたので、早速インストールしてみましょう。 デフォルトのインストール先は /opt
です。 インストールした後、Linuxディストリビューションに含まれるrootfsに移動し、 カーネルモジュールのビルドに必要となる make modules_prepare
をLinuxカーネルに対して実行 します。
# インストール先ディレクトリのパーミッションを変更
$ sudo chmod 0777 /opt
# 生成されたツールチェインを確認する
$ pwd
# /home/shino/scarthgap-work-2024_v1/poky/aiot-build
$ cd ./tmp/deploy/sdk/
$ pwd
# /home/shino/scarthgap-work-2024_v1/poky/aiot-build/tmp/deploy/sdk
$ ls *.sh
# poky-glibc-x86_64-core-image-weston-cortexa76-raspberrypi5-toolchain-5.0.5.sh
# ツールチェインをインストールする
$ ./poky-glibc-x86_64-core-image-weston-cortexa76-raspberrypi5-toolchain-5.0.5.sh
# Poky (Yocto Project Reference Distro) SDK installer version 5.0.5
# =================================================================
# Enter target directory for SDK (default: /opt/poky/5.0.5):
# You are about to install the SDK to "/opt/poky/5.0.5". Proceed [Y/n]?
# Extracting SDK...done
# Setting it up...done
# SDK has been successfully set up and is ready to be used.
# Each time you wish to use the SDK in a new shell session, you need to source the environment setup script e.g.
# $ . /opt/poky/5.0.5/environment-setup-cortexa76-poky-linux
# インストールされたツールチェインを確認する
$ ls /opt/poky/5.0.5
# environment-setup-cortexa76-poky-linux
# sysroots
# site-config-cortexa76-poky-linux
# version-cortexa76-poky-linux
# ツールチェインを利用するために必要な環境変数を設定する
$ cd /opt/poky/5.0.5
$ . ./environment-setup-cortexa76-poky-linux
# ツールチェインに含まれるカーネル開発に必要なオブジェクトをビルドする
$ cd ./sysroots/cortexa76-poky-linux/
$ pwd
# /opt/poky/5.0.5/sysroots/cortexa76-poky-linux
$ cd ./usr/src/kernel
$ make modules_prepare
# SYNC include/config/auto.conf.cmd
# HOSTCC scripts/basic/fixdep
# HOSTCC scripts/kconfig/conf.o
# HOSTCC scripts/kconfig/confdata.o
# HOSTCC scripts/kconfig/expr.o
# LEX scripts/kconfig/lexer.lex.c
# YACC scripts/kconfig/parser.tab.[ch]
# HOSTCC scripts/kconfig/lexer.lex.o
# HOSTCC scripts/kconfig/menu.o
# HOSTCC scripts/kconfig/parser.tab.o
# HOSTCC scripts/kconfig/preprocess.o
# ...
# VDSOSYM include/generated/vdso-offsets.h
# OBJCOPY arch/arm64/kernel/vdso/vdso.so
# LDS scripts/module.lds
$
カーネルモジュールをビルドしてみる
最後に、作成したSDKを使ってカーネルモジュール hello.ko
をビルドしてみましょう。Yocto向けのカーネルモジュールやアプリケーションのビルド、レシピの作成方法は、以下の 「meta-skelton」 が参考になります。
以下の手順でx86_64ビルド環境上でターゲット(Raspberry Pi 5)向けのバイナリを生成することができます。
# 作業用ディレクトリを作成する
$ mkdir ~/scarthgap-sample-mycode_v1
$ cd ~/scarthgap-sample-mycode_v1
# カーネルモジュールのサンプルソースコードを入手する
$ mkdir ./kernel_module_sample
$ cd ./kernel_module_sample
$ cp ~/scarthgap-work-2024_v1/poky/meta-skeleton/recipes-kernel/hello-mod/files/* ./
# ビルド用Makefileの内容を確認
$ cat Makefile
# obj-m := hello.o
#
# SRC := $(shell pwd)
#
# all:
# $(MAKE) -C $(KERNEL_SRC) M=$(SRC)
#
# modules_install:
# $(MAKE) -C $(KERNEL_SRC) M=$(SRC) modules_install
#
# clean:
# rm -f *.o *~ core .depend .*.cmd *.ko *.mod.c
# rm -f Module.markers Module.symvers modules.order
# rm -rf .tmp_versions Modules.symvers
# 開発ツールの環境変数を設定する
$ . /opt/poky/5.0.5/environment-setup-cortexa76-poky-linux
# 開発環境に設定されている環境変数を確認する
$ env
# PKG_CONFIG_PATH=/opt/poky/5.0.5/sysroots/cortexa76-poky-linux/usr/lib/pkgconfig:/opt/poky/5.0.5/sysroots/cortexa76-poky-linux/usr/share/pkgconfig
# SDKTARGETSYSROOT=/opt/poky/5.0.5/sysroots/cortexa76-poky-linux
# CPP=aarch64-poky-linux-gcc -E -mcpu=cortex-a76+crypto -mbranch-protection=standard -fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security --sysroot=/opt/poky/5.0.5/sysroots/cortexa76-poky-linux
# CXX=aarch64-poky-linux-g++ -mcpu=cortex-a76+crypto -mbranch-protection=standard -fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security --sysroot=/opt/poky/5.0.5/sysroots/cortexa76-poky-linux
# KCFLAGS=--sysroot=/opt/poky/5.0.5/sysroots/cortexa76-poky-linux
# OECORE_TARGET_SYSROOT=/opt/poky/5.0.5/sysroots/cortexa76-poky-linux
# LD=aarch64-poky-linux-ld --sysroot=/opt/poky/5.0.5/sysroots/cortexa76-poky-linux
# PKG_CONFIG_SYSROOT_DIR=/opt/poky/5.0.5/sysroots/cortexa76-poky-linux
# CC=aarch64-poky-linux-gcc -mcpu=cortex-a76+crypto -mbranch-protection=standard -fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security --sysroot=/opt/poky/5.0.5/sysroots/cortexa76-poky-linux
# CONFIGURE_FLAGS=--target=aarch64-poky-linux --host=aarch64-poky-linux --build=x86_64-linux --with-libtool-sysroot=/opt/poky/5.0.5/sysroots/cortexa76-poky-linux
# ビルドする
$ export KERNEL_SRC=$SDKTARGETSYSROOT/lib/modules/6.6.22-v8-16k/build
$ make clean
# rm -f *.o *~ core .depend .*.cmd *.ko *.mod.c
# rm -f Module.markers Module.symvers modules.order
# rm -rf .tmp_versions Modules.symvers
$ make all
# make -C /opt/poky/5.0.5/sysroots/cortexa76-poky-linux/lib/modules/6.6.22-v8-16k/build M=/home/shino/scarthgap-sample-mycode_v1/kernel_module_sample
# make[1]: Entering directory '/opt/poky/5.0.5/sysroots/cortexa76-poky-linux/usr/lib/modules/6.6.22-v8-16k/build'
# CC [M] /home/shino/scarthgap-sample-mycode_v1/kernel_module_sample/hello.o
# MODPOST /home/shino/scarthgap-sample-mycode_v1/kernel_module_sample/Module.symvers
# CC [M] /home/shino/scarthgap-sample-mycode_v1/kernel_module_sample/hello.mod.o
# LD [M] /home/shino/scarthgap-sample-mycode_v1/kernel_module_sample/hello.ko
# make[1]: Leaving directory '/opt/poky/5.0.5/sysroots/cortexa76-poky-linux/usr/lib/modules/6.6.22-v8-16k/build'
# ビルド成果物を確認する
$ ls .
# COPYING hello.ko hello.mod.c hello.o modules.order
# hello.c hello.mod hello.mod.o Makefile Module.symvers
# aarch64向けのバイナリを生成できている
$ file hello.ko
# hello.ko: ELF 64-bit LSB relocatable,
# ARM aarch64, version 1 (SYSV),
# BuildID[sha1]=f2319761c5dca0baa12bfbc7c60f3043d996fbb5,
# not stripped
以上が、Yoctoを利用する基本手順となります。
是非開発にご活用ください!ありがとうございました!