🐧 Linux 総合学習プラットフォーム
組込みビルド Yocto/Buildroot ・ 上級

組込みLinuxイメージを自作するとは

PCのLinuxはディストリビューションをインストーラで導入しますが、組込み機器ではターゲットのCPUやストレージに合わせてOSそのものを自分で組み立てます。クロスツールチェーンでビルドし、カーネル・ルートファイルシステム・ブートローダの3点をまとめて生成し、書き込み用のイメージを作るのが基本の流れです。この一連の自動化を担うのがBuildrootやYoctoといったビルドシステムです。手作業の積み上げと違い、設定さえ固めれば同じ成果物を何度でも再現できるのが最大の利点です。

普段パソコンにLinuxを入れるときは、UbuntuやFedoraのようなディストリビューションのインストーラをダウンロードし、画面の案内に従ってクリックしていけばOSが出来上がります。これはあらかじめ「PCという決まったハードウェア」向けに、必要なものが一式そろえて配られているからこそ成り立つ手軽さです。ところが組込み機器の世界では、この前提が崩れます。CPUはArmだったりRISC-Vだったりとさまざまで、メモリやストレージも数百MBしかないことがあり、画面もキーボードも持たない製品が珍しくありません。汎用のインストーラはそのまま使えず、その機器のために必要な部品だけを選んで、OSそのものを自分の手で組み立てることになります。この「組込みLinuxイメージを自作する」という考え方が、このトラックの出発点です。PCのように「入れる」のではなく、ターゲットに合わせて「作る」——この発想の転換が、まず最初の山になります。

なぜわざわざ自作するのかというと、組込み機器には削ぎ落としの要求があるからです。限られたフラッシュ容量に収めるため、使わないコマンドやドライバは入れたくありません。起動時間を縮めたい、消費電力を抑えたい、製品寿命の長さに合わせて構成を凍結したい——こうした要求に応えるには、汎用ディストリビューションのように「なんでも入っている」状態では都合が悪く、必要十分なものだけを選んで組み上げる必要があります。だからこそ、何を入れて何を入れないかを自分で決め、その決定を再現可能な形で保存できる仕組みが要るのです。さらに、特定のセンサーや独自基板に合わせた専用のドライバや設定を組み込む必要もあり、既製品をそのまま使うだけでは要求を満たせない、という事情も自作を後押しします。

ここで鍵になるのがクロスツールチェーン(bs-cross-toolchain)の存在です。開発に使う母艦は速いx86のPCである一方、できあがったプログラムを動かすのはArmなどの非力なターゲットCPUです。母艦のCPUと、プログラムが動くCPUが食い違うこの状況では、x86上で動きながらArm向けの実行ファイルを吐き出す特別なコンパイラ一式が必要になります。これがクロスコンパイル用のツールチェーンで、gccやC標準ライブラリ、リンカ、アセンブラなどをターゲット向けに仕立てたものです。ターゲット自身は非力でその場でコンパイルするには時間がかかりすぎるため、母艦の上で目的のアーキテクチャ向けにビルドする、というのが組込み開発の基本姿勢になります。後で出てくるBuildrootもYoctoも、まずこのクロスツールチェーンを用意するところから仕事を始めます。

イメージを構成する3つの部品

「OSを自作する」と言っても、巨大な一枚岩を一から書くわけではありません。実際には、世界中で独立して開発されている部品を集めて1つにまとめます。中心になるのは3つです。1つ目はハードウェアを直接制御するLinuxカーネル(bs-kernel)で、CPU・メモリ・各種デバイスを動かし、プロセスやファイルを管理する心臓部です。2つ目は、コマンド群やライブラリ、設定ファイルを収めたルートファイルシステム(bs-rootfs)で、起動後に / としてマウントされ、ユーザーやアプリが実際に触る「中身」にあたります。3つ目は、電源投入直後に最初に走ってカーネルを読み込み起動させるブートローダで、組込みではU-Bootがよく使われます。この3点がそろって初めて、ストレージに書いて電源を入れれば立ち上がる、ひとまとまりのシステムになります。どれか1つでも欠ければ、機器は沈黙したままです。

ビルドシステムが自動化するもの

これらの部品は、それぞれ取得元もビルド方法も設定項目も違います。カーネルはkernel.orgから、各コマンドはそれぞれのプロジェクトから集め、ターゲットのCPUに合わせて個別にクロスコンパイルし、最後にひとつのファイルシステムへ正しく配置する——この一連の作業を手で積み上げるのは、手順が膨大なうえに再現が困難です。バージョンの組み合わせや依存関係を1つ間違えただけで、ビルドが通らなかったり、起動しないイメージが出来たりします。そこを丸ごと引き受けて自動化するのがビルドシステムで、代表格がBuildroot(bs-buildroot)とYocto(bs-yocto)です。どちらも「どのアーキテクチャ向けに・何を入れて・どう作るか」という設定を受け取り、クロスツールチェーンの構築からカーネル・rootfsの生成、そして書き込み用イメージ(bs-image)の作成までを一気に走らせます。人間は方針を設定として与え、面倒な実作業は機械に任せる、という分業です。

ビルドシステムを使う最大の利点は、再現性です。手作業の積み上げでは、誰がいつどのPCで作ったかで成果物が微妙に変わり、「あの人の環境でしかビルドが通らない」という属人的な事態に陥りがちです。これに対しビルドシステムは、設定ファイルさえバージョン管理して固めておけば、別のマシンでも、半年後でも、同じ入力から同じ成果物を何度でも作り直せます。製品を長く保守する組込みの現場では、出荷したファームウェアと寸分違わぬものを後から再ビルドできることが決定的に重要です。不具合が報告されたとき、出荷時とまったく同じイメージを再現できなければ、原因の調査も修正版の作成もままなりません。この「設定を固めれば同じ結果が返る」という性質こそが、ビルドシステムを使う本質的な理由であり、次の節から見ていくBuildrootとYoctoに共通する土台でもあります。

本トラックでは、この自作の世界を順を追って見ていきます。まず代表的なビルドシステムであるBuildrootを取り上げ、menuconfigで構成を選んでmakeするだけ、というシンプルな流れを通して全体像をつかみます。続いて、商用製品で広く使われるYoctoを、レシピ・レイヤ・BitBakeという3つの概念から理解します。そのうえで、両者が生み出すカーネル・rootfs・ブートローダという成果物の正体と、それらを書き込む前に点検する方法を確認し、最後にBuildrootとYoctoをどう使い分けるかを整理します。どの節でも一貫して問うのは、「OSを組み立てるとは具体的に何をすることなのか」です。抽象的な言葉のままにせず、実際に出てくるコマンドやファイルと結びつけて理解していきましょう。

この項目に出てくる用語

Buildrootビルドルート
MakefileとKconfigで組込みLinuxイメージを生成する軽量ビルドシステム。
Yocto Projectヨクトプロジェクト
レイヤとレシピで組込みLinuxを構築する大規模ビルドフレームワーク。
クロスツールチェーンクロスツールチェーン
PC上でターゲットCPU向けの実行ファイルを作るコンパイラ等一式。
イメージイメージ
ストレージにそのまま書き込める形にまとめられた成果物ファイル。
ルートファイルシステムルートファイルシステム
/ 以下に展開されるコマンド・ライブラリ・設定一式。rootfsと略す。

関連コマンド

make menuconfigmake (Buildroot)bitbake

▶ 学習アプリでこの続きを学ぶ・演習する