1. 写在前面
在 Gradle源码分析(三)一文中,我们分析了Gradle构建流程的
Configure
阶段,这里将分析TaskGraph
阶段(gradle 源码版本为 5.6.4)。
2. TaskGraph
2.1 整体实现
这里我整理了 TaskGraph
阶段的一些主要操作,并绘制了调用链的时序图。如果对源码不感兴趣的同学只需要看这一部分的内容即可。
2.1.1 时序图
这里只绘制了关键的方法链,一些比较细的在源码部分有说到。
2.1.2 主要操作
TaskGraph
阶段 Gradle 主要做了下面这些事情。
- 执行
ExcludedTaskFilteringBuildConfigurationAction
,这里会解析-x
或--exclude-task
参数指定需要过滤的 tasks; - 执行
DefaultTaskBuildExecutionAction
,这里在没有指定需要执行的 tasks 时,给 default project 设置 default tasks,并给StartParameter
设置执行的 tasks; - 执行
TaskNameResolvingBuildConfigurationAction
,这里会解析查找符合条件的 tasks ,并添加到TaskGraph
中(tasks之间的依赖关系解析比如 dependsOn 就是在这里做的); - 填充
TaskGraph
,生成 task 的有向无环图; - 如果是指定了
--configure-on-demand
参数,调用BuildListener
的projectsEvaluated()
。
2.2 源码分析
2.2.1 执行 ExcludedTaskFilteringBuildConfigurationAction
TaskGraph
过程是发生在 DefaultGradleLauncher
的 prepareTaskExecution()
,先来看看它的源码。
// DefaultGradleLauncher.java
private void prepareTaskExecution() {
if (stage == Stage.Configure) {
taskExecutionPreparer.prepareForTaskExecution(gradle);
// ...
}
}
这里的 taskExecutionPreparer
是通过反射调用的 GradleScopeServices
的 createTaskExecutionPreparer()
。
// GradleScopeServices.java
TaskExecutionPreparer createTaskExecutionPreparer(BuildConfigurationActionExecuter buildConfigurationActionExecuter, IncludedBuildControllers includedBuildControllers, BuildOperationExecutor buildOperationExecutor) {
return new BuildOperatingFiringTaskExecutionPreparer(
new DefaultTaskExecutionPreparer(buildConfigurationActionExecuter, includedBuildControllers, buildOperationExecutor),
buildOperationExecutor);
}
即 BuildOperatingFiringTaskExecutionPreparer
对象,来看看其 prepareForTaskExecution()
。
// BuildOperatingFiringTaskExecutionPreparer.java
public void prepareForTaskExecution(GradleInternal gradle) {
buildOperationExecutor.run(new CalculateTaskGraph(gradle));
}
private class CalculateTaskGraph implements RunnableBuildOperation {
@Override
public void run(BuildOperationContext buildOperationContext) {
final TaskExecutionGraphInternal taskGraph = populateTaskGraph();
// ...
}
TaskExecutionGraphInternal populateTaskGraph() {
// 调用到了 DefaultTaskExecutionPreparer 的 prepareForTaskExecution()
delegate.prepareForTaskExecution(gradle);
return gradle.getTaskGraph();
}
}
可以看到,最终会调用到 DefaultTaskExecutionPreparer
的 prepareForTaskExecution()
,再来看看它的源码。
// DefaultTaskExecutionPreparer.java
public void prepareForTaskExecution(GradleInternal gradle) {
buildConfigurationActionExecuter.select(gradle);
// ... 省略部分代码
}
这里的 buildConfigurationActionExecuter
是通过反射调用的 GradleScopeServices
的 createBuildConfigurationActionExecuter()
,来看看其源码。
// GradleScopeServices.java
BuildConfigurationActionExecuter createBuildConfigurationActionExecuter(CommandLineTaskParser commandLineTaskParser, TaskSelector taskSelector, ProjectConfigurer projectConfigurer, ProjectStateRegistry projectStateRegistry) {
List<BuildConfigurationAction> taskSelectionActions = new LinkedList<BuildConfigurationAction>();
// 添加 DefaultTasksBuildExecutionAction
taskSelectionActions.add(new DefaultTasksBuildExecutionAction(projectConfigurer));
// 添加 TaskNameResolvingBuildConfigurationAction
taskSelectionActions.add(new TaskNameResolvingBuildConfigurationAction(commandLineTaskParser));
// 添加 ExcludedTaskFilteringBuildConfigurationAction
return new DefaultBuildConfigurationActionExecuter(Arrays.asList(new ExcludedTaskFilteringBuildConfigurationAction(taskSelector)), taskSelectionActions, projectStateRegistry);
}
即 DefaultBuildConfigurationActionExecuter
对象。注意这里的三个比较重要的 BuildConfigurationAction
。
- DefaultTasksBuildExecutionAction
- TaskNameResolvingBuildConfigurationAction
- ExcludedTaskFilteringBuildConfigurationAction
先看看 DefaultBuildConfigurationActionExecuter
的 select()
。
// DefaultBuildConfigurationActionExecuter.java
public void select(final GradleInternal gradle) {
projectStateRegistry.withLenientState(new Runnable() {
@Override
public void run() {
// 1. 会调用到这里
List<BuildConfigurationAction> processingBuildActions = CollectionUtils.flattenCollections(BuildConfigurationAction.class, configurationActions, taskSelectors);
// 2. 这里会遍历 processingBuildActions 分别调用它们的 configure()
configure(processingBuildActions, gradle, 0);
}
});
}
private void configure(final List<BuildConfigurationAction> processingConfigurationActions, final GradleInternal gradle, final int index) {
if (index >= processingConfigurationActions.size()) {
return;
}
processingConfigurationActions.get(index).configure(new BuildExecutionContext() {
@Override
public void proceed() {
configure(processingConfigurationActions, gradle, index + 1);
}
});
}
在 select()
里面经过 CollectionUtils.flattenCollections()
处理后,三个 BuildConfigurationAction
的顺序是这样的。
ExcludedTaskFilteringBuildConfigurationAction
DefaultTasksBuildExecutionAction
TaskNameResolvingBuildConfigurationAction
接着调用了 configure()
遍历所有的 BuildConfigurationAction
,并调用他们的 configure()
。也就是说首先会执行 ExcludedTaskFilteringBuildConfigurationAction
的 configure()
,来看看它做了什么。
// ExcludedTaskFilteringBuildConfigurationAction.java
public void configure(BuildExecutionContext context) {
GradleInternal gradle = context.getGradle();
// 1. 这里会获取通过参数 -x 或者 --exclude-task 指定的 tasks
Set<String> excludedTaskNames = gradle.getStartParameter().getExcludedTaskNames();
if (!excludedTaskNames.isEmpty()) {
final Set<Spec<Task>> filters = new HashSet<Spec<Task>>();
for (String taskName : excludedTaskNames) {
// 2. 解析这些 tasks,封装成 Spec<Task>
filters.add(taskSelector.getFilter(taskName));
}
// 3. 通过 useFilter() 将 Spec 设置给 TaskGraph
gradle.getTaskGraph().useFilter(Specs.intersect(filters));
}
// 4. 调用下一个 BuildConfigurationAction 的 configure()
context.proceed();
}
可以看到,ExcludedTaskFilteringBuildConfigurationAction
的流程如下:
- 获取通过参数
-x
或者--exclude-task
指定的需要过滤的 tasks; - 遍历这些 tasks,进行解析后封装成
Spec<Task>
; - 通过
useFilter()
设置给TaskGraph
,为后面构建TaskGraph
做准备; - 调用下一个
BuildConfigurationAction
的configure()
。
这里主要看一下 taskSelector.getFilter(taskName)
的解析过程;taskSelector
是 TaskSelector
的实例,来看看其 getFilter()
的源码。
// TaskSelector.java
public Spec<Task> getFilter(String path) {
// 1. 调用 taskPathResolver 的 resolvePath 解析 task
final ResolvedTaskPath taskPath = taskPathResolver.resolvePath(path, gradle.getDefaultProject());
if (!taskPath.isQualified()) {
ProjectInternal targetProject = taskPath.getProject();
// 2. 配置task依赖的project
configurer.configure(targetProject);
if (taskNameResolver.tryFindUnqualifiedTaskCheaply(taskPath.getTaskName(), taskPath.getProject())) {
// 能找到确切的则直接返回,这种能直接通过 path 过滤 task,避免配置 sub projects
return new TaskPathSpec(targetProject, taskPath.getTaskName());
}
}
// 3. 调用 getSelection() 找 project (必要时也会查找 sub project) 下所有符合的 tasks
final Set<Task> selectedTasks = getSelection(path, gradle.getDefaultProject()).getTasks();
return new Spec<Task>() {
@Override
public boolean isSatisfiedBy(Task element) {
return !selectedTasks.contains(element);
}
};
}
private TaskSelection getSelection(String path, ProjectInternal project) {
ResolvedTaskPath taskPath = taskPathResolver.resolvePath(path, project);
ProjectInternal targetProject = taskPath.getProject();
if (taskPath.isQualified()) {
// path 指定有具体的 project,比如 :app:clean,则配置具体的 project
configurer.configure(targetProject);
} else {
// path 没有指定具体的 project,比如 clean,则配置 project 和 sub project
configurer.configureHierarchy(targetProject);
}
// 查找所有符合条件的 tasks
TaskSelectionResult tasks = taskNameResolver.selectWithName(taskPath.getTaskName(), taskPath.getProject(), !taskPath.isQualified());
if (tasks != null) {
return new TaskSelection(taskPath.getProject().getPath(), path, tasks);
}
// 查找所有符合条件的 tasks
Map<String, TaskSelectionResult> tasksByName = taskNameResolver.selectAll(taskPath.getProject(), !taskPath.isQualified());
NameMatcher matcher = new NameMatcher();
String actualName = matcher.find(taskPath.getTaskName(), tasksByName.keySet());
if (actualName != null) {
return new TaskSelection(taskPath.getProject().getPath(), taskPath.getPrefix() + actualName, tasksByName.get(actualName));
}
throw new TaskSelectionException(matcher.formatErrorMessage("task", taskPath.getProject()));
}
getFilter()
方法的逻辑也很清晰;
- 调用
TaskPathResolver
的resolvePath()
解析 task; - 必要时调用
configure()
对 task 所依赖的 project 进行配置。这里可能有的童鞋会存在些许疑问,在 Gradle 的Configure
阶段明明已经配置过了 project,为什么这里还要再配置一次;举个栗子,比如在 app 目录下执行.././gradlew clean --configure-on-demand
,在 Configure 阶段因为有--configure-on-demand
参数,只会配置 root project,而 clean task 所依赖的 app project 并没有经过配置,所以这里需要有这个逻辑防止所执行的 task 依赖的 project 没有进行配置的情况; - 调用
getSelection()
找所有符合的 tasks,并封装成Spec<Task>
返回。
这里主要看下 resolvePath()
的源码。
// TaskPathResolver.java
public ResolvedTaskPath resolvePath(String path, ProjectInternal startFrom) {
ProjectInternal project;
String taskName; //eg. 'someTask' or 'sT'
String prefix; //eg. '', ':' or ':foo:bar'
// 如果 path 包含有 : 分隔符,比如 :app:assembleDebug
if (path.contains(Project.PATH_SEPARATOR)) {
// 拿最后一个 : 的索引
int idx = path.lastIndexOf(Project.PATH_SEPARATOR);
// taskName = assembleDebug
taskName = path.substring(idx + 1);
// prefix = :app:
prefix = path.substring(0, idx+1);
// projectPath = :app
String projectPath = Project.PATH_SEPARATOR.equals(prefix) ? prefix : path.substring(0, idx);
// 找 project
project = projectFinder.findProject(projectPath, startFrom);
} else {
// 如果path 就是纯粹的 taskName,比如 clean
// project = default project
project = startFrom;
// taskName = clean
taskName = path;
// prefix = ""
prefix = "";
}
return new ResolvedTaskPath(prefix, taskName, project);
}
2.2.2 执行 DefaultTaskBuildExecutionAction
执行完 ExcludedTaskFilteringBuildConfigurationAction
的 configure()
,紧接着就是执行 DefaultTaskBuildExecutionAction
的 configure()
了,来看看其源码。
// DefaultTaskBuildExecutionAction.java
public void configure(BuildExecutionContext context) {
StartParameter startParameter = context.getGradle().getStartParameter();
// 1. 首先看有没有指定执行的 task,如果有指定执行的 task,则直接返回;比如 ./gradlew clean,指定了需要执行 clean task,这里的 args 即 clean
for (TaskExecutionRequest request : startParameter.getTaskRequests()) {
if (!request.getArgs().isEmpty()) {
context.proceed();
return;
}
}
// 2. 如果没有指定要执行的task,则获取 default project 的 default tasks,比如执行 ./gradlew ,这种就是没有指定执行的 task
ProjectInternal project = context.getGradle().getDefaultProject();
projectConfigurer.configure(project);
List<String> defaultTasks = project.getDefaultTasks();
if (defaultTasks.size() == 0) {
// 3. 如果 default project 没有设置 default tasks,则指定为 help task
defaultTasks = Collections.singletonList(ProjectInternal.HELP_TASK);
LOGGER.info("No tasks specified. Using default task {}", GUtil.toString(defaultTasks));
} else {
// 4. 如果 default project 有设置 default tasks,则使用设置的 default tasks
LOGGER.info("No tasks specified. Using project default tasks {}", GUtil.toString(defaultTasks));
}
// 5. 设置需要执行的 tasks
startParameter.setTaskNames(defaultTasks);
// 6. 调用下一个 BuildConfigurationAction 的 configure()
context.proceed();
}
DefaultTaskBuildExecutionAction
的逻辑也十分的清晰:
- 先判断是否有指定需要执行的 task,如果有指定,则直接返回,比如
./gradlew clean
,这种就是指定了执行 clean task; - 如果没有指定则需要执行的 task,比如
./gradlew
,则获取 default project 的 default tasks,如果没有设置 default tasks,则使用 help task 作为 default tasks; - 如果有设置 default tasks,则不作操作;
- 给 StartParameter 指定需要执行的 tasks,即 default tasks;
- 调用下一个
BuildConfigurationAction
的configure()
。
举个简单的栗子方便理解。在 app 下执行 .././gradlew 脚本,这个时候 default project 即 app 对应的 project。在执行到 DefaultTaskBuildExecutionAction
的时候,因为 app 的 build.gradle 里面是没有配置 default tasks 的,所以这里会设置 help task 为 default task,也就是上面命令执行 task 实际上是 help task。
这个时候,修改 app 的 build.gradle 。
Task hello = task("hello") {
doLast {
println("hello, gradle")
}
}
List<String> tasks = new ArrayList<String>()
tasks.add(hello.name)
setDefaultTasks(tasks)
通过 setDefaultTasks()
设置 default tasks 是 hello task。这个时候再执行 .././gradlew 脚本,它执行的就是 hello task。
2.2.3 执行 TaskNameResolvingBuildConfigurationAction
执行完 DefaultTaskBuildExecutionAction
的 configure()
,紧接着就是执行 TaskNameResolvingBuildConfigurationAction
的 configure()
了,来看看其源码。
// TaskNameResolvingBuildConfigurationAction.java
public void configure(BuildExecutionContext context) {
GradleInternal gradle = context.getGradle();
TaskExecutionGraphInternal taskGraph = gradle.getTaskGraph();
// 1. 获取指定执行的 TaskExecutionRequest
List<TaskExecutionRequest> taskParameters = gradle.getStartParameter().getTaskRequests();
for (TaskExecutionRequest taskParameter : taskParameters) {
// 2. 解析 task,查找符合的 tasks
List<TaskSelector.TaskSelection> taskSelections = commandLineTaskParser.parseTasks(taskParameter);
for (TaskSelector.TaskSelection taskSelection : taskSelections) {
// 3. 添加所有符合的 tasks 到 TaskGraph
taskGraph.addEntryTasks(taskSelection.getTasks());
}
}
context.proceed();
}
这里先看一下 commandLineTaskParser.parseTasks(taskParameter)
的解析过程。
// CommandLineTaskParser.java
public List<TaskSelector.TaskSelection> parseTasks(TaskExecutionRequest taskExecutionRequest) {
List<TaskSelector.TaskSelection> out = Lists.newArrayList();
// 比如 :app:clean,args 即 [:app:clean]
List<String> remainingPaths = new LinkedList<String>(taskExecutionRequest.getArgs());
while (!remainingPaths.isEmpty()) {
String path = remainingPaths.remove(0);
// 和 getFilter() 里面一样,调用 getSelection() 查找所有符合的 tasks
TaskSelector.TaskSelection selection = taskSelector.getSelection(taskExecutionRequest.getProjectPath(), taskExecutionRequest.getRootDir(), path);
Set<Task> tasks = selection.getTasks();
remainingPaths = taskConfigurer.configureTasks(tasks, remainingPaths);
out.add(selection);
}
return out;
}
举个栗子,比如在 app 下面执行 .././gradlew :app:clean,这里的 taskExecutionRequest.getArgs()
为 [:app:clean]
,然后会根据这个 path 去查找所有符合的 tasks,再添加到 TaskGraph
里面。
看完解析过程,再来看看添加过程 taskGraph.addEntryTasks(taskSelection.getTasks())
,taskGraph
是 DefaultTaskExecutionGraph
,来看看其 addEntryTasks()
。
// DefaultTaskExecutionGraph.java
public void addEntryTasks(Iterable<? extends Task> tasks) {
Set<Task> taskSet = new LinkedHashSet<Task>();
for (Task task : tasks) {
taskSet.add(task);
requestedTasks.add(task);
}
// 调用 DefaultExecutionPlan.addEntryTasks()
executionPlan.addEntryTasks(taskSet);
// task graph 标记为 DIRTY 状态
graphState = GraphState.DIRTY;
}
这里主要做了两件事情:
- 调用
DefaultExecutionPlan
的addEntryTasks()
; - 将
TaskGraph
的状态标记为DIRTY
。
而这里的 addEntryTasks()
就会处理 task 之间的依赖关系,比如 dependsOn等。
// DefaultExecutionPlan.java
public void addEntryTasks(Collection<? extends Task> tasks) {
final Deque<Node> queue = new ArrayDeque<Node>();
Set<Node> nodesInUnknownState = Sets.newLinkedHashSet();
List<Task> sortedTasks = new ArrayList<Task>(tasks);
Collections.sort(sortedTasks);
for (Task task : sortedTasks) {
TaskNode node = taskNodeFactory.getOrCreateNode(task);
if (node.isMustNotRun()) {
requireWithDependencies(node);
} else if (filter.isSatisfiedBy(task)) {
// 这里就是前面 ExcludedTaskFilteringBuildConfigurationAction 获取到的需要过滤的
node.require();
}
entryTasks.add(node);
queue.add(node);
}
final Set<Node> visiting = Sets.newHashSet();
while (!queue.isEmpty()) {
Node node = queue.getFirst();
// 已经处理过了
if (node.getDependenciesProcessed()) {
queue.removeFirst();
continue;
}
boolean filtered = !nodeSatisfiesTaskFilter(node);
// 过滤掉
if (filtered) {
queue.removeFirst();
// 标记为处理
node.dependenciesProcessed();
node.doNotRequire();
filteredNodes.add(node);
continue;
}
if (visiting.add(node)) {
node.prepareForExecution();
// 主要是这个方法,里面处理依赖关系
node.resolveDependencies(dependencyResolver, new Action<Node>() {
@Override
public void execute(Node targetNode) {
if (!visiting.contains(targetNode)) {
queue.addFirst(targetNode);
}
}
});
if (node.isRequired()) {
for (Node successor : node.getDependencySuccessors()) {
if (nodeSatisfiesTaskFilter(successor)) {
successor.require();
}
}
} else {
nodesInUnknownState.add(node);
}
} else {
queue.removeFirst();
visiting.remove(node);
node.dependenciesProcessed();
}
}
resolveNodesInUnknownState(nodesInUnknownState);
}
重点看一下 node.resolveDependencies()
;这里的 node 是通过 TaskNodeFactory
的 getOrCreateNode()
创建的。
// TaskNodeFactory.java
public TaskNode getOrCreateNode(Task task) {
TaskNode node = nodes.get(task);
if (node == null) {
if (task.getProject().getGradle() == thisBuild) {
node = new LocalTaskNode((TaskInternal) task);
} else {
node = new TaskInAnotherBuild((TaskInternal) task, currentBuildId, taskGraph);
}
nodes.put(task, node);
}
return node;
}
即 LocalTaskNode
对象,来看看其 resolveDependencies()
。
// LocalTaskNode.java
public void resolveDependencies(TaskDependencyResolver dependencyResolver, Action<Node> processHardSuccessor) {
// dependsOn 的解析
for (Node targetNode : getDependencies(dependencyResolver)) {
addDependencySuccessor(targetNode);
processHardSuccessor.execute(targetNode);
}
// finalizedBy 的解析
for (Node targetNode : getFinalizedBy(dependencyResolver)) {
if (!(targetNode instanceof TaskNode)) {
throw new IllegalStateException("Only tasks can be finalizers: " + targetNode);
}
addFinalizerNode((TaskNode) targetNode);
processHardSuccessor.execute(targetNode);
}
// mustRunAfter 的解析
for (Node targetNode : getMustRunAfter(dependencyResolver)) {
addMustSuccessor(targetNode);
}
// shouldRunAfter 的解析
for (Node targetNode : getShouldRunAfter(dependencyResolver)) {
addShouldSuccessor(targetNode);
}
}
可以看到 task 的依赖关系解析就是在这里做的。
2.2.4 填充 TaskGraph
回到 DefaultTaskExecutionPreparer
的 prepareForTaskExecution()
,继续往下看。
// DefaultTaskExecutionPreparer.java
public void prepareForTaskExecution(GradleInternal gradle) {
buildConfigurationActionExecuter.select(gradle);
TaskExecutionGraphInternal taskGraph = gradle.getTaskGraph();
// 计算有向无环图
taskGraph.populate();
// ...
}
这里会调用了 DefaultTaskExecutionGraph
的 populate()
,来看看其源码。
// DefaultTaskExecutionGraph.java
public void populate() {
ensurePopulated();
}
private void ensurePopulated() {
switch (graphState) {
// ...
case DIRTY:
executionPlan.determineExecutionPlan();
allTasks = null;
graphState = GraphState.POPULATED;
return;
// ...
}
}
在前面添加 task 的时候,已经将 graphState
标记为了 DIRTY
状态,所以这里会走到 executionPlan.determineExecutionPlan()
,executionPlan
是 DefaultExecutionPlan
的实例,来看看其 determineExecutionPlan()
。
// DefaultExecutionPlan.java
public void determineExecutionPlan() {
LinkedList<NodeInVisitingSegment> nodeQueue = Lists.newLinkedList(Iterables.transform(entryTasks, new Function<TaskNode, NodeInVisitingSegment>() {
private int index;
@Override
@SuppressWarnings("NullableProblems")
public NodeInVisitingSegment apply(TaskNode taskNode) {
return new NodeInVisitingSegment(taskNode, index++);
}
}));
int visitingSegmentCounter = nodeQueue.size();
HashMultimap<Node, Integer> visitingNodes = HashMultimap.create();
Deque<GraphEdge> walkedShouldRunAfterEdges = new ArrayDeque<GraphEdge>();
Deque<Node> path = new ArrayDeque<Node>();
Map<Node, Integer> planBeforeVisiting = Maps.newHashMap();
while (!nodeQueue.isEmpty()) {
NodeInVisitingSegment nodeInVisitingSegment = nodeQueue.peekFirst();
int currentSegment = nodeInVisitingSegment.visitingSegment;
Node node = nodeInVisitingSegment.node;
if (node.isIncludeInGraph() || nodeMapping.contains(node)) {
nodeQueue.removeFirst();
visitingNodes.remove(node, currentSegment);
maybeRemoveProcessedShouldRunAfterEdge(walkedShouldRunAfterEdges, node);
continue;
}
boolean alreadyVisited = visitingNodes.containsKey(node);
visitingNodes.put(node, currentSegment);
if (!alreadyVisited) {
recordEdgeIfArrivedViaShouldRunAfter(walkedShouldRunAfterEdges, path, node);
removeShouldRunAfterSuccessorsIfTheyImposeACycle(visitingNodes, nodeInVisitingSegment);
takePlanSnapshotIfCanBeRestoredToCurrentTask(planBeforeVisiting, node);
for (Node successor : node.getAllSuccessorsInReverseOrder()) {
if (visitingNodes.containsEntry(successor, currentSegment)) {
if (!walkedShouldRunAfterEdges.isEmpty()) {
GraphEdge toBeRemoved = walkedShouldRunAfterEdges.pop();
TaskNode sourceTask = (TaskNode) toBeRemoved.from;
TaskNode targetTask = (TaskNode) toBeRemoved.to;
sourceTask.removeShouldSuccessor(targetTask);
restorePath(path, toBeRemoved);
restoreQueue(nodeQueue, visitingNodes, toBeRemoved);
restoreExecutionPlan(planBeforeVisiting, toBeRemoved);
break;
} else {
onOrderingCycle(successor, node);
}
}
nodeQueue.addFirst(new NodeInVisitingSegment(successor, currentSegment));
}
path.push(node);
} else {
nodeQueue.removeFirst();
maybeRemoveProcessedShouldRunAfterEdge(walkedShouldRunAfterEdges, node);
visitingNodes.remove(node, currentSegment);
path.pop();
nodeMapping.add(node);
MutationInfo mutations = getOrCreateMutationsOf(node);
for (Node dependency : node.getDependencySuccessors()) {
getOrCreateMutationsOf(dependency).consumingNodes.add(node);
mutations.producingNodes.add(dependency);
}
Project project = node.getProject();
if (project != null) {
projectLocks.put(project, getOrCreateProjectLock(project));
}
for (Node finalizer : node.getFinalizers()) {
if (!visitingNodes.containsKey(finalizer)) {
int position = finalizerTaskPosition(finalizer, nodeQueue);
nodeQueue.add(position, new NodeInVisitingSegment(finalizer, visitingSegmentCounter++));
}
}
}
}
executionQueue.clear();
Iterables.addAll(executionQueue, nodeMapping);
}
这个方法就是填充 TaskGraph,生成 task 的有向无环图。
2.2.5 必要时调用 BuildListener
的 projectsEvaluated()
继续往下看 DefaultTaskExecutionPreparer
的 prepareForTaskExecution()
。
// DefaultTaskExecutionPreparer.java
public void prepareForTaskExecution(GradleInternal gradle) {
buildConfigurationActionExecuter.select(gradle);
TaskExecutionGraphInternal taskGraph = gradle.getTaskGraph();
taskGraph.populate();
includedBuildControllers.populateTaskGraphs();
// 如果是 --configure-on-demand 的情况下,是在这里调用的 projectEvaluated
if (gradle.getStartParameter().isConfigureOnDemand()) {
new ProjectsEvaluatedNotifier(buildOperationExecutor).notify(gradle);
}
}
生成 task 的有向无环图后,会判断是否有指定 --configure-on-demand
参数,如果有指定,则调用 BuildListener
的 projectEvaluated()
,因为在 Configure
阶段,--configure-on-demand
只会对 root project 进行配置,如果对 Configure
阶段不太熟悉的,可以先看看 Gradle源码分析(三)。
最后,回到 DefaultGradleLauncher
的 prepareTaskExecution()
。
// DefaultGradleLauncher.java
private void prepareTaskExecution() {
if (stage == Stage.Configure) {
taskExecutionPreparer.prepareForTaskExecution(gradle);
// 解析完 tasks 填充 tasks 有向无环图后,将状态设置为 TaskGraph
stage = Stage.TaskGraph;
}
}
执行完上述流程后会将 Gradle 状态设置为 TaskGraph
。至此,Gradle 的 TaskGraph
阶段就分析完了。