Gradle学习系列(七):Android Gradle Plugin 源码解析

13,042 阅读13分钟

概述

又开始了一个新的系列,这个系列学习Gradle,目标就是彻底理解Gradle,主要还是做下自己理解的笔记,防止忘记

Gradle系列(一):Groovy学习

Gradle学习系列(二):Gradle核心解密

Gradle学习系列(三):Gradle插件

Gradle学习系列(四):Gradle依赖

Gradle学习系列(五):Gradle Transform

Gradle学习系列(六):Gradle 源码解析

Gradle学习系列(七):Android Gradle Plugin 源码解析

阅读前准备

首先务必要先阅读这篇文章Gradle学习系列(三):Gradle插件,这个是基础,自己先尝试自定义一个插件,然后在看源码会更简单一些

准备源码

这里有一个取巧的办法查看源码,首先建立一个java libary ,然后更改build为下面的代码

apply plugin: 'groovy'  //必须
apply plugin: 'maven'  //要想发布到Maven,此插件必须使用


dependencies {
    implementation gradleApi() //必须
    implementation localGroovy() //必须

    implementation 'com.android.tools.build:gradle:3.4.1'

}
repositories {
    mavenCentral() //必须
}

build一下,就可以在External Libraries看到gradle源码

image.png

开始阅读源码

首先找什么看呢? 当然找我们经常用的插件,看他的源码实现,我们经常用的插件是这个

apply plugin: 'com.android.application'

如何找这个插件的源码,这个就需要插件的基础知识了,不知道的返回去看Gradle学习系列(三):Gradle插件

image.png

直接看到实现类是AppPlugin,再继续看下AppPlugin的源码

public class AppPlugin extends AbstractAppPlugin {
    @Inject
    public AppPlugin(ToolingModelBuilderRegistry registry) {
        super(registry, true /*isBaseApplication*/);
    }

    ....
    @Override
    @NonNull
    protected Class<? extends AppExtension> getExtensionClass() {
        return BaseAppModuleExtension.class;
    }

}

我们知道插件类需要实现Plugin<Project>,而AppPlugin继承自AbstractAppPlugin所有继续向下找

public abstract class AbstractAppPlugin extends BasePlugin<AppExtensionImpl> {
    private final boolean isBaseApplication;

    ...
    @NonNull
    @Override
    protected BaseExtension createExtension(
            @NonNull Project project,
            @NonNull ProjectOptions projectOptions,
            @NonNull GlobalScope globalScope,
            @NonNull SdkHandler sdkHandler,
            @NonNull NamedDomainObjectContainer<BuildType> buildTypeContainer,
            @NonNull NamedDomainObjectContainer<ProductFlavor> productFlavorContainer,
            @NonNull NamedDomainObjectContainer<SigningConfig> signingConfigContainer,
            @NonNull NamedDomainObjectContainer<BaseVariantOutput> buildOutputs,
            @NonNull SourceSetManager sourceSetManager,
            @NonNull ExtraModelInfo extraModelInfo) {
        return project.getExtensions()
                .create(
                        "android",
                        getExtensionClass(),
                        project,
                        projectOptions,
                        globalScope,
                        sdkHandler,
                        buildTypeContainer,
                        productFlavorContainer,
                        signingConfigContainer,
                        buildOutputs,
                        sourceSetManager,
                        extraModelInfo,
                        isBaseApplication);
    }
}

AbstractAppPlugin继承自BasePlugin,继续向下看

public abstract class BasePlugin<E extends BaseExtension2>
        implements Plugin<Project>, ToolingRegistryProvider {

    ....

    @Override
    public final void apply(@NonNull Project project) {
        CrashReporting.runAction(
                () -> {
                    basePluginApply(project);
                    pluginSpecificApply(project);
                });
    }

我们看到BasePlugin实现了Plugin<Project>所以这个就是最终的一个实现类,我们看下apply这个里面是最主要的实现,里面调用了basePluginApply(project)方法,我们看一下源码

 private void basePluginApply(@NonNull Project project) {
        //上边坐了一些初始化操
        ...

        if (!projectOptions.get(BooleanOption.ENABLE_NEW_DSL_AND_API)) {
            //这里是最主要的几个方法
            threadRecorder.record(
                    ExecutionType.BASE_PLUGIN_PROJECT_CONFIGURE,
                    project.getPath(),
                    null,
                    //配置项目
                    this::configureProject);

            threadRecorder.record(
                    ExecutionType.BASE_PLUGIN_PROJECT_BASE_EXTENSION_CREATION,
                    project.getPath(),
                    null,
                    //配置扩展
                    this::configureExtension);

            threadRecorder.record(
                    ExecutionType.BASE_PLUGIN_PROJECT_TASKS_CREATION,
                    project.getPath(),
                    null,
                    //创建任务
                    this::createTasks);
        } 
    }

下面我们一次看一下这几个方法

configureProject

 private void configureProject() {
        ...
        //为Gradle插件处理所有的事情的sdk。每个项目大约有一个实例
        sdkHandler = new SdkHandler(project, getLogger());
        //创建AndroidBuilder,这是主构建器类。它得到了所有用于处理构建的数据(例如{@link
        //DefaultProductFlavor}、{@link DefaultBuildType}和依赖项)
        AndroidBuilder androidBuilder =
                new AndroidBuilder(
                        project == project.getRootProject() ? project.getName() : project.getPath(),
                        creator,
                        new GradleProcessExecutor(project),
                        new GradleJavaProcessExecutor(project),
                        extraModelInfo.getSyncIssueHandler(),
                        extraModelInfo.getMessageReceiver(),
                        getLogger());
        //创建dataBindingBuilder,
        dataBindingBuilder = new DataBindingBuilder();
        dataBindingBuilder.setPrintMachineReadableOutput(
                SyncOptions.getErrorFormatMode(projectOptions) == ErrorFormatMode.MACHINE_PARSABLE);

        ...

        // Enforce minimum versions of certain plugins
        //强制使用不低于当前支持插件的最小版本
        GradlePluginUtils.enforceMinimumVersionsOfPlugins(
                project, androidBuilder.getIssueReporter());

        // Apply the Java plugin
        //应用java插件
        project.getPlugins().apply(JavaBasePlugin.class);

        //创建构建缓存,如果启用,构建缓存目录将设置为用户定义的目录,如果用户定义的目录没有提供,则为默认目录
        @Nullable
        FileCache buildCache = BuildCacheUtils.createBuildCacheIfEnabled(project, projectOptions);
        //创建全局作用域,主要是为Android plugin 保存数据
        globalScope =
                new GlobalScope(
                        project,
                        new ProjectWrapper(project),
                        projectOptions,
                        dslScope,
                        androidBuilder,
                        sdkHandler,
                        registry,
                        buildCache);
        //找到assemble Task 添加描述
        project.getTasks()
                .getByName("assemble")
                .setDescription(
                        "Assembles all variants of all applications and secondary packages.");

        //执行时回调。这是在整个构建完成后调用的(不是在当前项目完成后)。
        //这个会被每个(android)项目调用,所以这个应该支持被调用2+次。  
        gradle.addBuildListener(
                new BuildListener() {
                    @Override
                    public void buildStarted(@NonNull Gradle gradle) {}

                    @Override
                    public void settingsEvaluated(@NonNull Settings settings) {}

                    @Override
                    public void projectsLoaded(@NonNull Gradle gradle) {}

                    @Override
                    public void projectsEvaluated(@NonNull Gradle gradle) {}

                    @Override
                    public void buildFinished(@NonNull BuildResult buildResult) {
                        // Do not run buildFinished for included project in composite build.
                        if (buildResult.getGradle().getParent() != null) {
                            return;
                        }
                        ModelBuilder.clearCaches();
                        sdkHandler.unload();
                        threadRecorder.record(
                                ExecutionType.BASE_PLUGIN_BUILD_FINISHED,
                                project.getPath(),
                                null,
                                () -> {
                                    WorkerActionServiceRegistry.INSTANCE
                                            .shutdownAllRegisteredServices(
                                                    ForkJoinPool.commonPool());
                                    Main.clearInternTables();
                                });
                        DeprecationReporterImpl.Companion.clean();
                    }
                });

    }

这个方法主要做了一下几件事

  • 创建SdkHandler,为Gradle插件处理所有的事情的sdk。每个项目大约有一个实例
  • 创建AndroidBuilder,这是主构建器类。它得到了所有用于处理构建的数据(例如{@linkDefaultProductFlavor}、{@link DefaultBuildType}和依赖项)
  • 创建DataBindingBuilder
  • 强制使用不低于当前支持插件的最小版本
  • 应用java插件
  • 创建构建缓存,如果启用,构建缓存目录将设置为用户定义的目录,如果用户定义的目录没有提供,则为默认目录
  • 创建全局作用域,主要是为Android plugin 保存数据
  • 找到assemble Task 添加描述
  • 监听构建完成回调,做一些清尾工作

configureExtension 配置扩展

什么是扩展我就不再重复说了,看我之前博客去

   private void configureExtension() {
        //是不是看起来很熟悉,是的这就是配置不固定数量的扩展,这个是配置的BuildType,
        //不懂的看之前博客,所以BuildType中才可以自定义名字
        final NamedDomainObjectContainer<BuildType> buildTypeContainer =
                project.container(
                        BuildType.class,
                        new BuildTypeFactory(
                                objectFactory,
                                project,
                                extraModelInfo.getSyncIssueHandler(),
                                extraModelInfo.getDeprecationReporter()));
        //一样的道理配置不定项扩展ProductFlavor
        final NamedDomainObjectContainer<ProductFlavor> productFlavorContainer =
                project.container(
                        ProductFlavor.class,
                        new ProductFlavorFactory(
                                objectFactory,
                                project,
                                extraModelInfo.getDeprecationReporter(),
                                project.getLogger()));
        //一样的道理配置不定项扩展SigningConfig
        final NamedDomainObjectContainer<SigningConfig> signingConfigContainer =
                project.container(
                        SigningConfig.class,
                        new SigningConfigFactory(
                                objectFactory,
                                GradleKeystoreHelper.getDefaultDebugKeystoreLocation()));
        //一样的道理配置不定项扩展BaseVariantOutput
        final NamedDomainObjectContainer<BaseVariantOutput> buildOutputs =
                project.container(BaseVariantOutput.class);

        project.getExtensions().add("buildOutputs", buildOutputs);

        sourceSetManager =
                new SourceSetManager(
                        project,
                        isPackagePublished(),
                        globalScope.getDslScope(),
                        new DelayedActionsExecutor());
        //这个就是创建 android 扩展
        extension =
                createExtension(
                        project,
                        projectOptions,
                        globalScope,
                        sdkHandler,
                        buildTypeContainer,
                        productFlavorContainer,
                        signingConfigContainer,
                        buildOutputs,
                        sourceSetManager,
                        extraModelInfo);

        globalScope.setExtension(extension);

        variantFactory = createVariantFactory(globalScope, extension);
        //创建TaskManager,任务管理类
        taskManager =
                createTaskManager(
                        globalScope,
                        project,
                        projectOptions,
                        dataBindingBuilder,
                        extension,
                        sdkHandler,
                        variantFactory,
                        registry,
                        threadRecorder);
        //创建VariantManager,变体管理类
        variantManager =
                new VariantManager(
                        globalScope,
                        project,
                        projectOptions,
                        extension,
                        variantFactory,
                        taskManager,
                        sourceSetManager,
                        threadRecorder);

        registerModels(registry, globalScope, variantManager, extension, extraModelInfo);

        ...

        //按顺序依次创建 signingConfig debug、buildType debug、buildType releas类型的 DSL。
        // create default Objects, signingConfig first as its used by the BuildTypes.
        variantFactory.createDefaultComponents(
                buildTypeContainer, productFlavorContainer, signingConfigContainer);
    }

这个方法主要是做了一下几件事

  • 配置不定项扩展BuildType,ProductFlavor,SigningConfig,BaseVariantOutput

    buildTypes {
        release {}
        debug {}
        vip {}
        aaa {}
    }
    
    
    flavorDimensions "xiaomi", "huawei"
    productFlavors {
        JD {
            dimension("xiaomi")
        }
        TAO {
            dimension("xiaomi")
        }
        PIN {
            dimension("huawei")
        }
    }
    

    所以我们才可以这样自定义每一项的名字,可以配置多项

  • 创建android 扩展,也就是我们最常用的

    android {
        compileSdkVersion 29
        ...
    }
    
  • 创建TaskManager,任务管理类

  • 创建VariantManager,变体管理类

  • 按顺序依次创建 signingConfig debug、buildType debug、buildType releas类型的 DSL。

createTasks

  private void createTasks() {
        threadRecorder.record(
                ExecutionType.TASK_MANAGER_CREATE_TASKS,
                project.getPath(),
                null,
                () -> taskManager.createTasksBeforeEvaluate());

        project.afterEvaluate(
                CrashReporting.afterEvaluate(
                        p -> {
                            sourceSetManager.runBuildableArtifactsActions();

                            threadRecorder.record(
                                    ExecutionType.BASE_PLUGIN_CREATE_ANDROID_TASKS,
                                    project.getPath(),
                                    null,
                                    this::createAndroidTasks);
                        }));
    }

这个方法分为俩个阶段,第一个是在BeforeEvaluate()创建createTasks,第二个是afterEvaluate之后createAndroidTasks

因为AndroidTask需要依赖配置项的配置才能生成任务,所以是在afterEvaluate之后创建,beforeEvaluate创建的任务跟我们编译没太大关系,所以重点分析afterEvaluate之后createAndroidTasks

createAndroidTasks

  final void createAndroidTasks() {
       ...
        //创建应用Task
        List<VariantScope> variantScopes = variantManager.createAndroidTasks();

    }

接下来我们看一下variantManagercreateAndroidTasks

 public List<VariantScope> createAndroidTasks() {
        variantFactory.validateModel(this);
        variantFactory.preVariantWork(project);
        //判断是否为空,如果为空就为这个list填充
        if (variantScopes.isEmpty()) {
            populateVariantDataList();
        }

        // Create top level test tasks.
        //创建项目级别的测试task
        taskManager.createTopLevelTestTasks(!productFlavors.isEmpty());

        //遍历variantScopes,然后为每一个VariantData创建Task
        for (final VariantScope variantScope : variantScopes) {
            createTasksForVariantData(variantScope);
        }

        //创建报告相关的task
        taskManager.createSourceSetArtifactReportTask(globalScope);

        taskManager.createReportTasks(variantScopes);

        return variantScopes;
    }

接下主要看下createTasksForVariantData方法

  public void createTasksForVariantData(final VariantScope variantScope) {
        final BaseVariantData variantData = variantScope.getVariantData();
        final VariantType variantType = variantData.getType();
        final GradleVariantConfiguration variantConfig = variantScope.getVariantConfiguration();
        //创建Assemble Task
        taskManager.createAssembleTask(variantData);
        if (variantType.isBaseModule()) {
            taskManager.createBundleTask(variantData);
        }

        if (variantType.isTestComponent()) {
           ...
        } else {
            //如果不是一个 Test moudle,则会调用 ApplicationTaskManager 的 createTasksForVariantScope 方法。
            taskManager.createTasksForVariantScope(variantScope);
        }
    }

这个最终会调用ApplicationTaskManager 的 createTasksForVariantScope ,在这个方法内部创建一系列适用于应用构建的Task

  @Override
    public void createTasksForVariantScope(@NonNull final VariantScope variantScope) {
        createAnchorTasks(variantScope);
        createCheckManifestTask(variantScope);

        handleMicroApp(variantScope);
        // Create all current streams (dependencies mostly at this point)
        createDependencyStreams(variantScope);

        // Add a task to publish the applicationId.
        createApplicationIdWriterTask(variantScope);

        // Add a task to process the manifest(s)

        // Add a task to create the res values

        // Add a task to compile renderscript files.

        // Add a task to merge the resource folders

        // Add tasks to compile shader

        // Add a task to merge the asset folders

        // Add a task to create the BuildConfig class

        // Add a task to process the Android Resources and generate source files

        // Add a task to process the java resources

        // Add external native build tasks

        // Add a task to merge the jni libs folders

        // Add feature related tasks if necessary

        // Add data binding tasks if enabled
    
        // Add a compile task   
    }

由于代码太长这里只留下了注释,注释也很清楚这里生成了一些列的 compileXXX、generateXXX、processXXX、mergeXXX的任务,这一系列的Task就是构建一个可运行完整APK所需要的偶有Task

有关Task的一些基础知识可以参考我这篇文章Gradle学习系列(二):Gradle核心探索

如何查看每个Task的实现类?

我们拿这个举例子

  createCheckManifestTask(variantScope);

我们跟进去源码看一下

 public void createCheckManifestTask(@NonNull VariantScope scope) {
        taskFactory.register(getCheckManifestConfig(scope));
    }

发现调用了taskFactory.register,继续跟下源码,进入TaskFactoryImpl的register

  override fun <T : Task> register(creationAction: TaskCreationAction<T>): TaskProvider<T> =
        taskContainer.registerTask(creationAction, null, null, null)

再继续跟进源码

fun <T : Task> TaskContainer.registerTask(
    creationAction: TaskCreationAction<T>,
    secondaryPreConfigAction: PreConfigAction? = null,
    secondaryAction: TaskConfigAction<in T>? = null,
    secondaryProviderCallback: TaskProviderCallback<T>? = null
): TaskProvider<T> {
    val actionWrapper = TaskAction(creationAction, secondaryPreConfigAction, secondaryAction, secondaryProviderCallback)
    return this.register(creationAction.name, creationAction.type, actionWrapper)
        .also { provider ->
            actionWrapper.postRegisterHook(provider)
        }
}

最终发现是调用了 TaskContainerregister(String var1, Class<T> var2, Action<? super T> var3);

所以最终还是要看Gradle API文档看下这个方法是干啥的

image.png

原来是创建一个新的任务,而任务名字和类型就是参数name,和type

image.png

所以需要回去看一下传入的name和type是什么

 public void createCheckManifestTask(@NonNull VariantScope scope) {
        taskFactory.register(getCheckManifestConfig(scope));
    }

    protected CheckManifest.CreationAction getCheckManifestConfig(@NonNull VariantScope scope) {
        return new CheckManifest.CreationAction(scope, false);
    }

继续看下new CheckManifest.CreationAction

 public static class CreationAction extends VariantTaskCreationAction<CheckManifest> {
        ...
        @NonNull
        @Override
        public String getName() {
            return getVariantScope().getTaskName("check", "Manifest");
        }

        @NonNull
        @Override
        public Class<CheckManifest> getType() {
            return CheckManifest.class;
        }

       ...

    }

最后发现这个Task的名字是checkXXXManifest,任务的类型是CheckManifest,所以CheckManifest就是task的实现类

public class CheckManifest extends AndroidVariantTask {
...
}
abstract class AndroidVariantTask : DefaultTask(), VariantAwareTask {

}

这样就找到了一个Task的实现类

Dex的编译过程源码分析

我们从这个方法开始分析Add a compile task

  @Override
    public void createTasksForVariantScope(@NonNull final VariantScope variantScope) {
        createAnchorTasks(variantScope);
        createCheckManifestTask(variantScope);
        ...
        // Add a compile task
        createCompileTask(variantScope);

        ...
    }
    protected void createCompileTask(@NonNull VariantScope variantScope) {
        TaskProvider<? extends JavaCompile> javacTask = createJavacTask(variantScope);
        addJavacClassesStream(variantScope);
        setJavaCompilerTask(javacTask, variantScope);
        createPostCompilationTasks(variantScope);
    }

首先创建了javac任务,任务名为compileXXXJavaWithJavac,实现类为AndroidJavaCompile,该Task的任务就是讲java源文件编译成class,接下来看一下createPostCompilationTasks方法

    public void createPostCompilationTasks(

            @NonNull final VariantScope variantScope) {

        

        AndroidConfig extension = variantScope.getGlobalScope().getExtension();

        // Merge Java Resources.
        //java资源合并
        createMergeJavaResTransform(variantScope);

        // ----- External Transforms -----
        // apply all the external transforms.
        //添加所有的transforms到transformManager
        List<Transform> customTransforms = extension.getTransforms();
        List<List<Object>> customTransformsDependencies = extension.getTransformsDependencies();

        for (int i = 0, count = customTransforms.size(); i < count; i++) {
            Transform transform = customTransforms.get(i);

            List<Object> deps = customTransformsDependencies.get(i);
            transformManager.addTransform(
                    taskFactory,
                    variantScope,
                    transform,
                    null,
                    task -> {
                        if (!deps.isEmpty()) {
                            task.dependsOn(deps);
                        }
                    },
                    taskProvider -> {
                        // if the task is a no-op then we make assemble task depend on it.
                        if (transform.getScopes().isEmpty()) {
                            TaskFactoryUtils.dependsOn(
                                    variantScope.getTaskContainer().getAssembleTask(),
                                    taskProvider);
                        }
                    });
        }

        ...
        // ----- Minify next -----
        //如果启用minifyEnabled=true,进行代码缩减,就是进行混淆
        CodeShrinker shrinker = maybeCreateJavaCodeShrinkerTransform(variantScope);
        if (shrinker == CodeShrinker.R8) {
            //如果是R8执行资源缩减
            maybeCreateResourcesShrinkerTransform(variantScope);
            maybeCreateDexSplitterTransform(variantScope);
            // TODO: create JavaResSplitterTransform and call it here (http://b/77546738)
            return;
        }

        // ----- 10x support
        //InstantRun 支持
        TaskProvider<PreColdSwapTask> preColdSwapTask = null;
        if (variantScope.getInstantRunBuildContext().isInInstantRunMode()) {

            TaskProvider<? extends Task> allActionsAnchorTask =
                    createInstantRunAllActionsTasks(variantScope);
            assert variantScope.getInstantRunTaskManager() != null;
            preColdSwapTask =
                    variantScope.getInstantRunTaskManager().createPreColdswapTask(projectOptions);
            TaskFactoryUtils.dependsOn(preColdSwapTask, allActionsAnchorTask);
        }

        // ----- Multi-Dex support
        //Multi-Dex 支持
        DexingType dexingType = variantScope.getDexingType();

        // Upgrade from legacy multi-dex to native multi-dex if possible when using with a device
        if (dexingType == DexingType.LEGACY_MULTIDEX) {
            if (variantScope.getVariantConfiguration().isMultiDexEnabled()
                    && variantScope
                                    .getVariantConfiguration()
                                    .getMinSdkVersionWithTargetDeviceApi()
                                    .getFeatureLevel()
                            >= 21) {
                dexingType = DexingType.NATIVE_MULTIDEX;
            }
        }
        ...
        //创建Dex task
        createDexTasks(variantScope, dexingType);
        ...
    }

这个主要做了一下几个工作

  • java资源合并
  • 添加所有的transforms到transformManager
  • 如果启用minifyEnabled=true,进行代码缩减,就是进行混淆
  • 如果是R8执行资源缩减
  • InstantRun 支持
  • Multi-Dex 支持
  • 创建Dex task

这里创建的Dex Task 其实就是TransfromTask类型,下面了解一下TransfromTask



/** A task running a transform. */
@CacheableTask
public class TransformTask extends StreamBasedTask implements Context {

    @TaskAction
    void transform(final IncrementalTaskInputs incrementalTaskInputs)
            throws IOException, TransformException, InterruptedException {
        ....
        recorder.record(
                ExecutionType.TASK_TRANSFORM,
                executionInfo,
                getProject().getPath(),
                getVariantName(),
                new Recorder.Block<Void>() {
                    @Override
                    public Void call() throws Exception {

                        transform.transform(
                                new TransformInvocationBuilder(TransformTask.this)
                                        .addInputs(consumedInputs.getValue())
                                        .addReferencedInputs(referencedInputs.getValue())
                                        .addSecondaryInputs(changedSecondaryInputs.getValue())
                                        .addOutputProvider(
                                                outputStream != null
                                                        ? outputStream.asOutput(
                                                                isIncremental.getValue())
                                                        : null)
                                        .setIncrementalMode(isIncremental.getValue())
                                        .build());

                        if (outputStream != null) {
                            outputStream.save();
                        }
                        return null;
                    }
                });
    }
    ...
      
}

最终调用了transform的transform,也就是调用了DexArchiveBuilderTransformtransform

public class DexArchiveBuilderTransform extends Transform {
    ...
}

下面的需要了解一些Transform知识,可以看我之前的文章Gradle学习系列(五):Gradle Transform

读到这里我恍然大悟,原来我们自定义的Transform,添加到了extension中,然后在打包阶段编译java->class之后,class->dex之前,遍历extension中的Transform(包括我们自定义的)然后添加到TransformManager 注册为 TransformTask,当执行Task时候,在调用Transformtransform方法,这样就达到了在dex之前修改字节码的目的

下面继续看DexArchiveBuilderTransformtransform方法

  @Override
    public void transform(@NonNull TransformInvocation transformInvocation)
            throws TransformException, IOException, InterruptedException {
    
            //这里是遍历目录下的class文件
            for (TransformInput input : transformInvocation.getInputs()) {

                for (DirectoryInput dirInput : input.getDirectoryInputs()) {
                    logger.verbose("Dir input %s", dirInput.getFile().toString());
                    convertToDexArchive(
                            transformInvocation.getContext(),
                            dirInput,
                            outputProvider,
                            isIncremental,
                            bootclasspathServiceKey,
                            classpathServiceKey,
                            additionalPaths);
                }
                //这里是遍历jar中的class文件
                for (JarInput jarInput : input.getJarInputs()) {
                    logger.verbose("Jar input %s", jarInput.getFile().toString());

                    D8DesugaringCacheInfo cacheInfo =
                            getD8DesugaringCacheInfo(
                                    desugarIncrementalTransformHelper,
                                    bootclasspath,
                                    classpath,
                                    jarInput);

                    List<File> dexArchives =
                            processJarInput(
                                    transformInvocation.getContext(),
                                    isIncremental,
                                    jarInput,
                                    outputProvider,
                                    bootclasspathServiceKey,
                                    classpathServiceKey,
                                    additionalPaths,
                                    cacheInfo);
                    if (cacheInfo != D8DesugaringCacheInfo.DONT_CACHE && !dexArchives.isEmpty()) {
                        cacheableItems.add(
                                new DexArchiveBuilderCacheHandler.CacheableItem(
                                        jarInput,
                                        dexArchives,
                                        cacheInfo.orderedD8DesugaringDependencies));
                    }
                }
            }
    }

我们继续跟一下 convertToDexArchive方法,从方法名字就可以看出是转换为dex文件


    private List<File> convertToDexArchive(
            @NonNull Context context,
            @NonNull QualifiedContent input,
            @NonNull TransformOutputProvider outputProvider,
            boolean isIncremental,
            @NonNull ClasspathServiceKey bootClasspath,
            @NonNull ClasspathServiceKey classpath,
            @NonNull Set<File> additionalPaths) {

            ...
                executor.execute(
                        ...
                            try (Closeable ignored = output = outputHandler.createOutput()) {
                                launchProcessing(
                                        parameters,
                                        output.getStandardOutput(),
                                        output.getErrorOutput(),
                                        messageReceiver);
                            } 
            }
        }
        return dexArchives.build();
    }

最后调用了launchProcessing方法,继续跟进源码

  private static void launchProcessing(
            @NonNull DexConversionParameters dexConversionParameters,
            @NonNull OutputStream outStream,
            @NonNull OutputStream errStream,
            @NonNull MessageReceiver receiver)
            throws IOException, URISyntaxException {
        DexArchiveBuilder dexArchiveBuilder =
                getDexArchiveBuilder(
                        dexConversionParameters.minSdkVersion,
                        dexConversionParameters.dexAdditionalParameters,
                        dexConversionParameters.inBufferSize,
                        dexConversionParameters.outBufferSize,
                        dexConversionParameters.bootClasspath,
                        dexConversionParameters.classpath,
                        dexConversionParameters.dexer,
                        dexConversionParameters.isDebuggable,
                        VariantScope.Java8LangSupport.D8
                                == dexConversionParameters.java8LangSupportType,
                        outStream,
                        errStream,
                        receiver);

        ...

        try (ClassFileInput input = ClassFileInputs.fromPath(inputPath);
                Stream<ClassFileEntry> entries = input.entries(bucketFilter)) {
            dexArchiveBuilder.convert(
                    entries,
                    Paths.get(new URI(dexConversionParameters.output)),
                    dexConversionParameters.isDirectoryBased());
        } catch (DexArchiveBuilderException ex) {
            throw new DexArchiveBuilderException("Failed to process " + inputPath.toString(), ex);
        }
    }

最终调用dexArchiveBuilder.convertDexArchiveBuilder有俩个实现类 D8DexArchiveBuilderDxDexArchiveBuilder在这里最中转换为dex文件

dex编译总结

  • 首先创建了javac任务,该Task的任务就是讲java源文件编译成class
  • java资源合并
  • 添加所有的transforms到transformManager
  • 如果启用minifyEnabled=true,进行代码缩减,就是进行混淆
  • 如果是R8执行资源缩减
  • InstantRun 支持
  • Multi-Dex 支持
  • 创建Dex task
  • 最终D8DexArchiveBuilderDxDexArchiveBuilder在这里最中转换为dex文件

总结

Android Gradle Plugin 主要做了三件事

  • 配置项目,主要做了以下工作

    • 创建SdkHandler,为Gradle插件处理所有的事情的sdk。每个项目大约有一个实例
    • 创建AndroidBuilder,这是主构建器类。它得到了所有用于处理构建的数据(例如{@linkDefaultProductFlavor}、{@link DefaultBuildType}和依赖项)
    • 创建DataBindingBuilder
    • 强制使用不低于当前支持插件的最小版本
    • 应用java插件
    • 创建构建缓存,如果启用,构建缓存目录将设置为用户定义的目录,如果用户定义的目录没有提供,则为默认目录
    • 创建全局作用域,主要是为Android plugin 保存数据
    • 找到assemble Task 添加描述
    • 监听构建完成回调,做一些清尾工作
  • 配置扩展

    • 配置不定项扩展BuildType,ProductFlavor,SigningConfig,BaseVariantOutput

      buildTypes {
          release {}
          debug {}
          vip {}
          aaa {}
      }
      
      
      flavorDimensions "xiaomi", "huawei"
      productFlavors {
          JD {
              dimension("xiaomi")
          }
          TAO {
              dimension("xiaomi")
          }
          PIN {
              dimension("huawei")
          }
      }
      

      所以我们才可以这样自定义每一项的名字,可以配置多项

    • 创建android 扩展,也就是我们最常用的

      android {
          compileSdkVersion 29
          ...
      }
      
    • 创建TaskManager,任务管理类

    • 创建VariantManager,变体管理类

    • 按顺序依次创建 signingConfig debug、buildType debug、buildType releas类型的 DSL。

  • 创建任务

    这个最终会调用ApplicationTaskManager 的 createTasksForVariantScope ,在这个方法内部创建一系列适用于应用构建的Task,这里只保留了注释

    @Override
        public void createTasksForVariantScope(@NonNull final VariantScope variantScope) {
            createAnchorTasks(variantScope);
            createCheckManifestTask(variantScope);
    
            handleMicroApp(variantScope);
            // Create all current streams (dependencies mostly at this point)
            createDependencyStreams(variantScope);
    
            // Add a task to publish the applicationId.
            createApplicationIdWriterTask(variantScope);
    
            // Add a task to process the manifest(s)
    
            // Add a task to create the res values
    
            // Add a task to compile renderscript files.
    
            // Add a task to merge the resource folders
    
            // Add tasks to compile shader
    
            // Add a task to merge the asset folders
    
            // Add a task to create the BuildConfig class
    
            // Add a task to process the Android Resources and generate source files
    
            // Add a task to process the java resources
    
            // Add external native build tasks
    
            // Add a task to merge the jni libs folders
    
            // Add feature related tasks if necessary
    
            // Add data binding tasks if enabled
        
            // Add a compile task   
        }
    
  • 然后分析了如何找到每个Task的实现类

  • 最后具体分析了Dex Task的工作流程

参考

【灵魂七问】深度探索 Gradle 自动化构建技术(五、Gradle 插件架构实现原理剖析 — 下)

Android Gradle Plugin源码分析

🍵补齐Android技能树——从AGP构建过程到APK打包过程