android源码分析-aapt,Android Gradle Plugin 源码分析(一)

本文是根据gradle3.1.2源码进行分析。Android Gradle Plugin本质上是一个gradle插件,肯定遵循自定义插件的结构,即继承Plugin类的源码,resources目录结构等。为简便起见,以下都将Android Gradle Plugin简称为AGP。

在分析源码之前,我们需要先下载AGP的源码。我们在此链接手动下载AGP3.1.2的源码。

Gradle 3.1.2源码的大概设计

cb0e085c466f

androidGradle.png

Extension:定义DSL类

Plugin:插件的入口

TaskManager:负责创建Task,本质上调用TaskContainer#create

Tasks:具体的任务类

Processor:处理具体的任务类

工具:真正的执行者

分析AppPlugin

我们在创建一个Android新项目时,项目模块的build.gradle文件中的第一行往往都是apply plugin: 'com.android.application'这行代码。这行代码会调用com.android.application插件的apply方法。

我们打开AGP源码的resources目录下的com.android.application.properties文件。其内容为implementation-class=com.android.build.gradle.AppPlugin

cb0e085c466f

AGP插件的配置

因此,我们从AppPlugin类的apply方法开始分析。

cb0e085c466f

apply.png

public class AppPlugin extends BasePlugin {

...

@Override

public void apply(@NonNull Project project) {

super.apply(project);

}

}

AppPlugin#apply方法很简单,只是调用父类BasePlugin#apply的方法。我们继续查看BasePlugin#apply。

@Override

public void apply(@NonNull Project project) {

// We run by default in headless mode, so the JVM doesn't steal focus.

System.setProperty("java.awt.headless", "true");

this.project = project;

this.projectOptions = new ProjectOptions(project);

project.getPluginManager().apply(AndroidBasePlugin.class);

checkConfigureOnDemandGradleVersionCompat();

checkPathForErrors();

checkModulesForErrors();

PluginInitializer.initialize(project);

ProfilerInitializer.init(project, projectOptions);

threadRecorder = ThreadRecorder.get();

ProcessProfileWriter.getProject(project.getPath())

.setAndroidPluginVersion(Version.ANDROID_GRADLE_PLUGIN_VERSION)

.setAndroidPlugin(getAnalyticsPluginType())

.setPluginGeneration(GradleBuildProject.PluginGeneration.FIRST)

.setOptions(AnalyticsUtil.toProto(projectOptions));

BuildableArtifactImpl.Companion.disableResolution();

if (!projectOptions.get(BooleanOption.ENABLE_NEW_DSL_AND_API)) {

TaskInputHelper.enableBypass();

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);

} else {

// 代码省略

}

}

上述代码中,依次执行configureProject,configureExtension,createTasks方法。

下面我们将依次分析这三个方法。

BasePlugin#configureProject

private void configureProject() {

final Gradle gradle = project.getGradle();

extraModelInfo = new ExtraModelInfo(project.getPath(), projectOptions, project.getLogger());

// 检查Gradle版本,如果Gradle版本低于所要求的最低版本,

// 则抛出异常。gradle3.1.2要求gradle版本最低为4.4

checkGradleVersion(project, getLogger(), projectOptions);

sdkHandler = new SdkHandler(project, getLogger());

// 省略代码

androidBuilder =

new AndroidBuilder(

project == project.getRootProject() ? project.getName() : project.getPath(),

creator,

new GradleProcessExecutor(project),

new GradleJavaProcessExecutor(project),

extraModelInfo.getSyncIssueHandler(),

extraModelInfo.getMessageReceiver(),

getLogger(),

isVerbose());

dataBindingBuilder = new DataBindingBuilder();

dataBindingBuilder.setPrintMachineReadableOutput(

SyncOptions.getErrorFormatMode(projectOptions) == ErrorFormatMode.MACHINE_PARSABLE);

// 检查是否有被移除的配置选项

if (projectOptions.hasRemovedOptions()) {

androidBuilder

.getIssueReporter()

.reportWarning(Type.GENERIC, projectOptions.getRemovedOptionsErrorMessage());

}

// 检查是否使用被弃用的配置选项

if (projectOptions.hasDeprecatedOptions()) {

extraModelInfo

.getDeprecationReporter()

.reportDeprecatedOptions(projectOptions.getDeprecatedOptions());

}

// Apply the Java plugin

project.getPlugins().apply(JavaBasePlugin.class);

project.getTasks()

.getByName("assemble")

.setDescription(

"Assembles all variants of all applications and secondary packages.");

// call back on execution. This is called after the whole build is done (not

// after the current project is done).

// This is will be called for each (android) projects though, so this should support

// being called 2+ times.

gradle.addBuildListener(

new BuildListener() {

@Override

public void buildStarted(@NonNull Gradle gradle) {

TaskInputHelper.enableBypass();

BuildableArtifactImpl.Companion.disableResolution();

}

@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;

}

sdkHandler.unload();

threadRecorder.record(

ExecutionType.BASE_PLUGIN_BUILD_FINISHED,

project.getPath(),

null,

() -> {

WorkerActionServiceRegistry.INSTANCE

.shutdownAllRegisteredServices(

ForkJoinPool.commonPool());

PreDexCache.getCache()

.clear(

FileUtils.join(

project.getRootProject().getBuildDir(),

FD_INTERMEDIATES,

"dex-cache",

"cache.xml"),

getLogger());

Main.clearInternTables();

});

}

});

gradle.getTaskGraph()

.addTaskExecutionGraphListener(

taskGraph -> {

TaskInputHelper.disableBypass();

Aapt2DaemonManagerService.registerAaptService(

Objects.requireNonNull(androidBuilder.getTargetInfo())

.getBuildTools(),

loggerWrapper,

WorkerActionServiceRegistry.INSTANCE);

for (Task task : taskGraph.getAllTasks()) {

if (task instanceof TransformTask) {

Transform transform = ((TransformTask) task).getTransform();

if (transform instanceof DexTransform) {

PreDexCache.getCache()

.load(

FileUtils.join(

project.getRootProject()

.getBuildDir(),

FD_INTERMEDIATES,

"dex-cache",

"cache.xml"));

break;

}

}

}

});

createLintClasspathConfiguration(project);

}

从上面代码可以看出,该方法前面主要做一些gradle版本检查,以及配置选项是否被弃用等等,诸如此类的工作。

BasePlugin#configureExtension

private void configureExtension() {

ObjectFactory objectFactory = project.getObjects();

final NamedDomainObjectContainer buildTypeContainer =

project.container(

BuildType.class,

new BuildTypeFactory(

objectFactory,

project,

extraModelInfo.getSyncIssueHandler(),

extraModelInfo.getDeprecationReporter()));

final NamedDomainObjectContainer productFlavorContainer =

project.container(

ProductFlavor.class,

new ProductFlavorFactory(

objectFactory,

project,

extraModelInfo.getDeprecationReporter(),

project.getLogger()));

final NamedDomainObjectContainer signingConfigContainer =

project.container(

SigningConfig.class,

new SigningConfigFactory(

objectFactory,

GradleKeystoreHelper.getDefaultDebugKeystoreLocation()));

final NamedDomainObjectContainer buildOutputs =

project.container(BaseVariantOutput.class);

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

sourceSetManager = createSourceSetManager();

extension =

createExtension(

project,

projectOptions,

androidBuilder,

sdkHandler,

buildTypeContainer,

productFlavorContainer,

signingConfigContainer,

buildOutputs,

sourceSetManager,

extraModelInfo);

ndkHandler =

new NdkHandler(

project.getRootDir(),

null, /* compileSkdVersion, this will be set in afterEvaluate */

"gcc",

"" /*toolchainVersion*/,

false /* useUnifiedHeaders */);

@Nullable

FileCache buildCache = BuildCacheUtils.createBuildCacheIfEnabled(project, projectOptions);

GlobalScope globalScope =

new GlobalScope(

project,

projectOptions,

androidBuilder,

extension,

sdkHandler,

ndkHandler,

registry,

buildCache);

variantFactory = createVariantFactory(globalScope, androidBuilder, extension);

taskManager =

createTaskManager(

globalScope,

project,

projectOptions,

androidBuilder,

dataBindingBuilder,

extension,

sdkHandler,

ndkHandler,

registry,

threadRecorder);

variantManager =

new VariantManager(

globalScope,

project,

projectOptions,

androidBuilder,

extension,

variantFactory,

taskManager,

sourceSetManager,

threadRecorder);

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

// map the whenObjectAdded callbacks on the containers.

signingConfigContainer.whenObjectAdded(variantManager::addSigningConfig);

buildTypeContainer.whenObjectAdded(

buildType -> {

SigningConfig signingConfig =

signingConfigContainer.findByName(BuilderConstants.DEBUG);

buildType.init(signingConfig);

variantManager.addBuildType(buildType);

});

productFlavorContainer.whenObjectAdded(variantManager::addProductFlavor);

// map whenObjectRemoved on the containers to throw an exception.

signingConfigContainer.whenObjectRemoved(

new UnsupportedAction("Removing signingConfigs is not supported."));

buildTypeContainer.whenObjectRemoved(

new UnsupportedAction("Removing build types is not supported."));

productFlavorContainer.whenObjectRemoved(

new UnsupportedAction("Removing product flavors is not supported."));

// create default Objects, signingConfig first as its used by the BuildTypes.

variantFactory.createDefaultComponents(

buildTypeContainer, productFlavorContainer, signingConfigContainer);

}

该方法主要是创建Extension,并且创建相应的TaskManager和VariantManager。AppPlugin对应的Extension是AppExtension,对应的TaskManager是ApplicationTaskManager。

然后依次添加signingConfig,buildType和productFlavor。主要通过调用Variant Manager的addSigningConfig,addBuildType以及addProductFlavor方法。

BasePlugin#createTasks

private void createTasks() {

threadRecorder.record(

ExecutionType.TASK_MANAGER_CREATE_TASKS,

project.getPath(),

null,

() -> taskManager.createTasksBeforeEvaluate());

project.afterEvaluate(

project ->

threadRecorder.record(

ExecutionType.BASE_PLUGIN_CREATE_ANDROID_TASKS,

project.getPath(),

null,

() -> createAndroidTasks(false)));

}

BasePlugin#createAndroidTasks

@VisibleForTesting

final void createAndroidTasks(boolean force) {

// Make sure unit tests set the required fields.

checkState(extension.getBuildToolsRevision() != null,

"buildToolsVersion is not specified.");

checkState(extension.getCompileSdkVersion() != null, "compileSdkVersion is not specified.");

ndkHandler.setCompileSdkVersion(extension.getCompileSdkVersion());

// get current plugins and look for the default Java plugin.

if (project.getPlugins().hasPlugin(JavaPlugin.class)) {

throw new BadPluginException(

"The 'java' plugin has been applied, but it is not compatible with the Android plugins.");

}

boolean targetSetupSuccess = ensureTargetSetup();

sdkHandler.ensurePlatformToolsIsInstalledWarnOnFailure(

extraModelInfo.getSyncIssueHandler());

// Stop trying to configure the project if the SDK is not ready.

// Sync issues will already have been collected at this point in sync.

if (!targetSetupSuccess) {

project.getLogger()

.warn("Aborting configuration as SDK is missing components in sync mode.");

return;

}

// don't do anything if the project was not initialized.

// Unless TEST_SDK_DIR is set in which case this is unit tests and we don't return.

// This is because project don't get evaluated in the unit test setup.

// See AppPluginDslTest

if (!force

&& (!project.getState().getExecuted() || project.getState().getFailure() != null)

&& SdkHandler.sTestSdkFolder == null) {

return;

}

if (hasCreatedTasks) {

return;

}

hasCreatedTasks = true;

extension.disableWrite();

taskManager.configureCustomLintChecks();

ProcessProfileWriter.getProject(project.getPath())

.setCompileSdk(extension.getCompileSdkVersion())

.setBuildToolsVersion(extension.getBuildToolsRevision().toString())

.setSplits(AnalyticsUtil.toProto(extension.getSplits()));

String kotlinPluginVersion = getKotlinPluginVersion();

if (kotlinPluginVersion != null) {

ProcessProfileWriter.getProject(project.getPath())

.setKotlinPluginVersion(kotlinPluginVersion);

}

// setup SDK repositories.

sdkHandler.addLocalRepositories(project);

threadRecorder.record(

ExecutionType.VARIANT_MANAGER_CREATE_ANDROID_TASKS,

project.getPath(),

null,

() -> {

variantManager.createAndroidTasks();

ApiObjectFactory apiObjectFactory =

new ApiObjectFactory(

androidBuilder,

extension,

variantFactory,

project.getObjects());

for (VariantScope variantScope : variantManager.getVariantScopes()) {

BaseVariantData variantData = variantScope.getVariantData();

apiObjectFactory.create(variantData);

}

// Make sure no SourceSets were added through the DSL without being properly configured

// Only do it if we are not restricting to a single variant (with Instant

// Run or we can find extra source set

if (projectOptions.get(StringOption.IDE_RESTRICT_VARIANT_NAME) == null) {

sourceSetManager.checkForUnconfiguredSourceSets();

}

// must run this after scopes are created so that we can configure kotlin

// kapt tasks

taskManager.addDataBindingDependenciesIfNecessary(

extension.getDataBinding(), variantManager.getVariantScopes());

});

// create the global lint task that depends on all the variants

taskManager.configureGlobalLintTask(variantManager.getVariantScopes());

// Create and read external native build JSON files depending on what's happening right

// now.

//

// CREATE PHASE:

// Creates JSONs by shelling out to external build system when:

// - Any one of AndroidProject.PROPERTY_INVOKED_FROM_IDE,

// AndroidProject.PROPERTY_BUILD_MODEL_ONLY_ADVANCED,

// AndroidProject.PROPERTY_BUILD_MODEL_ONLY,

// AndroidProject.PROPERTY_REFRESH_EXTERNAL_NATIVE_MODEL are set.

// - *and* AndroidProject.PROPERTY_REFRESH_EXTERNAL_NATIVE_MODEL is set

// or JSON files don't exist or are out-of-date.

// Create phase may cause ProcessException (from cmake.exe for example)

//

// READ PHASE:

// Reads and deserializes JSONs when:

// - Any one of AndroidProject.PROPERTY_INVOKED_FROM_IDE,

// AndroidProject.PROPERTY_BUILD_MODEL_ONLY_ADVANCED,

// AndroidProject.PROPERTY_BUILD_MODEL_ONLY,

// AndroidProject.PROPERTY_REFRESH_EXTERNAL_NATIVE_MODEL are set.

// Read phase may produce IOException if the file can't be read for standard IO reasons.

// Read phase may produce JsonSyntaxException in the case that the content of the file is

// corrupt.

boolean forceRegeneration =

projectOptions.get(BooleanOption.IDE_REFRESH_EXTERNAL_NATIVE_MODEL);

checkSplitConfiguration();

if (ExternalNativeBuildTaskUtils.shouldRegenerateOutOfDateJsons(projectOptions)) {

threadRecorder.record(

ExecutionType.VARIANT_MANAGER_EXTERNAL_NATIVE_CONFIG_VALUES,

project.getPath(),

null,

() -> {

for (VariantScope variantScope : variantManager.getVariantScopes()) {

ExternalNativeJsonGenerator generator =

variantScope.getExternalNativeJsonGenerator();

if (generator != null) {

// This will generate any out-of-date or non-existent JSONs.

// When refreshExternalNativeModel() is true it will also

// force update all JSONs.

generator.build(forceRegeneration);

}

}

});

}

BuildableArtifactImpl.Companion.enableResolution();

}

VariantManager#createAndroidTasks

public void createAndroidTasks() {

variantFactory.validateModel(this);

variantFactory.preVariantWork(project);

if (variantScopes.isEmpty()) {

recorder.record(

ExecutionType.VARIANT_MANAGER_CREATE_VARIANTS,

project.getPath(),

null /*variantName*/,

this::populateVariantDataList);

}

// Create top level test tasks.

recorder.record(

ExecutionType.VARIANT_MANAGER_CREATE_TESTS_TASKS,

project.getPath(),

null /*variantName*/,

() -> taskManager.createTopLevelTestTasks(!productFlavors.isEmpty()));

for (final VariantScope variantScope : variantScopes) {

recorder.record(

ExecutionType.VARIANT_MANAGER_CREATE_TASKS_FOR_VARIANT,

project.getPath(),

variantScope.getFullVariantName(),

() -> createTasksForVariantData(variantScope));

}

taskManager.createReportTasks(variantScopes);

}

该方法是创建变体和任务的入口。首先,判断variantScopes变量是否为空。variantScopes变量是VariantScope的List。而VariantScope是存放特定变体的数据。如果variantScopes为空,则会调用populateVariantDataList方法。populateVariantDataList方法用于创建所有的变体。现在我们查看一下populateVariantDataList方法如何创建变体的。

VariantManager#populateVariantDataList

public void populateVariantDataList() {

List flavorDimensionList = extension.getFlavorDimensionList();

if (productFlavors.isEmpty()) {

configureDependencies();

createVariantDataForProductFlavors(Collections.emptyList());

} else {

// ensure that there is always a dimension

if (flavorDimensionList == null || flavorDimensionList.isEmpty()) {

androidBuilder

.getIssueReporter()

.reportError(

EvalIssueReporter.Type.UNNAMED_FLAVOR_DIMENSION,

"All flavors must now belong to a named flavor dimension. "

+ "Learn more at "

+ "https://d.android.com/r/tools/flavorDimensions-missing-error-message.html");

} else if (flavorDimensionList.size() == 1) {

// if there's only one dimension, auto-assign the dimension to all the flavors.

String dimensionName = flavorDimensionList.get(0);

for (ProductFlavorData flavorData : productFlavors.values()) {

CoreProductFlavor flavor = flavorData.getProductFlavor();

if (flavor.getDimension() == null && flavor instanceof DefaultProductFlavor) {

((DefaultProductFlavor) flavor).setDimension(dimensionName);

}

}

}

// can only call this after we ensure all flavors have a dimension.

configureDependencies();

// Create iterable to get GradleProductFlavor from ProductFlavorData.

Iterable flavorDsl =

Iterables.transform(

productFlavors.values(),

ProductFlavorData::getProductFlavor);

// Get a list of all combinations of product flavors.

List> flavorComboList =

ProductFlavorCombo.createCombinations(

flavorDimensionList,

flavorDsl);

for (ProductFlavorCombo flavorCombo : flavorComboList) {

//noinspection unchecked

createVariantDataForProductFlavors(

(List) (List) flavorCombo.getFlavorList());

}

}

}

首先,通过extension变量获得变体的风味维度(即flavor dimension),然后,判断productFlavors是否为空,若为空,则调用configureDependencies和createVariantDataForProductFlavors方法。若不为空,则判断flavorDimensionList是否为null,若为null,则报告错误。如果你之前升级过gradle3.0,那么对这个报错信息肯定很熟悉。它提示你,所有的flavors都必须有一个维度,即dimension。dimension是Gradle3.0以上新加的特性。具体的内容可以见升级Gradle3.x文章。

分析完populateVariantDataList方法后,我们继续看VariantManager#createAndroidTasks 方法的执行过程。主要先后调用三个方法,createTopLevelTestTasks,createTasksForVariantData以及createReportTasks方法。createTopLevelTestTasks主要是用来创建一些测试任务,在这里就不具体分析了,有兴趣的可以自行查看源码。下面我们主要分析一下createTasksForVariantData方法。

VariantManager#createTasksForVariantData

/** Create tasks for the specified variant. */

public void createTasksForVariantData(final VariantScope variantScope) {

final BaseVariantData variantData = variantScope.getVariantData();

final VariantType variantType = variantData.getType();

final GradleVariantConfiguration variantConfig = variantScope.getVariantConfiguration();

final BuildTypeData buildTypeData = buildTypes.get(variantConfig.getBuildType().getName());

if (buildTypeData.getAssembleTask() == null) {

buildTypeData.setAssembleTask(taskManager.createAssembleTask(buildTypeData));

}

// Add dependency of assemble task on assemble build type task.

taskManager

.getTaskFactory()

.configure(

"assemble",

task -> {

assert buildTypeData.getAssembleTask() != null;

task.dependsOn(buildTypeData.getAssembleTask().getName());

});

createAssembleTaskForVariantData(variantData);

if (variantType.isForTesting()) {

// 省略代码

} else {

taskManager.createTasksForVariantScope(variantScope);

}

}

VariantManager类主要用于创建和管理变体。这个方法主要作用是创建变体的task。主要是将variantScope参数传给TaskManager的createTasksForVariantScope方法。createTasksForVariantScope方法逻辑很简单,在非测试环境下,直接调用TaskManager的createTasksForVariantScope方法。上面我们说过,AppPlugin的TaskManger实现类是ApplicationTaskManager。我们将代码定位到ApplicationTaskManager类的createTasksForVariantScope方法。

ApplicationTaskManager#createTasksForVariantScope

@Override

public void createTasksForVariantScope(@NonNull final VariantScope variantScope) {

BaseVariantData variantData = variantScope.getVariantData();

assert variantData instanceof ApplicationVariantData;

// 这个方法会创建preBuild任务

createAnchorTasks(variantScope);

createCheckManifestTask(variantScope);

// 这个主要是针对可穿戴设备

// Configure variantData to generate embedded wear application.

handleMicroApp(variantScope);

// Create all current streams (dependencies mostly at this point)

createDependencyStreams(variantScope);

// Add a task to publish the applicationId.

createApplicationIdWriterTask(variantScope);

taskFactory.create(new MainApkListPersistence.ConfigAction(variantScope));

taskFactory.create(new BuildArtifactReportTask.ConfigAction(variantScope));

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

recorder.record(

ExecutionType.APP_TASK_MANAGER_CREATE_MERGE_MANIFEST_TASK,

project.getPath(),

variantScope.getFullVariantName(),

() -> createMergeApkManifestsTask(variantScope));

// Add a task to create the res values

recorder.record(

ExecutionType.APP_TASK_MANAGER_CREATE_GENERATE_RES_VALUES_TASK,

project.getPath(),

variantScope.getFullVariantName(),

() -> createGenerateResValuesTask(variantScope));

// Add a task to compile renderscript files.

recorder.record(

ExecutionType.APP_TASK_MANAGER_CREATE_CREATE_RENDERSCRIPT_TASK,

project.getPath(),

variantScope.getFullVariantName(),

() -> createRenderscriptTask(variantScope));

// Add a task to merge the resource folders

recorder.record(

ExecutionType.APP_TASK_MANAGER_CREATE_MERGE_RESOURCES_TASK,

project.getPath(),

variantScope.getFullVariantName(),

(Recorder.VoidBlock) () -> createMergeResourcesTask(variantScope, true));

// Add tasks to compile shader

recorder.record(

ExecutionType.APP_TASK_MANAGER_CREATE_SHADER_TASK,

project.getPath(),

variantScope.getFullVariantName(),

() -> createShaderTask(variantScope));

// Add a task to merge the asset folders

recorder.record(

ExecutionType.APP_TASK_MANAGER_CREATE_MERGE_ASSETS_TASK,

project.getPath(),

variantScope.getFullVariantName(),

() -> {

createMergeAssetsTask(variantScope);

});

// Add a task to create the BuildConfig class

recorder.record(

ExecutionType.APP_TASK_MANAGER_CREATE_BUILD_CONFIG_TASK,

project.getPath(),

variantScope.getFullVariantName(),

() -> createBuildConfigTask(variantScope));

recorder.record(

ExecutionType.APP_TASK_MANAGER_CREATE_PROCESS_RES_TASK,

project.getPath(),

variantScope.getFullVariantName(),

() -> {

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

createApkProcessResTask(variantScope);

// Add a task to process the java resources

createProcessJavaResTask(variantScope);

});

recorder.record(

ExecutionType.APP_TASK_MANAGER_CREATE_AIDL_TASK,

project.getPath(),

variantScope.getFullVariantName(),

() -> createAidlTask(variantScope));

// Add NDK tasks

if (!isComponentModelPlugin()) {

recorder.record(

ExecutionType.APP_TASK_MANAGER_CREATE_NDK_TASK,

project.getPath(),

variantScope.getFullVariantName(),

() -> createNdkTasks(variantScope));

} else {

if (variantData.compileTask != null) {

variantData.compileTask.dependsOn(getNdkBuildable(variantData));

} else {

variantScope.getCompileTask().dependsOn(getNdkBuildable(variantData));

}

}

variantScope.setNdkBuildable(getNdkBuildable(variantData));

// Add external native build tasks

recorder.record(

ExecutionType.APP_TASK_MANAGER_CREATE_EXTERNAL_NATIVE_BUILD_TASK,

project.getPath(),

variantScope.getFullVariantName(),

() -> {

createExternalNativeBuildJsonGenerators(variantScope);

createExternalNativeBuildTasks(variantScope);

});

// Add a task to merge the jni libs folders

recorder.record(

ExecutionType.APP_TASK_MANAGER_CREATE_MERGE_JNILIBS_FOLDERS_TASK,

project.getPath(),

variantScope.getFullVariantName(),

() -> createMergeJniLibFoldersTasks(variantScope));

// Add data binding tasks if enabled

createDataBindingTasksIfNecessary(variantScope, MergeType.MERGE);

// Add a compile task

recorder.record(

ExecutionType.APP_TASK_MANAGER_CREATE_COMPILE_TASK,

project.getPath(),

variantScope.getFullVariantName(),

() -> addCompileTask(variantScope));

createStripNativeLibraryTask(taskFactory, variantScope);

if (variantScope.getVariantData().getMultiOutputPolicy().equals(MultiOutputPolicy.SPLITS)) {

if (extension.getBuildToolsRevision().getMajor() < 21) {

throw new RuntimeException(

"Pure splits can only be used with buildtools 21 and later");

}

recorder.record(

ExecutionType.APP_TASK_MANAGER_CREATE_SPLIT_TASK,

project.getPath(),

variantScope.getFullVariantName(),

() -> createSplitTasks(variantScope));

}

recorder.record(

ExecutionType.APP_TASK_MANAGER_CREATE_PACKAGING_TASK,

project.getPath(),

variantScope.getFullVariantName(),

() -> {

BuildInfoWriterTask buildInfoWriterTask =

createInstantRunPackagingTasks(variantScope);

createPackagingTask(variantScope, buildInfoWriterTask);

});

// create the lint tasks.

recorder.record(

ExecutionType.APP_TASK_MANAGER_CREATE_LINT_TASK,

project.getPath(),

variantScope.getFullVariantName(),

() -> createLintTasks(variantScope));

}

在上述代码中看到,大部分的任务都是在createTasksForVariantScope方法里使用taskFactory创建的。taskFactory是TaskFactory接口的对象。TaskFactory的实现类是TaskFactoryImp。

我们运行一个Android工程的assembleRelease任务,就可以看到任务的执行顺序,如下所示:

:app:preBuild UP-TO-DATE

:app:preReleaseBuild

:app:compileReleaseAidl

:app:compileReleaseRenderscript

:app:checkReleaseManifest

:app:generateReleaseBuildConfig

:app:prepareLintJar UP-TO-DATE

:app:mainApkListPersistenceRelease

:app:generateReleaseResValues

:app:generateReleaseResources

:app:mergeReleaseResources

:app:createReleaseCompatibleScreenManifests

:app:processReleaseManifest

:app:splitsDiscoveryTaskRelease

:app:processReleaseResources

:app:generateReleaseSources

:app:javaPreCompileRelease

:app:compileReleaseJavaWithJavac

:app:compileReleaseNdk NO-SOURCE

:app:compileReleaseSources

:app:lintVitalRelease

:app:mergeReleaseShaders

:app:compileReleaseShaders

:app:generateReleaseAssets

:app:mergeReleaseAssets

:app:transformClassesWithDexBuilderForRelease

:app:transformDexArchiveWithExternalLibsDexMergerForRelease

:app:transformDexArchiveWithDexMergerForRelease

:app:mergeReleaseJniLibFolders

:app:transformNativeLibsWithMergeJniLibsForRelease

:app:transformNativeLibsWithStripDebugSymbolForRelease

:app:processReleaseJavaRes NO-SOURCE

:app:transformResourcesWithMergeJavaResForRelease

:app:packageRelease

:app:assembleRelease

总结

本篇文章主要分析了Android Gradle3.1.2插件的源码大体设计,以及如何通过apply plugin: 'com.android.application'创建了变体和任务的。

在下一篇文章,会继续分析具体Task的执行过程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值