准备工作
本文就Android Gradle Plugin的源码做简要分析,其中Android Gradle Plugin版本为2.3.0,Gradle版本为3.3。我们通过Gradle的依赖管理来查阅源码,所以在dependencies中引入com.android.tools.build:gradle:2.3.0依赖后,就可以在工程的External Libraries下找到Android Gradle Plugin的源码了。
简介
Gradle作为一个异常强大的构建工具,为了满足不同平台的需求,比如:Java平台有Java构建逻辑,Android平台有Android构建逻辑。Gradle务必是要支持自定义构建的,这个功能正是由Gradle Plugin提供,而对应于Android工程的构建逻辑就是由Android Gradle Plugin实现的了。
AGP(请允许我使用缩写)其实包含多个Gradle Plugin,不过通常开发过程中,我们只会用到其中的两个——com.android.application、com.android.library,对应于Android工程的Application与Library模块;当然,除了这两个插件,AGP还包含:com.android.test、com.android.atom、com.android.instantapp等插件。这些类似于域名的东西被称为Gradle Plugin Id,用于唯一标示一个插件。如果大家接触过早期的AGP,相信还见过android与android-library两个插件ID,当然这样命名不太具唯一性,所以后面更名为了域名格式;到2.3.0版本我们依然可以使用这两个废弃(deprecated)的ID——apply plugin: 'android'
,当然不推荐大家使用了。
AGP定义了标准的Android工程构建流程,但是对于不同的Android应用,又会有各自的构建需求,比如,Android版本,CUP架构,应用分发渠道等等的不同,要实现这些应用的差异性构建,需要使用到一个名为Gradle Plugin Extension的特性。对应于前面提到的AGP中各个插件都有与之对应的一个“Extension”。各个应用不同的构建需求,就是配置在“Extension”中。
上面提到的插件及其扩展,在源码中都有与之对应的类来实现,比如:com.android.application插件对应于类AppPlugin.java与AppExtension.java;com.android.library插件对应于类LibraryPlugin.java与LibraryExtension.java。都在gradle-2.3.0库中,当然其它插件的实现也在这里。刚才提及的那些插件ID的定义(或者说命名),也可以在库中的META-INFO目录中找到。
本节提到的一些Gradle相关的特性和名词,有不了解的可以参阅这篇文章:Write Custom Plugin,里面介绍了Gradle Plugin的实现及如何发布。接下来我们就正式进入源码吧。
Application模块
在Android工程中,Application模块所使用的插件就是com.android.application,先看下模块级构建文件build.gradle的内容:
apply plugin: 'com.android.application'
...
android {
defaultConfig {...}
signingConfigs {...}
buildTypes {...}
productFlavors {...}
}
...
以上就是Application模块基本的构建文件的结构了。第一行代码表示:应用名为com.android.application的插件;之后的android
代码块其实是为一个名为android
的extension object
赋值的过程,各个应用差异化构建的配置信息便是保存在这个对象里的。之所以能以DSL为extension object
赋值,这得益于Groovy语言的支持:Groovy DSL。
跟踪进第一行代码,最后会调用方法AppPlugin.apply(),不过这里只是简单地调用AppPlugin的父类BasePlugin的方法,而BasePlugin类是所有定义在AGP中的插件的父类,所以:
protected void apply(@NonNull Project project) {
...
threadRecorder.record(...
this::configureProject);
threadRecorder.record(...
this::configureExtension);
threadRecorder.record(...
this::createTasks);
...
}
}
上面代码中threadRecorder对象负责记录代码块执行时间,并且清晰地指出应用AGP插件时,做了三件事:configureProject,configExtension,createTasks。所以执行脚本时,AGP各自插件的基本流程是一样的,下面来看下这三个基本阶段。
configureProject
在配置工程阶段,主要做的是创建一些后续阶段会用到的对象,其中最重