概述
又开始了一个新的系列,这个系列学习Gradle,目标就是彻底理解Gradle,主要还是做下自己理解的笔记,防止忘记
Gradle学习系列(五):Gradle Transform
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源码
开始阅读源码
首先找什么看呢? 当然找我们经常用的插件,看他的源码实现,我们经常用的插件是这个
apply plugin: 'com.android.application'
复制代码
如何找这个插件的源码,这个就需要插件的基础知识了,不知道的返回去看Gradle学习系列(三):Gradle插件
直接看到实现类是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();
}
复制代码
接下来我们看一下variantManager
的createAndroidTasks
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)
}
}
复制代码
最终发现是调用了 TaskContainer
的 register(String var1, Class<T> var2, Action<? super T> var3);
所以最终还是要看Gradle API
文档看下这个方法是干啥的
原来是创建一个新的任务,而任务名字和类型就是参数name,和type
所以需要回去看一下传入的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,也就是调用了DexArchiveBuilderTransform
的transform
public class DexArchiveBuilderTransform extends Transform {
...
}
复制代码
下面的需要了解一些Transform
知识,可以看我之前的文章Gradle学习系列(五):Gradle Transform
读到这里我恍然大悟,原来我们自定义的Transform
,添加到了extension
中,然后在打包阶段编译java->class
之后,class->dex
之前,遍历extension
中的Transform
(包括我们自定义的)然后添加到TransformManager
注册为 TransformTask
,当执行Task
时候,在调用Transform
的transform
方法,这样就达到了在dex
之前修改字节码的目的
下面继续看DexArchiveBuilderTransform
的transform
方法
@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.convert
而 DexArchiveBuilder
有俩个实现类 D8DexArchiveBuilder
和 DxDexArchiveBuilder
在这里最中转换为dex文件
dex编译总结
- 首先创建了javac任务,该Task的任务就是讲java源文件编译成class
- java资源合并
- 添加所有的transforms到transformManager
- 如果启用minifyEnabled=true,进行代码缩减,就是进行混淆
- 如果是R8执行资源缩减
- InstantRun 支持
- Multi-Dex 支持
- 创建Dex task
- 最终
D8DexArchiveBuilder
和DxDexArchiveBuilder
在这里最中转换为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的工作流程