みつきんのメモ

組み込みエンジニアです。Interface誌で「My オリジナルLinuxの作り方」連載中

bitbakeで作成したパッケージをapt(ただしデバッグ用途に限る)

はじめに

前回dnfについて書いたが、今回はaptについて紹介する。

YoctoProjectではレシピからパッケージを作成しそれらをルートFSにインストールすることでディストリビューションを構築している。 IMAGE_FEATURESにpackage-managementが含まれている場合、パッケージデータベースがルートFSに含まれるようになるため、 rpmやdpkgなどのパッケージ管理ツールでパッケージ情報を参照できる。

bitbakeで作成したパッケージファイルを実機にコピーし、rpm -idpkg -iなどでインストールすることは可能だが、 dnfやaptなどのツールでネットワーク越しパッケージをインストールできるようにするためには、パッケージシステムのリポジトリを作成し、 そのデータをHTTPなどのサーバを経由してアクセス可能にする必要がある。

ルートFSをいちいち作り直さなくても良くなるため、dnfやaptが使えると便利ではあるが、リポジトリを作成するのが手間ではある。 しかし実はbitbakeではパッケージのインデックスを作成し、リポジトリの作成を支援する仕組みが存在する。

ここでは署名検証や署名自体のプロセスをスキップし、デバッグ用途に限ってのみ使用できるリポジトリの運用方法を紹介する。

dnfやipkを使用する場合と比較してBitBake + aptはなぜか情報が少ないため、実機を使用した少しだけ具体的な手順を示す。

ターゲットボードはラズベリーパイ4、使用するYoctoProjectのバージョンはkirkstone(4.0)とする。

環境構築

作業環境

$ mkdir -p ~/yocto/rpi-kirkstone
$ cd ~/yocto/rpi-kirkstone

pokyの取得

$ git clone -b kirkstone git://git.yoctoproject.org/poky.git

環境変数の設定

$ source poky/oe-init-build-env

レイヤの取得

$ bitbake-layers layerindex-fetch meta-raspberrypi

local.confを編集

conf/local.confに下記の部分を追加

MACHINE = "raspberrypi4-64"
DL_DIR = "${TOPDIR}/../downloads"
PACKAGE_CLASSES = "package_deb"

# enable uart
ENABLE_UART = "1"

PACKAGE_CLASSESにpackage_debを設定し、使用するパッケージ管理システムをdebパッケージに変更する。

aptの下準備

下準備として下記のことを行う。

  1. ルートFSのサイズ変更
  2. package-managementの有効化
  3. PACKAGE_FEED_URISの設定

まず、通常ルートFSのパーティションサイズは必要最小限で作成されるため、 パッケージ追加に備えて少し余裕をもたせる。今回は2GiBとする。

次に、パッケージデータベースを含めるためIMAGE_FEATURESを修正する。

最後に、PACKAGE_FEED_URISを指定してリポジトリのURLをルートFSの含める。 この変数を設定することで/etc/apt/sources.listというファイルが追加され、 ターゲットから参照するリポジトリを指定することができる。

そのためにはlocal.confに下記を追加する。

IMAGE_ROOTFS_EXTRA_SPACE = "2097152"
EXTRA_IMAGE_FEATURES += "package-management" 

PACKAGE_FEED_URIS  = "http://<IPアドレス>:8000"

PACKAGE_FEED_URISにビルドホストのIPアドレスを指定する。

ビルドと書き込み

イメージをビルドし、マイクロSDに書き込む。

$ bitbake core-image-base
$ bmaptool copy ./tmp/deploy/images/raspberrypi4-64/core-image-base-raspberrypi4-64.wic.bz2 /dev/sdX

/dev/sdXは環境に応じて適宜読み替える。

このマイクロSDでラズベリーパイ4を起動する。

パッケージリポジトリを作成する

下記を実行しターゲットから参照可能なリポジトリを作成する。 HTTPサーバはpython3のhttp.serverモジュールを使用する。

$ bitbake package-index
$ cd ./tmp/deploy/deb
$ python3 -m http.server 8000

パッケージ追加の例

例としてnanoパッケージをビルドし、ターゲットに追加することを考える。

ビルドホスト

  1. bitbakeでnanoパッケージをビルドする
  2. bitbake package-indexでリポジトリを更新する

nanoはmeta-oeに含まれているため、meta-oeを追加する。

$ bitbake-layers layerindex-fetch meta-oe
$ bitbake nano
$ bitbake package-index

ターゲット

  1. ターゲットの時刻を補正する
  2. apt updateでターゲットのデータベースを更新する
  3. apt install nanoでインストールする
# date -s date -s '2022-11-29 04:58'
# apt update
# apt install nano

ターゲットの時刻が大幅にずれているとaptコマンドが失敗するため時刻を補正する。 dateコマンドは実行時点の実際の時刻を設定すること。

古いバージョンのYoctoProjectの場合

kirkstoneではPACKAGE_FEED_URISによって生成される/etc/apt/sources.listリポジトリ設定に [trusted=yes]が入るようになったため、署名されていないリポジトリでも問題なくapt updateができるが、 古いバージョンのYoctoProjectでは、下記のようにする必要がある。

# apt update --allow-insecure-repositories

まとめ

実機を使用してaptコマンドを使用する場合の手順をまとめた。

前回の通り、bitbakeしながらルートFSを調整していくタイミングでは 毎回実機上のルートFSを書き直す必要がなくなるので便利。

PACKAGE_FEED_URISをちゃんと書いておくと、ターゲット側でいちいちリポジトリ情報を設定しないくて済むのも便利。 署名検証のプロセスを省略しているのでリリース環境に持っていくにはもう一手間以上必要。

bitbakeで作成したパッケージをdnf(ただしデバッグ用途に限る)

はじめに

ただしイケメンに限る」ていで書き始める。

YoctoProjectではレシピからパッケージを作成しそれらをルートFSにインストールすることでディストリビューションを構築している。 IMAGE_FEATURESにpackage-managementが含まれている場合、パッケージデータベースがルートFSに含まれるようになるため、 rpmやdpkgなどのパッケージ管理ツールでパッケージ情報を参照できる。

bitbakeで作成したパッケージファイルを実機にコピーし、rpm -idpkg -iなどでインストールすることは可能だが、 dnfやaptなどのツールでネットワーク越しパッケージをインストールできるようにするためには、パッケージシステムのリポジトリを作成し、 そのデータをHTTPなどのサーバを経由してアクセス可能にする必要がある。

ルートFSをいちいち作り直さなくても良くなるため、dnfやaptが使えると便利ではあるが、リポジトリを作成するのが手間ではある。 しかし実はbitbakeではパッケージのインデックスを作成し、リポジトリの作成を支援する仕組みが存在する。

ここでは署名検証や署名自体のプロセスをスキップし、デバッグ用途に限ってのみ使用できるリポジトリの運用方法を紹介する。

下準備

下準備として下記のことを行う。

  1. ルートFSのサイズ変更
  2. package-managementの有効化
  3. PACKAGE_FEED_URISの設定

まず、通常ルートFSのパーティションサイズは必要最小限で作成されるため、 パッケージ追加に備えて少し余裕をもたせる。今回は2GiBとする。

次に、パッケージデータベースを含めるためIMAGE_FEATURESを修正する。

最後に、PACKAGE_FEED_URISを指定してリポジトリのURLをルートFSの含める。 この変数を設定することで/etc/yum.repos.d/oe-remote-repo.repoというファイルが追加され、 ターゲットから参照するリポジトリを指定することができる。

そのためにはlocal.confに下記を追加する。

IMAGE_ROOTFS_EXTRA_SPACE = "2097152"
EXTRA_IMAGE_FEATURES += "package-management" 

PACKAGE_FEED_URIS  = "http://192.168.7.1:8000"

192.168.7.1はrunqemuで実行する場合のホストPCのIPアドレスであるため、 実機を使用する場合は、実機から参照可能なビルドホストのIPアドレスを指定する。

このイメージでターゲットを起動する。

パッケージリポジトリを作成する

下記を実行しターゲットから参照可能なリポジトリを作成する。 HTTPサーバはpython3のhttp.serverモジュールを使用する。

$ bitbake package-index
$ cd ./tmp/deploy/rpm
$ python3 -m http.server 8000

パッケージ追加の例

例としてnanoパッケージをビルドし、ターゲットに追加することを考える。

ビルドホスト

  1. bitbakeでnanoパッケージをビルドする
  2. bitbake package-indexでリポジトリを更新する

nanoはmeta-oeに含まれているため、meta-oeを追加する。

$ bitbake-layers layerindex-fetch meta-oe
$ bitbake nano
$ bitbake package-index

ターゲット

  1. dnf makecacheでターゲットのデータベースを更新する
  2. dnf install nanoでインストールする
# dnf makecache
# dnf install nano

まとめ

bitbakeしながらルートFSを調整していくタイミングでは 毎回実機上のルートFSを書き直す必要がなくなるので便利。

PACKAGE_FEED_URISをちゃんと書いておくと、ターゲット側でいちいちリポジトリ情報を設定しないくて済むのも便利。 署名検証のプロセスを省略しているのでリリース環境に持っていくにはもう一手間以上必要。

YoctoProject 4.1(langdale)をためす

はじめに

2022/10/24付でYoctoProjct 4.1 langdaleがリリースされていたので試す。

ターゲットはラズベリーパイ4

環境を構築する

作業環境

$ mkdir -p ~/yocto/rpi-langdale
$ cd ~/yocto/rpi-langdale

pokyの取得

$ git clone -b langdale git://git.yoctoproject.org/poky.git

環境変数の設定

$ source poky/oe-init-build-env

meta-raspberrypiの取得

執筆時点(2022/11/08)ではlangdaleブランチはlayerindexに登録されていない様子。 一旦masterブランチを取得して切り替える。

$ bitbake-layers layerindex-fetch meta-raspberrypi -b master
$ pushd ../poky/meta-raspberrypi
$ git switch -c langdale origin/langdale
$ cd ../meta-openembedded
$ git switch -c langdale origin/langdale
$ popd

local.confを編集

conf/local.confに下記の部分を追加

MACHINE = "raspberrypi4-64"
DL_DIR = "${TOPDIR}/../downloads"

# enable uart
ENABLE_UART = "1"

# systemd
DISTRO_FEATURES:append = " systemd pam"
VIRTUAL-RUNTIME_init_manager = "systemd"
DISTRO_FEATURES_BACKFILL_CONSIDERED = "sysvinit"
VIRTUAL-RUNTIME_initscripts = ""

# connman
IMAGE_INSTALL:append = " connman \
               connman-client \
"

bitbake実行

$ bitbake core-image-base

エラー発生

下記のようなエラーが発生した。

ERROR: Nothing RPROVIDES 'linux-firmware-rpidistro-bcm43455' (but /home/mickey/yocto/rpi-langdale/poky/meta/recipes-core/packagegroups/packagegroup-base.bb RDEPENDS on or otherwise requires it)
linux-firmware-rpidistro RPROVIDES linux-firmware-rpidistro-bcm43455 but was skipped: because it has a restricted license 'synaptics-killswitch'. Which is not listed in LICENSE_FLAGS_ACCEPTED

Upgrading to Yocto Langdaleに情報がある。

The linux-firmware-rpidistro package provided by the meta-raspberrypi layer has components licensed under more restrictive terms. This license must be explicitly enabled. Read more at https://meta-raspberrypi.readthedocs.io/en/latest/ipcompliance.html.

リンクを辿ると、WiFi/BT firmwareのBLOBのライセンスである「Synapticsライセンス」が法的リスクをはらんでいるっぽいので、 取り扱いを厳密にするということらしい。このリスクを受け入れる場合は、local.confかdistro.confに下記を追加すればビルド可能になるとのこと。

LICENSE_FLAGS_ACCEPTED = "synaptics-killswitch"

関連パッケージを確認

tmp/deploy/licenses/core-image-base-raspberrypi4-64/license.manifest でSynapticsライセンスが適用されるパッケージを確認する。

PACKAGE NAME: linux-firmware-rpidistro-bcm43456
PACKAGE VERSION: 20210315-3+rpt7
RECIPE NAME: linux-firmware-rpidistro
LICENSE: Synaptics-rpidistro

bcm43456のファームウェアだということがわかる。

書き込み

./tmp/deploy/images/raspberrypi4-64/core-image-base-raspberrypi4-64.wic.bz2が書き込み用イメージとなる。

これをbmaptoolでマイクロSDカードに書き込む。

$ sudo bmaptool copy ./tmp/deploy/images/raspberrypi4-64/core-image-base-raspberrypi4-64.wic.bz2 /dev/sdX

/dev/sdXは適宜読み替え。

起動確認

マイクロSDカードをラズパイ4に挿入し電源を投入する。

root@raspberrypi4-64:~# cat /etc/os-release
ID=poky
NAME="Poky (Yocto Project Reference Distro)"
VERSION="4.1 (langdale)"
VERSION_ID=4.1
PRETTY_NAME="Poky (Yocto Project Reference Distro) 4.1 (langdale)"
DISTRO_CODENAME="langdale"

まとめ

langdaleをためした。

pokyの方は特に躓く点はなかったが、 meta-raspberrypiのlangdaleブランチはlayerindexにまだ登録されていないので、 若干のワークアラウンドが必要。

また、少なくともラズベリーパイ4のWiFi/BTのファームウェアのライセンスにには法的リスクが報告されているため、 使用するためにはそのリスクを受け入れたという表明が必要になっている。

おそらく個人使用時にはあまり関係ないと思われるが要注意。

YoctoProject コンソールでrunqemu

はじめに

YoctoProjectではqemuのイメージをビルドした場合、runqemuコマンドで実行することができる。 基本的には、ウィンドウが生成されその中に画面が表示される。 sshなどで接続したりして、qemuの画面表示をコンソールに出力したい場合などの方法を調査した。

runqemuのオプション

runqemuに指定できるオプション。

$ runqemu -h

Usage: you can run this script with any valid combination
of the following environment variables (in any order):
  KERNEL - the kernel image file to use
  BIOS - the bios image file to use
  ROOTFS - the rootfs image file or nfsroot directory to use
  DEVICE_TREE - the device tree blob to use
  MACHINE - the machine name (optional, autodetected from KERNEL filename if unspecified)
  Simplified QEMU command-line options can be passed with:
    nographic - disable video console
    novga - Disable VGA emulation completely
    sdl - choose the SDL UI frontend
    gtk - choose the Gtk UI frontend
    gl - enable virgl-based GL acceleration (also needs gtk or sdl options)
    gl-es - enable virgl-based GL acceleration, using OpenGL ES (also needs gtk or sdl options)
    egl-headless - enable headless EGL output; use vnc (via publicvnc option) or spice to see it
    (hint: if /dev/dri/renderD* is absent due to lack of suitable GPU, 'modprobe vgem' will create
    one suitable for mesa llvmpipe software renderer)
    serial - enable a serial console on /dev/ttyS0
    serialstdio - enable a serial console on the console (regardless of graphics mode)
    slirp - enable user networking, no root privilege is required
    snapshot - don't write changes back to images
    kvm - enable KVM when running x86/x86_64 (VT-capable CPU required)
    kvm-vhost - enable KVM with vhost when running x86/x86_64 (VT-capable CPU required)
    publicvnc - enable a VNC server open to all hosts
    audio - enable audio
    [*/]ovmf* - OVMF firmware file or base name for booting with UEFI
  tcpserial=<port> - specify tcp serial port number
  qemuparams=<xyz> - specify custom parameters to QEMU
  bootparams=<xyz> - specify custom kernel parameters during boot
  help, -h, --help: print this text
  -d, --debug: Enable debug output
  -q, --quiet: Hide most output except error messages

最初は「Simplified QEMU command-line options can be passed with:」のあたりを読み飛ばして、 qemuparamsqemuのパラメータをちまちま渡していたが、実行されるqemuコマンドラインを見ると、 同じオプションがすでに設定されており、qemuparamsで渡したパラメータが無効化されていることに気づいた。

nographicとserialstdio

nographic

ウィンドウによる画面表示が全く不要な場合は、下記のようにnographicを指定する。

$ runqemu nographic

画面表示用のウィンドウが生成されずに、シリアルコンソール出力がターミナル上に出力される。

serialstdio

シリアル出力をstdioに流すための設定であるserialstdioを指定した場合は、画面表示用のウィンドウが生成された上で、 シリアルコンソール出力がターミナル上に出力される。

$ runqemu serialstdio

まとめ

ssh接続している環境でrunqemuしたい場合はnographicが便利。 実機に左右されないYoctoProjectの機能を試したい場合はこれで十分行ける。

yocto raspberrypi4でNFSブート

はじめに

ラズベリーパイシリーズで、ルートファイルシステムNFSでマウントする。

以前にyocto raspberrypi3でNFSブートの記事を書いたが、 最近のmeta-raspberrypiでは作法が変わっているので焼き直し。

本稿で説明するのはyoctoの作法ではなくmeta-raspberrypiの作法なので、他のSoC向けのBSPレイヤでは適用できないので注意。

ベース環境の取得

$ mkdir -p ~/yocto/rpi4-nfs
$ cd ~/yocto/rpi4-nfs
$ git clone git://git.yoctoproject.org/poky.git -b kirkstone

oe-init-build-envの読み込み

下記を実行する。

$ cd ~/yocto/rpi4-nfs
$ source poky/oe-init-build-env

meta-raspberrypiをビルド対象に追加

下記を実行する。

$ bitbake-layers layerindex-fetch meta-raspberrypi

local.confの修正

以前とは異なり、最近のmeta-raspberrypiではCMDLINE変数を直接編集することはできない。 rpi-cmdline.bbのCMDLINE変数は下記のように定義されており、必要に応じて各変数の内容を上書きする。

CMDLINE = " \
    ${CMDLINE_ISOL_CPUS} \
    ${CMDLINE_DWC_OTG} \
    ${CMDLINE_SERIAL} \
    ${CMDLINE_ROOTFS} \
    ${CMDLINE_CMA} \
    ${CMDLINE_KGDB} \
    ${CMDLINE_LOGO} \
    ${CMDLINE_PITFT} \
    ${CMDLINE_DEBUG} \
    ${CMDLINE_RNDIS} \
    "

nfsブートに関連する変数はCMDLINE_ROOTFSとなるため、これをnfsブート用に上書きするために conf/local.confに下記を追加する。

MACHINE = "raspberrypi4"

CMDLINE_ROOTFS = "ip=dhcp root=/dev/nfs nfsroot=192.168.1.1:/srv/exports,vers=3,tcp rw rootwait"

動作確認

bitbakeの実行

$ bitbake core-image-base

書き込み

bmaptoolで書き込む。

$ sudo bmaptool copy core-image-base-raspberrypi4.wic.bz2 /dev/sdX

/dev/sdXは環境に応じて適宜読み替える。

nfsサーバ

インストール

$ sudo apt-get install -y nfs-kernel-server

公開ディレクトリの設定

/etc/exportsに下記の内容を追加する。

/exports 192.168.1.0/24(rw,sync,no_root_squash,no_subtree_check)

NFSデーモンの再起動

変更した設定を読み込むためにNFSデーモンを再起動

$ sudo systemctl restart nfs-kernel-server

ルートFSの展開

bitbakeで生成されたルートFSのイメージを/exportsに展開する。

sudo tar -I pbzip2 -xf ./build/tmp/deploy/images/raspberrypi4/core-image-base-raspberrypi4.tar.bz2 -C /srv/exports/

まとめ

4年も経つといろいろ変わってる。

kasを便利に使う

はじめに

bitbakeをラップして、操作を簡略化するためのツールとして以前にも何回か取り上げたkas

筆者の印象としては下記のようなものだった。

kasコンフィグはyaml形式のテキストであるため、比較的簡単に書ける。 複数のgitリポジトリを管理するためにrepoツールなどもあるが、 bitbakeに特化した作業をするのであればkasは便利かもしれない。 ただ、kasはあくまでも完成したレイヤを利用する人が使うには便利だが、 レイヤを開発する段階ではbitbakeを直接使用したほうが便利だと思う。

当時は、ディレクトリツリーにも自由度がないし「完成した構成で一発でビルドしたい場合だけしか使えないんだろう」と思っていた。

バージョンが上がったからなのか、当時からできたのか判らないが、実は結構ディレクトリツリーを自由に構成できるということがわかり、 ビルド環境の雛形を作成するために使用する場合でもbitbake-layers layerindex-fetchよりも便利じゃないか?と発見した。

ディレクトリ構成

好きな構成

筆者はもともと下記のような構成を好んでいた。

.
├── build
└── layers
    ├── meta-openembedded
    ├── meta-raspberrypi
    └── poky

kasのデフォルト

しかしkasのデフォルトでは下記のような構成になる。

.
├── build
├── meta-openembedded
├── meta-raspberrypi
└── poky

このような構成ではレシピに対してgrepしたいときにbuildディレクトリをいちいちexcludeする必要があり、開発時はなり鬱陶しい。

layerindex-fetch

最近良く使っているbitbake-layers layerindex-fetchの場合は下記のようになる。

.
├── build
└── poky
    ├── meta-openembedded
    └── meta-raspberrypi

これであれば、レシピに対してのgrepをpoky以下に限定することができるため及第点。

実のところ

実はkasを使用していても「好きな構成」のツリーを作れることがわかった。

kas再考

kasはYAMLでビルド時の構成を設定する。 YAMLはincludeすることができるため、local.confの部分とレイヤ構成の部分を分けて書くことができる。

例えば一般的なlocal.confの内容はほとんど一緒なので、それをkas-local.yamlとかで作成しておき、 作りたいターゲットマシン向けのレイヤ構成やマシン名などを定義した別のYAMLファイルからincludeすることができる。

以下、とりあえずやってみる。

YAMLファイル作成

kas-local.yaml

一般的なlocal.confを生成するためのYAMLを作成する。

header:
  version: 12

local_conf_header:
  stanard: |
    DISTRO ?= "poky"
    PACKAGE_CLASSES ?= "package_rpm"
    EXTRA_IMAGE_FEATURES ?= "debug-tweaks"
    USER_CLASSES ?= "buildstats"
    PATCHRESOLVE = "noop"

    BB_DISKMON_DIRS ??= "\
    STOPTASKS,${TMPDIR},1G,100K \
    STOPTASKS,${DL_DIR},1G,100K \
    STOPTASKS,${SSTATE_DIR},1G,100K \
    STOPTASKS,/tmp,100M,100K \
    HALT,${TMPDIR},100M,1K \
    HALT,${DL_DIR},100M,1K \
    HALT,${SSTATE_DIR},100M,1K \
    HALT,/tmp,10M,1K"
    PACKAGECONFIG:append:pn-qemu-system-native = " sdl"
    CONF_VERSION = "2"

初回に自動生成されるlocal.confの内容のうちMACHINEDISTROの設定とコメント行を削除したものになる。

kas-rpi4-64.yaml

「好きな構成」のディレクトリツリーを構築しつつ、raspberrypi4の64ビット向けのビルドを行うためのYAMLを作成する。

header:
  version: 12
  includes:
    - kas-local.yaml

machine: raspberrypi4-64
distro: poky
target:
  - core-image-base

repos:
  poky:
    url: https://git.yoctoproject.org/git/poky 
    refspec: kirkstone
    path: layers/poky
    layers:
      meta:
      meta-poky:
      meta-yocto-bsp:

  meta-raspberrypi:
    url: git://git.yoctoproject.org/meta-raspberrypi
    refspec: kirkstone
    path: layers/meta-raspberrypi

  meta-openembedded:
    url: http://git.openembedded.org/meta-openembedded
    refspec: kirkstone
    path: layers/meta-openembedded
    layers:
      meta-oe:

レイヤの取得とlocal.conf生成

下記のコマンドを実行してみる。

kas checkout ./kas-rpi4-64.yaml

すると、次のことが行われる。

  • レイヤのダウンロード
  • bblayers.confの生成
  • local.confの生成

すでにダウンロード済みのレイヤはダウンロードしない。

このコマンドを実行した結果次のようなディレクトリツリーが構築される。

.
├── build
│   └── conf
└── layers
    ├── meta-openembedded
    ├── meta-raspberrypi
    └── poky

「好きな構成」のツリーと同じとなっている。

キモはreposノードの配下に記述されたpathにある。

urlが指定されている場合はリモートリポジトリとして認識され、 デフォルトでは実行時のカレントディレクトリにデータがダウンロードされる。 pathが指定されている場合は、その位置にダウンロードされるようになる。 また、urlがなくpathのみが存在する場合はローカルリポジトリとして認識され、 指定された位置にあるデータをレイヤとして取り扱う。

まとめ

ここまでで、いつものbitbake実行環境と同様の環境が構築できた。 bitbake-layers layerindex-fetchは各リポジトリのURLを知らなくても良いが、 OpenEmbedded Layer Indexに登録されているものしか適用できない。

kasの場合、逆説的にそれぞれのリポジトリのURLを知っていればOpenEmbedded Layer Indexに登録されていないものについても自動化することができる。

以前は「完成した環境を簡単にビルドするためだけに使うツール」という認識だったが、 実のところ「ビルド環境の土台を作成するツール」としてもかなり便利に使えるのではないだろうか。

Yocto イメージレシピの調査

はじめに

bitbakeでビルド可能なイメージについて調査する。

pokyのmetaレイヤに含まれるものは下記のようになっている。

イメージのレシピ ディレクト
build-appliance-image_15.0.0.bb recipes-core/images
core-image-base.bb recipes-core/images
core-image-minimal-dev.bb recipes-core/images
core-image-minimal-initramfs.bb recipes-core/images
core-image-minimal-mtdutils.bb recipes-core/images
core-image-minimal.bb recipes-core/images
core-image-ptest-all.bb recipes-core/images
core-image-ptest-fast.bb recipes-core/images
core-image-tiny-initramfs.bb recipes-core/images
core-image-sato-dev.bb recipes-sato/images
core-image-sato-sdk.bb recipes-sato/images
core-image-sato.bb recipes-sato/images
core-image-rt-sdk.bb recipes-rt/images
core-image-rt.bb recipes-rt/images
core-image-weston-sdk.bb recipes-graphics/images
core-image-weston.bb recipes-graphics/images
core-image-x11.bb recipes-graphics/images
core-image-full-cmdline.bb recipes-extended/images
core-image-kernel-dev.bb recipes-extended/images
core-image-testcontroller-initramfs.bb recipes-extended/images
core-image-testcontroller.bb recipes-extended/images

この内、いくつかをピックアップして調査する。

レシピの内容を確認

これらのレシピは下記のような変数に影響受けることが多い。

  • MACHINE_FEATURES
  • DISTRO_FEATURES
  • IMAGE_FEATURES

ここではこれらをまとめてFEATURES変数と呼ぶ。

core-image-minimal

最小構成のイメージ。ターゲットのブートに最低限必要なパッケージを含んでいる。

具体的には下記のように設定されている。

IMAGE_INSTALL = "packagegroup-core-boot ${CORE_IMAGE_EXTRA_INSTALL}"

packagegroup-core-bootが最低限ブートに必要なパッケージを含んでいる。 実際のpackagegroup-core-bootの中身は、bitbake実行時の変数の値によって異なるため単純に一覧にすることはできない。

CORE_IMAGE_EXTRA_INSTALLは任意にイメージに追加したいパッケージの変数となる。この変数はlocal.confでのみ記述することができる。 パッケージ追加にはよくlocal.confにIMAGE_INSTALL:appendを記載する例を見かけるが、CORE_IMAGE_EXTRA_INSTALLに設定された値も最終的にIMAGE_INSTALL変数に代入されるため、 結果的には同じような働きをする。

core-image-minimal-dev

core-image-minimalの内容に、下記の内容が追加される。

IMAGE_FEATURES += "dev-pkgs"

dev-pkgsについては下記のように説明されている。

# - dbg-pkgs            - debug symbol packages for all installed packages in the rootfs

core-image-minimal-initramfs

core-image-minimalとは全く異なる。パッケージのインストールに関わる部分は下記のようになっている。

INITRAMFS_SCRIPTS ?= "\
                      initramfs-framework-base \
                      initramfs-module-setup-live \
                      initramfs-module-udev \
                      initramfs-module-install \
                      initramfs-module-install-efi \
                     "

PACKAGE_INSTALL = "${INITRAMFS_SCRIPTS} ${VIRTUAL-RUNTIME_base-utils} udev base-passwd ${ROOTFS_BOOTSTRAP_INSTALL}"

このイメージはIMAGE_INSTALL変数の影響を受けない。

core-image-minimal-mtdutils

core-image-minimalに下記が追加される。

IMAGE_INSTALL += "mtd-utils"

IMAGE_INSTALLに対して+=を使用しているが、local.confではこの記述は許容されていないので注意が必要。

Using IMAGE_INSTALL with the += BitBake operator within the /conf/local.conf file or from within an image recipe is not recommended. Use of this operator in these ways can cause ordering issues. Since core-image.bbclass sets IMAGE_INSTALL to a default value using the ?= operator, using a += operation against IMAGE_INSTALL results in unexpected behavior when used within conf/local.conf. Furthermore, the same operation from within an image recipe may or may not succeed depending on the specific situation. In both these cases, the behavior is contrary to how most users expect the += operator to work.

core-image-full-cmdline

内容としてはcore-image-minimal + packagegroup-core-full-cmdline + αという感じだが、レシピの作りとしてはcore-image-minimalをベースにはしていない。 パッケージのインストールに関わる部分は下記のようになっている。

IMAGE_FEATURES += "splash ssh-server-openssh"

IMAGE_INSTALL = "\
    packagegroup-core-boot \
    packagegroup-core-full-cmdline \
    ${CORE_IMAGE_EXTRA_INSTALL} \
    "

core-image-base

コンソール主体のイメージのレシピの中で実はこれが分かりづらい。レシピ全体を示す。

SUMMARY = "A console-only image that fully supports the target device \
hardware."

IMAGE_FEATURES += "splash"

LICENSE = "MIT"

inherit core-image

このイメージはcore-image.bbclassがインストールしようとするものを全てインストールするようなものになっている。 MACHINE_FEATURESなどのFEATURES変数で設定した値が全て反映されるため、fully supports the target device hardware.という位置づけになっている。

逆にcore-image-minimalもcore-image-full-cmdlineもIMAGE_INSTALL変数に=で値を設定することによって、core-image.bbclassでインストールされるパッケージに対して制限をかけている。

core-image-x11

core-image-baseにx11-base関連のFEATURESが追加されている。

IMAGE_FEATURES += "splash package-management x11-base"

REQUIRED_DISTRO_FEATURES = "x11"

DISTRO_FEATURESで"x11"を要求している。

core-image-weston

core-image-baseにweston関連のFEATUREが追加されている。

IMAGE_FEATURES += "splash package-management ssh-server-dropbear hwcodecs weston"

CORE_IMAGE_BASE_INSTALL += "gtk+3-demo"
CORE_IMAGE_BASE_INSTALL += "${@bb.utils.contains('DISTRO_FEATURES', 'x11', 'weston-xwayland matchbox-terminal', '', d)}"

DISTRO_FEATURESx11が設定されている場合、weston-xwaylandとmatchbox-terminalが追加されるようになっている。 BSPによってはこの部分がトラブルを起こすことがある。下記のようにDISTRO_FEATURESからx11を削除する必要となるケースがある。

DISTRO_FEATURES:remove = "x11"

core-image-sato

core-image-baseにx11-sato関連のFEATURESが追加されている。

IMAGE_FEATURES += "splash package-management x11-base x11-sato ssh-server-dropbear hwcodecs"

FEATURES変数とpackagegroup

イメージのレシピでは一部を除いてIMAGE_INSTALLで直接パッケージを使用せずにFEATURES変数の有無で必要なパッケージが選択されるようになっている。 これはFEATURES変数とpackagegroupは紐付けられていて、FEATRUESを設定することで、その機能の実現に必要なパッケージを含むpackagegroupが選択されるようになっているためである。

core-image.bbclassに下記のように定義されている。

FEATURE_PACKAGES_weston = "packagegroup-core-weston"
FEATURE_PACKAGES_x11 = "packagegroup-core-x11"
FEATURE_PACKAGES_x11-base = "packagegroup-core-x11-base"
FEATURE_PACKAGES_x11-sato = "packagegroup-core-x11-sato"
FEATURE_PACKAGES_tools-debug = "packagegroup-core-tools-debug"
FEATURE_PACKAGES_eclipse-debug = "packagegroup-core-eclipse-debug"
FEATURE_PACKAGES_tools-profile = "packagegroup-core-tools-profile"
FEATURE_PACKAGES_tools-testapps = "packagegroup-core-tools-testapps"
FEATURE_PACKAGES_tools-sdk = "packagegroup-core-sdk packagegroup-core-standalone-sdk-target"
FEATURE_PACKAGES_nfs-server = "packagegroup-core-nfs-server"
FEATURE_PACKAGES_nfs-client = "packagegroup-core-nfs-client"
FEATURE_PACKAGES_ssh-server-dropbear = "packagegroup-core-ssh-dropbear"
FEATURE_PACKAGES_ssh-server-openssh = "packagegroup-core-ssh-openssh"

厳密にはFEATURES変数と1:1で定義されている訳ではないが、その関係性を推測することはできる。

基本的にはpackagegroup内ではパッケージ間の依存関係が考慮されており、 packagegroup単位での追加、削除を行う場合には、パッケージ間の依存関係でトラブルになる可能性は低いであろうことが予想できる。

まとめ

pokyでビルド可能なイメージのレシピのうち下記のものを調査した。

  • core-image-minimal
  • core-image-minimal-dev
  • core-image-minimal-initramfs
  • core-image-minimal-mtdutils
  • core-image-full-cmdline
  • core-image-base
  • core-image-x11
  • core-image-weston
  • core-image-sato

それぞれのイメージがどのようにパッケージを選択しているのかなど、ざっくりと理解できた。 FEATURES変数により選択されるパッケージが変化するため、IMAGE_INSTALL変数に直接パッケージを羅列している訳ではないということがわかった。 core-image-minimal-initramfsについては名前に反してcore-image-minimalはベースにしておらず、IMAGE_INSTALL変数が作用しないこともわかった。

基本的にはコンソール環境では、core-image-baseを選択するのが良さそう。 core-image-x11やcore-image-westonなどのGUIを含むイメージはcore-image-baseをベースとしている。