みつきんのメモ

組み込みエンジニアです。Interface誌で「Yocto Projectではじめる 組み込みLinux開発入門」連載中

raspaberrypi2でcore-image-sato

yoctoでGUIを動かすための基本的なイメージであるcore-image-satoだが、 RPiではすんなりビルドが通らなかったことや、X-Windowsが古い、重いなどのイメージがあり、 RPiのような非力な環境で動かすために、労力を使うメリットを感じなかったため、 特に深追いしていなかった。 RPi2はそこそこパワーのある環境なので、試しに作ってみた。

今回は手順的なところよりも、発生した問題に対してどのように対処したかを重点的にメモしておく。

作成手順

yoctoの基本環境

$ mkdir ~/work/rpi2
$ cd ~/work/rpi2
$ git clone git://git.yoctoproject.org/poky.git

meta-raspberrypi

今まではagherzanさんのmeta-raspberrypiを使わせてもらっていたが、 blog開始当時とは異なり、yoctoprojectのリポジトリのRPi2化が進んだため、 こちらを使用するようにする。

$ cd ~/work/rpi2/poky
$ git clone git://git.yoctoproject.org/meta-raspberrypi

ビルド環境の設定

毎度おなじみの環境変数の設定およびビルドディレクトリの作成、移動。

$ cd ~/work/rpi2
$ source poky/oe-init-build-env build_sato

oe-init-build-envのあとにディレクトリ名を指定すると、 その名前でビルドディレクトリが作成される。 今回は、build_satoとする。

conf/bblayers.conf

これもおなじみとなってきたが、ビルドに使用するレイヤーの設定。

BBLAYERS ?= " \
  /home/mickey/work/rpi2/poky/meta \
  /home/mickey/work/rpi2/poky/meta-yocto \
  /home/mickey/work/rpi2/poky/meta-yocto-bsp \
  /home/mickey/work/rpi2/poky/meta-raspberrypi \
  "

BBLAYERSにmeta-raspberrypiを追加する。

conf/local.conf

こちらも毎度の設定だが、肝となる設定ファイル。

MACHINE ?= "raspberrypi2"
BB_NUMBER_THREADS = "6"
PARALLEL_MAKE = "-j 6"
GPU_MEM = "128"
LICENSE_FLAGS_WHITELIST += "commercial"
DL_DIR ?= "${TOPDIR}/../downloads"

ここではMACHINEをraspberrypi2に設定している。 DL_DIRの行はなくても構わないが、ダウンロードディレクトリを一段上げている。

bitbake実行

core-image-satoのビルドを実行する。

$ bitbake core-image-sato

エラー

bitbake

| checking for KHR/khrplatform.h... yes
| checking if arm-poky-linux-gnueabi-gcc  -march=armv7-a -marm  -mthumb-interwork -mfloat-abi=hard -mfpu=neon-vfpv4 -mtune=cortex-a7 --sysroot=/home/mickey/work/rpi2/build_sato/tmp/sysroots/raspberrypi2 -std=gnu99 supports -Wno-int-conversion... yes
| checking for X11... yes
| checking for EGL... no
| configure: error: Package requirements (egl) were not met:
|
| No package 'egl' found
|
| Consider adjusting the PKG_CONFIG_PATH environment variable if you
| installed software in a non-standard prefix.
|
| Alternatively, you may set the environment variables EGL_CFLAGS
| and EGL_LIBS to avoid the need to call pkg-config.
| See the pkg-config man page for more details.
| Configure failed. The contents of all config.log files follows to aid debugging
| ERROR: oe_runconf failed
| WARNING: exit code 1 from a shell command.
| ERROR: Function failed: do_configure (log file is located at /home/mickey/work/rpi2/build_sato/tmp/work/cortexa7hf-vfp-vfpv4-neon-poky-linux-gnueabi/libepoxy/1.2+gitAUTOINC+20062c25e7-r0/temp/log.do_configure.14448)
ERROR: Task 4685 (/home/mickey/work/rpi2/poky/meta/recipes-graphics/libepoxy/libepoxy_git.bb, do_configure) failed with exit code '1'
NOTE: Tasks Summary: Attempted 2779 tasks of which 0 didn't need to be rerun and 1 failed.
Waiting for 0 running tasks to finish:

Summary: 1 task failed:
/home/mickey/work/rpi2/poky/meta/recipes-graphics/libepoxy/libepoxy_git.bb, do_configure
Summary: There was 1 ERROR message shown, returning a non-zero exit code.

エラーメッセージと、詳細なログの場所が表示される。

ここで注目するのは以下の行。

| ERROR: Function failed: do_configure (log file is located at /home/mickey/work/rpi2/build_sato/tmp/work/cortexa7hf-vfp-vfpv4-neon-poky-linux-gnueabi/libepoxy/1.2+gitAUTOINC+20062c25e7-r0/temp/log.do_configure.14448)
ERROR: Task 4685 (/home/mickey/work/rpi2/poky/meta/recipes-graphics/libepoxy/libepoxy_git.bb, do_configure) failed with exit code '1'

上の行はログファイルの格納場所がフルパスが書かれている。このファイルをエディタで開いて解析したりする。 下の行はどのレシピでエラーが発生したかが書かれている。ここではlibepoxy_git.bbでエラーが発生している。

問題点

ここではログファイルを解析する前に、明確に以下の行に問題がありそうだと見受けられる。

| checking for EGL... no
| configure: error: Package requirements (egl) were not met:
|
| No package 'egl' found
|
| Consider adjusting the PKG_CONFIG_PATH environment variable if you

レシピのconfigure処理中にeglが見つからないことが問題になっていると推測できる。

環境にeglが存在しないのにconfigが有効化されていることが問題だと考えられるので、対処法は2種類考えられる。

  1. eglを環境に追加する
  2. eglをconfigから無効化する

これはeglが見つからないことが原因でエラーとなるレシピが他にどれだけ居るか(居そうか)?というところが アプローチを決定するなんとなくの要因となる。

configでeglが有効化される要因

libepoxy_git.bbを見てみる。

DEPENDS = "util-macros virtual/egl"

依存関係にvirtual/eglが明示されている。

virtual/eglというレシピについて

virtualというキーワードから推測されるように、virtual/eglという名前のレシピは存在しない。 その名の通り仮想レシピとなる。

EGL自体はハードウェアに依存するが、EGLの機能を使用するレシピはEGLに依存するだけで通常ハードウェアには依存しない。

f:id:mickey_happygolucky:20150628003530p:plain

仮想レシピが存在しない場合、EGLの機能を使用するためだけにハードウェア毎にレシピを分ける必要が出てくる。

f:id:mickey_happygolucky:20150628003540p:plain

そのような問題を解決するために、EGLの機能を利用するがハードウェアに依存しないレシピからは「virtual/egl」に依存関係を設定すると、ハードウェア環境によって適切なeglの機能を提供するレシピが選択されるようになっている。

f:id:mickey_happygolucky:20150628003553p:plain

具体的には、PREFERRED_PROVIDER_virtual/eglによって指定されたレシピが選択されるようになっている。 この、PREFERRED_PROVIDERは各ボードのBSPのレイヤーなどで設定されているがlocal.confで上書きすることもできる。

仮想レシピの機能を提供するレシピには以下のように記述をしておく。

PROVIDES = "virtual/egl"

その他の仮想レシピとしてはvirtual/kernelなどが存在する。

virtual/eglの実態

virtual/eglが実際にはどのレシピになるかを確認する。

$ bitbake virtual/egl -v
...
NOTE: selecting userland to satisfy virtual/egl due to PREFERRED_PROVIDERS

userlandのレシピが選択されている。

eglのレシピが存在しているのにエラーが出る原因

virtual/eglで選択されたuserlandは、この時点で正しくビルドされている。 本来の解釈であれば、eglライブラリは存在するはずである。なぜeglが見つからないのか。

ログメッセージの以下を再度見ると、eglの検出にはpkg-configを利用している。 pkg-configがライブラリの検出するためには「ライブラリ.pc」というファイルが必要になる。

この場合、「egl.pc」が必要になる。

| configure: error: Package requirements (egl) were not met:
|
| No package 'egl' found
|
| Consider adjusting the PKG_CONFIG_PATH environment variable if you
| installed software in a non-standard prefix.
|
| Alternatively, you may set the environment variables EGL_CFLAGS
| and EGL_LIBS to avoid the need to call pkg-config.
| See the pkg-config man page for more details.

userlandのレシピが、egl.pcを提供するかどうかを調べる。 tmp以下にあるuserlandのビルドディレクトリからegl.pcが見つかるかどうかで判断する。

$ cd tmp/work/
$ find -name 'userland'
./raspberrypi2-poky-linux-gnueabi/userland
./raspberrypi2-poky-linux-gnueabi/userland/git-r4/pkgdata/runtime-reverse/userland
./raspberrypi2-poky-linux-gnueabi/userland/git-r4/pkgdata/runtime/userland
./raspberrypi2-poky-linux-gnueabi/userland/git-r4/pkgdata/userland
./raspberrypi2-poky-linux-gnueabi/userland/git-r4/license-destdir/userland
./raspberrypi2-poky-linux-gnueabi/userland/git-r4/packages-split/userland-dbg/usr/src/debug/userland
./raspberrypi2-poky-linux-gnueabi/userland/git-r4/packages-split/userland
./raspberrypi2-poky-linux-gnueabi/userland/git-r4/sysroot-destdir/sysroot-providers/userland
./raspberrypi2-poky-linux-gnueabi/userland/git-r4/package/usr/src/debug/userland

つまりuserlandのビルドディレクトリは「./raspberrypi2-poky-linux-gnueabi/userland」

$ find ./raspberrypi2-poky-linux-gnueabi/userland -name 'egl.pc'

みつからない。 つまり、userlandのレシピはegl.pcを提供していないことがわかる。

対処方法

meta-raspberrypiにおいてvirtual/eglの機能を提供するレシピは、実はuserlandの他にも存在している。 そしてそれは、egl.pcを提供している。

vc-graphicsの存在

以下のように検索すると、virtual/eglの機能を提供する仮想レシピがuserlandの他にも存在することがわかる。

$ cd ~/work/rpi2/poky/meta-raspberrypi
$ grep -r 'virtual/egl' .
./recipes-graphics/vc-graphics/vc-graphics.inc:PROVIDES = "virtual/libgles2 virtual/egl"
./recipes-graphics/userland/userland_git.bb:            virtual/egl"

egl.pcの提供

vc-graphics.incを見ると以下の記述が見つかる。

SRC_URI += " \
    file://egl.pc \
    file://vchiq.sh \
"

つまり、egl.pcを提供している。

vc-graphics.incを使用しているレシピ

.incファイルは複数のレシピで共通化できる部分を抜き出したもの。

つまり、.incに記述された部分をイメージに取り込むためには、これをインクルードしているレシピを特定する必要がある。

以下のコマンドでvc-graphics.incをインクルードしているレシピを絞り込む

$ grep -r 'vc-graphics.inc' .
./recipes-graphics/vc-graphics/vc-graphics.bb:require vc-graphics.inc
./recipes-graphics/vc-graphics/vc-graphics-hardfp.bb:require vc-graphics.inc

vc-graphics.bbとvc-graphics-hardfp.bbが見つかる。 これらはTUNEのパラメータをsoft-floatにするかhard-floatにするかで選択する。

bitbakeのログに以下のようにcallconvention-hardが出ているため、 この環境はhard-floatとなるので、vc-graphics-hardfp.bbを使用する。

Build Configuration:
BB_VERSION        = "1.27.1"
BUILD_SYS         = "x86_64-linux"
NATIVELSBSTRING   = "Ubuntu-15.04"
TARGET_SYS        = "arm-poky-linux-gnueabi"
MACHINE           = "raspberrypi2"
DISTRO            = "poky"
DISTRO_VERSION    = "1.8+snapshot-20150627"
TUNE_FEATURES     = "arm armv7a vfp thumb neon callconvention-hard vfpv4 cortexa7"
TARGET_FPU        = "vfp-vfpv4-neon"

virtual/eglがvc-graphics-hardfpを選択されるようにする

先述の通り、PREFERRED_PROVIDER_virtual/eglをlocal.confで上書きするのだが注意点がある。

vc-graphics.incとuserland_git.bbをそれぞれ見てみる。

vc-graphics.inc

PROVIDES = "virtual/libgles2 virtual/egl"

userland_git.bb

PROVIDES = "virtual/libgles2 \
            virtual/egl"

それぞれ、virtual/libgles2も提供しているため、virtual/eglのみを変更すると、 userlandとvc-graphpicsのレシピが同時にインストールされることになる。

しかし、これらは同時にインストールすることはできない^1ため、 virtual/eglとvirtual/libgles2はセットで上書きする必要がある。

conf/local.confの修正

以下の記述をlocal.confに追加する。

PREFERRED_PROVIDER_virtual/egl = "vc-graphics-hardfp"
PREFERRED_PROVIDER_virtual/libgles2 = "vc-graphics-hardfp"

動作確認

イメージを作成して動作確認する。

ビルド

$ cd ~/work/rpi2/build_sato
$ bitbake core-image-sato

焼きこみ

$ sudo dd if=./tmp/deploy/images/raspberrypi2/core-image-sato-raspberrypi2.rpi-sdimg of=/dev/sdb bs=40M

実行画面

f:id:mickey_happygolucky:20150628002923j:plain

動作した。