TL;DR
- macOS上のAndroid StudioでAOSPのソースコードを読む環境を構築したので、方法をシェアします
- AOSPに含まれる IDEGen というツールでIntelliJ IDEAプロジェクトファイル
android.ipr
を生成して、Android Studioで開く、というのが基本的な手順です - プロジェクトを開いた後、ソースコード間でクラスが適切に参照されるように、SDK構成の設定や、ソースパス・参照順序の調整が必要です
- AOSPに含まれる IDEGen というツールでIntelliJ IDEAプロジェクトファイル
はじめに
Android Open Source Project (AOSP) のソースコードを読む場合、一般的には、Developer Collaboration Project が公開しているAndroidソースコード検索サービスを使うのが便利です。ソースコードをダウンロードする必要もないし、色々なOSバージョンのソースコードをすぐ読めます。OpenGlok というソースコード検索エンジンが使われていて、ソースコードの検索機能も充実しています。
ただ、Android Studioでソースコードを見られれば、クラスやメソッドの参照先・被参照元もさくさく探せて最高なはず。というわけで、Android StudioでAOSPを読む環境を構築しました。
筆者の環境
- macOS (Sierra: 10.12.4)
- Android Studio 2.3.1
AOSPソースコードをダウンロードする
まずは、AOSPのソースコードをダウンロードしてきます。
Case-sensitiveなファイルシステムについて
AOSPのビルドにはcase-sensitiveなファイルシステムが必要です。そのため、Establishing a Build Environment に書かれているように、macOSではcase-sensitiveなファイルシステムのディスクイメージを作成し、そこにAOSPのソースコードをダウンロードする必要があります。ただ、ソースコードを読むだけなら別に問題ないだろう、ということで、筆者はmacOSのファイルシステムに直接ソースコードをダウンロードしました (今のところ無問題です)。
repo コマンドのインストール
AOSPのソースコードは多くのGitレポジトリに分かれているので、それらをいい感じにまとめて扱ってくれる repo
コマンド (中身はPythonスクリプト) をインストールします。
Downloading the Source で説明されているように、curl
コマンドで repo
スクリプトをダウンロードするのが定石ですが、Homebrew を使ってもインストールできます。
brew install repo
ソースコードのダウンロード
Downloading the Source の説明に従いつつ、repo
コマンドを使ってソースコードをダウンロードします。
デフォルトだと master
ブランチのソースコードがダウンロードされますが、タグを指定してダウンロードするのがよいと思います。OSバージョンとタグの関係は Codenames, Tags, and Build Numbers を見るとわかります。
私は、2017年4月14日現在で最新だった android-7.1.2_r6
をダウンロードしました。
# ソースコードを格納するディレクトリを作成し、その中に移動する
mkdir android-7.1.2_r6
cd android-7.1.2_r6
# ブランチ android-7.1.2_r6 を指定して、repo クライアントを初期化する
repo init -u https://android.googlesource.com/platform/manifest -b android-7.1.2_r6
# ソースコードをダウンロードする
repo sync
通信環境にもよりますが、ソースコードのダウンロードには数時間かかります。気長に待ちましょう。
IntelliJ IDEAプロジェクトファイルを生成する
ソースコードがダウンロードできたら、ダウンロードしたソースコードがまるっと含まれる、IntelliJ IDEAプロジェクトファイル (.ipr) ファイルを生成します。IPRファイルの生成には、AOSPに含まれるIDEGenというツールを使います。
基本的には、IDEGenの README に書かれているように、AOSPソースツリーのルートで以下のコマンドを実行するだけです。
make idegen
development/tools/idegen/idegen.sh
が、コマンドを実行する前に、ちょっとだけMakefileを修正します。
ファイルシステムのcase-sensitiveness検査をスキップする
AOSPのソースコードをcase-insensitiveなファイルシステムにダウンロードした場合、そのままだと、Make中に行われる検査にひっかかりエラーとなります。
build/core/main.mk:159: ************************************************************
build/core/main.mk:160: You are building on a case-insensitive filesystem.
build/core/main.mk:161: Please move your source tree to a case-sensitive filesystem.
build/core/main.mk:162: ************************************************************
build/core/main.mk:163: *** Case-insensitive filesystems not supported.
検査にひっかかったとしてもMakeの実行が継続されるように、build/core/main.mk
で、Case-insensitive filesystems not supported
というエラーメッセージを出力している行をコメントアウトします。
diff --git a/core/main.mk b/core/main.mk
index a612f835d..035788200 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -160,7 +160,7 @@ $(warning ************************************************************)
$(warning You are building on a case-insensitive filesystem.)
$(warning Please move your source tree to a case-sensitive filesystem.)
$(warning ************************************************************)
-$(error Case-insensitive filesystems not supported)
+# $(error Case-insensitive filesystems not supported)
endif
# Make sure that there are no spaces in the absolute path; the
android.ipr を生成する
あとは、AOSPソースツリーのルートディレクトリで以下のコマンドを実行してください。実行に成功した場合、同じディレクトリに android.ipr
というファイルが生成されます。
make idegen
development/tools/idegen/idegen.sh
筆者は make idegen
の実行で何箇所かつまづきました。次の節で、筆者が遭遇した問題とその解決方法を説明しているので、もし同じ問題にぶち当たったら参考にしてください。
make idegen
のトラブルシューティング
xcode-select: error
と言われる場合
make idegen
の実行時に以下のようなエラーメッセージが出る場合
xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance
build/core/combo/mac_version.mk:26: none of the installed SDKs (ac_sdk_versions_installed) match supported versions (10.8 10.9 10.10 10.11), trying 10.8
build/core/combo/mac_version.mk:36: no SDK 10.8 at /Library/Developer/CommandLineTools/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk, trying legacy dir
build/core/combo/mac_version.mk:40: *****************************************************
build/core/combo/mac_version.mk:41: * Can not find SDK 10.8 at /Developer/SDKs/MacOSX10.8.sdk
build/core/combo/mac_version.mk:42: *****************************************************
build/core/combo/mac_version.mk:43: *** Stop.. Stop.
アクティブなデベロッパーディレクトリが、コマンドラインツールのものになっていることが原因です。xcode-select
コマンドを使って、デベロッパーディレクトリの場所を Xcode.app
内のディレクトリに変更してください。
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
インストールされているSDKがない、と言われる場合
make idegen
の実行時に以下のようなエラーメッセージが出る場合
build/core/combo/mac_version.mk:26: none of the installed SDKs (ac_sdk_versions_installed) match supported versions (10.8 10.9 10.10 10.11), trying 10.8
build/core/combo/mac_version.mk:36: no SDK 10.8 at /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk, trying legacy dir
build/core/combo/mac_version.mk:40: *****************************************************
build/core/combo/mac_version.mk:41: * Can not find SDK 10.8 at /Developer/SDKs/MacOSX10.8.sdk
build/core/combo/mac_version.mk:42: *****************************************************
build/core/combo/mac_version.mk:43: *** Stop.. Stop.
AOSPのMakefileが前提にしているmacOS SDKのバージョンと、マシンにインストールされているSDKのバージョンが一致していないことが原因です。まず、インストールされているmacOS SDKのバージョンを確認してください。筆者の場合は、10.12のみでした。
$ ls /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs
MacOSX.sdk MacOSX10.12.sdk
このバージョン番号を、build/core/combo/mac_version.mk
で定義されている変数 mac_sdk_versions_supported
に追加すれば、上記のエラーが発生しなくなります。
diff --git a/core/combo/mac_version.mk b/core/combo/mac_version.mk
index 51394c64b..8fa08c6e6 100644
--- a/core/combo/mac_version.mk
+++ b/core/combo/mac_version.mk
@@ -9,7 +9,7 @@ ifndef build_mac_version
build_mac_version := $(shell sw_vers -productVersion)
-mac_sdk_versions_supported := 10.8 10.9 10.10 10.11
+mac_sdk_versions_supported := 10.8 10.9 10.10 10.11 10.12
ifneq ($(strip $(MAC_SDK_VERSION)),)
mac_sdk_version := $(MAC_SDK_VERSION)
ifeq ($(filter $(mac_sdk_version),$(mac_sdk_versions_supported)),)
could not find jdk tools.jar
と言われる場合
make idegen
の実行時に以下のようなエラーメッセージが出る場合
build/core/config.mk:601: *** Error: could not find jdk tools.jar at /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/../lib/tools.jar, please check if your JDK was installed correctly. Stop.
JAVA_HOME
に相当するディレクトリのパスを、ANDROID_JAVA_HOME
環境変数として定義してください。
# 設定例
export ANDROID_JAVA_HOME=`/usr/libexec/java_home -v 1.8`
Android StudioでAOSPソースツリーを開く
android.ipr ファイルを指定してプロジェクトを開く
android.ipr
ファイルが生成できたら、Android Studioで android.ipr
ファイルを開きます。AOSPのルートディレクトリを開くのではなく、そこに配置されている android.ipr
ファイルを開くように注意してください。
プロジェクトを開くと、ファイルのインデックスなどでしばらくビジーになるので、処理が終わるのを待ちます。
プロジェクト設定を変更する
開いたプロジェクトはこのままだといくつか問題があるので、メニュー "File" - "Project Structure..." からプロジェクト設定を変更します。
JDKを設定する
"Project Structure" ウィンドウ左部分にある "SDKs" を選択して、このプロジェクトに設定するためのSDK構成を作成します。SDKの種類は "JDK" で、JDK home pathにはマシンにインストールされているJDKのHomeディレクトリを指定してください (/usr/libexec/java_home
コマンドで確認できます)。また、AOSPのソースコードからJDKのクラスが参照されないよう、"Classpath" を全て削除します。
新しいSDK構成が作成できたら、それをプロジェクトのSDKとして設定します。ウィンドウ左部分から再度 "Project" を選択して、作成したSDK構成を選択します。
"Android" モジュールを削除する
"Android" という名前のモジュールが自動的に作成されてしまっていますが、不要なので、"Modules" にて削除します。
external/libgdx 内にある emu ディレクトリをソースパスから除外する
external/libgdx 内の emu
ディレクトリに格納されているJavaクラスが、libcore-luni が提供するJava標準クラスと衝突しているため、emu
ディレクトリをソースパスから除外します。
"Modules" で "android" モジュールを選択した後、"Sources" タブで該当ディレクトリを選択して、 "Excluded" マークをONに変更します。
変更が必要なディレクトリは (筆者がダウンロードした android-7.1.2_r6
ブランチのソースツリーでは) 以下の3つでした。
- external/libgdx/backends/gdx-backends-gwt/src/com/badlogic/gdx/backends/gwt/emu
- external/libgdx/extensions/gdx-box2d/gdx-box2d-gwt/src/com/badlogic/gdx/physics/box2d/gwt/emu
- external/libgdx/extensions/gdx-controllers/gdx-controllers-gwt/src/com/badlogic/gdx/controllers/gwt/emu
ソースコードをJarファイルよりも優先して参照するようにする
AOSPのソースツリーにはJarファイルが多数含まれており、デフォルトでは、それらのJarファイルがソースファイルよりも優先して参照されるようになっています。
このままだと、コードリーディングしているときにソースファイル間を上手くジャンプできないので、ソースファイルが最優先で参照されるように依存順序を変更します。"Modules" で "android" モジュールを選択した後、"Dependencies" タブで依存の順序を変更し、"<Module source>" が最初に参照されるようにします。
気が遠くなるくらい大変なので、Alt+上カーソルキー のショートカットを使うことをお勧めします。
Happy Code Reading!!
これで、一通りのAOSPのソースコードがAndroid Studioで読めるようになります。例えば、Android Studioのナビゲーション機能を使えば、あるクラスを継承しているクラスの一覧、なども簡単に調べられるようになります。
残課題
今回はAOSPソースツリーをビルドしていないので、AIDLファイルから生成されるインターフェースなど、ビルドにより生成されるものが存在しておらず、それらの参照ができない状態なのが残念なところです。