diff --git a/README.md b/README.md index ee302f8..1e6985d 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,8 @@ Android Notes [Gradle 练习之一 --- 输出项目第三方库以及本地依赖库的权限信息](https://github.com/Omooo/Android-Notes/blob/master/blogs/Android/Gradle/%E4%BE%9D%E8%B5%96%E6%9D%83%E9%99%90%E4%BF%A1%E6%81%AF.md) +[Android Gradle Plugin 流程分析](https://github.com/Omooo/Android-Notes/blob/master/blogs/Android/Gradle/Android%20Gradle%20Plugin%20%E6%B5%81%E7%A8%8B%E5%88%86%E6%9E%90.md) + ##### JVM、ART 相关 - Class 文件格式 diff --git a/blogs/Android/Gradle/Android Gradle Plugin 流程分析.md b/blogs/Android/Gradle/Android Gradle Plugin 流程分析.md index 048dff6..fdc9ec4 100644 --- a/blogs/Android/Gradle/Android Gradle Plugin 流程分析.md +++ b/blogs/Android/Gradle/Android Gradle Plugin 流程分析.md @@ -2,17 +2,17 @@ Android Gradle Plugin 主要流程分析 --- -#### 前言 +### 前言 > 本文摘自:[Android Gradle Plugin 插件主要流程](https://github.com/5A59/android-training/blob/master/gradle/android_gradle_plugin-%E4%B8%BB%E8%A6%81%E6%B5%81%E7%A8%8B%E5%88%86%E6%9E%90.md) > > 感谢美团大佬 [@5A59](https://github.com/5A59) 的分享! -#### 概述 +### 概述 ![Android Plugin 流程分析概述.png](https://i.loli.net/2019/08/14/Ubpnexm3cK5yOPW.png) -#### 准备工作 +### 准备工作 这个阶段主要有过程: @@ -47,7 +47,7 @@ AppPlugin 里面没有做过多的操作,主要是重写了 createTaskManager .setPluginGeneration(GradleBuildProject.PluginGeneration.FIRST); ``` -#### 配置项目 +### 配置项目 这个阶段有四个过程: @@ -72,7 +72,7 @@ private void configureProject(){ } ``` -#### 配置 Extension +### 配置 Extension 这一阶段主要做了以下几件事情: @@ -137,7 +137,7 @@ private void configureProject(){ } ``` -#### 创建不依赖 flavor 的 Task +### 创建不依赖 flavor 的 Task ```java private void createTasks() { @@ -169,7 +169,7 @@ private void configureProject(){ 这些 task 都是不需要依赖 flavor 数据的公共 task。 -#### 创建构建 Task +### 创建构建 Task 在介绍下面的流程之前,先明确几个概念,flavor、dimension、variant。 @@ -201,3 +201,129 @@ createAndroidTasks 的调用时机和上面不一样,是在 project.afterEvalu 在 BasePlugin.createAndroidTasks 里,是调用 VariantManager.createAndroidTasks 完成工作的。 +创建 task 的时候,会先通过 populateVariantDataList 生成 flavor 相关的数据结构,然后调用 createTasksForVariantData 创建 flavor 对应的 task。 + +分别看下这两个方法所做的事情: + +1. populateVariantDataList + + 在方法里,会先根据 flavor 和 dimension 创建对应的组合,存放在 flavorComboList 里,之后调用 createVariantDataForProductFlavors 创建对应的 VariantData。 + + 其中重要的几个方法: + + ```java + // 创建 flavor 和 dimension 的组合 + List> flavorComboList = + ProductFlavorCombo.createCombinations( + flavorDimensionList, + flavorDsl); + // 为每个组合创建 VariantData + for (ProductFlavorCombo flavorCombo : flavorComboList) { + //noinspection unchecked + createVariantDataForProductFlavors( + (List) (List) flavorCombo.getFlavorList()); + } + ``` + + 创建出来的 VariantData 都是 BaseVariantData 的子类,里面保存了一些 Task,可以看一下 BaseVariantData 里的一些重要的结构,对 BaseVariantData 有个大概的了解。 + + ```java + public abstract class BaseVariantData implements TaskContainer { + private final GradleVariantConfiguration variantConfiguration; + private VariantDependencies variantDependency; + private final VariantScope scope; + public Task preBuildTask; + public Task sourceGenTask; + public Task resourceGenTask; // 资源处理 + public Task assetGenTask; + public CheckManifest checkManifestTask; // 检测manifest + public AndroidTask packageSplitResourcesTask; // 打包资源 + public AndroidTask packageSplitAbiTask; + public RenderscriptCompile renderscriptCompileTask; + public MergeResources mergeResourcesTask; // 合并资源 + public ManifestProcessorTask processManifest; // 处理 manifest + public MergeSourceSetFolders mergeAssetsTask; // 合并 assets + public GenerateBuildConfig generateBuildConfigTask; // 生成 BuildConfig + public GenerateResValues generateResValuesTask; + public Sync processJavaResourcesTask; + public NdkCompile ndkCompileTask; // ndk 编译 + public JavaCompile javacTask; + public Task compileTask; + public Task javaCompilerTask; // java 文件编译 + // ... + } + ``` + + VariantData 里保存了很多 Task,下一步就是要创建这些 task。 + +2. createTasksForVariantData + + 创建完 variant 数据,就要给每个 variantData 创建对应的 task,对应的 task 有 assembleXxxTask、prebuildXxx、generateXxxSource、generateXxxResources、generateXxxAssets、processXxxManifest 等等,重点关注几个方法: + + ```java + VariantManager.createAssembleTaskForVariantData() // 创建 assembleXXXTask + TaskManager.createTasksForVariantScope() // 是一个抽象类,具体实现在 ApplicationTaskManager.createTasksForVariantScope() + TaskManager.createPostCompilationTasks() // 创建 .class to dex 的 task, 创建 transformTask,我们创建的 transform 就是这个阶段添加进来的,是在 addCompileTask 里调用的 + + // createTasksForVariantScope 是一个抽象方法,具体实现在子类中,可以看一下 ApplicationTaskManager.createTasksForVariantScope() + // createTasksForVariantScope 里的实现,如果在业务中有需要查看相关 task 源码时,可以来这里找 + void createTasksForVariantScope() { + this.createCheckManifestTask(tasks, variantScope); // 检测 manifest + this.handleMicroApp(tasks, variantScope); + this.createDependencyStreams(tasks, variantScope); + this.createApplicationIdWriterTask(tasks, variantScope); // application id + this.createMergeApkManifestsTask(tasks, variantScope); // 合并 manifest + this.createGenerateResValuesTask(tasks, variantScope); + this.createRenderscriptTask(tasks, variantScope); + this.createMergeResourcesTask(tasks, variantScope, true); // 合并资源文件 + this.createMergeAssetsTask(tasks, variantScope, (BiConsumer)null); // 合并 assets + this.createBuildConfigTask(tasks, variantScope); // 生成 BuildConfig + this.createApkProcessResTask(tasks, variantScope); // 处理资源 + this.createProcessJavaResTask(tasks, variantScope); + this.createAidlTask(tasks, variantScope); // 处理 aidl + this.createShaderTask(tasks, variantScope); + this.createNdkTasks(tasks, variantScope); // 处理 ndk + this.createExternalNativeBuildJsonGenerators(variantScope); + this.createExternalNativeBuildTasks(tasks, variantScope); + this.createMergeJniLibFoldersTasks(tasks, variantScope); // 合并 jni + this.createDataBindingTasksIfNecessary(tasks, variantScope); // 处理 databinding + this.addCompileTask(tasks, variantScope); + createStripNativeLibraryTask(tasks, variantScope); + this.createSplitTasks(tasks, variantScope); + this.createPackagingTask(tasks, variantScope, buildInfoWriterTask); // 打包 apk + this.createLintTasks(tasks, variantScope); // lint + } + + // createPostCompilationTasks 实现: + // 处理 Android Transform + void createPostCompilationTasks() { + for (int i = 0, count = customTransforms.size(); i < count; i++) { + Transform transform = customTransforms.get(i); + // TransformManager.addTransform 实际上是为 transform 创建了一个 Task + transformManager + .addTransform(tasks, variantScope, transform) + .ifPresent(t -> { + if (!deps.isEmpty()) { + t.dependsOn(tasks, deps); + } + // if the task is a no-op then we make assemble task depend on it. + if (transform.getScopes().isEmpty()) { + variantScope.getAssembleTask().dependsOn(tasks, t); + } + }); + } + } + ``` + +### 总结 + +![plugin-summary.png](https://i.loli.net/2019/08/22/1zcRLBIFxNrQqDg.png) + +这里总结几个要点: + +1. com.android.application 入口类是 AppPlugin,但大部分工作都是在 BasePlugin 里完成的。 +2. build.gradle 里见到的 android {} dsl 是在 BasePlugin.configureExtension() 里声明的。 +3. 主要的 task 是在 BasePlugin.createAndroidTask 里生成的。 +4. 主要 Task 的实现可以在 TaskManager 中找到。 +5. Transform 会转化为 TransformTask。 + diff --git a/images/Android/Gradle/plugin-summary.png b/images/Android/Gradle/plugin-summary.png new file mode 100644 index 0000000..8cfb921 Binary files /dev/null and b/images/Android/Gradle/plugin-summary.png differ