Yoctoで既存のレシピをカスタマイズしたいとき、.bb ファイルを直接編集してはいけない。アップストリームが更新されたら、あなたの変更は消える。
代わりに使うのが .bbappend ファイルだ。元のレシピに「追記」する仕組みで、アップストリームの更新を取り込んでも自分の変更が生き残る。
この記事では、Yocto Scarthgap 5.0 LTS をベースに、bbappendの基礎から実践的なユースケース5つまでを解説する。
bbappendとは何か
.bbappend ファイルは、別のレイヤーにある .bb レシピに対して変数やタスクを追記するためのファイルだ。
仕組みはシンプル。BitBakeがレシピを読み込むとき、対応する .bbappend があれば、レシピの末尾に内容を追記してから処理する。つまり .bbappend に書いた設定は .bb の設定を上書きできる。
meta-poky/recipes-example/someapp/someapp_1.0.bb ← 元のレシピ
meta-mylayer/recipes-example/someapp/someapp_%.bbappend ← あなたの追記
この分離が重要な理由は2つある。
- アップストリームとの共存:
meta-pokyをgit pullで更新しても、あなたのカスタマイズはmeta-mylayerに残る - 変更の可視性: どのレイヤーが何を変更しているか、
bitbake-layers show-appendsで一覧できる
レイヤーの作成方法についてはレイヤー作成ガイドを参照。
ファイル名の命名規則
bbappendのファイル名は、対象レシピのファイル名と一致させる必要がある。
バージョン完全一致
someapp_1.0.bbappend → someapp_1.0.bb にのみ適用
someapp_1.1.bbappend → someapp_1.1.bb にのみ適用
バージョンが完全に一致しないと適用されない。レシピのバージョンが上がると bbappend が無視される。
ワイルドカード % を使う(推奨)
バージョンアップのたびに bbappend のファイル名を変えるのは面倒だ。% ワイルドカードを使えば、バージョンに関係なく適用できる。
someapp_%.bbappend → someapp_1.0.bb, someapp_2.3.bb 等すべてに適用
適用確認
bbappendが正しく認識されているか確認するには、以下のコマンドを使う。
# bbappend の一覧と対応レシピを表示
bitbake-layers show-appends
# 特定レシピの全バージョンを確認(バージョン不一致の特定に便利)
bitbake-layers show-recipes someapp
変数の操作方法
bbappendで最も使う操作は、変数への値の追加と上書きだ。
値を追加する(:append)
:append は変数の末尾に値を追加する。先頭にスペースを入れること。 :append はスペースを自動挿入しない。
# 正しい(先頭スペースあり)
SRC_URI:append = " file://my-patch.patch"
# 間違い(スペースなし → 前の値と結合して壊れる)
SRC_URI:append = "file://my-patch.patch"
+= でも追加できるが、:append のほうが「追記である」ことが明示的で好まれる。
# これも動く(+= はスペースを自動挿入する)
SRC_URI += "file://my-patch.patch"
値を削除する(:remove)
DISTRO_FEATURES:remove = "bluetooth wifi"
値を上書きする
# 完全に上書き
SOME_VARIABLE = "new-value"
FILESEXTRAPATHS — 追加ファイルの検索パス
bbappendで独自のファイル(パッチ、設定ファイル等)を追加する場合、そのファイルの置き場所をBitBakeに教える必要がある。
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"
この1行には3つの重要なポイントがある。
:=(即時展開)を使う:${THISDIR}は「このファイルがあるディレクトリ」を指す変数。遅延展開(=)だと.bbファイル側のディレクトリに解決されてしまう- 末尾のコロン
:は必須: FILESEXTRAPATHS はコロン区切りのリスト。コロンがないと次のパスと結合して壊れる :prependを使う: 既存のパスより先に検索させるため
タスクの拡張
bbappendでは、レシピのタスク(do_install, do_configure等)に処理を追加できる。
do_install:append() {
install -d ${D}${sysconfdir}
install -m 0644 ${WORKDIR}/myconfig.conf ${D}${sysconfdir}/
}
:append はタスクの末尾に処理を追加する。元のタスクの処理は維持される。
:prepend を使えば先頭に追加することもできる。
do_configure:prepend() {
# configure の前に実行される処理
cp ${WORKDIR}/my-makefile ${S}/Makefile
}
実践パターン5選
ここからは実際のユースケースを5つ紹介する。
パターン1: パッチを当てる
最も基本的なユースケース。アップストリームのソースコードにバグ修正や機能追加のパッチを当てる。
ディレクトリ構成:
meta-mylayer/
recipes-example/
someapp/
someapp_%.bbappend
someapp/
0001-fix-memory-leak.patch
# someapp_%.bbappend
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
SRC_URI:append = " file://0001-fix-memory-leak.patch"
${PN} はパッケージ名(この場合 someapp)に展開される。${THISDIR}/${PN} でbbappendと同じディレクトリ内の someapp/ サブディレクトリを指す。
パターン2: 設定ファイルを追加する
独自の設定ファイルをターゲットに配置する。
meta-mylayer/
recipes-core/
busybox/
busybox_%.bbappend
files/
custom-inittab
# busybox_%.bbappend
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"
SRC_URI:append = " file://custom-inittab"
do_install:append() {
install -m 0644 ${WORKDIR}/custom-inittab ${D}${sysconfdir}/inittab
}
パターン3: systemdサービスを追加する
既存のアプリケーションにsystemdサービスファイルを追加して自動起動させる。systemdレシピの詳しい書き方はsystemd自動起動ガイドを参照。
meta-mylayer/
recipes-example/
myapp/
myapp_%.bbappend
files/
myapp.service
# myapp_%.bbappend
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"
SRC_URI:append = " file://myapp.service"
SYSTEMD_SERVICE:${PN} = "myapp.service"
SYSTEMD_AUTO_ENABLE:${PN} = "enable"
FILES:${PN} += "${systemd_system_unitdir}/myapp.service"
do_install:append() {
install -d ${D}${systemd_system_unitdir}
install -m 0644 ${WORKDIR}/myapp.service ${D}${systemd_system_unitdir}/
}
注意: このパターンは、元の .bb レシピが inherit systemd を含んでいる前提だ。inherit ディレクティブは .bb と .bbclass でのみ有効で、.bbappend では公式にサポートされていない。元のレシピがsystemdクラスを継承していない場合は、bbappendではなくレシピ自体の修正が必要になる。
パターン4: コンパイルオプションを変更する
PACKAGECONFIG を使って、レシピのビルドオプションを変更する。
# curl_%.bbappend
# OpenSSLサポートを有効化
PACKAGECONFIG:append = " openssl"
# GnuTLSサポートを無効化
PACKAGECONFIG:remove = "gnutls"
PACKAGECONFIG は多くのレシピで対応しているオプション管理の仕組みだ。対応オプションはレシピの .bb ファイル内の PACKAGECONFIG[xxx] で定義されている。
autotools系のレシピでは、configure オプションを直接追加することもできる。
EXTRA_OECONF:append = " --enable-my-feature"
パターン5: 依存関係を追加する
ビルド時やランタイムの依存関係を追加する。
# mypackage_%.bbappend
# ビルド時依存
DEPENDS:append = " libssl"
# ランタイム依存(${PN} でパッケージを明示する)
RDEPENDS:${PN}:append = " python3"
RDEPENDS には ${PN} が必要だ。RDEPENDS はパッケージごとに設定する変数で、${PN} を省略するとどのパッケージの依存関係かが不明になる。
よくあるトラブルと対処法
bbappendが適用されない
# まず bbappend が認識されているか確認
bitbake-layers show-appends | grep someapp
# レイヤーが bblayers.conf に登録されているか確認
bitbake-layers show-layers
原因として多いのは、バージョン番号の不一致(% を使っていない)とレイヤーの未登録だ。
変数の値がおかしい
# Scarthgap 推奨のデバッグコマンド
bitbake-getvar -r someapp SRC_URI
bitbake-getvar -r someapp FILESEXTRAPATHS
bitbake-getvar は変数の最終的な値と、どのファイルで設定されたかを表示してくれる。
ファイルが見つからない(do_fetch エラー)
FILESEXTRAPATHS の設定ミスが原因であることが多い。
:=を=にしていないか- 末尾のコロン
:を忘れていないか files/ディレクトリの位置がFILESEXTRAPATHSのパスと一致しているか
まとめ
bbappendは、Yoctoで既存レシピをカスタマイズする唯一の正しい方法だ。覚えるポイントは少ない。
- ファイル名は
レシピ名_%.bbappend(%ワイルドカード推奨) - ファイルを追加するときは
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"(:=と末尾コロン必須) - 値の追加は
:append(先頭スペース忘れずに) - タスクの拡張は
do_install:append() { ... } - 困ったら
bitbake-layers show-appendsとbitbake-getvarで確認
基礎を押さえたら、次はビルド環境の最適化にも取り組もう。
bbappendやレシピのカスタマイズをもっと深く学びたい人には、以下の書籍がおすすめだ。特に『Yocto Project Customization』はカスタムレイヤーの設計パターンに特化している。