32blogby Studio Mitsu

Yoctoレシピの書き方:.bbファイル作成ガイド

Yoctoレシピの書き方をゼロから解説。Hello Worldからgit取得、CMake継承、イメージ追加まで実例付き。

by omitsu14 min read

当記事にはアフィリエイト広告が含まれています

目次

Yoctoレシピ(.bbファイル)は、ソースの取得方法・ビルド手順・インストール先をBitBakeに伝える設計図だ。自作アプリでもGitHubのOSSでも、レシピさえ書ければYoctoイメージに組み込める。

この記事では、Yoctoレシピを ゼロから作成する方法 を、Hello WorldからGitHub取得、CMake/Autotools継承まで、実際のコード例とともに解説する。

Yoctoレシピとは

レシピ(Recipe) とは、特定のソフトウェアをビルドしてインストールするための「設計図」だ。Yocto Development Tasks Manualに仕様の全体像がある。

拡張子は .bb で、以下の情報を記述する:

  • どこから ソースコードを取得するか(SRC_URI)
  • どうやって ビルドするか(do_compile)
  • どこに インストールするか(do_install)
  • ライセンス は何か(LICENSE)

レシピファイルの命名規則

レシピファイル名は パッケージ名_バージョン.bb の形式で命名する。

text
hello-world_1.0.bb      # hello-world バージョン1.0
myapp_2.3.1.bb          # myapp バージョン2.3.1
busybox_1.36.1.bb       # busybox バージョン1.36.1

ファイル名からパッケージ名(PN)とバージョン(PV)が自動的に設定される。変数の全リストはYocto Reference Manual — Variables Glossaryで確認できる。

レシピの基本構造

text
# hello-world_1.0.bb

# ===== メタデータ =====
SUMMARY = "Hello World サンプル"
DESCRIPTION = "Yoctoレシピの学習用サンプルアプリケーション"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"

# ===== ソースコードの取得 =====
SRC_URI = "file://hello.c"

# ===== ビルドディレクトリの設定 =====
S = "${WORKDIR}"

# ===== ビルド処理 =====
do_compile() {
    ${CC} ${CFLAGS} ${LDFLAGS} -o hello hello.c
}

# ===== インストール処理 =====
do_install() {
    install -d ${D}${bindir}
    install -m 0755 hello ${D}${bindir}
}

主要な変数

レシピで使う主要な変数を表にまとめた。

変数名説明
SUMMARYパッケージの短い説明"Hello World サンプル"
DESCRIPTIONパッケージの詳細説明"学習用サンプルアプリ..."
LICENSEライセンス種別(SPDX表記)"MIT", "GPL-2.0-only", "Apache-2.0"
LIC_FILES_CHKSUMライセンスファイルのチェックサムfile://LICENSE;md5=xxx
SRC_URIソースコードの取得元"file://", "git://", "https://"
Sソースコードの展開先ディレクトリ$/git

ビルド・インストール用の変数

変数名説明展開例
${WORKDIR}ビルド作業ディレクトリ/tmp/work/.../hello-world/1.0-r0/
${D}インストール先のルート.../image/
${bindir}/usr/bin のパス/usr/bin
${libdir}/usr/lib のパス/usr/lib
${sysconfdir}/etc のパス/etc
${CC}クロスコンパイラarm-poky-linux-gnueabi-gcc

Hello Worldレシピを作成する

まずは最もシンプルなレシピを作成してみよう。

カスタムレイヤーを作成

レシピは自作レイヤー内に配置するのがベストプラクティスだ。Pokyのレイヤーに直接置いてはいけない。

bash
cd ~/yocto/poky
source oe-init-build-env build

# 新しいレイヤーを作成
cd ..
bitbake-layers create-layer meta-mylayer

# レイヤーをビルドに追加
cd build
bitbake-layers add-layer ../meta-mylayer

レイヤーの詳細はレイヤー作成ガイドを参照してほしい。

レシピ用ディレクトリとソースコードを作成

bash
mkdir -p ../meta-mylayer/recipes-example/hello-world/files

files/hello.c を作成する。

c
// files/hello.c
#include <stdio.h>

int main(void) {
    printf("Hello from Yocto!\n");
    printf("This app was built with a custom recipe.\n");
    return 0;
}

レシピファイルを作成

hello-world_1.0.bb を作成する。

text
# hello-world_1.0.bb
SUMMARY = "Hello World - Yoctoレシピ学習用サンプル"
DESCRIPTION = "Yoctoでカスタムレシピを作成する方法を学ぶためのサンプルアプリケーション"

LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"

SRC_URI = "file://hello.c"

S = "${WORKDIR}"

do_compile() {
    ${CC} ${CFLAGS} ${LDFLAGS} -o hello hello.c
}

do_install() {
    install -d ${D}${bindir}
    install -m 0755 hello ${D}${bindir}
}

ビルドしてイメージに組み込む

bash
# 個別にレシピをビルド
bitbake hello-world

# ビルド成功のメッセージ
NOTE: Tasks Summary: Attempted 123 tasks of which 120 didn't need to be rerun

conf/local.conf に以下を追加してイメージに組み込む:

text
IMAGE_INSTALL:append = " hello-world"

イメージを再ビルドしてQEMUで確認:

bash
bitbake core-image-minimal
runqemu qemux86-64 nographic

# ログイン後、helloコマンドを実行
root@qemux86-64:~# hello
Hello from Yocto!
This app was built with a custom recipe.

GitHubからソースを取得する

実際の開発では、外部リポジトリからソースを取得するパターンの方が多い。

例:nlohmann/jsonライブラリ

text
# nlohmann-json_3.11.3.bb
SUMMARY = "JSON for Modern C++"
DESCRIPTION = "Header-only JSON library for C++"
HOMEPAGE = "https://github.com/nlohmann/json"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://LICENSE.MIT;md5=f969127d7b7ed0a8a63c2bbeae002588"

# GitHubからソースを取得
SRC_URI = "git://github.com/nlohmann/json.git;protocol=https;branch=develop"

# 特定のコミットを指定(再現性のため必須)
SRCREV = "9cca280a4d0ccf0c08f47a99aa71d1b0e52f8d03"

# ソースの展開先(gitクローン時は ${WORKDIR}/git)
S = "${WORKDIR}/git"

inherit cmake

EXTRA_OECMAKE = "-DJSON_BuildTests=OFF"

SRC_URIの書き方パターン

取得元SRC_URI の書き方
ローカルファイルfile://hello.c
Git (HTTPS)git://github.com/user/repo.git;protocol=https;branch=main
Git (SSH)git://git@github.com/user/repo.git;protocol=ssh;branch=main
HTTP/HTTPShttps://example.com/file.tar.gz
パッチファイルfile://fix-build.patch

継承クラスを活用する

Yoctoには、よく使うビルドパターンをまとめた「クラス」がある。inherit で継承すると、do_compiledo_install を自動化できる。

クラス用途主な自動化
cmakeCMakeプロジェクトcmake → make → make install
autotoolsAutoconfプロジェクトconfigure → make → make install
mesonMesonプロジェクトmeson → ninja → install
setuptools3Pythonパッケージsetuptools / wheel インストール
systemdsystemdサービスサービスの有効化

CMakeプロジェクトの例

text
# myapp-cmake_1.0.bb
SUMMARY = "My CMake App"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"

SRC_URI = "git://github.com/user/myapp.git;protocol=https;branch=main"
SRCREV = "abc123def456..."
S = "${WORKDIR}/git"

# CMakeクラスを継承するだけでビルドが自動化される
inherit cmake

EXTRA_OECMAKE = "-DBUILD_TESTS=OFF -DCMAKE_BUILD_TYPE=Release"

Autotoolsプロジェクトの例

text
# myapp-autotools_1.0.bb
SUMMARY = "My Autotools App"
LICENSE = "GPL-2.0-only"
LIC_FILES_CHKSUM = "file://COPYING;md5=..."

SRC_URI = "https://example.com/myapp-1.0.tar.gz"
SRC_URI[sha256sum] = "def456..."

inherit autotools

EXTRA_OECONF = "--disable-docs"

systemdサービス

起動時にアプリを自動実行したい場合は inherit systemd を使う。詳しい設定方法はsystemdサービスガイドを参照してほしい。

よくあるエラーと解決方法

LIC_FILES_CHKSUM mismatch

text
ERROR: License checksum mismatch...

原因: ライセンスファイルのMD5ハッシュが一致しない。

解決: 正しいMD5を計算して更新。

bash
md5sum LICENSE

do_fetch failed

text
ERROR: Fetcher failure: Unable to find file...

原因: SRC_URIのパスが間違っている、またはネットワーク問題。

解決: パスを確認。Gitの場合はSRCREVを正しいコミットハッシュに設定。

Nothing PROVIDES 'hello-world'

text
ERROR: Nothing PROVIDES 'hello-world'

原因: レイヤーがbblayers.confに追加されていない。

解決: bitbake-layers add-layer でレイヤーを追加して確認。

SRC_URI checksum mismatch

text
ERROR: SRC_URI checksum mismatch...

原因: HTTP/HTTPSで取得するファイルのチェックサムが未設定または不一致。

解決: 正しいチェックサムを計算して設定。

bash
sha256sum ダウンロードしたファイル.tar.gz

依存関係の管理

実際のレシピでは、他のパッケージへの依存関係を設定する場面が多い。Yoctoではビルド時と実行時の依存を区別する。

DEPENDSとRDEPENDS

変数タイミング
DEPENDSビルド時 — コンパイルに必要なライブラリ/ヘッダDEPENDS = "openssl zlib"
RDEPENDS:${PN}実行時 — ターゲットに必要なパッケージRDEPENDS:${PN} = "libssl"
text
# myapp_1.0.bb — 依存関係の設定例
SUMMARY = "My App with Dependencies"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"

SRC_URI = "file://myapp.c"
S = "${WORKDIR}"

# ビルド時: OpenSSLのヘッダとライブラリが必要
DEPENDS = "openssl"

# 実行時: OpenSSLの共有ライブラリが必要
RDEPENDS:${PN} = "openssl"

do_compile() {
    ${CC} ${CFLAGS} ${LDFLAGS} -o myapp myapp.c -lssl -lcrypto
}

do_install() {
    install -d ${D}${bindir}
    install -m 0755 myapp ${D}${bindir}
}

requireとinclude

レシピのロジックを複数ファイルに分割できる:

  • require — 別ファイルを読み込む(ファイルがなければエラー)
  • include — 別ファイルを読み込む(なければスキップ)
text
# myapp_1.0.bb
require myapp-common.inc

SRC_URI = "https://example.com/myapp-1.0.tar.gz"
SRC_URI[sha256sum] = "abc123..."

Pokyの公式レシピでも、バージョン間でメタデータを共有するためにこの手法が多用されている。

FAQ

SRCREVとAUTOREVの違いは?

SRCREV は特定のGitコミットハッシュに固定する変数で、マシンやCI環境が変わっても同じコードをビルドできる。AUTOREVSRCREV = "${AUTOREV}")はビルドのたびに最新コミットを取得する。BitBake User Manualでもプロダクション用途でのAUTOREVは非推奨とされている。ビルドの再現性が損なわれ、未テストの変更が混入するリスクがある。

SRC_URIに複数のファイルを追加するには?

スペース区切りで列挙するか、バックスラッシュで改行して記述する:

text
SRC_URI = "file://main.c \
           file://utils.c \
           file://utils.h \
           file://config.json \
           "

file:// のファイルはレシピと同じ階層の files/ ディレクトリか、レシピ名と同じ名前のディレクトリに配置する。

レシピ内でPythonは使える?

使える。BitBakeレシピではインライン式 ${@expression} と、Python関数 python do_taskname() の2つの方法がある:

text
# Python式で変数を設定
DATEVAR = "${@time.strftime('%Y%m%d', time.gmtime())}"

python do_configure:prepend() {
    bb.note("Configuring with custom Python logic")
}

詳細はBitBake User ManualのPythonタスクの章を参照。

inheritとrequireの違いは?

inherit.bbclass ファイルを読み込み、標準的なビルド動作(cmakeautotools等)を追加する。require / include は別の .bb.inc ファイルを読み込み、レシピのメタデータを共有する。inherit は「このビルドシステムを使う」、require は「共有設定を読み込む」と覚えるとわかりやすい。

ビルドに失敗したレシピをデバッグするには?

devshell を使うと、レシピのビルド環境にインタラクティブシェルで入れる:

bash
bitbake -c devshell hello-world

クロスコンパイラやsysrootパス等の環境変数がセットされた状態でターミナルが開くため、手動でmakeを実行したりファイルを確認できる。体系的なデバッグ手法はビルドエラーデバッグガイドを参照。

/etcに設定ファイルを配置するには?

do_install${sysconfdir}/etc に展開される)を使う:

text
do_install() {
    install -d ${D}${sysconfdir}/myapp
    install -m 0644 ${WORKDIR}/myapp.conf ${D}${sysconfdir}/myapp/
}

設定ファイルは SRC_URI にも追加するのを忘れずに。

do_installとdo_deployの違いは?

do_install はターゲットのルートファイルシステムのステージングエリア(${D})にファイルを配置する。do_deploy はデプロイディレクトリに出力する——ブートイメージやブートローダバイナリ等、rootfsに含まれないが書き込み時に必要なアーティファクト向けだ。大半のレシピでは do_install だけで事足りる。

まとめ

この記事ではYoctoレシピの作成方法を解説した。

  • レシピは .bb ファイルで、取得・ビルド・インストールの全工程を記述する
  • 主要変数:SRC_URIdo_compiledo_installDEPENDSRDEPENDS
  • 自作レイヤーにレシピを配置するのがベストプラクティス
  • inherit でCMake/Autotools/Mesonプロジェクトを自動化
  • IMAGE_INSTALL:append でイメージに組み込む
  • SRCREV は必ず固定する(再現性のため)
  • DEPENDS でビルド時、RDEPENDS で実行時の依存を管理する

レシピ作成のリファレンスはYocto Development Tasks Manualが最も正確だ。次のステップに進もう。

組み込みLinuxの世界をもっと深く学びたい人には、以下の書籍がおすすめだ。

関連記事: