1. 寫在前面
在 Gradle源碼分析(三)一文中,我們分析了Gradle構(gòu)建流程的
Configure階段,這里將分析TaskGraph階段(gradle 源碼版本為 5.6.4)。
2. TaskGraph
2.1 整體實(shí)現(xiàn)
這里我整理了 TaskGraph 階段的一些主要操作,并繪制了調(diào)用鏈的時(shí)序圖。如果對(duì)源碼不感興趣的同學(xué)只需要看這一部分的內(nèi)容即可。
2.1.1 時(shí)序圖
這里只繪制了關(guān)鍵的方法鏈,一些比較細(xì)的在源碼部分有說(shuō)到。

2.1.2 主要操作
TaskGraph階段 Gradle 主要做了下面這些事情。
- 執(zhí)行
ExcludedTaskFilteringBuildConfigurationAction,這里會(huì)解析-x或--exclude-task參數(shù)指定需要過(guò)濾的 tasks; - 執(zhí)行
DefaultTaskBuildExecutionAction,這里在沒(méi)有指定需要執(zhí)行的 tasks 時(shí),給 default project 設(shè)置 default tasks,并給StartParameter設(shè)置執(zhí)行的 tasks; - 執(zhí)行
TaskNameResolvingBuildConfigurationAction,這里會(huì)解析查找符合條件的 tasks ,并添加到TaskGraph中(tasks之間的依賴關(guān)系解析比如 dependsOn 就是在這里做的); - 填充
TaskGraph,生成 task 的有向無(wú)環(huán)圖; - 如果是指定了
--configure-on-demand參數(shù),調(diào)用BuildListener的projectsEvaluated()。
2.2 源碼分析
2.2.1 執(zhí)行 ExcludedTaskFilteringBuildConfigurationAction
TaskGraph 過(guò)程是發(fā)生在 DefaultGradleLauncher 的 prepareTaskExecution(),先來(lái)看看它的源碼。
// DefaultGradleLauncher.java
private void prepareTaskExecution() {
if (stage == Stage.Configure) {
taskExecutionPreparer.prepareForTaskExecution(gradle);
// ...
}
}
這里的 taskExecutionPreparer 是通過(guò)反射調(diào)用的 GradleScopeServices 的 createTaskExecutionPreparer()。
// GradleScopeServices.java
TaskExecutionPreparer createTaskExecutionPreparer(BuildConfigurationActionExecuter buildConfigurationActionExecuter, IncludedBuildControllers includedBuildControllers, BuildOperationExecutor buildOperationExecutor) {
return new BuildOperatingFiringTaskExecutionPreparer(
new DefaultTaskExecutionPreparer(buildConfigurationActionExecuter, includedBuildControllers, buildOperationExecutor),
buildOperationExecutor);
}
即 BuildOperatingFiringTaskExecutionPreparer 對(duì)象,來(lái)看看其 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() {
// 調(diào)用到了 DefaultTaskExecutionPreparer 的 prepareForTaskExecution()
delegate.prepareForTaskExecution(gradle);
return gradle.getTaskGraph();
}
}
可以看到,最終會(huì)調(diào)用到 DefaultTaskExecutionPreparer 的 prepareForTaskExecution(),再來(lái)看看它的源碼。
// DefaultTaskExecutionPreparer.java
public void prepareForTaskExecution(GradleInternal gradle) {
buildConfigurationActionExecuter.select(gradle);
// ... 省略部分代碼
}
這里的 buildConfigurationActionExecuter 是通過(guò)反射調(diào)用的 GradleScopeServices 的 createBuildConfigurationActionExecuter(),來(lái)看看其源碼。
// 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 對(duì)象。注意這里的三個(gè)比較重要的 BuildConfigurationAction。
- DefaultTasksBuildExecutionAction
- TaskNameResolvingBuildConfigurationAction
- ExcludedTaskFilteringBuildConfigurationAction
先看看 DefaultBuildConfigurationActionExecuter 的 select()。
// DefaultBuildConfigurationActionExecuter.java
public void select(final GradleInternal gradle) {
projectStateRegistry.withLenientState(new Runnable() {
@Override
public void run() {
// 1. 會(huì)調(diào)用到這里
List<BuildConfigurationAction> processingBuildActions = CollectionUtils.flattenCollections(BuildConfigurationAction.class, configurationActions, taskSelectors);
// 2. 這里會(huì)遍歷 processingBuildActions 分別調(diào)用它們的 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() 里面經(jīng)過(guò) CollectionUtils.flattenCollections() 處理后,三個(gè) BuildConfigurationAction 的順序是這樣的。
ExcludedTaskFilteringBuildConfigurationActionDefaultTasksBuildExecutionActionTaskNameResolvingBuildConfigurationAction
接著調(diào)用了 configure() 遍歷所有的 BuildConfigurationAction,并調(diào)用他們的 configure()。也就是說(shuō)首先會(huì)執(zhí)行 ExcludedTaskFilteringBuildConfigurationAction 的 configure(),來(lái)看看它做了什么。
// ExcludedTaskFilteringBuildConfigurationAction.java
public void configure(BuildExecutionContext context) {
GradleInternal gradle = context.getGradle();
// 1. 這里會(huì)獲取通過(guò)參數(shù) -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. 通過(guò) useFilter() 將 Spec 設(shè)置給 TaskGraph
gradle.getTaskGraph().useFilter(Specs.intersect(filters));
}
// 4. 調(diào)用下一個(gè) BuildConfigurationAction 的 configure()
context.proceed();
}
可以看到,ExcludedTaskFilteringBuildConfigurationAction 的流程如下:
- 獲取通過(guò)參數(shù)
-x或者--exclude-task指定的需要過(guò)濾的 tasks; - 遍歷這些 tasks,進(jìn)行解析后封裝成
Spec<Task>; - 通過(guò)
useFilter()設(shè)置給TaskGraph,為后面構(gòu)建TaskGraph做準(zhǔn)備; - 調(diào)用下一個(gè)
BuildConfigurationAction的configure()。
這里主要看一下 taskSelector.getFilter(taskName) 的解析過(guò)程;taskSelector 是 TaskSelector 的實(shí)例,來(lái)看看其 getFilter() 的源碼。
// TaskSelector.java
public Spec<Task> getFilter(String path) {
// 1. 調(diào)用 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())) {
// 能找到確切的則直接返回,這種能直接通過(guò) path 過(guò)濾 task,避免配置 sub projects
return new TaskPathSpec(targetProject, taskPath.getTaskName());
}
}
// 3. 調(diào)用 getSelection() 找 project (必要時(shí)也會(huì)查找 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 沒(méi)有指定具體的 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() 方法的邏輯也很清晰;
- 調(diào)用
TaskPathResolver的resolvePath()解析 task; - 必要時(shí)調(diào)用
configure()對(duì) task 所依賴的 project 進(jìn)行配置。這里可能有的童鞋會(huì)存在些許疑問(wèn),在 Gradle 的Configure階段明明已經(jīng)配置過(guò)了 project,為什么這里還要再配置一次;舉個(gè)栗子,比如在 app 目錄下執(zhí)行.././gradlew clean --configure-on-demand,在 Configure 階段因?yàn)橛?--configure-on-demand參數(shù),只會(huì)配置 root project,而 clean task 所依賴的 app project 并沒(méi)有經(jīng)過(guò)配置,所以這里需要有這個(gè)邏輯防止所執(zhí)行的 task 依賴的 project 沒(méi)有進(jìn)行配置的情況; - 調(diào)用
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)) {
// 拿最后一個(gè) : 的索引
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 執(zhí)行 DefaultTaskBuildExecutionAction
執(zhí)行完 ExcludedTaskFilteringBuildConfigurationAction 的 configure(),緊接著就是執(zhí)行 DefaultTaskBuildExecutionAction 的 configure() 了,來(lái)看看其源碼。
// DefaultTaskBuildExecutionAction.java
public void configure(BuildExecutionContext context) {
StartParameter startParameter = context.getGradle().getStartParameter();
// 1. 首先看有沒(méi)有指定執(zhí)行的 task,如果有指定執(zhí)行的 task,則直接返回;比如 ./gradlew clean,指定了需要執(zhí)行 clean task,這里的 args 即 clean
for (TaskExecutionRequest request : startParameter.getTaskRequests()) {
if (!request.getArgs().isEmpty()) {
context.proceed();
return;
}
}
// 2. 如果沒(méi)有指定要執(zhí)行的task,則獲取 default project 的 default tasks,比如執(zhí)行 ./gradlew ,這種就是沒(méi)有指定執(zhí)行的 task
ProjectInternal project = context.getGradle().getDefaultProject();
projectConfigurer.configure(project);
List<String> defaultTasks = project.getDefaultTasks();
if (defaultTasks.size() == 0) {
// 3. 如果 default project 沒(méi)有設(shè)置 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 有設(shè)置 default tasks,則使用設(shè)置的 default tasks
LOGGER.info("No tasks specified. Using project default tasks {}", GUtil.toString(defaultTasks));
}
// 5. 設(shè)置需要執(zhí)行的 tasks
startParameter.setTaskNames(defaultTasks);
// 6. 調(diào)用下一個(gè) BuildConfigurationAction 的 configure()
context.proceed();
}
DefaultTaskBuildExecutionAction 的邏輯也十分的清晰:
- 先判斷是否有指定需要執(zhí)行的 task,如果有指定,則直接返回,比如
./gradlew clean,這種就是指定了執(zhí)行 clean task; - 如果沒(méi)有指定則需要執(zhí)行的 task,比如
./gradlew,則獲取 default project 的 default tasks,如果沒(méi)有設(shè)置 default tasks,則使用 help task 作為 default tasks; - 如果有設(shè)置 default tasks,則不作操作;
- 給 StartParameter 指定需要執(zhí)行的 tasks,即 default tasks;
- 調(diào)用下一個(gè)
BuildConfigurationAction的configure()。
舉個(gè)簡(jiǎn)單的栗子方便理解。在 app 下執(zhí)行 .././gradlew 腳本,這個(gè)時(shí)候 default project 即 app 對(duì)應(yīng)的 project。在執(zhí)行到 DefaultTaskBuildExecutionAction 的時(shí)候,因?yàn)?app 的 build.gradle 里面是沒(méi)有配置 default tasks 的,所以這里會(huì)設(shè)置 help task 為 default task,也就是上面命令執(zhí)行 task 實(shí)際上是 help task。

這個(gè)時(shí)候,修改 app 的 build.gradle 。
Task hello = task("hello") {
doLast {
println("hello, gradle")
}
}
List<String> tasks = new ArrayList<String>()
tasks.add(hello.name)
setDefaultTasks(tasks)
通過(guò) setDefaultTasks() 設(shè)置 default tasks 是 hello task。這個(gè)時(shí)候再執(zhí)行 .././gradlew 腳本,它執(zhí)行的就是 hello task。

2.2.3 執(zhí)行 TaskNameResolvingBuildConfigurationAction
執(zhí)行完 DefaultTaskBuildExecutionAction 的 configure(),緊接著就是執(zhí)行 TaskNameResolvingBuildConfigurationAction 的 configure() 了,來(lái)看看其源碼。
// TaskNameResolvingBuildConfigurationAction.java
public void configure(BuildExecutionContext context) {
GradleInternal gradle = context.getGradle();
TaskExecutionGraphInternal taskGraph = gradle.getTaskGraph();
// 1. 獲取指定執(zhí)行的 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) 的解析過(guò)程。
// 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() 里面一樣,調(diào)用 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;
}
舉個(gè)栗子,比如在 app 下面執(zhí)行 .././gradlew :app:clean,這里的 taskExecutionRequest.getArgs() 為 [:app:clean],然后會(huì)根據(jù)這個(gè) path 去查找所有符合的 tasks,再添加到 TaskGraph 里面。
看完解析過(guò)程,再來(lái)看看添加過(guò)程 taskGraph.addEntryTasks(taskSelection.getTasks()),taskGraph 是 DefaultTaskExecutionGraph,來(lái)看看其 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);
}
// 調(diào)用 DefaultExecutionPlan.addEntryTasks()
executionPlan.addEntryTasks(taskSet);
// task graph 標(biāo)記為 DIRTY 狀態(tài)
graphState = GraphState.DIRTY;
}
這里主要做了兩件事情:
- 調(diào)用
DefaultExecutionPlan的addEntryTasks(); - 將
TaskGraph的狀態(tài)標(biāo)記為DIRTY。
而這里的 addEntryTasks() 就會(huì)處理 task 之間的依賴關(guān)系,比如 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 獲取到的需要過(guò)濾的
node.require();
}
entryTasks.add(node);
queue.add(node);
}
final Set<Node> visiting = Sets.newHashSet();
while (!queue.isEmpty()) {
Node node = queue.getFirst();
// 已經(jīng)處理過(guò)了
if (node.getDependenciesProcessed()) {
queue.removeFirst();
continue;
}
boolean filtered = !nodeSatisfiesTaskFilter(node);
// 過(guò)濾掉
if (filtered) {
queue.removeFirst();
// 標(biāo)記為處理
node.dependenciesProcessed();
node.doNotRequire();
filteredNodes.add(node);
continue;
}
if (visiting.add(node)) {
node.prepareForExecution();
// 主要是這個(gè)方法,里面處理依賴關(guān)系
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);
}
重點(diǎn)看一下 node.resolveDependencies();這里的 node 是通過(guò) TaskNodeFactory 的 getOrCreateNode() 創(chuàng)建的。
// 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 對(duì)象,來(lái)看看其 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 的依賴關(guān)系解析就是在這里做的。
2.2.4 填充 TaskGraph
回到 DefaultTaskExecutionPreparer 的 prepareForTaskExecution(),繼續(xù)往下看。
// DefaultTaskExecutionPreparer.java
public void prepareForTaskExecution(GradleInternal gradle) {
buildConfigurationActionExecuter.select(gradle);
TaskExecutionGraphInternal taskGraph = gradle.getTaskGraph();
// 計(jì)算有向無(wú)環(huán)圖
taskGraph.populate();
// ...
}
這里會(huì)調(diào)用了 DefaultTaskExecutionGraph 的 populate(),來(lái)看看其源碼。
// DefaultTaskExecutionGraph.java
public void populate() {
ensurePopulated();
}
private void ensurePopulated() {
switch (graphState) {
// ...
case DIRTY:
executionPlan.determineExecutionPlan();
allTasks = null;
graphState = GraphState.POPULATED;
return;
// ...
}
}
在前面添加 task 的時(shí)候,已經(jīng)將 graphState 標(biāo)記為了 DIRTY 狀態(tài),所以這里會(huì)走到 executionPlan.determineExecutionPlan(),executionPlan 是 DefaultExecutionPlan 的實(shí)例,來(lái)看看其 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);
}
這個(gè)方法就是填充 TaskGraph,生成 task 的有向無(wú)環(huán)圖。
2.2.5 必要時(shí)調(diào)用 BuildListener 的 projectsEvaluated()
繼續(xù)往下看 DefaultTaskExecutionPreparer 的 prepareForTaskExecution()。
// DefaultTaskExecutionPreparer.java
public void prepareForTaskExecution(GradleInternal gradle) {
buildConfigurationActionExecuter.select(gradle);
TaskExecutionGraphInternal taskGraph = gradle.getTaskGraph();
taskGraph.populate();
includedBuildControllers.populateTaskGraphs();
// 如果是 --configure-on-demand 的情況下,是在這里調(diào)用的 projectEvaluated
if (gradle.getStartParameter().isConfigureOnDemand()) {
new ProjectsEvaluatedNotifier(buildOperationExecutor).notify(gradle);
}
}
生成 task 的有向無(wú)環(huán)圖后,會(huì)判斷是否有指定 --configure-on-demand 參數(shù),如果有指定,則調(diào)用 BuildListener 的 projectEvaluated() ,因?yàn)樵?Configure 階段,--configure-on-demand 只會(huì)對(duì) root project 進(jìn)行配置,如果對(duì) Configure 階段不太熟悉的,可以先看看 Gradle源碼分析(三)。
最后,回到 DefaultGradleLauncher 的 prepareTaskExecution()。
// DefaultGradleLauncher.java
private void prepareTaskExecution() {
if (stage == Stage.Configure) {
taskExecutionPreparer.prepareForTaskExecution(gradle);
// 解析完 tasks 填充 tasks 有向無(wú)環(huán)圖后,將狀態(tài)設(shè)置為 TaskGraph
stage = Stage.TaskGraph;
}
}
執(zhí)行完上述流程后會(huì)將 Gradle 狀態(tài)設(shè)置為 TaskGraph。至此,Gradle 的 TaskGraph 階段就分析完了。