簡介
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()
configureProject
該方法用來配置我們的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;
}
}
}
});
}
configureExtension
配置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);
}
createTasks
該方法用來創建一系列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。