我们在日常开发中,无论是使用图形构建按钮还是使用命令开启构建任务,其会经历设置,陪着,构建任务依赖图,最终执行我们输入的任务。但是其内部如何进行这一系列过程的,今天我们就分析Android中输入 ./gradlew assembleBuild后, gradle的生命周期原理。
Gradle命令入口
在我们每一个android下面都有一个 gradlew.bat脚本文件,其为我们执行 ./gradlew命令的入口。其最终会执行下面的命令
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
其最终会调用GradleWrapperMain类,调用其main方法,其为gradle源码中的类。也是我们执行gradlew命令的入口。到这里我们要继续看起源码,必须下载对应的gradle源码。
Gradle源码
我们可以从github下载对应的源码,我这里分析的源码下载的是7.3的。下载下来用Intellij idead编译需要一段时间,后续开启缓存模式构建就快了。
Gradle下载
接下来我们准备好源码,进入GradleMain看起源码。我们开发中知道,如果第一次构建项目其会更加我们项目下的gradle目录下的wrapper.properties进行下载对应的版本,如果本地有其就不会下载,今天我们就探究一下其原理。
- wrapper.properties配置
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
GradleWrapperMain
读取wrapper的配置
- 其首先从我们目录下gradle的配置文件读取配置信息,即上面列出的
- 然后创建WrapperExeucter
- 接着执行其ececute,其会传入Install和BootstrapMainStarter
public static void main(String[] args) {
File wrapperJar = wrapperJar();
File propertiesFile = wrapperProperties(wrapperJar);
....
WrapperExecutor wrapperExecutor = WrapperExecutor.forWrapperPropertiesFile(propertiesFile);
wrapperExecutor.execute(
args,
new Install(logger, new Download(logger, "gradlew", UNKNOWN_VERSION), new PathAssembler(gradleUserHome, rootDir)),
new BootstrapMainStarter());
}
WrapperExecuter
其executer方法,内部会首先调用Install对应的方法,去判断是否需要下载Gradle,然后调用bootstrapMainStarter的启动方法
public void execute(String[] args, Install install, BootstrapMainStarter bootstrapMainStarter) throws Exception {
File gradleHome = install.createDist(config);
bootstrapMainStarter.start(args, gradleHome);
}
Install配置Gradle
其createDist方法,就是根据配置里的信息去下载对应版本的gradle,如果本地存在,则直接加载缓存。
public File createDist(final WrapperConfiguration configuration) {
//下载地址
final URI distributionUrl = configuration.getDistribution();
// 文件256校验码
final String distributionSha256Sum = configuration.getDistributionSha256Sum();
//本地对应的配置
final PathAssembler.LocalDistribution localDistribution = pathAssembler.
getDistribution(configuration);
final File distDir = localDistribution.getDistributionDir();
final File localZipFile = localDistribution.getZipFile();
...
//是否需要下载,本地文件是否存在
boolean needsDownload = !localZipFile.isFile();
URI safeDistributionUrl = Download.safeUri(distributionUrl);
if (needsDownload) {
File tmpZipFile = new File(localZipFile.getParentFile(),
localZipFile.getName() + ".part");
tmpZipFile.delete();
logger.log("Downloading " + safeDistributionUrl);
//开始下载
download.download(distributionUrl, tmpZipFile);
tmpZipFile.renameTo(localZipFile);
}
...
//校验文件是否下载正确
verifyDownloadChecksum(configuration.getDistribution().toString(),
localZipFile, distributionSha256Sum);
//解压
unzip(localZipFile, distDir);
}
经过上面的步骤,就按照gradle目录下的配置,下载好对应的gradle版本包,即我们后面整体gradle执行代码。
BootstrapMainStarter开启任务
其start方法,开始gradle的构建流程,其调用流程比较复杂,不同版本代码逻辑有些不同。具体过程不是我们本文的重点,我简单梳理了一个大致调用流程,感兴趣的可以作为参看查看其源码。其最终会调用VintageBuildModelController的doBuildState。
流程图
接下来我们分析其生命周期的每个阶段做了什么。
Gradle生命周期
查看对应VintageBuildModelController类State,其主要有四个阶段。
生命周期阶段
private enum Stage implements StateTransitionController.State {
Created,
LoadSettings,
Configure,
ScheduleTasks,
TaskGraph
}
�其doBuilldState会根据对应要执行到的阶段,依次调用对应的方法。下面我们依次分析。
LoadSettings
进入doBuildStages会根据传递的状态执行到对应的状态
private void doBuildStages(Stage upTo) {
prepareSettings();
if (upTo == Stage.LoadSettings) {
return;
}
prepareProjects();
if (upTo == Stage.Configure) {
return;
}
prepareTaskGraph();
if (upTo == Stage.ScheduleTasks) {
return;
}
prepareTaskExecution();
}
最终执行的为prepareTaskExecution。最初执行的为prepareSetting,对应的周期阶段为LoadtingSetting.
SettingPreparer开启LoadSetting
preparesetting方法内部调用SettingPrepare的preparesetting方法,开始任务,同时执行前,将Stage设置为LoadSetting。
private void prepareSettings() {
controller.transitionIfNotPreviously(Stage.Created, Stage.LoadSettings,
() -> settingsPreparer.prepareSettings(gradle));
}
其对应的实现类为DefaultSettingsPreparer,其具体流程如下
- 判断是否为RootBuild,如果是,从顶层开始,否则从内部开始
- 然后查找对应的Setting.gradle并加载
@Override
public void prepareSettings(GradleInternal gradle) {
SettingsLoader settingsLoader = gradle.isRootBuild() ?
settingsLoaderFactory.forTopLevelBuild() :
settingsLoaderFactory.forNestedBuild();
settingsLoader.findAndLoadSettings(gradle);
}
我们以RootBuild为例分析,其调用forTopLenvelBuild方法,返回对应的SettingLoader,其类似其他代码,通过逐级代理,预处理任务,最终的SettingLoader为DefaultSettingsLoader�
public SettingsLoader forTopLevelBuild() {
return new GradlePropertiesHandlingSettingsLoader(
new InitScriptHandlingSettingsLoader(
new CompositeBuildSettingsLoader(
new ChildBuildRegisteringSettingsLoader(
new CommandLineIncludedBuildSettingsLoader(
defaultSettingsLoader()
),
buildRegistry,
buildIncluder),
buildRegistry),
initScriptHandler),
buildLayoutFactory,
gradlePropertiesController
);
}
DefalutSeetingLoader查找处理_setting.gradle_
�其类注释说明其功能,定位和处理setting.gradle文件,读取里面配置的Module. 上面最后会调用findAndLoadSettings,我们查看源码,探究其如何定位和处理对应的文件
public SettingsInternal findAndLoadSettings(GradleInternal gradle) {
StartParameter startParameter = gradle.getStartParameter();
//获取构建项目下setting文件或目录
SettingsLocation settingsLocation = buildLayoutFactory.getLayoutFor(new BuildLayoutConfiguration(startParameter));
//根据查找的文件,加载读取内容
SettingsInternal settings = findSettingsAndLoadIfAppropriate(gradle, startParameter, settingsLocation, gradle.getClassLoaderScope());
ProjectSpec spec = ProjectSpecs.forStartParameter(startParameter, settings);
if (useEmptySettings(spec, settings, startParameter)) {
settings = createEmptySettings(gradle, startParameter, settings.getClassLoaderScope());
}
//根据setting项目描述配置rootProjet相关信息
setDefaultProject(spec, settings);
return settings;
}
定位setting文件
其首先获取我们项目整体目录,然后在其目录下获取setting.gradle文件
- 构建项目是否使用空setting结构,如是则直接返回空
- 获取目录下setting文件
- 如果存在检测是否为文件,否则抛出异常
- 如果存在则返回对应的Buildlayout
BuildLayout会保护具体文件的地址信息
public BuildLayout getLayoutFor(BuildLayoutConfiguration configuration) {
if (configuration.isUseEmptySettings()) {
return buildLayoutFrom(configuration, null);
}
File explicitSettingsFile = configuration.getSettingsFile();
if (explicitSettingsFile != null) {
if (!explicitSettingsFile.isFile()) {
throw new MissingResourceException(explicitSettingsFile.toURI(), String.format("Could not read settings file '%s' as it does not exist.", explicitSettingsFile.getAbsolutePath()));
}
return buildLayoutFrom(configuration, explicitSettingsFile);
}
return getLayoutFor(configuration.getCurrentDir(), configuration.isSearchUpwards());
}
public BuildLayout(File rootDirectory, File settingsDir, @Nullable File settingsFile, ScriptFileResolver scriptFileResolver) {
super(settingsDir, settingsFile);
this.rootDirectory = rootDirectory;
this.scriptFileResolver = scriptFileResolver;
}
加载setting.gradle文件
其通过SettingProcessor处理对应的文件,然后返回SettingInternal类
/**
* Finds the settings.gradle for the given startParameter, and loads it if contains the project selected by the
* startParameter, or if the startParameter explicitly specifies a settings script. If the settings file is not
* loaded (executed), then a null is returned.
*/
private SettingsInternal findSettingsAndLoadIfAppropriate(
GradleInternal gradle,
StartParameter startParameter,
SettingsLocation settingsLocation,
ClassLoaderScope classLoaderScope
) {
SettingsInternal settings = settingsProcessor.process(gradle, settingsLocation, classLoaderScope, startParameter);
validate(settings);
return settings;
}
SettingInternal具体实现类为DefalutSetting,其中settingsProcessor有多个实现类,类似上面的处理,其也是逐级嵌套,最终的为**ScriptEvaluatingSettingsProcessor,**我们看起代码 �发现其会加载对应文件里的内容,然后创建SettingsInternal
public SettingsInternal process(GradleInternal gradle,
SettingsLocation settingsLocation,
ClassLoaderScope baseClassLoaderScope,
StartParameter startParameter) {
//统计时间配置
Timer settingsProcessingClock = Time.startTimer();
//解析gradleProperties文件的配置信息
Map<String, String> properties = gradleProperties.mergeProperties(emptyMap());
//解析里面的内容,并加载
TextResourceScriptSource settingsScript = new TextResourceScriptSource(textFileResourceLoader.loadFile("settings file", settingsLocation.getSettingsFile()));
//创建SettingInternal
SettingsInternal settings = settingsFactory.createSettings(gradle, settingsLocation.getSettingsDir(), settingsScript, properties, startParameter, baseClassLoaderScope);
gradle.getBuildListenerBroadcaster().beforeSettings(settings);
applySettingsScript(settingsScript, settings);
LOGGER.debug("Timing: Processing settings took: {}", settingsProcessingClock.getElapsed());
return settings;
}
创建Settinginternal
public SettingsInternal createSettings(...){
ClassLoaderScope classLoaderScope = baseClassLoaderScope.createChild("settings[" + gradle.getIdentityPath() + "]");
ScriptHandlerInternal settingsScriptHandler = scriptHandlerFactory.create(settingsScript, classLoaderScope);
DefaultSettings settings = instantiator.newInstance(DefaultSettings.class,
serviceRegistryFactory,
gradle,
classLoaderScope,
baseClassLoaderScope,
settingsScriptHandler,
settingsDir,
settingsScript,
startParameter
);
DynamicObject dynamicObject = ((DynamicObjectAware) settings).getAsDynamicObject();
((ExtensibleDynamicObject) dynamicObject).addProperties(gradleProperties);
return settings;
}
总结
到这里LoadSetting就结束了,其主要做了以下工作
- 查找setting文件
- 加载解析gradle.properties文件
- 解析setting文件内容,并创建对应的类:DefalutSetting
Configure
项目配置阶段入口方法为 prepareProjects,与LoadSetting类似,其也有对应的Prepare处理,其为ProjectPrepare
private void prepareProjects() {
controller.transitionIfNotPreviously(Stage.LoadSettings, Stage.Configure,
() -> projectsPreparer.prepareProjects(gradle));
}
ProjectsPreparer
其方法传入的参数GradleInternal,包含了上一阶段处理完的settings 对象配置,即DefalutSetting. 其对应的实现类为DefalutProjectsPreparer.同样与LoadSetting类似,其也判断是否为RootBuild,同时其也会判断是否配置的后台
if (buildModelParameters.isConfigureOnDemand() && gradle.isRootBuild()) {
projectConfigurer.configure(gradle.getRootProject());
} else {
projectConfigurer.configureHierarchy(gradle.getRootProject());
new ProjectsEvaluatedNotifier(buildOperationExecutor).notify(gradle);
}
无论何种情况,都有ProjectConfigurer处理
TaskPathProjectEvaluator处理Project
ProjectConfigurer的实现类为TaskPathProjectEvaluator。两个方法的区别时,configureHierarchyFully会先配置自己,然后依次遍历配置每一个项目,最终入口都是config.因此我们就直接分析config。
@Override
public void configureHierarchy(ProjectInternal project) {
configure(project);
for (Project sub : project.getSubprojects()) {
configure((ProjectInternal) sub);
}
}
@Override
public void configure(ProjectInternal project) {
if (cancellationToken.isCancellationRequested()) {
throw new BuildCancelledException();
}
// Need to configure intermediate parent projects for configure-on-demand
ProjectInternal parentProject = project.getParent();
if (parentProject != null) {
configure(parentProject);
}
project.getOwner().ensureConfigured();
}
最终调用eensureConfigured,通过层层导演,最终会调用ProjectConfigureAction的execute方法
//in class ConfigureActionsProjectEvaluator
@Override
public void evaluate(ProjectInternal project, ProjectStateInternal state) {
for (ProjectConfigureAction configureAction : configureActions) {
configureAction.execute(project);
}
}
ProjectConfigureAction的实现类有多个,我们看该类注释
/**
* Can be implemented by plugins to auto-configure each project.
*
* <p>Implementations are discovered using the JAR service locator mechanism (see {@link org.gradle.internal.service.ServiceLocator}).
* Each action is invoked for each project that is to be configured, before the project has been configured. Actions are executed
* in an arbitrary order.
*/
public interface ProjectConfigureAction extends Action<ProjectInternal> {
}
其可被对应的插件实现,去配置每一个项目,这样结合我们在开发android项目都会使用插件,这样当执行到此阶段,即会自动配置,因此我们直接看对应的实现,即PluginsProjectConfigureActions�
PluginsProjectConfigureActions自动配置每个Project
@Override
public void execute(ProjectInternal project) {
for (Action<ProjectInternal> action : actions) {
action.execute(project);
}
}
到这里配置阶段结束,具体的配置有具体的插件实现,其会在此阶段配置好自己。我们WrapperPluginAutoApplyAction为例,其最终会调用我们对应插件的apply方法。
public void execute(ProjectInternal project) {
project.getPluginManager().apply("org.gradle.wrapper");
}
这里配置的是wrapper这个插件。我们查看给方法注释
/**
* Applies the plugin with the given ID. Does nothing if
* the plugin has already been applied.
* <p>
* Plugins in the {@code "org.gradle"} namespace can be applied
*directly via name.
* That is, the following two lines are equivalent…
* <pre class='autoTested'>
* pluginManager.apply "org.gradle.java"
* pluginManager.apply "java"
* </pre>
*
* @param pluginId the ID of the plugin to apply
* @since 2.3
*/
void apply(String pluginId);
总结
该阶段主要会默认配置org.gradle下的Project,然后调用具体每个插件的实现,配置每个插件。
TaskGraph
接下来是task有向图的构建,其在上一阶段的基础上,配置每个task的依赖关系。
ScheduleTasks
分析任务图的构建我们需要回到流程图分析那里,其调用VintageBuildController.doBuildStage的发起点是在DefaultTreeWorkPrepare.这里其分成了多个阶段,即其首先调用doBuildStage达到_TaskSchedule_ �阶段,然后调用populateTaskGraph真正的构建任务图**。**我们看起代码
// in the DefaultTreeWorkPrepare
@Override
public void scheduleRequestedTasks() {
//该方法到达TaskSchedule
buildController.prepareToScheduleTasks();
//完成真正task有向图构建
includedBuildTaskGraph.prepareTaskGraph(() -> {
//处理初步任务有向图
buildController.scheduleRequestedTasks();
//填充任务图
includedBuildTaskGraph.populateTaskGraphs();
//结束构建,根据输入发起任务
buildController.finalizeWorkGraph(true);
});
}
prepareTaskGraph
doBuildStages内部,在执行完配置后,进入下一个阶段,调用该方法,将其Stage转移到ScheduTasks,我们查看源码看起做了什么工作 其通过TaskGraphPrepares的prepareForTaskScheduling开启处理
private void prepareTaskGraph() {
controller.transitionIfNotPreviously(Stage.Configure, Stage.ScheduleTasks,
() -> taskGraphPreparer.prepareForTaskScheduling(gradle));
}
TaskGraphPrepares有两个实现类,类似上面的处理也是逐级嵌套依次处理。其分别是:
- DefaultTaskSchedulingPreparer
- �ExcludedTaskFilteringProjectsPreparer
其中 DefaultTaskSchedulingPreparer存在delegate,因此其不是不最终的调用而是ExcludedTaskFilteringProjectsPreparer
//DefaultTaskSchedulingPreparer
@Override
public void prepareForTaskScheduling(GradleInternal gradle) {
// Make root build substitutions available
if (gradle.isRootBuild()) {
buildStateRegistry.afterConfigureRootBuild();
}
delegate.prepareForTaskScheduling(gradle);
}
// ExcludedTaskFilteringProjectsPreparer
@Override
public void prepareForTaskScheduling(GradleInternal gradle) {
Set<String> excludedTaskNames = gradle.getStartParameter().getExcludedTaskNames();
if (!excludedTaskNames.isEmpty()) {
final Set<Spec<Task>> filters = new HashSet<Spec<Task>>();
for (String taskName : excludedTaskNames) {
filters.add(taskSelector.getFilter(taskName));
}
gradle.getTaskGraph().useFilter(Specs.intersect(filters));
}
}
查看代码我们知道,这里主要做了两部分工作
- DefaultTaskSchedulingPreparer通知项目配置完成
- 将不需要添加到依赖图的任务排除
prepareTaskGraph
IncludedBuildTaskGraph在VintageBuildController.doBuildStage到达ScheduleTask后,完成前期工作后开始构建任务图,其实现类为DefalutIncludedBuildTaskGraph
/**
* Does the work to schedule tasks and prepare the task graphs for execution.
*/
void prepareTaskGraph(Runnable action){
withState(() -> {
expectInState(State.NotPrepared);
state = State.QueuingTasks;
buildOperationExecutor.run(new RunnableBuildOperation() {
@Override
public void run(BuildOperationContext context) {
action.run();
context.setResult(new CalculateTreeTaskGraphBuildOperationType.Result() {
});
}
@Override
public BuildOperationDescriptor.Builder description() {
return BuildOperationDescriptor
.displayName("Calculate build tree task graph")
.details(new CalculateTreeTaskGraphBuildOperationType.Details() {
});
}
});
expectInState(State.Populated);
state = State.ReadyToRun;
return
}
该方法是通过CalculateTreeTaskGraphBuildOperationType告知我们做了什么,同时保存结果。其真正的工作是action.run,其实际调用的就是里面包裹的方法
/**
* Computing the task graph for the build tree based on the inputs
* and build configuration.
*/
public final class CalculateTreeTaskGraphBuildOperationTyp
includedBuildTaskGraph.prepareTaskGraph(() -> {
buildController.scheduleRequestedTasks();
includedBuildTaskGraph.populateTaskGraphs();
buildController.finalizeWorkGraph(true);
})
TaskExecution
其主要为task的执行配置Gradle对象,其是通过TaskExecutionPreparer的prepareForTaskExecution发起
/**
* Responsible for preparing `Gradle` instances for task execution. The result is passed to a {@link org.gradle.execution.BuildWorkExecutor} for execution. Prior to preparing for task execution, the `Gradle` instance has its projects configured by a {@link org.gradle.configuration.ProjectsPreparer}.
*
* <p>This includes resolving the entry tasks and calculating the task graph.</p>
*/
public interface TaskExecutionPreparer {
void prepareForTaskExecution(GradleInternal gradle);
}
�查看类注释,其主要解决Task入口,和任务图计算,其实现类为DefaultTaskExecutionPreparer,
@Override
public void prepareForTaskExecution(GradleInternal gradle) {
buildConfigurationActionExecuter.select(gradle);
if (buildModelParameters.isConfigureOnDemand() && gradle.isRootBuild()) {
new ProjectsEvaluatedNotifier(buildOperationExecutor).notify(gradle);
}
}
�其核心在第一个调用,其会对任务进行选择. 其通过buildConfigurationActionExecuter的seletc发起
@Override
public void select(final GradleInternal gradle) {
// We know that we're running single-threaded here, so we can use coarse grained locks
projectStateRegistry.withMutableStateOfAllProjects(() -> {
configure(taskSelectors, gradle, 0);
});
}
其中configure内部为遍历taskSelectors,依次取出每一个taskSelector,即BuildConfigurationAction �然后调用其config去筛选计算任务。
rivate void configure(final List<? extends BuildConfigurationAction> processingConfigurationActions, final GradleInternal gradle, final int index) {
if (index >= processingConfigurationActions.size()) {
return;
}
processingConfigurationActions.get(index).configure(new BuildExecutionContext() {
@Override
public GradleInternal getGradle() {
return gradle;
}
@Override
public void proceed() {
configure(processingConfigurationActions, gradle, index + 1);
}
});
}
BuildConfigurationAction
其默认有两个实现类,因此遍历即分别调用这两个类
- DefaultTasksBuildExecutionAction
- TaskNameResolvingBuildConfigurationAction
- TaskNameResolvingBuildConfigurationAction
其根据平常去构建taskGraph
@Override
public void configure(BuildExecutionContext context) {
GradleInternal gradle = context.getGradle();
TaskExecutionGraphInternal taskGraph = gradle.getTaskGraph();
List<TaskExecutionRequest> taskParameters = gradle.getStartParameter().getTaskRequests();
for (TaskExecutionRequest taskParameter : taskParameters) {
List<TaskSelection> taskSelections = commandLineTaskParser.parseTasks(taskParameter);
for (TaskSelection taskSelection : taskSelections) {
LOGGER.info("Selected primary task '{}' from project {}", taskSelection.getTaskName(), taskSelection.getProjectPath());
//添加到taskGraph
taskGraph.addEntryTasks(taskSelection.getTasks());
}
}
context.proceed();
}
- DefaultTasksBuildExecutionAction
�其是处理project默认的task,如果没有会为其添加helpTask
public void configure(BuildExecutionContext context) {
StartParameter startParameter = context.getGradle().getStartParameter();
for (TaskExecutionRequest request : startParameter.getTaskRequests()) {
if (!request.getArgs().isEmpty()) {
context.proceed();
return;
}
}
// 获取Project默认的Tasks
ProjectInternal project = context.getGradle().getDefaultProject();
//so that we don't miss out default tasks
projectConfigurer.configure(project);
//处理默认的task
List<String> defaultTasks = project.getDefaultTasks();
if (defaultTasks.size() == 0) {
defaultTasks = new ArrayList<>();
for (BuiltInCommand command : builtInCommands) {
defaultTasks.addAll(command.asDefaultTask());
}
LOGGER.info("No tasks specified. Using default task {}", GUtil.toString(defaultTasks));
} else {
LOGGER.info("No tasks specified. Using project default tasks {}", GUtil.toString(defaultTasks));
}
//将处理后的tasks,设置到参数里,交由我们上面分析的TaskNameResolvingBuildConfigurationAction
//处理
startParameter.setTaskNames(defaultTasks);
context.proceed();
}
到这里,通过doBuildStage中的prepareForTaskExecution,我们将处理后的任务添加到了taskGraph中。
populateTaskGraphs
该方法完成任务图的填充。
/**
* Finish populating task graphs, once all entry point tasks have been scheduled.
*/
void populateTaskGraphs();
@Override
public void populateTaskGraphs() {
withState(() -> {
assertCanQueueTask();
includedBuilds.populateTaskGraphs();
state = State.Populated;
return null;
});
}
Controller填充任务图
填充任务图具体有对应的IncludeBuildControllers完成
@Override
public void populateTaskGraphs() {
boolean tasksDiscovered = true;
while (tasksDiscovered) {
tasksDiscovered = false;
for (IncludedBuildController buildController : ImmutableList.copyOf(buildControllers.values())) {
if (buildController.populateTaskGraph()) {
tasksDiscovered = true;
}
}
}
for (IncludedBuildController buildController : buildControllers.values()) {
buildController.prepareForExecution();
}
}
到这里就完成了任务图的构建,同时为下一步任务执行做好准备,触发时间开始执行任务
finalizeWorkGraph
�其会调用taskGraph的polulate,如果一切就绪
@Override
public void finalizeWorkGraph(boolean workScheduled) {
if (workScheduled) {
TaskExecutionGraphInternal taskGraph = gradle.getTaskGraph();
taskGraph.populate();
}
finalizeGradleServices(gradle);
}
我们查看该方法对应的注释
/**
* Does the work to populate the task graph based on tasks that have been added. Fires events and no further tasks should be added.
*/
void populate();
后续具体执行这里就不分析了。
总结
经过上面的整个分析,我们就清楚的知道了,当我们在AndroidStudio中敲下命令后,其如何去检测我们gradle的版本,并进行下载。同时我们项目中的setting.gradle的作用,最后就是任务如何添加,依赖关系如何构建。其中有的地方逻辑比较复杂,这里没有去深入分析,重点是掌握其整个流程。后续有需要,我们就可深入去分析研究它。