
1.4 常用项目的调试环境配置
由于本书涉及非常多Java编译器、Kotlin编译器甚至IntelliJ IDEA相关的概念,配置好相关源代码的编译和调试环境会非常有帮助。当然,这不是必需的,本书绝大多数内容并不直接依赖这些环境。
1.4.1 Java编译器
在开始之前,请大家准备好一台硬盘剩余容量不小于10GB、内存不小于16GB的计算机。操作系统选择Linux、macOS、Windows均可,推荐使用Linux。下面我们以Ubuntu 20.04为例,介绍如何配置Java编译器的编译和调试环境。配置完成之后的JDK所在的目录如图1-3所示。

图1-3 配置完成之后的JDK所在的目录
首先从GitHub下载JDK源代码,如代码清单1-7所示。为了叙述方便,我们使用$ws表示工作目录。工作目录应尽量避免层级过深,目录名称应避免出现空格、非ASCII字符以及特殊字符,以免遇到部分工具出错的问题。
代码清单1-7 下载OpenJDK源代码

源代码比较大,下载可能需要几分钟时间。下载完成之后切换到我们需要阅读的代码版本,例如JDK 17,如代码清单1-8所示。
代码清单1-8 切换到JDK 17对应的分支

接下来需要检查一下当前环境是否已经满足编译JDK的要求,如代码清单1-9所示。
代码清单1-9 检查当前编译环境

如果当前环境中缺少某些依赖,configure会运行失败,并给出错误信息。读者可以按照错误信息结合自己的实际环境安装相应的依赖,并重新运行configure命令直到成功为止,如图1-4所示。

图1-4 bash configure运行成功之后的输出
接下来我们就可以编译自己的Java编译器和Java虚拟机了,如代码清单1-10所示。
代码清单1-10 编译JDK

编译后可以根据提示找到对应的Java可执行程序,读者可以试着用它编译并运行一段Java源代码。
Java编译器的源代码可以使用IntelliJ IDEA来阅读。为了方便配置工程,JDK源代码中提供了创建相应工程的配置文件的脚本。
代码清单1-11 创建IntelliJ IDEA工程的配置文件

这个脚本会依赖Apache Ant,如果运行时提示需要设置ANT_HOME,那么请先安装Ant。可以从https://ant.apache.org/bindownload.cgi直接下载Ant的压缩包,解压之后将环境变量ANT_HOME的值设置为Ant的根目录,再次运行idea.sh脚本即可。
工程文件生成之后,使用IntelliJ IDEA打开$ws/jdk目录,就可以阅读JDK的Java部分源代码了,如图1-5所示。

图1-5 使用IntelliJ IDEA阅读JDK源代码
Java编译器也是一个普通的Java程序,我们可以直接在IntelliJ IDEA中运行并调试它,如图1-6所示。

图1-6 单步调试Java编译器
提示
配置环境时,最容易出问题的就是C/C++编译器。为了避免麻烦,建议读者严格按照官方的要求安装相应的编译工具链,更多细节参见https://openjdk.org/groups/build/doc/building.html。
1.4.2 Kotlin编译器
本节我们将为大家介绍如何下载和配置Kotlin源代码的编译和阅读环境,其中包括Kotlin编译器、标准库、官方编译器插件、官方Gradle插件等。时常翻阅Kotlin源代码,对于理解本书的内容将会有非常大的帮助。
在下载和编译Kotlin源代码之前,请大家准备好一台硬盘剩余容量不小于20GB、内存不小于16GB的计算机。Kotlin源代码的编译对操作系统没有明确要求,不过实测搭载Apple Silicon芯片的macOS在编译Kotlin源代码时会遇到一些依赖问题,例如找不到对应的JDK版本等,因此建议使用搭载了X86芯片的计算机,以避免出现不必要的麻烦。
首先下载源代码。从https://github.com/JetBrains/kotlin下载Kotlin源代码到本地目录$ws/kotlin中,默认分支为master,如代码清单1-12所示。
代码清单1-12 下载Kotlin源代码

代码下载完以后,Windows用户需要添加如代码清单1-13所示的配置,以支持长路径。
代码清单1-13 配置git以支持长路径

由于我们只是希望阅读源代码,因此不需要考虑不同JDK版本兼容的问题。在local.properties中添加如代码清单1-14所示的配置,以使用JDK 1.8.0及以上版本完成编译。
代码清单1-14 使用JDK 1.8.0及以上版本完成编译

这样Kotlin源代码调试环境就配置完成了。读者可以使用IntelliJ IDEA打开Kotlin源代码的目录,导入相应的Gradle工程,并开始阅读源代码。
编译Kotlin源代码比较容易,直接运行对应的Gradle任务即可,如代码清单1-15所示。
代码清单1-15 将Kotlin编译器编译到dist/kotlinc中

编译之后,我们就可以在$ws/kotlin/dist/kotlinc目录下找到Kotlin编译器的可执行程序,如图1-7所示。
我们可以直接在命令行运行这些程序,也可以通过cli-runner模块来运行它们。cli-runner模块的入口如图1-8所示。

图1-7 编译后的Kotlin编译器的可执行程序

图1-8 cli-runner模块的入口
找到cli-runner模块中的Main类,直接运行它的main函数,我们会得到如图1-9所示的错误信息。
这是因为cli-runner只是一个简单的程序入口,并没有包含Kotlin编译器的具体实现。我们可以通过设置虚拟机参数kotlin.home来明确需要运行的Kotlin编译器的路径,如图1-10所示。

图1-9 直接运行cli-runner的main函数时输出的错误信息

图1-10 添加参数kotlin.home指向编译好的Kotlin编译器
这样我们就可以轻松实现单步调试Kotlin编译器了。如图1-11所示,直接运行Kotlin编译器相当于在命令行运行kotlinc,会进入交互式命令行,我们在其中输入一行Kotlin代码,然后交互式命令行会读取该输入并且调用eval函数对其进行求值。

图1-11 单步调试Kotlin编译器
顺带提一句,这里指向的Kotlin编译器目录也可以是从官方下载的版本,但需要本地源代码版本与下载的二进制版本相对应。
1.4.3 IntelliJ社区版
本节我们将为大家简单介绍如何编译和调试IntelliJ社区版的源代码。
在此之前,请大家准备好一台硬盘剩余容量不小于30GB、内存不小于16GB的计算机。IntelliJ社区版的源代码只涉及Java程序,本书撰写时使用的JDK版本为17,对操作系统没有明确要求。
首先从https://github.com/JetBrains/intellij-community下载IntelliJ社区版源代码到$ws/intellij-community目录中,切换到希望调试的分支,例如222.4345,这是IntelliJ IDEA 2022.2的一个稳定版本的分支,如代码清单1-16所示。
代码清单1-16 下载IntelliJ社区版源代码并切换到222.4345分支

如果需要阅读Android插件相关的源代码,可以接着通过如代码清单1-17所示的命令将其下载到$ws/intellij-community/android目录中,选择与IntelliJ社区版源代码相同的分支。这实际上也是Android Studio的核心源代码。
代码清单1-17 下载Android插件的源代码

下载完成之后,使用IntelliJ IDEA打开$ws/intellij-community目录时会同时加载android目录下的模块。
顺带提一句,Jetpack Compose的IntelliJ插件在$ws/intellij-community/android/compose-ide-plugin目录中。
至此,IntelliJ社区版源代码就下载完成了。
读者此时可以使用IntelliJ IDEA打开$ws/intellij-community目录,尝试阅读IntelliJ社区版源代码了。其中,Kotlin的IntelliJ插件的源代码在$ws/intellij-community/plugins/kotlin目录下。
源代码打开之后需要配置JDK才可以编译,对于222.4345版本的源代码,建议选择JDK 11。接下来在如图1-12所示的运行选项下拉列表中选择IDEA开始运行,经过一段时间的编译之后就会启动一个调试用的IntelliJ IDEA实例。
如果想要运行安装了Android插件的IntelliJ IDEA,需要选择IDEA with Android。不过在运行之前,需要先单击下拉菜单中的Edit Configurations选项,对IDEA with Android的配置进行修改,如图1-13所示,删除框中的Run Gradle task 'dependencies:setupAndroid-PluginRuntimeForIdea',并单击OK按钮保存修改。

图1-12 IntelliJ源代码的运行配置

图1-13 修改IDEA with Android的配置
保存之后再运行IDEA with Android,就会看到一个启用了Android插件的IntelliJ IDEA运行起来了,如图1-14所示。我们甚至可以单步调试这个程序,以了解IntelliJ IDEA内部的运行细节。

图1-14 运行IDEA with Android会同时安装Android插件
提示
IDEA with Android运行配置的问题已经在master分支上修复了,如果读者拉取的是比较新的代码版本,就不需要额外对运行配置进行修改了。
这里稍微说明一下源代码版本的选择。IntelliJ社区版和Android插件的源代码版必须保持一致,以避免出现不兼容的情况。另外,建议读者根据JetBrains官方发布的IntelliJ社区版的版本号选择稳定版本的源代码进行阅读和调试,最近的稳定版的版本号可以在JetBrains ToolBox中看到,如图1-15所示。

图1-15 在JetBrains ToolBox中查看IntelliJ的版本
如果直接使用开发中的版本,运行调试时难免会遇到问题。我在撰写本书时,曾直接拉取了master分支的最新代码,运行IDEA with Android之后发现Android插件没有被正常启用。通过分析日志发现,Android插件的配置文件引用了android-navigator模块的配置文件,却没有把android-navigator模块添加到Android插件的依赖中。Android插件加载失败的异常日志如代码清单1-18所示。
代码清单1-18 Android插件加载失败的异常日志

当然这个问题还是比较容易解决的,在Android插件模块的依赖中添加android-navigator模块即可。不过,为了避免不必要的麻烦,我们在阅读和调试开源项目源代码时,应当尽量选用稳定版本。
另外,本书第9章中会有阅读和调试Jetpack Compose的IntelliJ插件的需求,默认情况下运行IDEA with Android时不会安装Jetpack Compose插件,因此我们需要将Compose的IntelliJ插件添加到程序的依赖中。
首先单击菜单File中的Project Structure,单击弹出的对话框左侧边栏中的Modules,找到intellij.idea.community.main.android的依赖,单击+,选择3 Module Dependency,如图1-16所示。

图1-16 为intellij.idea.community.main.android添加依赖
在选择模块对话框中直接输入compose搜索compose-ide-plugin模块,如图1-17所示,选中并单击OK按钮进行确认。

图1-17 搜索compose-ide-plugin模块
再在Project Structure对话框中单击OK按钮,使得新增加的依赖生效。重新运行IDEA with Android,启动调试用的IntelliJ IDEA实例之后,我们就可以在其中找到Jetpack Compose插件了,如图1-18所示。

图1-18 成功添加Jetpack Compose插件的IntelliJ IDEA
1.4.4 Jetpack Compose编译器插件
Jetpack Compose属于AOSP(Android Open Source Project,Android开源项目)的一部分,其源代码的下载和配置方式与Android的系统源代码、Android Studio的源代码非常类似。
在开始之前,请大家准备好一台硬盘剩余容量不小于50GB、内存不小于16GB的计算机。操作系统推荐使用Linux、macOS。下面我们以Ubuntu 20.04为例,介绍Jetpack Compose的编译和调试环境的配置。
下载AOSP的源代码时需要使用repo命令,因此我们需要先将repo命令下载下来,放到系统路径中。repo命令的安装方法如代码清单1-19所示。
代码清单1-19 安装repo命令

这里我们将repo命令下载到用户目录下的bin目录中,接着将bin目录添加到系统路径中,如代码清单1-20所示。
代码清单1-20 将bin目录添加到系统路径中

repo命令本质上就是一个Python脚本,目前repo命令支持的最低Python版本为3.6,因此需要强制使用Python 3来运行repo命令,如代码清单1-21所示。
代码清单1-21 强制使用Python 3运行repo命令

我们也可以把代码清单1-20和代码清单1-21中的两条命令写入~/.bash_profile中(如果使用zsh,则写入~/.zshrc中),方便后续使用。
重启命令行,或者执行source~/.bash_profile(如果使用zsh,则执行source~/.zshrc)以使新增的配置生效。
接下来就是枯燥的源代码下载工作了,如代码清单1-22所示。
代码清单1-22 下载androidx-main分支的代码

为了确保git能够识别大量的文件更改情况,还需要添加如代码清单1-23所示的配置。
代码清单1-23 提高git识别文件更改的数量限制

接下来就可以运行如代码清单1-24所示的命令,使用Android Studio打开Jetpack Compose的源代码了。
代码清单1-24 运行Gradle任务启动Android Studio

任务初次运行时会下载相关依赖和Android Studio的可执行程序,稍等片刻就可以看到如图1-19所示的效果。

图1-19 使用Android Studio打开Jetpack Compose工程
我们也可以找到Compose编译器插件的单元测试进行调试,如图1-20所示。
提示
Jetpack Compose源代码的编译和调试的详细说明请参考官方文档:https://android.googlesource.com/platform/frameworks/support/+/refs/heads/androidx-main/compose/README.md。

图1-20 单步调试Compose的编译器插件