Android 編譯流程解析01-AppPlugin初始化

簡介

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()configureExtensioncreateTasks()

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。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章