Android编译由Gradle插件来完成。
在平时开发中,我们都知道,添加以下Gradle插件,我们就可以编译Android项目。
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
}
apply plugin: 'com.android.application' //主项目
apply plugin: 'com.android.library' //Library
那我们要如何看到com.android.tools.build:gradle
的源码呢?
我们可以在app的gradle引入
compileOnly "com.android.tools.build:gradle:3.0.1"
然后就可以在External Libraries
中,看到源码了。
接着,我们来看下com.android.application.properties
implementation-class=com.android.build.gradle.AppPlugin
可以看到,AppPlugin这个类,即com.android.application
的入口是AppPlugin
public class AppPlugin extends BasePlugin implements Plugin<Project> {
//...
}
我们来看其中的apply方法
@Override
public void apply(@NonNull Project project) {
super.apply(project);
}
可以看到,其调用了父类BasePlugin
,我们来看BasePlugin
的apply方法
protected 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");
project.getPluginManager().apply(AndroidBasePlugin.class);
checkPluginVersion();
TaskInputHelper.enableBypass();
this.project = project;
this.projectOptions = new ProjectOptions(project);
ExecutionConfigurationUtil.setThreadPoolSize(projectOptions);
checkPathForErrors();
checkModulesForErrors();
PluginInitializer.initialize(project, projectOptions);
ProfilerInitializer.init(project, projectOptions);
//获得threadRecorder
threadRecorder = ThreadRecorder.get();
ProcessProfileWriter.getProject(project.getPath())
.setAndroidPluginVersion(Version.ANDROID_GRADLE_PLUGIN_VERSION)
.setAndroidPlugin(getAnalyticsPluginType())
.setPluginGeneration(GradleBuildProject.PluginGeneration.FIRST);
//记录一个方法的耗时,内部会调用configureProject()
threadRecorder.record(
ExecutionType.BASE_PLUGIN_PROJECT_CONFIGURE,
project.getPath(),
null,
this::configureProject);
//记录一个方法的耗时,内部会调用configureExtension()
threadRecorder.record(
ExecutionType.BASE_PLUGIN_PROJECT_BASE_EXTENSION_CREATION,
project.getPath(),
null,
this::configureExtension);
//记录一个方法的耗时,内部会调用createTasks()
threadRecorder.record(
ExecutionType.BASE_PLUGIN_PROJECT_TASKS_CREATION,
project.getPath(),
null,
this::createTasks);
}
可以看到,这里主要执行了三个方法: configureProject()
、configureExtension
、createTasks()
该方法用来配置我们的Project
private void configureProject() {
extraModelInfo = new ExtraModelInfo(projectOptions, project.getLogger());
checkGradleVersion();
//创建SdkHandler,SdkHandler需要用到android.jar这个包
sdkHandler = new SdkHandler(project, getLogger());
if (!project.getGradle().getStartParameter().isOffline()
&& projectOptions.get(BooleanOption.ENABLE_SDK_DOWNLOAD)
&& !projectOptions.get(BooleanOption.IDE_INVOKED_FROM_IDE)) {
SdkLibData sdkLibData = SdkLibData.download(getDownloader(), getSettingsController());
sdkHandler.setSdkLibData(sdkLibData);
}
//创建一个构建的对象 AndroidBuilder
androidBuilder = new AndroidBuilder(
project == project.getRootProject() ? project.getName() : project.getPath(),
creator,
new GradleProcessExecutor(project),
new GradleJavaProcessExecutor(project),
extraModelInfo,
getLogger(),
isVerbose());
//创建一个构建的对象 DataBindingBuilder
dataBindingBuilder = new DataBindingBuilder();
dataBindingBuilder.setPrintMachineReadableOutput(
extraModelInfo.getErrorFormatMode() ==
ExtraModelInfo.ErrorFormatMode.MACHINE_PARSABLE);
//关联Java和Jacoco(单元测试) Plugin
// Apply the Java and Jacoco plugins.
project.getPlugins().apply(JavaBasePlugin.class);
project.getPlugins().apply(JacocoPlugin.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.
project.getGradle()
.addBuildListener(
new BuildListener() {
@Override
public void buildStarted(Gradle gradle) {
TaskInputHelper.enableBypass();
}
@Override
public void settingsEvaluated(Settings settings) {
}
@Override
public void projectsLoaded(Gradle gradle) {
}
@Override
public void projectsEvaluated(Gradle gradle) {
}
@Override
public void buildFinished(BuildResult buildResult) {
// Do not run buildFinished for included project in composite build.
if (buildResult.getGradle().getParent() != null) {
return;
}
ExecutorSingleton.shutdown();
sdkHandler.unload();
threadRecorder.record(
ExecutionType.BASE_PLUGIN_BUILD_FINISHED,
project.getPath(),
null,
() -> {
//清除缓存
PreDexCache.getCache()
.clear(
FileUtils.join(
project.getRootProject()
.getBuildDir(),
FD_INTERMEDIATES,
"dex-cache",
"cache.xml"),
getLogger());
Main.clearInternTables();
});
}
});
project.getGradle()
.getTaskGraph()
.addTaskExecutionGraphListener(
taskGraph -> {
TaskInputHelper.disableBypass();
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;
}
}
}
});
}
配置Extension扩展,也就是我们平时通过android{}
来进行配置的内容
private void configureExtension() {
//创建4个对象容器
//buildType节点
final NamedDomainObjectContainer<BuildType> buildTypeContainer =
project.container(
BuildType.class,
new BuildTypeFactory(instantiator, project, extraModelInfo));
//productFlavor节点
final NamedDomainObjectContainer<ProductFlavor> productFlavorContainer =
project.container(
ProductFlavor.class,
new ProductFlavorFactory(
instantiator, project, project.getLogger(), extraModelInfo));
//签名
final NamedDomainObjectContainer<SigningConfig> signingConfigContainer =
project.container(SigningConfig.class, new SigningConfigFactory(instantiator));
//VariantOutput,变体,比如debug、release、也可和productFlavor组合
final NamedDomainObjectContainer<BaseVariantOutput> buildOutputs =
project.container(BaseVariantOutput.class);
project.getExtensions().add("buildOutputs", buildOutputs);
//创建Extension
extension =
createExtension(
project,
projectOptions,
instantiator,
androidBuilder,
sdkHandler,
buildTypeContainer,
productFlavorContainer,
signingConfigContainer,
buildOutputs,
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, instantiator, androidBuilder, extension);
//创建taskManager,会管理我们Task的创建
taskManager =
createTaskManager(
globalScope,
project,
projectOptions,
androidBuilder,
dataBindingBuilder,
extension,
sdkHandler,
ndkHandler,
registry,
threadRecorder);
//创建variantManager
variantManager =
new VariantManager(
globalScope,
project,
projectOptions,
androidBuilder,
extension,
variantFactory,
taskManager,
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);
}
该方法用来创建一系列Task
private void createTasks() {
//记录耗时,并调用createTasksBeforeEvaluate()
//createTasksBeforeEvaluate会创建很多Task,但是都是和系统相关的
//比如卸载应用,系统检测,连接设备等
threadRecorder.record(
ExecutionType.TASK_MANAGER_CREATE_TASKS,
project.getPath(),
null,
() ->
taskManager.createTasksBeforeEvaluate(
new TaskContainerAdaptor(project.getTasks())));
project.afterEvaluate( //afterEvaluate调用时,项目已经配置好了
project ->
//记录耗时,并调用createAndroidTasks()来创建Task,不同的productFlavor、buildTypes创建的task也不同
threadRecorder.record(
ExecutionType.BASE_PLUGIN_CREATE_ANDROID_TASKS,
project.getPath(),
null,
() -> createAndroidTasks(false)));
}
来看createAndroidTasks()
//...
threadRecorder.record(
ExecutionType.VARIANT_MANAGER_CREATE_ANDROID_TASKS,
project.getPath(),
null,
() -> {
//调用variantManager的createAndroidTasks()
variantManager.createAndroidTasks();
ApiObjectFactory apiObjectFactory =
new ApiObjectFactory(
androidBuilder,
extension,
variantFactory,
instantiator,
project.getObjects());
for (VariantScope variantScope : variantManager.getVariantScopes()) {
BaseVariantData variantData = variantScope.getVariantData();
apiObjectFactory.create(variantData);
}
});
//...
来看variantManager.createAndroidTasks()
public void createAndroidTasks() {
variantFactory.validateModel(this);
variantFactory.preVariantWork(project);
final TaskFactory tasks = new TaskContainerAdaptor(project.getTasks());
if (variantScopes.isEmpty()) {
recorder.record(
ExecutionType.VARIANT_MANAGER_CREATE_VARIANTS,
project.getPath(),
null /*variantName*/,
//创建出所有的variant变体
this::populateVariantDataList);
}
// Create top level test tasks.
recorder.record(
ExecutionType.VARIANT_MANAGER_CREATE_TESTS_TASKS,
project.getPath(),
null /*variantName*/,
//创建测试使用的方法
() -> taskManager.createTopLevelTestTasks(tasks, !productFlavors.isEmpty()));
for (final VariantScope variantScope : variantScopes) {
recorder.record(
ExecutionType.VARIANT_MANAGER_CREATE_TASKS_FOR_VARIANT,
project.getPath(),
variantScope.getFullVariantName(),
//根据Variant变体创建出相应的一堆Task
() -> createTasksForVariantData(tasks, variantScope));
}
//创建依赖报告、签名报告的Task
taskManager.createReportTasks(tasks, variantScopes);
}
来看createTasksForVariantData
public void createTasksForVariantData(
final TaskFactory tasks, final VariantScope variantScope) {
final BaseVariantData variantData = variantScope.getVariantData();
final VariantType variantType = variantData.getType();
final GradleVariantConfiguration variantConfig = variantScope.getVariantConfiguration();
//添加assemble开头的一系列Task
final BuildTypeData buildTypeData = buildTypes.get(variantConfig.getBuildType().getName());
if (buildTypeData.getAssembleTask() == null) {
buildTypeData.setAssembleTask(taskManager.createAssembleTask(tasks, buildTypeData));
}
tasks.named("assemble", new Action<Task>() {
@Override
public void execute(Task task) {
assert buildTypeData.getAssembleTask() != null;
task.dependsOn(buildTypeData.getAssembleTask().getName());
}
});
createAssembleTaskForVariantData(tasks, variantData);
//是否是测试的Task
if (variantType.isForTesting()) {
//...
} else {
//创建一堆Task
taskManager.createTasksForVariantScope(tasks, variantScope);
}
}
可以看到,最终会调用createTasksForVariantScope()
@Override
public void createTasksForVariantScope(
@NonNull final TaskFactory tasks, @NonNull final VariantScope variantScope) {
BaseVariantData variantData = variantScope.getVariantData();
assert variantData instanceof ApplicationVariantData;
createAnchorTasks(tasks, variantScope);
//检查Manifest是否符合规范 -> PreBuildTask
createCheckManifestTask(tasks, variantScope);
handleMicroApp(tasks, variantScope);
// Create all current streams (dependencies mostly at this point)
createDependencyStreams(tasks, variantScope);
// Add a task to publish the applicationId.
createApplicationIdWriterTask(tasks, variantScope);
// Add a task to process the manifest(s)
recorder.record(
//合并Manifest
ExecutionType.APP_TASK_MANAGER_CREATE_MERGE_MANIFEST_TASK,
project.getPath(),
variantScope.getFullVariantName(),
() -> createMergeApkManifestsTask(tasks, variantScope));
// Add a task to create the res values
recorder.record(
//生成res values
ExecutionType.APP_TASK_MANAGER_CREATE_GENERATE_RES_VALUES_TASK,
project.getPath(),
variantScope.getFullVariantName(),
() -> createGenerateResValuesTask(tasks, variantScope));
// Add a task to compile renderscript files.
recorder.record(
ExecutionType.APP_TASK_MANAGER_CREATE_CREATE_RENDERSCRIPT_TASK,
project.getPath(),
variantScope.getFullVariantName(),
() -> createRenderscriptTask(tasks, variantScope));
// Add a task to merge the resource folders
//合并Resource文件
recorder.record(
ExecutionType.APP_TASK_MANAGER_CREATE_MERGE_RESOURCES_TASK,
project.getPath(),
variantScope.getFullVariantName(),
(Recorder.VoidBlock) () -> createMergeResourcesTask(tasks, variantScope, true));
// Add a task to merge the asset folders
recorder.record(
//合并Assert文件
ExecutionType.APP_TASK_MANAGER_CREATE_MERGE_ASSETS_TASK,
project.getPath(),
variantScope.getFullVariantName(),
() -> createMergeAssetsTask(tasks, variantScope, null));
// Add a task to create the BuildConfig class
recorder.record(
//创建BuildConfig.java
ExecutionType.APP_TASK_MANAGER_CREATE_BUILD_CONFIG_TASK,
project.getPath(),
variantScope.getFullVariantName(),
() -> createBuildConfigTask(tasks, 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(tasks, variantScope);
// Add a task to process the java resources
createProcessJavaResTask(tasks, variantScope);
});
recorder.record(
//创建AIDL
ExecutionType.APP_TASK_MANAGER_CREATE_AIDL_TASK,
project.getPath(),
variantScope.getFullVariantName(),
() -> createAidlTask(tasks, variantScope));
recorder.record(
ExecutionType.APP_TASK_MANAGER_CREATE_SHADER_TASK,
project.getPath(),
variantScope.getFullVariantName(),
() -> createShaderTask(tasks, variantScope));
// Add NDK tasks
if (!isComponentModelPlugin()) {
recorder.record(
ExecutionType.APP_TASK_MANAGER_CREATE_NDK_TASK,
project.getPath(),
variantScope.getFullVariantName(),
() -> createNdkTasks(tasks, variantScope));
} else {
if (variantData.compileTask != null) {
variantData.compileTask.dependsOn(getNdkBuildable(variantData));
} else {
variantScope.getCompileTask().dependsOn(tasks, 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(tasks, 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(tasks, variantScope));
// Add data binding tasks if enabled
createDataBindingTasksIfNecessary(tasks, variantScope);
// Add a compile task
recorder.record(
//编译代码
ExecutionType.APP_TASK_MANAGER_CREATE_COMPILE_TASK,
project.getPath(),
variantScope.getFullVariantName(),
() -> addCompileTask(tasks, variantScope));
createStripNativeLibraryTask(tasks, variantScope);
if (variantScope.getOutputScope().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(tasks, variantScope));
}
recorder.record(
ExecutionType.APP_TASK_MANAGER_CREATE_PACKAGING_TASK,
project.getPath(),
variantScope.getFullVariantName(),
() -> {
AndroidTask<BuildInfoWriterTask> buildInfoWriterTask =
createInstantRunPackagingTasks(tasks, variantScope);
createPackagingTask(tasks, variantScope, buildInfoWriterTask);
});
// create the lint tasks.
recorder.record(
ExecutionType.APP_TASK_MANAGER_CREATE_LINT_TASK,
project.getPath(),
variantScope.getFullVariantName(),
() -> createLintTasks(tasks, variantScope));
}
可以看到,这里创建了很多的Task。
至此,我们对AppPlugin
的初始化工作有了一定的了解。
下篇文章我们来详见讲解下AppPlugin中的Task。
Android 编译流程解析系列
Android 编译流程解析01-AppPlugin初始化
Android 编译流程解析02-相关Task解析
Android 编译流程解析03-手动编译Apk