LeavaTailの日記

LeavaTailの日記

Linuxエンジニアを目指した技術者の備忘録

組込みLinuxディストリビューションを構築する(Yocto編)

関連記事

概要

Yocto (Zeus)でARM64用のLinuxディストリビューション一式 (Linuxカーネル、U-Boot、ルートファイルシステム、ツールチェイン) を生成する。
また、QEMU (virtボード)でU-Bootをロードし、そこからLinxuカーネルの起動とルートファイルシステムのマウントまでの手順を確認した。

はじめに

前回の記事で、QEMUx86_64アーキテクチャ上でARM用にビルドしたLinuxカーネルを起動させることに成功した。

leavatail.hatenablog.com

その時はLinuxシステムの構築にBuildRootを使用したが、今回はYoctoを使用してLinuxシステムを構築する。

Yoctoについて

Yocto Projectは、開発者がLinuxディストリビューションを構築する仕組みを提供するプロジェクトである。 Yoctoの特徴としては、以下のようなものがあげられる。

Yoctoは複数のコンポーネントから構成されている。下図はコンポーネントについて簡略に表したものである。

Yoctoの全体像イメージ

  • poky : リファレンス・ビルド・システム
    独自のLinuxディストリビューションを構築するためのシステム。 (厳密には違うが) pokyはYocto専用のLinuxディストリビューションであり、ここでカーネルイメージやrootfsを生成する。 記事によっては、yocto=pokyのことを指していることもある。

  • bitbake: ビルドツール
    Yocto(poky)上で利用される組込みLinuxシステム向けのビルドツール。 Makeのようなもので、依存関係を解決したうえでイメージ(カーネルイメージやrootfsなど)を生成する。
    具体的にbitbakeでは、「レシピの解析」「ソースコードのダウンロード」「パッチ適用」「ビルド」を一括で実施してくれる。

  • レシピ: ソフトウェアのビルド定義
    ソフトウェアのビルドやインストール方法が書かれたファイル。

  • レイヤー: メタ情報の集合
    レシピなどを含めた情報を集めた層。レイヤーは重ねることで機能を追加することができ、アーキテクチャによる依存を最小限にすることができる。
    レイヤーやレシピの詳細な説明については、参考資料を参照。

  • 構成情報: ターゲットマシンの構成定義
    CPUアーキテクチャなどのターゲットマシンごとの定義。

環境構成

前回の記事で作成した環境を利用する。

実行環境

仮想マシンの構築にはVagrantVirtualBox、BoxイメージにはUbuntu /bionic64を利用する。

今回使用するホスト環境は下記の通り。

テスト環境 詳細
CPU intel core i7-9700
メモリ DDR4-2666 32G
ストレージ M.2 SSD(500GB)
Virtualbox v6.0.18

実行環境の準備

Yoctoの要件として空きディスク容量が50Gであることが求められる。 しかし、Vagrantのデフォルト仮想マシンのディスク容量は10Gであるので、Vagrantの定義ファイルを修正する必要がある。

今回は、vagrant-disksizeを使用して、ディスク容量を拡張する。 またyoctoではイメージ生成時間が長くなる傾向があるので、CPU数とメモリ容量も拡張しておく。 Vagrantfileの修正箇所は下記の通りである。

$ git diff
diff --git a/Vagrantfile b/Vagrantfile
index 1c4ee1e..bb5337f 100644
--- a/Vagrantfile
+++ b/Vagrantfile
@@ -45,17 +45,20 @@ Vagrant.configure("2") do |config|
   # argument is a set of non-required options.
   # config.vm.synced_folder "../data", "/vagrant_data"
 
+  config.ssh.forward_x11 = true
+
   # Provider-specific configuration so you can fine-tune various
   # backing providers for Vagrant. These expose provider-specific options.
   # Example for VirtualBox:
   #
-  # config.vm.provider "virtualbox" do |vb|
-  #   # Display the VirtualBox GUI when booting the machine
+  config.vm.provider "virtualbox" do |vb|
+    # Display the VirtualBox GUI when booting the machine
   #   vb.gui = true
-  #
-  #   # Customize the amount of memory on the VM:
-  #   vb.memory = "1024"
-  # end
+
+    # Customize the amount of memory on the VM:
+    vb.cpus = 8
+    vb.memory = "16384"
+  end
+
+  config.disksize.size = '200GB'
   #
   # View the documentation for the provider you are using for more
   # information on available options.

Yoctoを使用するにあたってX11転送は必須ではないが、デスクトップ環境イメージを利用する際に不便なので設定している。

システム構築のためのセットアップ

  1. 必要なパッケージをインストールする。

     vagrant@ubuntu-bionic:~$ sudo apt-get install gawk wget git-core diffstat unzip texinfo gcc-multilib \
                              build-essential chrpath socat cpio python python3 python3-pip python3-pexpect \
                              xz-utils debianutils iputils-ping python3-git python3-jinja2 libegl1-mesa libsdl1.2-dev \
                              pylint3 xterm
    
  2. Pokyリポジトリをクローンする。(執筆時点の最新バージョンyocto-3.0にチェックアウトする)

     vagrant@ubuntu-bionic:~$ git clone git://git.yoctoproject.org/poky
     vagrant@ubuntu-bionic:~$ cd poky/
     vagrant@ubuntu-bionic:~/poky$ git fetch --tag
     vagrant@ubuntu-bionic:~/poky$ git tag
     vagrant@ubuntu-bionic:~/poky$ git checkout tags/yocto-3.0 -b yocto-3.0
    
  3. ビルド環境の初期化する。

     vagrant@ubuntu-bionic:~/poky$ source oe-init-build-env
    
     You had no conf/local.conf file. This configuration file has therefore been
     created for you with some default values. You may wish to edit it to, for
     example, select a different MACHINE (target hardware). See conf/local.conf
     for more information as common configuration options are commented.
    
     You had no conf/bblayers.conf file. This configuration file has therefore been
     created for you with some default values. To add additional metadata layers
     into your configuration please add entries to conf/bblayers.conf.
    
     The Yocto Project has extensive documentation about OE including a reference
     manual which can be found at:
         http://yoctoproject.org/documentation
    
     For more information about OpenEmbedded see their website:
         http://www.openembedded.org/
    
    
     ### Shell environment set up for builds. ###
    
     You can now run 'bitbake <target>'
    
     Common targets are:
         core-image-minimal
         core-image-sato
         meta-toolchain
         meta-ide-support
    
     You can also run generated qemu images with a command like 'runqemu qemux86'
    
     Other commonly useful commands are:
      - 'devtool' and 'recipetool' handle common recipe tasks
      - 'bitbake-layers' handles common layer tasks
      - 'oe-pkgdata-util' handles common target package tasks
    
  4. 構成ファイルlocal.confを修正する。

diff --git a/build/conf/local.conf b/build/conf/local.conf
index 2e0bb41e64..1941917154 100644
--- a/build/conf/local.conf
+++ b/build/conf/local.conf
@@ -18,7 +18,7 @@
 # of emulated machines available which can boot and run in the QEMU emulator:
 #
 #MACHINE ?= "qemuarm"
-#MACHINE ?= "qemuarm64"
+MACHINE ?= "qemuarm64"
 #MACHINE ?= "qemumips"
 #MACHINE ?= "qemumips64"
 #MACHINE ?= "qemuppc"
@@ -265,3 +265,6 @@ PACKAGECONFIG_append_pn-qemu-system-native = " sdl"
 # track the version of this file when it was generated. This can safely be ignored if
 # this doesn't mean anything to you.
 CONF_VERSION = "1"
+
+BB_NUMBER_THREADS = '8'
+PARALLEL_MAKE = '-j 8'

修正内容は次の通りとなっている。

  • MACHINE ?=でターゲット対象アーキテクチャをarm64に変更する。
  • BB_NUMBER_THREADS:で並列処理するレシピ数を8に変更する。
  • PARALLEL_MAKE:コンパイル時に使用するコア数を8に変更する。

Yoctoによるビルド実行

今回は、最小限のシステムデスクトップ環境の2種類のLinuxディストリビューションを構築している。

最小システムのビルドと起動

  1. 最小限のシステムをビルドする。

     vagrant@ubuntu-bionic:~/poky/build$ bitbake core-image-minimal
    
  2. ビルドしたイメージは tmp/deploy/images に格納される。

     vagrant@ubuntu-bionic:~/poky/build$ ls -l tmp/deploy/images/qemuarm64/
     total 423572
     lrwxrwxrwx 2 vagrant vagrant        73 Jun 12 05:56 Image -> Image--5.15.32+git0+63e25b5717_387a676543-r0-qemuarm64-20220612044554.bin
     -rw-r--r-- 2 vagrant vagrant  20445696 Jun 12 05:56 Image--5.15.32+git0+63e25b5717_387a676543-r0-qemuarm64-20220612044554.bin
     lrwxrwxrwx 2 vagrant vagrant        73 Jun 12 05:56 Image-qemuarm64.bin -> Image--5.15.32+git0+63e25b5717_387a676543-r0-qemuarm64-20220612044554.bin
     -rw-r--r-- 2 vagrant vagrant      1779 Jun 12 06:06 core-image-minimal-qemuarm64-20220612044554.qemuboot.conf
     -rw-r--r-- 2 vagrant vagrant  11512832 Jun 12 06:57 core-image-minimal-qemuarm64-20220612044554.rootfs.ext4
     -rw-r--r-- 2 vagrant vagrant       721 Jun 12 06:06 core-image-minimal-qemuarm64-20220612044554.rootfs.manifest
     -rw-r--r-- 2 vagrant vagrant   2753520 Jun 12 06:06 core-image-minimal-qemuarm64-20220612044554.rootfs.tar.bz2
     -rw-r--r-- 2 vagrant vagrant    242743 Jun 12 06:06 core-image-minimal-qemuarm64-20220612044554.testdata.json
     lrwxrwxrwx 2 vagrant vagrant        55 Jun 12 06:06 core-image-minimal-qemuarm64.ext4 -> core-image-minimal-qemuarm64-20220612044554.rootfs.ext4
     lrwxrwxrwx 2 vagrant vagrant        59 Jun 12 06:06 core-image-minimal-qemuarm64.manifest -> core-image-minimal-qemuarm64-20220612044554.rootfs.manifest
     lrwxrwxrwx 2 vagrant vagrant        57 Jun 12 06:06 core-image-minimal-qemuarm64.qemuboot.conf -> core-image-minimal-qemuarm64-20220612044554.qemuboot.conf
     lrwxrwxrwx 2 vagrant vagrant        58 Jun 12 06:06 core-image-minimal-qemuarm64.tar.bz2 -> core-image-minimal-qemuarm64-20220612044554.rootfs.tar.bz2
     lrwxrwxrwx 2 vagrant vagrant        57 Jun 12 06:06 core-image-minimal-qemuarm64.testdata.json -> core-image-minimal-qemuarm64-20220612044554.testd
     -rw-r--r-- 2 vagrant vagrant   2004411 Jun 12 05:56 modules--5.15.32+git0+63e25b5717_387a676543-r0-qemuarm64-20220612044554.tgz
     lrwxrwxrwx 2 vagrant vagrant        75 Jun 12 05:56 modules-qemuarm64.tgz -> modules--5.15.32+git0+63e25b5717_387a676543-r0-qemuarm64-20220612044554.tgz
    
  3. QEMUで生成したイメージをエミュレートする。(nographicを指定することで、現在のターミナルからシリアル接続することができる)

     vagrant@ubuntu-bionic:~/poky/build$ runqemu qemuarm64 nographic
     runqemu - INFO - Running MACHINE=qemuarm64 bitbake -e ...
     runqemu - INFO - Continuing with the following parameters:
     KERNEL: [/home/vagrant/poky/build/tmp/deploy/images/qemuarm64/Image--5.15.32+git0+63e25b5717_387a676543-r0-qemuarm64-20220612044554.bin]
     MACHINE: [qemuarm64]
     FSTYPE: [ext4]
     ROOTFS: [/home/vagrant/poky/build/tmp/deploy/images/qemuarm64/core-image-sato-qemuarm64-20220612065747.rootfs.ext4]
     CONFFILE: [/home/vagrant/poky/build/tmp/deploy/images/qemuarm64/core-image-sato-qemuarm64-20220612065747.qemuboot.conf]
    
     runqemu - INFO - Setting up tap interface under sudo
     runqemu - INFO - Network configuration: ip=192.168.7.2::192.168.7.1:255.255.255.0::eth0:off:8.8.8.8
     runqemu - INFO - Running /home/vagrant/poky/build/tmp/work/x86_64-linux/qemu-helper-native/1.0-r1/recipe-sysroot-native/usr/bin/qemu-system-aarch64 -device virtio-net-device,netdev=net0,mac=52:54:00:12:34:02 -netdev         tap,id=net0,ifname=tap0,script=no,downscript=no -object rng-random,filename=/dev/urandom,id=rng0 -device virtio-rng-pci,rng=rng0 -drive id=disk0,file=/home/vagrant/poky/build/tmp/deploy/images/qemuarm64/        core-image-sato-qemuarm64-20220612065747.rootfs.ext4,if=none,format=raw -device virtio-blk-device,drive=disk0 -device qemu-xhci -device usb-tablet -device usb-kbd  -machine virt -cpu cortex-a57 -smp 4 -m 512 -serial mon:stdio     -serial     null -nographic -device virtio-gpu-pci -kernel /home/vagrant/poky/build/tmp/deploy/images/qemuarm64/Image--5.15.32+git0+63e25b5717_387a676543-r0-qemuarm64-20220612044554.bin -append 'root=/dev/vda rw  mem=512M     ip=192.168.7.2::192.168.7.1:255.255.255.0::eth0:off:8.8.8.8 console=ttyAMA0 console=hvc0  '
    

デスクトップ環境を構築する

  1. デスクトップ環境をビルドする

     vagrant@ubuntu-bionic:~/poky/build$ bitbake core-image-sato
    
  2. ビルドしたイメージは tmp/deploy/images に格納される。

     vagrant@ubuntu-bionic:~/poky/build$ ls -l tmp/deploy/images/qemuarm64/
     total 423580
     lrwxrwxrwx 2 vagrant vagrant        73 Jun 12 05:56 Image -> Image--5.15.32+git0+63e25b5717_387a676543-r0-qemuarm64-20220612044554.bin
     -rw-r--r-- 2 vagrant vagrant  20445696 Jun 12 05:56 Image--5.15.32+git0+63e25b5717_387a676543-r0-qemuarm64-20220612044554.bin
     lrwxrwxrwx 2 vagrant vagrant        73 Jun 12 05:56 Image-qemuarm64.bin -> Image--5.15.32+git0+63e25b5717_387a676543-r0-qemuarm64-20220612044554.bin
     -rw-r--r-- 2 vagrant vagrant      1767 Jun 12 08:46 core-image-sato-qemuarm64-20220612065747.qemuboot.conf
     -rw-r--r-- 2 vagrant vagrant 522982400 Jun 25 09:26 core-image-sato-qemuarm64-20220612065747.rootfs.ext4
     -rw-r--r-- 2 vagrant vagrant     28808 Jun 12 08:46 core-image-sato-qemuarm64-20220612065747.rootfs.manifest
     -rw-r--r-- 2 vagrant vagrant  96465741 Jun 12 08:46 core-image-sato-qemuarm64-20220612065747.rootfs.tar.bz2
     -rw-r--r-- 2 vagrant vagrant    243264 Jun 12 08:46 core-image-sato-qemuarm64-20220612065747.testdata.json
     lrwxrwxrwx 2 vagrant vagrant        52 Jun 12 08:46 core-image-sato-qemuarm64.ext4 -> core-image-sato-qemuarm64-20220612065747.rootfs.ext4
     lrwxrwxrwx 2 vagrant vagrant        56 Jun 12 08:46 core-image-sato-qemuarm64.manifest -> core-image-sato-qemuarm64-20220612065747.rootfs.manifest
     lrwxrwxrwx 2 vagrant vagrant        54 Jun 12 08:46 core-image-sato-qemuarm64.qemuboot.conf -> core-image-sato-qemuarm64-20220612065747.qemuboot.conf
     lrwxrwxrwx 2 vagrant vagrant        55 Jun 12 08:46 core-image-sato-qemuarm64.tar.bz2 -> core-image-sato-qemuarm64-20220612065747.rootfs.tar.bz2
     lrwxrwxrwx 2 vagrant vagrant        54 Jun 12 08:46 core-image-sato-qemuarm64.testdata.json -> core-image-sato-qemuarm64-20220612065747.testdata.json
     -rw-r--r-- 2 vagrant vagrant   2004411 Jun 12 05:56 modules--5.15.32+git0+63e25b5717_387a676543-r0-qemuarm64-20220612044554.tgz
     lrwxrwxrwx 2 vagrant vagrant        75 Jun 12 05:56 modules-qemuarm64.tgz -> modules--5.15.32+git0+63e25b5717_387a676543-r0-qemuarm64-20220612044554.tgz        
    
  3. QEMUで生成したイメージをエミュレートする。

     vagrant@ubuntu-bionic:~/poky/build$ runqemu qemuarm64
    

これにより、新規のウインドウが立ち上がる。

Yoctoの起動画面

デスクトップ環境ではのメインメニューから"Terminal"を選択することで、コンソールにログインできる。

アプリケーション選択画面

ツールチェインの生成

  1. ツールチェインをビルドする。

     vagrant@ubuntu-bionic:~/poky/build$ bitbake meta-toolchain
    
  2. ビルドしたツールチェインは tmp/deploy/sdk に格納される。

     vagrant@ubuntu-bionic:~/poky/build $ ls -l tmp/deploy/sdk/
     total 135232
     -rw-r--r-- 2 vagrant vagrant     11909 Jun 25 10:28 poky-glibc-x86_64-meta-toolchain-cortexa57-qemuarm64-toolchain-4.0.host.manifest
     -rwxr-xr-x 2 vagrant vagrant 138233871 Jun 25 10:30 poky-glibc-x86_64-meta-toolchain-cortexa57-qemuarm64-toolchain-4.0.sh
     -rw-r--r-- 2 vagrant vagrant      1730 Jun 25 10:28 poky-glibc-x86_64-meta-toolchain-cortexa57-qemuarm64-toolchain-4.0.target.manifest
     -rw-r--r-- 2 vagrant vagrant    225233 Jun 25 10:28 poky-glibc-x86_64-meta-toolchain-cortexa57-qemuarm64-toolchain-4.0.testdata.json
    
  3. ツールチェインをインストールする。

     vagrant@ubuntu-bionic:~/poky/build$ ./tmp/deploy/sdk/poky-glibc-x86_64-meta-toolchain-cortexa57-qemuarm64-toolchain-4.0.sh 
     Poky (Yocto Project Reference Distro) SDK installer version 4.0
     ===============================================================
     Enter target directory for SDK (default: /opt/poky/4.0): 
     You are about to install the SDK to "/opt/poky/4.0". Proceed [Y/n]? Y
     Extracting SDK...............................................done
     Setting it up...done
     SDK has been successfully set up and is ready to be used.
     Each time you wish to use the SDK in a new shell session, you need to source the environment setup script e.g.
      $ . /opt/poky/4.0/environment-setup-cortexa57-poky-linux        
    

ツールチェインの利用

Autotoolsを利用するプロジェクトを生成したツールチェインでビルドする。

github.com

  1. 環境をセットアップする (現在のプロセス shell 単位に反映される)

     vagrant@ubuntu-bionic:/vagrant/Autotools-tutorial$  . /opt/poky/4.0/environment-setup-cortexa57-poky-linux 
    
  2. 設定された環境変数configureを実施する

     vagrant@ubuntu-bionic:/vagrant/Autotools-tutorial$ ./configure ${CONFIGURE_FLAGS}
    
  3. 設定された環境設定でプロジェクトのビルドを実施する

     vagrant@ubuntu-bionic:/vagrant/Autotools-tutorial$ make
    

おわりに

Linuxシステムを構築するツールYoctoを使用して、組込みLinuxディストリビューションを構築した。 YoctoはBuildRootなどと比較して、設定が複雑な印象があるが、純正性の高いディストリビューションを作成することができそうだ。またレイヤーによる概念により、再利用性が高くなっている。

変更履歴

  • 2020/02/23: 記事公開
  • 2022/06/08: 章構成を変更
  • 2022/06/25: ビルドによる成果物一覧を追加

参考

Yocto Projectの公式ガイド

Yoctoについて解説している記事

Yoctoのレシピ/レイヤーについて解説

BitBakeの解説