みつきんのメモ

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

raspberrypiでメディアサーバ(その2)

raspberrypi+yoctoでNAS+メディアサーバを構築した話の続き。 その際にハマった点や修正方法を記述する。 最終的には採用しなかった修正なども含まれるが、その際は採用しなかった旨を記述する。

なぜyoctoか? yoctoprojectがどういうものであるか?などについては一切触れない。

詳しい情報はhttp://www.yoctoproject.orgをみたりgoogle先生に聞いたりすると 正確な情報が手に入る。

作業用metaの作成

rootfsのイメージにパッケージを追加するだけならlocal.confに IMAGE_INSTALL_append で記述すれば可能だが、 ソースにパッチを当てたり、bbappendでレシピの一部を上書きしたりするには metaを修正する必要が出てくるため、作業用のmetaとしてmeta-localを作成する。

既存のレシピを修正すると大本のpokyの修正があった場合などに 管理が困難になることが考えられるためこの方法を採用している。

meta-localの構造

meta-localの最小構成として以下の構造になる。

meta-local
└── conf
    └── layer.conf

このようになるようにディレクトリやファイルを作成する。

$ cd ~/raspberrypi_dylan/poky
$ mkdir -p meta-local/conf
$ touch meta-local/conf/layer.conf

layer.confの作成

meta-local/conf/layer.confを下記の内容で作成する。

# We have a conf and classes directory, add to BBPATH
BBPATH .= ":${LAYERDIR}"

# We have recipes-* directories, add to BBFILES
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb ${LAYERDIR}/recipes*/*/*.bbappend"

BBFILE_COLLECTIONS += "local"
BBFILE_PATTERN_local = "^${LAYERDIR}/"
BBFILE_PRIORITY_local = "7"

BBFILE_PRIORITYは小さい数字ほどそのレイヤ(meta)は先に処理される。 他のレイヤの内容を参照する必要がある場合は、そのレイヤよりあとに処理されるように数字を調整する。

パッケージの追加

実現したい機能を追加するために必要なパッケージを含むmetaを取得する。

meta-oe

sambaのパッケージはmeta-oeにあるためmeta-oeを取得。

$ cd ~/raspberrypi_dylan/poky
$ git clone git://github.com/openembedded/meta-oe.git -b dylan

meta-baryon

mediatombのパッケージはmeta-baryonにあるためmeta-baryonも取得。

$ git clone git://git.yoctoproject.org/meta-baryon -b dylan

rpi-basic-image.bbappendの作成

rpi-basic-imageにsambaとmediatombを追加するために meta-local/recipes-core/images/rpi-basic-image.bbappendを作成する。

$ mkdir -p meta-local/recipes-core/images
$ touch meta-local/recipes-core/images/rpi-basic-image.bbappend

rpi-basic-image.bbappendの内容を以下のようにする。

IMAGE_INSTALL += "samba \
             mediatomb  \
"

rpi-basic-image.bbappend追加後のmeta-localは以下のようになる。

meta-local
├── conf
│   └── layer.conf
└── recipes-core
    └── images
        └── rpi-basic-image.bbappend

bblayers.confの編集

追加したmeta-local、mata-oe、meta-baryonを認識させるために、 build/conf/bblayers.confを修正。

BBLAYERS ?= " \
  /home/mickey/raspberrypi_dylan/poky/meta \
  /home/mickey/raspberrypi_dylan/poky/meta-yocto \
  /home/mickey/raspberrypi_dylan/poky/meta-yocto-bsp \
  /home/mickey/raspberrypi_dylan/poky/meta-raspberrypi \
  /home/mickey/raspberrypi_dylan/poky/meta-oe/meta-oe \
  /home/mickey/raspberrypi_dylan/poky/meta-baryon \
  /home/mickey/raspberrypi_dylan/poky/meta-local \
  "

bitbakeの実行

パッケージ追加の準備ができたのでbitbakeを実行してみる。

$ cd ~/raspberrypi_dylan/build
$ bitbake rpi-basic-image

コンソール新たに開くなどして環境変数が設定されていない場合は、 再度をsource oe-init-build-envを実行する。

$ cd ~/raspberrypi_dylan
$ source poky/oe-init-build-env build

mesaでビルドエラー

| ERROR: oe_runmake failed
| ERROR: Function failed: do_compile (see /home/mickey/raspberrypi_dylan/build/tmp/work/armv6-vfp-poky-linux-gnueabi/mesa/2_9.0.2-r9.1/temp/log.do_compile.32246 for further information)
ERROR: Task 1856 (/home/mickey/raspberrypi_dylan/poky/meta/recipes-graphics/mesa/mesa_9.0.2.bb, do_compile) failed with exit code '1'
NOTE: Tasks Summary: Attempted 2482 tasks of which 1669 didn't need to be rerun and 1 failed.
Waiting for 0 running tasks to finish:
Summary: 1 task failed:
  /home/mickey/raspberrypi_dylan/poky/meta/recipes-graphics/mesa/mesa_9.0.2.bb, do_compile
  Summary: There were 4 WARNING messages shown.
  Summary: There was 1 ERROR message shown, returning a non-zero exit code.

do_compileでエラーが発生している。 詳細なログは /home/mickey/raspberrypi_dylan/build/tmp/work/armv6-vfp-poky-linux-gnueabi/mesa/2_9.0.2-r9.1/temp/log.do_compile.32246 にある。

../../../../src/egl/wayland/wayland-drm/wayland-drm-client-protocol.h: In function 'wl_drm_create_buffer':
../../../../src/egl/wayland/wayland-drm/wayland-drm-client-protocol.h:182:2: error: implicit declaration of function 'wl_proxy_marshal_constructor' [-Werror=implicit-function-declaration]

いくつかエラーっぽいものが出ているが、[-Werror=implicit-function-declaration]はgccのバージョンが上がって チェックが厳しくなったことによるもの。 これを回避するにはコードを修正するのが正しいやり方だが、ここで使用しているソースコードはdylan時点でのものなので、 upstreamでは修正されている可能性が高い。 古いソースコードのままでコンパイルするにはconfigure時に-Werror=no-implicit-function-declarationを使用するという方法がある。

mesaレシピの修正

修正の方針が決まったらレシピを修正する。 主な手順は以下のようになる。

  1. パッチを作成
  2. meta-local/recipes-graphics/mesa/mesaにパッチを格納
  3. meta-local/recipes-graphics/mesa/mesa_9.0.2.bbappendを作成

パッチの作成

このようにパッチを作成する。

diff -Narubp a/configure.ac b/configure.ac
--- a/configure.ac  2014-10-06 11:08:29.937869593 +0900
+++ b/configure.ac  2014-10-06 11:08:20.521870042 +0900
@@ -198,7 +198,7 @@ if test "x$GCC" = xyes; then
     # generating a loadable driver module that has undefined symbols.
     save_CFLAGS="$CFLAGS"
     AC_MSG_CHECKING([whether $CC supports -Werror=missing-prototypes])
-    CFLAGS="$CFLAGS -Werror=implicit-function-declaration"
+    CFLAGS="$CFLAGS -Wno-implicit-function-declaration"
     CFLAGS="$CFLAGS -Werror=missing-prototypes"
     AC_LINK_IFELSE([AC_LANG_PROGRAM()],
           AC_MSG_RESULT([yes]),

これは/tmp/0001_avoid-implicit-function-declaration.patchとして置いておく。

次にmeta-local/recipes-graphics/mesa/mesaの場所に格納する。

$ cd ~/raspberrypi_dylan/poky
$ mkdir -p meta-local/recipes-graphics/mesa/mesa
$ cp /tmp/0001_avoid-implicit-function-declaration.patch meta-local/recipes-graphics/mesa/mesa

bbappendの作成

mesa_9.0.2.bbappendを作成しパッチを適用する。

$ touch meta-local/recipes-graphics/mesa/mesa_9.0.2.bbappend

mesa_9.0.2.bbappendは以下のようになる。

FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"

SRC_URI += "file://0001_avoid-implicit-function-declaration.patch"

mediatombでビルドエラー

(注)結果的にはmediatombへのパッチは適用しなかったので興味がなければ読み飛ばしてください。

| ERROR: oe_runmake failed
| ERROR: Function failed: do_compile (see /home/mickey/raspberrypi_dylan/build/tmp/work/armv6-vfp-poky-linux-gnueabi/mediatomb/0.12.1-r4/temp/log.do_compile.17948 for further information)
ERROR: Task 379 (/home/mickey/raspberrypi_dylan/poky/meta-baryon/recipes-multimedia/mediatomb/mediatomb_0.12.1.bb, do_compile) failed with exit code '1'
NOTE: Tasks Summary: Attempted 2556 tasks of which 2479 didn't need to be rerun and 1 failed.
Waiting for 0 running tasks to finish:
Summary: 1 task failed:
  /home/mickey/raspberrypi_dylan/poky/meta-baryon/recipes-multimedia/mediatomb/mediatomb_0.12.1.bb, do_compile
  Summary: There were 8 WARNING messages shown.
  Summary: There was 1 ERROR message shown, returning a non-zero exit code.

do_compileでエラーになっている。 /home/mickey/raspberrypi_dylan/build/tmp/work/armv6-vfp-poky-linux-gnueabi/mediatomb/0.12.1-r4/temp/log.do_compile.17948を確認する。

../src/metadata/ffmpeg_handler.cc:263:9: warning: 'int av_open_input_file(AVFormatContext**, const char*, AVInputFormat*, int, AVFormatParameters*)' is deprecated (declared at /home/mickey/raspberrypi_dyl\
an/build/tmp/sysroots/raspberrypi/usr/include/libavformat/avformat.h:1368) [-Wdeprecated-declarations]

こちらは[-Wdeprecated-declarations]が問題になっている様子。 -Wno-deprecated-declarationsで回避できる。

mediatombレシピの修正

mesaと同じように下記の手順でレシピを修正する。

  1. パッチを作成
  2. meta-local/recipes-multimedia/mediatomb/mediatombにパッチを格納
  3. meta-local/recipes-multimedia/mediatomb/mediatomb_0.12.1.bbappendを作成

パッチの作成

diff -Narubp a/configure.ac b/configure.ac
--- a/configure.ac  2015-01-15 08:27:24.226722160 +0900
+++ b/configure.ac  2015-01-15 20:20:53.787938149 +0900
@@ -365,7 +365,7 @@ AC_CACHE_SAVE

 CPPFLAGS_SAVE="$CPPFLAGS"
 CFLAGS_SAVE="$CFLAGS"
-CXXFLAGS_SAVE="$CXXFLAGS"
+CXXFLAGS_SAVE="$CXXFLAGS -Wno-deprecated-declarations"
 LDFLAGS_SAVE="$LDFLAGS"

 if test "x$EXTERNAL_TRANSCODING_OPTION_ENABLED" = xyes; then
@@ -1970,4 +1970,3 @@ if test "x$STATIC_OPTION_ENABLED" = xyes
 fi

 echo
-

これを/tmp/0001_avoid_deprecated_declarations.patchとして置いておく。 meta-local/recipes-multimedia/mediatomb/mediatombに格納する。

$ cd ~/raspberrypi_dylan/poky
$ mkdir -p meta-local/recipes-multimedia/mediatomb/mediatomb
$ cp /tmp/0001_avoid_deprecated_declarations.patch meta-local/recipes-multimedia/mediatomb/mediatomb

bbappendの作成

mediatomb_0.12.1.bbappendを作成しパッチを適用する。

$ touch meta-local/recipes-multimedia/mediatomb/mediatomb_0.12.1.bbappend

mediatomb_0.12.1.bbappendは以下のようになる。

FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"

SRC_URI += "file://0001_avoid_deprecated_declarations.patch"

まだエラー

上記パッチで[-Wdeprecated-declarations]を適用したが、まだ下記のようなエラーが発生する。

../src/metadata/ffmpeg_handler.cc: In function 'void addFfmpegMetadataFields(zmm::Ref<CdsItem>, AVFormatContext*)':
../src/metadata/ffmpeg_handler.cc:92:25: error: 'AVFormatContext' has no member named 'title'
../src/metadata/ffmpeg_handler.cc:94:6: error: 'AVFormatContext' has no member named 'title'
../src/metadata/ffmpeg_handler.cc:96:51: error: 'AVFormatContext' has no member named 'title'
../src/metadata/ffmpeg_handler.cc:98:25: error: 'AVFormatContext' has no member named 'author'
../src/metadata/ffmpeg_handler.cc:100:6: error: 'AVFormatContext' has no member named 'author'
../src/metadata/ffmpeg_handler.cc:102:51: error: 'AVFormatContext' has no member named 'author'
../src/metadata/ffmpeg_handler.cc:104:25: error: 'AVFormatContext' has no member named 'album'
../src/metadata/ffmpeg_handler.cc:106:6: error: 'AVFormatContext' has no member named 'album'
../src/metadata/ffmpeg_handler.cc:108:51: error: 'AVFormatContext' has no member named 'album'
../src/metadata/ffmpeg_handler.cc:110:18: error: 'AVFormatContext' has no member named 'year'
../src/metadata/ffmpeg_handler.cc:112:6: error: 'AVFormatContext' has no member named 'year'
../src/metadata/ffmpeg_handler.cc:114:64: error: 'AVFormatContext' has no member named 'year'
../src/metadata/ffmpeg_handler.cc:116:25: error: 'AVFormatContext' has no member named 'genre'
../src/metadata/ffmpeg_handler.cc:118:6: error: 'AVFormatContext' has no member named 'genre'
../src/metadata/ffmpeg_handler.cc:120:51: error: 'AVFormatContext' has no member named 'genre'
../src/metadata/ffmpeg_handler.cc:122:25: error: 'AVFormatContext' has no member named 'comment'
../src/metadata/ffmpeg_handler.cc:124:6: error: 'AVFormatContext' has no member named 'comment'
../src/metadata/ffmpeg_handler.cc:126:51: error: 'AVFormatContext' has no member named 'comment'
../src/metadata/ffmpeg_handler.cc:128:18: error: 'AVFormatContext' has no member named 'track'
../src/metadata/ffmpeg_handler.cc:130:6: error: 'AVFormatContext' has no member named 'track'
../src/metadata/ffmpeg_handler.cc:132:64: error: 'AVFormatContext' has no member named 'track'
../src/metadata/ffmpeg_handler.cc: In function 'void addFfmpegResourceFields(zmm::Ref<CdsItem>, AVFormatContext*, int*, int*)':
../src/metadata/ffmpeg_handler.cc:181:71: error: 'CODEC_TYPE_VIDEO' was not declared in this scope
../src/metadata/ffmpeg_handler.cc:212:31: error: 'CODEC_TYPE_AUDIO' was not declared in this scope
../src/metadata/ffmpeg_handler.cc: In function 'void FfmpegNoOutputStub(void*, int, const char*, va_list)':
../src/metadata/ffmpeg_handler.cc:242:6: note: the mangling of 'va_list' has changed in GCC 4.4
make[2]: *** [libmediatomb_a-ffmpeg_handler.o] Error 1

ffmpegで定義されている構造体が違っているらしい。 これは外部のライブラリ(ffmpeg)とバージョンの不整合が起きている可能性が高い。

mediatombの解決方法

試しにmeta-baryonをmasterブランチで取得し直したところ解決できた。

$ cd ~/raspberrypi_dylan/poky
$ rm -rf ./meta-baryon
$ git clone git://git.yoctoproject.org/meta-baryon
$ cd ../build
$ bitbake rpi-basic-image

(つづく)