深く考えずにFirefox OSの移植に挑戦!……中です。【前編】

本稿では、一般的な評価ボードを対象にFirefox OSの移植に挑戦した顛末を、ざっくばらんに書きました。
じつのところ、本稿執筆段階ではまだFirefox OSの移植には成功しておりません。しかし、Firefox OSと、その移植ベースとなるAndroidのバージョン依存関係の事などをとりあえずまとめましたのでここで公開に至りました。よって、Firefox OSの移植を成功させるための情報を求めている方には大変申し訳ありませんが、せめて、本稿に書かれた失敗を繰り返さないようにしていただければと思います。

by Kenichiro Mitsuda  2014/04/7

vol1_thumb

1. この記事について

現在、手元にあった評価用ボードコンピュータへのFirefox OSの移植に挑戦しています。
この記事では、移植の作業の中で調べたことや行ったことを、前後編に分けてお届けします。 前編では、Firefox OSを移植しようと思った訳やFirefox OSの構造についての簡単な説明、移植手順を簡単に説明した後、実際にターゲットボードへの移植~最初の失敗までのまとめました。
後編では、ターゲットボードへの移植をさらに掘り下げて、移植ベースとなるAndroidのバージョンやFirefox OSのバージョンについて調べた結果やそれらを対象に行った移植作業などをまとめました。
また本文の中では特に断りなくmanifestファイルに対する操作が出てきます。manifestファイルになじみのない方のために、かんたんな解説「Android manifestファイル解説~超ざっくり編」を用意してあるので、必要に応じて参照してください。

2. ボードコンピュータでFirefox OS動かしたい!

2.1. 事の起こり

会社にあった何かの評価用のボードコンピュータで、イマドキのリッチなUIを持つOSを動かしてみる事になった。
今回のターゲットとなるボードコンピュータの主なスペックは以下の通りで、最近流行のRaspberry PiやBeagleBone Blackよりちょっと高級なもの。

項目スペック
ProcessorARM® Cortex™-A9 DualCore
Maximum Frequency866MHZ
Memory512MB DDR3
SD ConnectorSD Card
USB2(OTG 2.0 & USB-UART)
Ethernet10/100/1000
Displays1080p HDMI & 8-bit VGA
Tbl.2-1 ターゲットボードの主要スペック

ただしホビー向けボードとは違い、製造元からはBSP版のLinux kernelと、それを用いたUbuntu Desktop 12.04 のビルド&インストール方法が公開されているのみ。
まずは、このターゲットボードで動作させるOSを選ぶために世間様の動向を軽く調べてみた。するとAndroidの2.2(Froyo)、2.3(Gingerbread)および4.1.2(Jelly Bean)は移植した人がいる模様で、そのうち2.3と4.1.2は移植の手順も公開されてた。
これならば、最近のAndroid例えば Jelly Bean MR2(4.3)やKitKat(4.4)を動かしてみるってのもありかと思って、これらのAndroidの事を調べてみると、どうやらJelly Bean MR1(4.2)以降は

  • 動作推奨メモリの増加(1GByte以上?)
  • 高いグラフィックス性能が必要(OpenGL ES 2.0以上?)

といった感じで要求するスペックが高騰。どうやら先人たちも、このターゲットボードの性能との兼ね合いから移植が止まっていることがわかった。
う~ん、Androidを移植することについてはテンションがDown……。

2.2. Firefox OS !?

そんな折り、たまたま参加したイベントで Mozilla Japanの方による「Firefox OS」についての講演を聞く機会があった。そこで紹介されたFirefox OSの特徴のうち、特に

  • Android 4.0(Ice Cream Sandwich)以降が動作しているなら移植は可能
  • メインメモリ256MByteでも動作可能。将来的に 128MByteでも動作する予定

という点にコレだ!とテンションUp。
Firefox OSなら、今回のターゲットボードのような組込み向けボードへの移植に関しても

  • Android動作の実績あり → 意外とすんなり動いちゃうかも!?
  • メモリ256MByteでも動作可 → ターゲットボードの性能でも余裕?
  • Firefox OSは最新のモバイルOS → 最先端行ってます!的な空気が出るかも。

そんなお花畑妄想でもって、あまり深く考えずに移植をスタートしました。
以下、本稿では一般的なボードコンピュータにFirefox OSを移植しようとしてやったアレコレを明かしていきます。

3. まずは Study & Hands-on

3.1. 移植のための情報収集

Firefox OSの移植に必要な情報……と言っても、そもそも情報はあまり多くない。
現状の情報源としては、まず第一にmozilla自身が運営するオフィシャルサイト
http://www.mozilla.org/ja/firefox/os/

英語が多い orz)、次いでGeekたちが集うFirefox OSコミュニティのサイト(日本語!)
http://fxos.org/

と言ったところ。とりあえず、コミュニティのサイトを見ていると”Firefox OS 本体のカスタマイズ用ドキュメント”としてオフィシャルサイトの以下のページが紹介されていた。
MDN(MOZILLA DEVELOPER NETWORK) の “Porting Boot to Gecko”
https://developer.mozilla.org/en-US/Firefox_OS/Porting
が、このページは英語で書かれており、かつ、記述も簡素なためちょっと厳しそう。
で、もう一度Firefox OSコミュニティに戻るとトップページで宣伝されている書籍 〝Firefox OSアプリ開発ガイド”[1]が目についた。
「べ、別にアプリが作りたいんじゃないだからね」とは思ったものの、念のため販売サイトで目次を見てみると……

目次 第6章 各種デバイス向けのビルド手順
……
6.2 サポート対象外デバイス向けのビルド

Fig.3-1 Firefox OSアプリ開発ガイドの目次(抜粋)

キターー!というわけでコミュニティの方々に感謝しつつ、本を購入し、ハンズオン開始!

3.2. アーキテクチャと移植のポイントをStudy

ここで、Firefox OSの移植手順を理解するために、AndroidとFirefox OSそれぞれのアーキテクチャを比較してみよう。実はFirefox OSではAndorid のLinuxカーネルやHAL、ライブラリおよびデバイスドライバをまるまる流用し、その上に独自のWebランタイムやUIを構築している。Firefox OSを移植するための前提として、「Android 4.0(Ice Cream Sandwich)以降が動作していること」とあるのはこのような構造を持つからだ。

Fig. 2 2  AndroidとFirefox OSのアーキテクチャ
Fig.3-2 AndroidとFirefox OSのアーキテクチャ

これらの事から、Firefox OSの移植とはAndroidのアプリケーションフレームワークやAndroidランタイム(主に、Javaを動作させる仕組み)と HTMLを処理するための Mozilla製webランタイムやUIをすげ替えることになる。この「すげ替え」とは、AndroidやFirefox OSのソースコード群を定義している〝manifestファイル”を編集することを意味する。

3.3. 教科書どおりのHands-on

Firefox OSアプリ開発ガイド[1]では、Beagleboard-xMをターゲットに以下のような流れで移植が行われる。

  1. ソースコード取得
    • B2Gレポジトリ(Firefox OSのビルドに必要なスクリプトなどを含む)を取得
    • ターゲットボードに合わせて config.sh を修正
    • ターゲットボードに合わせてmanifestファイルを作成
    • config.shを実行してソースコードを取得
  2. ソースコードの改造
    • 既知のバグ対処
    • ビルドエラー対処
  3. Firefox OSのビルド
  4. ブート用SDカードの作成
  5. 動作確認

まずは本に従い粛々と移植を試みた結果、Beagleboard-xMで無事Firefox OSの起動を確認。これはこれでちょっと感動。
こんな感じなら、結構イケるんじゃない?と気を良くして本番へGo!


COLUMN—「Firefox OSアプリ開発ガイド」の6.2章でつまずいた点

実際にはTypoなどに引っかかって、そこそこやり直したりした。以下、主に引っかかったところ

  • 執筆時との情報のズレ
    本書[1]を見ながら作成したmanifestファイルと本書[1]の購入者限定サポートサイト(url 6)からダウンロードしたものを比較すると、一部のプロジェクトでrevisionが異なるなど違いがあった。Firefox OSを動かすことが目的ならDownload(ただし、本書の購入者限定)したものを使うのが吉。
  • 手順の抜け
    本書[1]のpp214のリスト6.2.9の説明に「このフォルダが残っていると、ビルド時にプロジェクトファイルの競合がおきてしまいエラーになりますので、必ず削除してください。」とあるが、実際にはフォルダ実体だけでなく、manifestファイルからもこのプロジェクトの記述 … の部分を削除する必要があった。 またmanifestファイルは、最初に作成したものと、ソースコード取得時に/B2G/.repo/manifests/配下にコピーされたものの2つがあるため、両方から削除(又はコメントアウト)する必要があった。
  • pp224–225のリスト6.2.25にあるコマンド mktarball.shの引数が間違っていた。
    誤)../../../../build/tools/mktarball.sh ../../../host/linux-x86/bin/fs_get_stats android_rootfs rootfs rootfs.tar.bz2
    正) ../../../../build/tools/mktarball.sh ../../../host/linux-x86/bin/fs_get_stats android_rootfs . rootfs rootfs.tar.bz2 #ピリオドを追加
  • pp225のリスト6.2.26のmkbootscrのフォントが読みにくかったりして、間違いを繰り返した。最終的に動作したのは以下のとおり(本来は1行で記述)
    setenv bootargs ‘console=ttyO2,115200n8 androidboot.console=ttyO2 mem=256M root=/dev/mmcblk0p2 rw rootfstype=ext4 rootwait init=/init ip=off omap_vout.vid1_static_vrfb_alloc=y vram=8M omapfb.vram=0:8M omapdss.def_disp=dvi omapfb.mode=dvi:1024×768-16’

教訓:

  • この手の本に誤植は付き物なので、失敗してもいろいろ試してみる事が大事。
  • あと、出版社のwebにサポートページがあるのでこまめにチェックすると吉!

4. ターゲットボードへの移植1回目
Firefox OS v1-train + Android(JB4.1)

本[1]に従って、Beagleboard-xMで無事Firefox OS が起動したので、Hands-onと同じ手順でターゲットボードへの移植に挑戦。
とりあえず、B2Gレポジトリの取得はつつがなく完了。ここから先が移植作業の本番。

4.1. config.shの編集

B2Gレポジトリの中にあるconfig.shは、環境変数の設定とソースコード取得をするためのスクリプト。これをハンズオンと同様、ターゲットボード名を引数に指定された際、内部でDEVICE=<ターゲットボード名>、LUNCH=<Androidのlunchコマンドの引数>が設定されるように修正。

"pandaboard")
echo DEVICE=panda &amp;amp;gt;&amp;amp;gt; .tmp-config &amp;amp;amp;&amp;amp;amp;
repo_sync $1
;;
"ターゲットボード名")
echo DEVICE=ターゲットボード名 &amp;amp;gt;&amp;amp;gt; .tmp-config &amp;amp;amp;&amp;amp;amp;
echo LUNCH=AndroidのLUNCHコマンドの引数 &amp;amp;gt;&amp;amp;gt; .tmp-config &amp;amp;amp;&amp;amp;amp;
repo_sync $1
;;

list.4-1 config.shの修正

4.2. ターゲットボード向けmanifestファイル作成

Hands-onと同じく、PandaBoard向けのFirefox OSバージョン1.0(v1-trainブランチ)のmanifestファイルを参考にして、ターゲットボードのmanifestファイルを作成することに。
大まかな手順は、ターゲットボードのandroid-4.1.2用manifestファイルをベースに

  • Firefox OS独自のプロジェクトの追加
  • Firefox OSで不要なプロジェクトの削除

を行う。なお、manifestファイル名もHands-onに合わせて”<ターゲットボード名>.xml”とした。

4.2.1 manifesファイルへのFirefox OS独自プロジェクトの追加

まずは、Firefox OS独自のプロジェクトの追加から。参考のためFirefox OSのバージョン1.0(v1-trainブランチ)のmanifestファイルをダウンロード。

&amp;amp;gt; git clone https://github.com/mozilla-b2g/b2g-manifest.git
&amp;amp;gt; cd b2g-manifest/
&amp;amp;gt; git checkout -b v1-train-work origin/v1-train

list.4-2 Firefox OS manifestファイルの取得(v1-trainブランチより)

b2g-manifestディレクトリの中から、ボードコンピュータPandaBoard 向けmanifestファイルpandaboard.xmlを見てみると……

▼pandaboard.xmlの抜粋

&amp;amp;lt;remote name="aosp" fetch="https://android.googlesource.com/"/&amp;amp;gt;
&amp;amp;lt;remote name="b2g" fetch="git://github.com/mozilla-b2g/"/&amp;amp;gt;
&amp;amp;lt;remote name="linaro" fetch="http://android.git.linaro.org/git-ro/"/&amp;amp;gt;
&amp;amp;lt;remote name="caf" fetch="git://codeaurora.org/"/&amp;amp;gt;
&amp;amp;lt;remote name="mozilla" fetch="git://github.com/mozilla/"/&amp;amp;gt;
&amp;amp;lt;remote name="mozillaorg" fetch="https://git.mozilla.org/releases"/&amp;amp;gt;
&amp;amp;lt;default revision="refs/tags/android-4.0.4_r2.1" remote="caf" sync-j="4"/&amp;amp;gt;

&amp;amp;lt;!-- Gonk specific things and forks --&amp;amp;gt;
&amp;amp;lt;project path="build" name="platform_build" remote="b2g"
   revision="7cb46499e0b91ca20f6aed58d6067d7c451875b9" upstream="v1-train"&amp;amp;gt;
     &amp;amp;lt;copyfile src="core/root.mk" dest="Makefile"/&amp;amp;gt;
&amp;amp;lt;/project&amp;amp;gt;
&amp;amp;lt;project path="dalvik" name="fake-dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce" upstream="v1-train"/&amp;amp;gt;
&amp;amp;lt;project path="gaia" name="gaia.git" remote="mozillaorg" revision="v1-train"/&amp;amp;gt;
&amp;amp;lt;project path="gecko" name="gecko.git" remote="mozillaorg" revision="gecko-18"/&amp;amp;gt;
&amp;amp;lt;project path="gonk-misc" name="gonk-misc" remote="b2g" revision="v1-train" upstream="v1-train"/&amp;amp;gt;
&amp;amp;lt;project path="rilproxy" name="rilproxy" remote="b2g" revision="f634b3d50effdd42828cc757c01fdbf74e562a36" upstream="v1-train"/&amp;amp;gt;
&amp;amp;lt;project path="external/moztt" name="moztt" remote="b2g" revision="1333283efce26b17a815bc4c98da330edcda9f66" upstream="v1-train"/&amp;amp;gt;

&amp;amp;lt;!-- Stock Android things --&amp;amp;gt;
…<省略>…

list.4-3 pandaboard 向けmanifestファイルpandaboard.xml(抜粋)

list.4-3の9行目のコメントのとおり、10行目~19行目がFirefox OSでのみ必要となるソフトウェアプロジェクトだ。なので、これらはターゲットボード向けのmanifestファイルにもそのままコピーすることに決定。21行目以降は、Androidと共通のソフトウェアプロジェクトやpandaboard向けのkernelや各種ドライバ等のソフトウェアプロジェクトが定義されている。
おっとここで、念のために21行目以降のソフトウェアプロジェクトにもFirefox OS向けの独自実装が無いかを確認しよう。

手がかりとして、1~6行目に定義されているremote要素の属性fetchに注目してみると、以下の表のサーバがソースコードのダウンロード元として定義されていることがわかる。

Nameダウンロード元サーバ(fetch)備考
Aosphttps://android.googlesource.com/オープンソース版Androidの配布元
b2ggit://github.com/mozilla-b2g/Firefox OSのソースコード配布元
Linarohttp://android.git.linaro.org/git-ro/ARM系CPUのLinuxカーネルなどを開発する非営利団体Linaroのソースコード配布元
Cafgit://codeaurora.org/主にQualcomm社製SoC向けLinux /Androidのソースコード配布元
Mozillagit://github.com/mozilla/Firefoxの開発元であるMozillaの各種ソースコード配布元
Mozillaorghttps://git.mozilla.org/releasesMozillaのリリース物の配布元

このことから、21行目以降の要素の属性remoteが”b2g”, “mozilla”, “mozillaorg”と定義されているものは、Firefox OS向けに独自実装されたソフトウェアプロジェクトと考えられる。この方針でpandaboard.xmlを検索してみると、以下のソフトウェアプロジェクトが該当した。
▼Firefox OS独自実装のソフトウェアプロジェクト

&amp;amp;lt;project path="external/opensans" name="platform_external_opensans" remote="b2g" revision="b5b4c226ca1d71e936153cf679dda6d3d60e2354" upstream="v1-train"/&amp;amp;gt;
&amp;amp;lt;project path="external/screencap-gonk" name="screencap-gonk" remote="b2g" revision="e6403c71e9eca8cb943739d5a0a192deac60fc51" upstream="v1-train"/&amp;amp;gt;
&amp;amp;lt;project path="device/ti/panda" name="android-device-panda" remote="b2g" revision="eec93d3e9eb7765f63415e2ad42003a00b5996b4" upstream="v1-train"/&amp;amp;gt;
&amp;amp;lt;project path="external/negatus" name="Negatus" remote="mozilla" revision="151697c638a6781e83c76d4a01fb001aabde4e79"/&amp;amp;gt;
&amp;amp;lt;project path="external/orangutan" name="orangutan" remote="b2g" revision="601280aed7d7f29f1a78496f6fa41bd79c16305c" upstream="v1-train"/&amp;amp;gt;

list.4-4 Firefox OS向けの実装と思われるソフトウェアプロジェクト

ここで、3の”device/ti/panda”は明らかにPandaBoardのデバイスドライバと思われるため除外し、残りの”external/”配下に置かれるものはターゲットボード向けのmanifestファイルに含めることにする。とりあえず、以上でFirefox OS独自プロジェクトの追加は完了。

4.2.2. manifesファイルからFirefox OSで不要なプロジェクトの削除

次はFirefox OSで不要なプロジェクトの削除。これのややこしい点は、具体的に不要なプロジェクトが何かという情報が無かったこと。今回はハンズオンで使用した、beagleboard-xMのAndroid用manifestファイルとFirefox OS用に作成したそれの差分を抽出し、Android用manifestファイルから削除されたソフトウェアプロジェクトをターゲットボード向けmanifestファイルからも削除した。

Fig. 3-2 Firefox OSで不要なソフトウェアプロジェクトの削除
Fig. 4-1 Firefox OSで不要なソフトウェアプロジェクトの削除

こうすれば、少なくともターゲットボード向けのmanifestファイルに、間違ってBeagleboard-xM向けのソースコードが混ざることは無いだろう。
ちなみに、Firefox OSで不要なプロジェクトはザックリ言えば以下のような感じ

  • AndroidのJavaに関係するソフトウェアプロジェクト
    • Javaランタイム:dalvik
    • アプリケーションフレームワーク:frameworks/配下のJavaのコード
    • Javaで作成された標準アプリ: packages/ 配下に置かれるもの等
  • その他
    • Firefox OSが提供する機能で置き換えるもの:WebKitなど
    • Androidでしか必要ないもの:CTS(互換性テストスイート)
    • Firefox OSでは未サポートのサービス:external/配下の物多数

ちなみに、Beagleboard-xMでFirefox OSでは不要となったソフトウェアプロジェクトの数は148。これだけでも、Firefox OSがAndroidに比べて軽いような気がしてくる。

4.3. ソースコードの取得

コンソールから ./config.sh <ターゲットボード名> <manifestファイル名>[return] でバリバリダウンロード開始。しばし待つ。

4.4. ソースコードの修正

とりあえず、ターゲットボードのAndroid向け改造+ハンズオンで実施したFirefox OS向けの改造を施す。

4.5. Firefox OSのビルド

Firefox OSのビルドは B2G レポジトリにあるスクリプトbuild.sh で実施。
スクリプトを実行すると、Androidのenvsetup.sh, lunchコマンド結果と似た環境変数の設定が行われたと思ったら、いきなりエラーで停止した。
エラーメッセージによるとLOCAL_NDK_VERSIONの不整合が問題らしい。
Firefox OSはビルドシステムもAndroidと共通なため、ここでエラーが出たLOCAL_NDK_VERSIONとはAndroidのAPI Level(NDKバージョンを含む)の事と思われる。そこでまず、AndroidのAPI Levelの変遷を確認するために、Androidの開発者向け公式のサイトでAndroidのバージョンとAPIの関係をチェック。
 http://source.android.com/source/build-numbers.html
これによると、ターゲットボードのAndroidはバージョン”4.1.2″なので、API Level は16だとわかる。
つぎに、firefox OSのv1-tranchのマニフェストファイルで指定されているAndroidのバージョンを確認すると”4.0.4″。ということは、API Levelは15!
つまり、firefox OSのv1-tranchではベースとしてICS(android-4.0.4_r2.1)が想定されているのに対して、ターゲットボードのmanifestファイルではandroid-4.1.2_r1を使用していたのが原因らしい。

Android (AOSP)Firefox OS (B2G)
Code nameVersionAPI Levelv1-train
Ice Cream Sandwichandroid-4.0.4_r2.115
Jelly Bean (4.1)(省略)16未サポート
 android-4.1.2_r116未サポート
 (省略)16未サポート

移植のベースとなるAndroidのバージョンを4.0.4(ICS)にしてやり直すしかない。
とりあえず、ダメ元でターゲットボード用のmanifestファイルを開いて、defaultで指定されている revision を”android-4.0.4_r2.1″に修正し、./config.sh コマンドを再実行……。
結果、一部のプロジェクトが存在しないとかで、repo syncに失敗 orz.


教訓:

  • バージョンを変える際はmanifestファイルも取得しなおすこと。バージョンによって、含まれるプロジェクトが変わったり、同じプロジェクトでも指定されるバージョンが特別だったりする。
  • Firefox OSをポーティングするときは、ベースとするAndroidのバージョンに気を付ける。

Android manifestファイル解説~超ざっくり編 (PDF)


深く考えずにFirefox OSの移植に挑戦!……中です。【後編】