ククログ

株式会社クリアコード > ククログ > Firefoxの独自ビルドの作成方法(2015年版)

Firefoxの独自ビルドの作成方法(2015年版)

概要

弊社はMozilla FirefoxをはじめとしたMozilla製品の技術サポートを提供していますが、希に、自社製品の一部としてFirefoxを顧客向けに配布したいというご相談を頂くことがあります。

結論から先に言うと、このような場合にはFirefoxをソースから独自にビルドする必要があります。 この記事では、Windows上でのFirefox 38.2.1ESRのローカライズ済み(日本語版)インストーラを作成するまでの手順を紹介します。

2022年8月12日追記:本記事よりも新しい情報が2017年版の同趣旨の記事にありますので、基本的にはそちらをご参照下さい。この記事はアーカイブ目的で保存された物です。

背景・動機

弊社ではFx Meta Installerというソフトウェアを開発・公開しており、これを使うと、「自組織向けにカスタマイズされたFirefox」と呼べるひとそろいの環境を手軽に展開することができます。 弊社ではサポートビジネスの一環として、顧客組織内での展開用にFx Meta Installerを使ったカスタマイズのご案内をしておりますが、このようなケースは「自組織内で使うための限定的な再配布」にあたるため、Mozilla公式で配布されているFirefoxのインストーラを使用しても問題はありません。

しかし、希に、弊社のサポートサービス提供先の組織内での利用ではなく、その組織(企業)が顧客向けの製品として、Firefoxに特定のアドオンや設定ファイルをバンドルした物をFx Meta Installerベースで作成して提供したいというご相談を頂く事があります。 このようなケースは「自組織外への再配布」となるため、ライセンスの都合上、そこに「Firefox」というブランドが付与された製品を同梱することはできません。

そこで登場するのが「ノーブランド版」です。 「Firefox」というブランドが付与されていない「Firefoxのソースに基づいた別製品」を配布する分には、上記のような制約はありません。 ただ、そのようなバイナリは一般公開されていないため、Firefoxのソースを使って自分で作る必要があります。

以上が、Firefoxの独自ビルド作成の動機ということになります。 (なので、正確にはこの記事の趣旨は「Firefoxのソースに基づいた別製品のビルド方法」と言うことになります。)

情報のありか

Firefoxのビルドに関する情報は、Build Instructionsから辿ることができます。 Windowsでのビルドでは、Windows build prerequisitesSimple Firefox buildを見ると必要な情報が手に入ります。 以下の手順も、基本的にはこれらのページから得られる情報に基づいています。

ビルド環境の構築

Windows上でFirefoxをビルドするために必要なソフトウェアは、すべて無料で入手できます。

Visutal StudioとWindows SDKが特にファイルサイズが大きく、ダウンロードにはそれなりに時間がかかります。

ソースの入手

Firefoxのソースコードはスナップショットのtarballとしても入手できますが、ここではMercurialのリポジトリをcloneする方法で手順を解説します。

環境構築の際に導入したMozillaBuildはMinGWのコマンドラインコンソールを含んでおり、ビルドの作業はこのコンソールから行います。 C:\mozilla-build\start-shell-msvc2013.bat をダブルクリックしてコンソールを開きましょう。

コンソールを開いたら、リポジトリをcloneするためのディレクトリを用意します。

$ mkdir /c/mozilla-source
$ cd /c/mozilla-source

次に、Firefoxのリポジトリをcloneします。

Firefoxやその他のMozilla製品のリポジトリはhttps://hg.mozilla.org/で公開されています。 Nightlyの最新版やESR版など、どのバージョンをビルドしたいかによってどのリポジトリをcloneするかが変わります。 ESRを含むリリース版のFirefoxのソースはreleases/以下にあり、ESRの場合はreleases/mozilla-esr38のようにバージョン番号を含むパスのリポジトリ、一般向けのリリース版の場合はreleases/mozilla-releaseのリポジトリです。 今回はFirefox 38.2.1ESRをビルドしたいので、releases/mozilla-esr38をcloneします。

$ hg clone https://hg.mozilla.org/releases/mozilla-esr38

リポジトリの規模が数GBと大きいので、cloneにはそれなりの時間がかかります。

Firefox本体のリポジトリをcloneできたら、次は言語リソースのリポジトリをcloneします。 言語リソースのリポジトリは言語ごとに分かれており、ESRを含むリリース版のFirefoxの日本語用言語リソースはreleases/l10n/mozilla-release/jaです。

$ hg clone https://hg.mozilla.org/releases/l10n/mozilla-release/ja ja

cloneする際に、hgコマンドの3番目の引数としてディレクトリ名を、明示的に言語コード名のjaと指定します。 これは、MozillaBuildでのビルド時には言語リソースが言語コード名に基づいて検索されるためです。

ビルドの準備

cloneしたリポジトリは、次のリリースに向けての作業が進行している状態になっています。 Firefox 38.2.1ESRのように特定のバージョンをビルドするには、タグに基づいてそのリビジョンのソースをチェックアウトする必要があります。 リポジトリに現在含まれている各リリースのタグは、以下の要領で確認できます。

$ cd /c/mozilla-source/mozilla-esr38
$ hg tags | grep -E -e "FIREFOX_.+_RELEASE" | less

Firefox 38.2.1ESRのタグはFIREFOX_38_2_1esr_RELEASEです。 Firefox本体のリポジトリと言語リソースのリポジトリでタグ名は共通なので、それぞれチェックアウトします。

$ TARGET=FIREFOX_38_2_1esr_RELEASE
$ cd /c/mozilla-source/ja
$ hg checkout $TARGET
$ cd /c/mozilla-source/mozilla-esr38
$ hg checkout $TARGET

次に、ビルドオプションを指定します。 ビルドオプションの指定はFirefox本体のリポジトリのトップレベルのディレクトリに.mozconfigという名前のテキストファイルとして保存します。 今回の例ではc/mozilla-source/mozilla-esr38/.mozconfigの位置です。

ビルドオプションは様々な物がありますが、今回は公式のFirefox 38.2.1ESRのノーブランド版という事以外の違いを持たせる必要はないため、Firefox 38.2.1ESRでabout:buildconfigを開いて確認できるビルドオプション公式のビルドで使用している設定を参考にできます。

(2015年9月28日補記) Firefoxではabout:buildconfigを開くとそのバイナリの元になったビルドオプションの一覧を見ることができますが、実際の.mozconfigには、それらに加えて環境変数の指定なども必要です。 単にビルドオプションだけを指定した状態だと、Visual Studioのランタイムライブラリがインストーラに含まれないなど、一般ユーザの環境で使用するには不都合があるビルド結果となってしまいます。

ビルド環境が64bit版のWindowsで、Visual Studio 2013 Communityを使う場合の基本的なビルド設定は、Firefox自体のリポジトリのbuild/win32/mozconfig.vs2013-win64の位置(※今回ビルドしたいのはFirefox 38.2.1ESRなので、オンラインで例を見る場合はmozilla-esr38リポジトリの物を参照して下さい)にファイルがあります。

このファイルに書かれている設定内容はMozillaで使用しているビルド環境向けの物なのですが、ここまでの手順通りに必要なソフトウェアを導入した場合、Visual Studioのインストール先パスなどが実際の物と異なっています。 ここまでの手順通りに環境を整えた場合のパスを指定するように改めた上で、Firefox 38.2.1ESRのabout:buildconfigに列挙されているオプション群から必要でない物を除外し、ローカライズに必要なオプションを足した物が、以下の例です(行頭の#はコメントアウトです)。

#---------- based on build/win32/mozconfig.vs2013-win64 -------------
_VSPATH="/C/Program Files (x86)/Microsoft Visual Studio 12.0"
export WIN32_REDIST_DIR=${_VSPATH}/VC/redist/x86/Microsoft.VC120.CRT

export MOZ_TOOLS=C:/mozilla-build/moztools

export INCLUDE=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/include/shared:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/include/um:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/include/winrt:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/include/winrt/wrl:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/include/winrt/wrl/wrappers:${_VSPATH}/vc/include:${_VSPATH}/vc/atlmfc/include:/c/tools/sdks/dx10/include

export LIBPATH=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/Lib/winv6.3/um/x86:${_VSPATH}/vc/lib:${_VSPATH}/vc/atlmfc/lib:/c/tools/sdks/dx10/lib
export LIB=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/Lib/winv6.3/um/x86:${_VSPATH}/vc/lib:${_VSPATH}/vc/atlmfc/lib:/c/tools/sdks/dx10/lib

export PATH="/c/Program Files (x86)/Windows Kits/8.1/bin/x86:${_VSPATH}/Common7/IDE:${_VSPATH}/VC/BIN/amd64_x86:${_VSPATH}/VC/BIN/amd64:${_VSPATH}/Common7/Tools:${_VSPATH}/VC/VCPackages:/c/mozilla-build/moztools:${PATH}"

export WINDOWSSDKDIR="/c/Program Files (x86)/Windows Kits/8.1/"

. $topsrcdir/build/mozconfig.vs-common

mk_export_correct_style LIB
mk_export_correct_style LIBPATH
mk_export_correct_style PATH
mk_export_correct_style INCLUDE
mk_export_correct_style WIN32_REDIST_DIR

mk_add_options "export MOZ_TOOLS=$MOZ_TOOLS"
#--------------------------------------------------------------------

ac_add_options --enable-crashreporter
ac_add_options --enable-release
#ac_add_options --enable-update-channel=esr
#ac_add_options --enable-update-packaging
ac_add_options --enable-jemalloc
ac_add_options --enable-require-all-d3dc-versions
#ac_add_options --with-google-api-keyfile=/c/builds/gapi.data
#ac_add_options --with-google-oauth-api-keyfile=/c/builds/google-oauth-api.key
#ac_add_options --with-mozilla-api-keyfile=/c/builds/mozilla-desktop-geoloc-api.key
ac_add_options --enable-warnings-as-errors
#ac_add_options --enable-official-branding

mk_add_options MOZ_CO_LOCALES=ja
ac_add_options --enable-ui-locale=ja
ac_add_options --with-l10n-base=/c/mozilla-source

--with-l10n-baseで指定するパスは、言語リソースのリポジトリのパスではなく、その1つ上位のディレクトリのパスです。 MozillaBuildは、ここにMOZ_CO_LOCALESで指定した言語コード名を足したパスの /c/mozilla-source/ja に言語リソースがあることを期待します。

ビルドの実施

準備ができたら、いよいよビルドです。 Firefox本体のリポジトリにcdして、./mach buildを実行すればビルドが始まります。 ビルドにどの程度時間がかかったかを計測するために、timeコマンドを使うことをお薦めします。

$ cd /c/mozilla-source/mozilla-esr38
$ time ./mach build

ビルドに使用するマシンの性能にもよりますが、弊社で使用した環境は以下の通りで、ビルド時間はおよそ1時間でした。

  • Interl Core i5 2.5GHz

  • 8GB RAM

  • Windows 7 Ultimate SP1 64bit

ビルドが完了したら、本当に動作するか確かめてみましょう。 以下のコマンドを実行すると、ビルドされたFirefoxが起動します。 アプリケーション名は「Nightly」になっているはずです。

$ ./mach run

正しく動作することを確認できたら、インストーラを作成しましょう。 これは以下のコマンドで行えます。

$ time ./mach build installer

できあがったインストーラは、カレントディレクトリから見てobj-i686-pc-mingw32/dist/install/sea/の位置、フルパスではC:\mozilla-source\mozilla-esr38\obj-i686-pc-mingw32\dist\install\sea\の位置に出力されます。

ノーブランド化する

実は、この段階ではまだ「ノーブランド版」とは言いにくい状態です。 というのも、言語リソース内で「Firefox」と決め打ちされている箇所があるため、このままではUI上のあちこちで「Firefox」という名前を目にすることになってしまうからです。

というわけで、ソース中に残っている「Firefox」という文字列を置換してみましょう。 これはsedを使って簡単に行えます。

(なお、MinGWに同梱されているsed-iオプションを使うと、ファイルのパーミッションが意図せず変更されてしまうという問題が起こります。 MinGW 上の sed による置換で permission denied を回避するにはで解説されている手順を参考に、あらかじめC:\mozilla-sourceおよびその配下のすべてのファイルについてUsersにフルコントロールの権限を与えておきましょう。)

(2015年10月16日訂正) ノーブランド化後のアプリケーションの正式な名前を「My Custom Browser」、省略した短い名前を「Browser」にすると仮定すると、一括置換の操作は以下のように行えます。

$ cd /c/mozilla-source
$ name="My Custom Browser"
$ shortname="Browser"
$ grep -E -e "\b(Nightly|Firefox)\b" -r ja/browser ja/toolkit mozilla-esr38/browser/branding | \
    grep -v -E -e "Binary" | \
    cut -d ":" -f 1 | sort | uniq | \
    while read path; do sed -i -r -e "s/Mozilla Firefox/$name/g" \
                                  -e "s/((MOZ_APP_DISPLAYNAME|Shorter).*)(Nightly|Firefox)/\1$shortname/g" \
                                  -e "s/(Short.*)(Nightly|Firefox)/\1$name/g" \
                                  -e "s/\bFirefox\b/$shortname/g" \
                                  -e "s/\bNightly\b/$name/g" \
                          "$path"; done

短い名前には空白文字を含められない事に注意が必要です。 「Mozilla Firefox」と書かれている箇所の置換は容易ですが、「Nightly」と書かれている部分はそれが長い名前なのか短い名前なのかが場合によってまちまちなので、ここでは確実に短い名前と断定できる部分(例えばMOZ_APP_DISPLAYNAMEbrandShorterNameの値など)は短い名前にして、それ以外は長い名前にしています。

Gitではgit grepを使うことが多そうな場面ですが、Mercurialではhg grepとすると現在のリビジョンではなく履歴に対する検索となるため、リビジョンによっては検索漏れが出てしまいます。 なので、ここでは通常のgrepを使っています。

この方法は「Nightly」または「Firefox」という文字列を無差別に置換しているため、文脈的におかしな箇所が残っていることがあります。 例えば「My Custom Browser および My Custom Browser ロゴは 米国 Mozilla Foundation の米国およびその他の国における商標です。」のような記述になっているかも知れませんので、こういった例は適宜手作業で自然な内容に書き直す必要があります。

(2015年10月7日追記) その一例として、「about:rights」の内容が挙げられます。 about:rightsには、使用者自身の権利に関する情報、具体的にはプライバシーポリシーであったり、ノーブランド版のFirefoxと組み合わせて使用するWebサービスそのものの利用規約であったりが表示される事になっています。 この情報は初期状態ではプレースホルダ的な内容になっているため、自分で書き換える必要があります。

about:rightsの内容を変えるには、toolkit/content/aboutRights-unbranded.xhtmlの位置にあるファイル(Firefox 38ESRでも同じ位置にあります)を直接書き換えるか、そこで参照しているエンティティを定義している言語リソースの項目を書き換えます。 特定言語のビルドしか提供しないのであれば、aboutRights-unbranded.xhtmlだけを直接書き換えれば十分でしょう。 なお、文章に日本語などの非ASCII文字を含める場合は、ファイルの文字エンコーディングはUTF-8にする必要があります。

また、画像の差し替えも行えます。 ブランドに関する画像はFirefox本体のリポジトリのbrowser/branding/nightly以下にある物が使われるので、必要であればこれらの画像も差し替えておきます。

(2015年10月26日追記) これらの手順で変更できるのは表示上のアプリケーション名のみで、この状態のノーブランド版Firefoxを通常のFirefoxと同時に運用する際には、プロファイルを明示的に分ける必要があるなど、いくつか気をつけないといけない点があります。 そういった点を気にしなくてもよくするためには、内部的なアプリケーション名まで含めたノーブランド化が必要となります。

ソース上でのノーブランド化を終えたら、もう一度ビルドします。

$ cd /c/mozilla-source/mozilla-esr38
$ time (./mach configure &&  ./mach build && ./mach build installer)

ブランド名の一部はconfigureの段階で決定されるため、ブランド名変更後は./mach configureを手動で実行して、configureをやり直す必要があります。 configureの条件が変わるせいで、ここまででビルド済みのバイナリは大部分が使えなくなるため、ビルド時間は新規にビルドした時と同程度かかります。 前述の弊社環境では45分ほどでした。

一方、言語リソースの不自然な箇所を直しただけだったり、画像を差し替えただけだったりの場合は、configureし直す必要はありません。

$ cd /c/mozilla-source/mozilla-esr38
$ time (./mach build && ./mach build installer)

今度は変更が影響する部分だけ再ビルドされるため、全体のビルドに比べて短時間で完了します。 前述の弊社環境では7分ほどでした。

ノーブランド版のベースにするバージョンを更新する

ノーブランド版は、1回作成して提供すれば終わりという性質の物ではありません。 Firefox 38.3ESR、Firefox 38.4ESRといった要領で、その後のセキュリティアップデートにも追従していく必要があります。

セキュリティアップデートの反映は、以下の手順で行います。

  1. ノーブランド化のための変更を元に戻す。

  2. リポジトリを最新の状態に更新する。

  3. セキュリティアップデート版のタグをチェックアウトする。

  4. ノーブランド化のための変更を再反映する。

  5. ビルドし直す。

ノーブランド化のための変更をコミットしていない状態であれば、hg shelveを使えます。 ~/.hgrcを編集(作成)して以下の通り記述し、hg shelveを有効化しておいて下さい。

[extensions]
shelve=

hg shelve/hg unshelveは、git stash/git stash popによく似た機能です。 hg shelveするとコミットしていない変更が一時的に退避され、hg unshelveすると退避していた変更をもう一度反映できます。 ローカルリポジトリをリモートリポジトリの最新の状態に同期するには、hg pullする前にhg shelveで変更を取り消しておく必要があります。

$ cd /c/mozilla-source/mozilla-esr38
$ hg shelve
$ hg pull

リポジトリが最新の状態に更新されたら、新しいリリースのタグ名を調べてチェックアウトします。 新しいリリースがFirefox 38.3.0ESRであれば、恐らくタグ名はFIREFOX_38_3_0esr_RELEASEになっているはずです。 以下は、その前提でFirefox 38.3.0ESRをチェックアウトする例です。

$ TARGET=FIREFOX_38_3_0esr_RELEASE
$ cd /c/mozilla-source/mozilla-esr38
$ hg checkout $TARGET

最新リリースのソースをチェックアウトできたら、先程hg shelveで退避しておいたノーブランド化のための変更を書き戻します。

$ cd /c/mozilla-source/mozilla-esr38
$ hg unshelve

ESR版はセキュリティアップデートのみの提供なので基本的にはブランディング部分のコードに変更はありませんが、通常リリース版では新しいリソースの追加や既存リソースの削除が行われている場合がありますので、hg unshelveの結果が期待通りになっていないかもしれません。 そのような場合は改めて、ノーブランド化の作業をやり直して下さい。

Firefox本体を更新したら、同様の手順で言語リソースも更新します。

$ cd /c/mozilla-source/ja
$ hg shelve
$ hg pull
$ hg checkout $TARGET
$ hg unshelve

その後、インストーラを作り直します。

$ cd /c/mozilla-source/mozilla-esr38
$ time (./mach configure && ./mach build && ./mach build installer)

直前までできていたビルドが失敗するようになってしまったときは?

変更があった箇所だけの差分ビルドは、必要最小限の時間でビルドを完了できるため手軽ですが、変更点が期待通りに検出されなかった場合などに、configureやビルドの段階でエラーになることがあります。

そのような時は、ビルド結果が格納されているディレクトリ(obj-i686-pc-mingw32)を削除してもう一度完全なビルドをやり直すとうまくいきます。

$ cd /c/mozilla-source/mozilla-esr38
$ rm -r ./obj-i686-pc-mingw32
$ time (./mach build && ./mach build installer)

まとめ

以上、Firefox 38.2.1ESRをノーブランド化した物を独自にビルドするための手順を簡単に解説しました。

ちなみに、ここからさらにソースコードに手を加えれば、より自由度の高いカスタマイズが可能になりますが、そうすると元のFirefoxのソースからかけ離れていくため、以後のセキュリティアップデートへの追従が非常に大変な事になります。 基本的にはソースコードに対して行う変更は最小限に留めて、カスタマイズはアドオンや設定ファイルの組み合わせで行うようにすると良いでしょう。