.bbappend はYoctoで既存レシピをカスタマイズするための仕組みだ。元の .bb ファイルを直接編集せず、パース時に変更を追記することで、アップストリームの更新と自分のカスタマイズを完全に分離できる。
.bb を直接いじると、次に git pull した瞬間に変更が消える。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 変数がファイルの検索パスを制御する。
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で inherit は使える?
公式には inherit は .bb と .bbclass でのみ有効だ。BitBake User Manual も .bbappend を inherit の有効な場所として記載していない。実際に動くケースもあるが、元レシピが必要なクラスを継承していなければ、bbappendではなくレシピ自体を修正するか新しいレシピを作るのが正しい。
:append と += は何が違う?
どちらも値を追加するが、:append はオーバーライドスタイルの演算子で、すべての += の後に実行される。:append はスペースを自動挿入しないので自分で入れる必要がある。+= はパース時に評価されスペースを自動挿入する。bbappendでは、元レシピの代入より確実に後で実行される :append が推奨される。
同じレシピに複数のbbappendを適用できる?
できる。複数のレイヤーが同じレシピへのbbappendを持っている場合、bblayers.conf に記載された順番で適用される。変数が競合した場合は後のレイヤーが勝つ。bitbake-layers show-appends で適用順を確認しよう。
元レシピの変数を完全に上書きするには?
単純な代入(=)を使う。bbappendの内容は元レシピの後に追記されるので、bbappendでの = が最終的な値になる。ただし SRC_URI のような累積的な変数には :append を使うこと。= で上書きすると元の値が全部消えてしまう。
レイヤー内のディレクトリ構成は重要?
bbappendは元レシピと同じ相対パスに置く必要がある。元レシピが meta-poky/recipes-core/busybox/busybox_1.36.1.bb なら、bbappendは meta-mylayer/recipes-core/busybox/busybox_%.bbappend に置く。BitBakeはレシピ名で照合するが、同じディレクトリ構成にしておくのが読みやすさの面で重要だ。
対応するレシピが存在しないbbappendはどうなる?
デフォルトではBitBakeが無視する。これを検出するには local.conf に BB_DANGLINGAPPENDS_WARNLEVEL = "error" を追加する。対応レシピのないbbappendがあるとビルドがエラーで止まるようになり、レシピの削除やリネーム後に残った古いbbappendを見つけやすい。
元レシピがインストールするファイルを削除できる?
できる。do_install:append() で rm を使えば、元の do_install が配置したファイルを削除できる。
do_install:append() {
rm -f ${D}${bindir}/unwanted-binary
}
あるいは PACKAGES や FILES 変数で最終パッケージからファイルを除外する方法もある。ビルドディレクトリからは消さずにパッケージにだけ含めない、という使い分けができる。
まとめ
bbappendは、Yoctoで既存レシピをカスタマイズする唯一の正しい方法だ。覚えるポイントは少ない。
- ファイル名は
レシピ名_%.bbappend(%ワイルドカード推奨) - ファイルを追加するときは
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"(:=と末尾コロン必須) - 値の追加は
:append(先頭スペース忘れずに) - タスクの拡張は
do_install:append() { ... } - 困ったら
bitbake-layers show-appendsとbitbake-getvarで確認
基礎を押さえたら、次はビルド環境の最適化にも取り組もう。
bbappendやレシピのカスタマイズをもっと深く学びたい人には、以下の書籍がおすすめだ。特に『Yocto Project Customization』はカスタムレイヤーの設計パターンに特化している。
関連記事: