1. 寫在前面
在 Gradle源碼分析(四)一文中,我們分析了Gradle構(gòu)建流程的
TaskGraph
階段鳍刷,這里將分析RunTasks
階段(gradle 源碼版本為 5.6.4)。
2. RunTasks
2.1 整體實(shí)現(xiàn)
這里我整理了 RunTasks
階段的一些主要操作畏邢,并繪制了調(diào)用鏈的時(shí)序圖。如果對(duì)源碼不感興趣的同學(xué)只需要看這一部分的內(nèi)容即可兽间。
2.1.1 時(shí)序圖
2.1.2 主要操作
RunTasks
階段 Gradle 主要做了下面這些事情预烙。
- 處理 --dry-run;
- 回調(diào)傳給
whenReady()
的閉包谴仙; - 創(chuàng)建線程和
ExecutorWorker
迂求; - 執(zhí)行 task 前的預(yù)處理碾盐;
- 調(diào)用
TaskActionListener
的beforeAction()
晃跺,遍歷Task
的Action
,并調(diào)用其execute()
毫玖,調(diào)用TaskActionListener
的afterAction()
掀虎。
2.2 源碼分析
2.2.1 處理 --dry-run
RunTasks
的過(guò)程發(fā)生在 DefaultGradleLauncher
的 runWork()
中,先來(lái)看看其源碼付枫。
// DefaultGradleLauncher.java
private void runWork() {
// ...
List<Throwable> taskFailures = new ArrayList<Throwable>();
buildExecuter.execute(gradle, taskFailures);
// ...
}
這里調(diào)用了 buildExecuter
的 execute()
烹玉,而 buildExecuter
是通過(guò)反射調(diào)用GradleScopeServices
的createBuildExecuter()
生成的。
// GradleScopeServices.java
BuildWorkExecutor createBuildExecuter(StyledTextOutputFactory textOutputFactory, IncludedBuildControllers includedBuildControllers, BuildOperationExecutor buildOperationExecutor) {
return new BuildOperationFiringBuildWorkerExecutor(
new IncludedBuildLifecycleBuildWorkExecutor(
new DefaultBuildWorkExecutor(
// 記住這兩個(gè) BuildExecutionAction
asList(new DryRunBuildExecutionAction(textOutputFactory),
new SelectedTaskExecutionAction())),
includedBuildControllers),
buildOperationExecutor);
}
這里有兩個(gè)比較重要的 BuildExecutionAction
阐滩,暫時(shí)先記住它們:
DryRunBuildExecutionAction
SelectedTaskExecutionAction
上面的代碼最終會(huì)調(diào)用到 DefaultBuildWorkExecutor
的 execute()
二打,來(lái)看看其源碼。
// DefaultBuildWorkExecutor.java
public void execute(GradleInternal gradle, Collection<? super Throwable> failures) {
execute(gradle, 0, failures);
}
// 和 TaskGraph 階段的 BuildConfigurationAction 執(zhí)行差不多
private void execute(final GradleInternal gradle, final int index, final Collection<? super Throwable> taskFailures) {
if (index >= executionActions.size()) {
return;
}
executionActions.get(index).execute(new BuildExecutionContext() {
@Override
public GradleInternal getGradle() {
return gradle;
}
@Override
public void proceed() {
execute(gradle, index + 1, taskFailures);
}
}, taskFailures);
}
這里遍歷執(zhí)行了傳給 DefaultBuildWorkExecutor
構(gòu)造器的 BuildConfigurationAction
的 execute()
掂榔,也就是前面提到的 DryRunBuildExecutionAction
和 SelectedTaskExecutionAction
继效。來(lái)看看 DryRunBuildExecutionAction
的 execute()
做了什么症杏。
// DryRunBuildExecutionAction.java
public void execute(BuildExecutionContext context, Collection<? super Throwable> taskFailures) {
GradleInternal gradle = context.getGradle();
// 判斷是否有指定參數(shù) -m 或者 --dry-run
if (gradle.getStartParameter().isDryRun()) {
for (Task task : gradle.getTaskGraph().getAllTasks()) {
// 如果有指定,則直接攔截task的執(zhí)行瑞信,改為打印 task 的 name 以及執(zhí)行順序
textOutputFactory.create(DryRunBuildExecutionAction.class)
.append(((TaskInternal) task).getIdentityPath().getPath())
.append(" ")
.style(StyledTextOutput.Style.ProgressStatus)
.append("SKIPPED")
.println();
}
} else {
// 3. 如果沒有配置厉颤,則執(zhí)行下一個(gè) BuildExecutionAction 的 execute()
context.proceed();
}
}
可以看到 DryRunBuildExecutionAction
的作用是攔截 task 的執(zhí)行過(guò)程。
- 首先通過(guò)
StartParameter
獲取到是否有指定-m
或者--dry-run
參數(shù)凡简; - 如果有指定該參數(shù)逼友,則攔截 tasks 的執(zhí)行,改為遍歷所有待執(zhí)行的 tasks秤涩,逐個(gè)打印其 path帜乞;
- 如果沒有指定該參數(shù),則執(zhí)行下一個(gè)
BuildExecutionAction
的execute()
筐眷。
來(lái)看看 ./gradlew clean --dry-run
的效果圖挖函。
2.2.2 回調(diào)傳給 whenReady() 的閉包
接下來(lái)會(huì)執(zhí)行到 SelectedTaskExecutionAction
的 execute()
,來(lái)看看其源碼浊竟。
// SelectedTaskExecutionAction.java
public void execute(BuildExecutionContext context, Collection<? super Throwable> taskFailures) {
GradleInternal gradle = context.getGradle();
TaskExecutionGraphInternal taskGraph = gradle.getTaskGraph();
// 是否有指定參數(shù) --continue怨喘,如果為true,在失敗的時(shí)候依舊會(huì)繼續(xù)執(zhí)行
if (gradle.getStartParameter().isContinueOnFailure()) {
taskGraph.setContinueOnFailure(true);
}
taskGraph.addTaskExecutionGraphListener(new BindAllReferencesOfProjectsToExecuteListener());
// 執(zhí)行 tasks
taskGraph.execute(taskFailures);
}
這里首先會(huì)看是否有指定 --continue
振定,該參數(shù)表示在執(zhí)行失敗的時(shí)候是否繼續(xù)執(zhí)行 tasks必怜,然后調(diào)用 DefaultTaskExecutionGraph
的 execute()
準(zhǔn)備 run tasks。
// DefaultTaskExecutionGraph.java
public void execute(Collection<? super Throwable> failures) {
ProjectExecutionServiceRegistry projectExecutionServices = new ProjectExecutionServiceRegistry();
executeWithServices(projectExecutionServices, failures);
// ...
}
private void executeWithServices(ProjectExecutionServiceRegistry projectExecutionServices, Collection<? super Throwable> failures) {
Timer clock = Time.startTimer();
// 1. 確保task的有向無(wú)環(huán)圖已經(jīng)生成
ensurePopulated();
if (!hasFiredWhenReady) {
ProjectStateRegistry projectStateRegistry = gradleInternal.getServices().get(ProjectStateRegistry.class);
// 2. 調(diào)用 TaskExecutionGraphListener 的 graphPopulated()
projectStateRegistry.withLenientState(new Runnable() {
@Override
public void run() {
buildOperationExecutor.run(new NotifyTaskGraphWhenReady(DefaultTaskExecutionGraph.this, graphListeners.getSource(), gradleInternal));
}
});
hasFiredWhenReady = true;
}
try {
// 3. 調(diào)用 DefaultPlanExecutor的process()
planExecutor.process(executionPlan, failures,
new BuildOperationAwareExecutionAction(
buildOperationExecutor.getCurrentOperation(),
new InvokeNodeExecutorsAction(nodeExecutors, projectExecutionServices)
)
);
}
// ...
}
這里首先調(diào)用了 ensurePopulated()
確保 task 的有向無(wú)環(huán)圖已經(jīng)生成后频,然后會(huì)調(diào)用 NotifyTaskGraphWhenReady
的 run()
梳庆,來(lái)看看其源碼。
// NotifyTaskGraphWhenReady(DefaultTaskExecutionGraph的內(nèi)部類)
public void run(BuildOperationContext context) {
graphListener.graphPopulated(taskExecutionGraph);
}
這里會(huì)調(diào)用 TaskExecutionGraphListener
的 graphPopulated()
卑惜;為什么提這個(gè)方法膏执,這就得看看 DefaultTaskExecutionGraph
的 whenReady()
了,這也是編寫 gradle 腳本經(jīng)常使用的一個(gè)方法露久。
// DefaultTaskExecutionGraph.java
public void whenReady(final Closure closure) {
graphListeners.add(new ClosureBackedMethodInvocationDispatch("graphPopulated", listenerBuildOperationDecorator.decorate("TaskExecutionGraph.whenReady", closure)));
}
public void whenReady(final Action<TaskExecutionGraph> action) {
graphListeners.add(listenerBuildOperationDecorator.decorate("TaskExecutionGraph.whenReady", TaskExecutionGraphListener.class, new TaskExecutionGraphListener() {
@Override
public void graphPopulated(TaskExecutionGraph graph) {
action.execute(graph);
}
}));
}
可以看到更米,傳給 whenReady()
的動(dòng)作實(shí)際上是被封裝成了 TaskExecutionGraphListener
,所以調(diào)用 TaskExecutionGraphListener
的 graphPopulated()
即回調(diào)了傳給 whenReady()
的動(dòng)作毫痕。
接著調(diào)用了 planExecutor
的 process()
征峦,注意這里傳遞的參數(shù) BuildOperationAwareExecutionAction
,后面會(huì)使用到消请。
2.2.3 創(chuàng)建線程和 ExecutorWorker
planExecutor
是通過(guò)反射調(diào)用的 ExecutionGradleServices
的 createPlanExecutor()
栏笆。
// ExecutionGradleServices.java
PlanExecutor createPlanExecutor(
ParallelismConfigurationManager parallelismConfigurationManager,
ExecutorFactory executorFactory,
WorkerLeaseService workerLeaseService,
BuildCancellationToken cancellationToken,
ResourceLockCoordinationService coordinationService) {
// 這個(gè)參數(shù)gradle并行構(gòu)建的時(shí)候會(huì)有用 org.gradle.parallel = true
int parallelThreads = parallelismConfigurationManager.getParallelismConfiguration().getMaxWorkerCount();
if (parallelThreads < 1) {
throw new IllegalStateException(String.format("Cannot create executor for requested number of worker threads: %s.", parallelThreads));
}
return new DefaultPlanExecutor(
parallelismConfigurationManager.getParallelismConfiguration(),
executorFactory,
workerLeaseService,
cancellationToken,
coordinationService
);
}
即 DefaultPlanExecutor
的實(shí)例,來(lái)看看其 process()
的源碼臊泰。
// DefaultPlanExecutor.java
public void process(ExecutionPlan executionPlan, Collection<? super Throwable> failures, Action<Node> nodeExecutor) {
// 創(chuàng)建線程池
ManagedExecutor executor = executorFactory.create("Execution worker for '" + executionPlan.getDisplayName() + "'");
try {
WorkerLease parentWorkerLease = workerLeaseService.getCurrentWorkerLease();
// org.gradle.parallel=true 的時(shí)候會(huì)開啟多個(gè) ExecutorWorker 并行構(gòu)建
startAdditionalWorkers(executionPlan, nodeExecutor, executor, parentWorkerLease);
new ExecutorWorker(executionPlan, nodeExecutor, parentWorkerLease, cancellationToken, coordinationService).run();
awaitCompletion(executionPlan, failures);
}
// ...
}
private void startAdditionalWorkers(ExecutionPlan executionPlan, Action<? super Node> nodeExecutor, Executor executor, WorkerLease parentWorkerLease) {
// 創(chuàng)建多個(gè) ExecutorWorker 并行構(gòu)建
for (int i = 1; i < executorCount; i++) {
executor.execute(new ExecutorWorker(executionPlan, nodeExecutor, parentWorkerLease, cancellationToken, coordinationService));
}
}
這里會(huì)創(chuàng)建線程池 ManagedExecutor
和任務(wù) ExecutorWorker
蛉加,在開啟了 org.gradle.parallel
的情況下,會(huì)創(chuàng)建多個(gè)線程和任務(wù)并行執(zhí)行。
2.2.4 task 執(zhí)行前的預(yù)處理
接著會(huì)調(diào)用到 ExecutorWorker
的 run()
针饥,來(lái)看看其源碼祟偷。
// ExecutorWorker(DefaultPlanExecutor.java的內(nèi)部類)
public void run() {
WorkerLease childLease = parentWorkerLease.createChild();
while (true) {
// 調(diào)用 executeNextNode()
boolean nodesRemaining = executeNextNode(childLease, new Action<Node>() {
@Override
public void execute(Node work) {
nodeExecutor.execute(work);
// ...
}
});
if (!nodesRemaining) {
// 沒有任務(wù)執(zhí)行了。
break;
}
}
}
private boolean executeNextNode(final WorkerLease workerLease, final Action<Node> nodeExecutor) {
final MutableReference<Node> selected = MutableReference.empty();
final MutableBoolean nodesRemaining = new MutableBoolean();
coordinationService.withStateLock(new Transformer<ResourceLockState.Disposition, ResourceLockState>() {
@Override
public ResourceLockState.Disposition transform(ResourceLockState resourceLockState) {
// 是否取消執(zhí)行
if (cancellationToken.isCancellationRequested()) {
executionPlan.cancelExecution();
}
nodesRemaining.set(executionPlan.hasNodesRemaining());
// 沒有任務(wù)執(zhí)行了打厘,則標(biāo)記為結(jié)束
if (!nodesRemaining.get()) {
return FINISHED;
}
try {
selected.set(executionPlan.selectNext(workerLease, resourceLockState));
} catch (Throwable t) {
resourceLockState.releaseLocks();
executionPlan.abortAllAndFail(t);
nodesRemaining.set(false);
}
if (selected.get() == null && nodesRemaining.get()) {
return RETRY;
} else {
return FINISHED;
}
}
});
Node selectedNode = selected.get();
if (selectedNode != null) {
execute(selectedNode, workerLease, nodeExecutor);
}
return nodesRemaining.get();
}
private void execute(final Node selected, final WorkerLease workerLease, Action<Node> nodeExecutor) {
try {
if (!selected.isComplete()) {
try {
// 執(zhí)行 ExecutorWorker里面創(chuàng)建的 Action 匿名內(nèi)部類實(shí)例的 execute()
nodeExecutor.execute(selected);
} catch (Throwable e) {
selected.setExecutionFailure(e);
}
}
}
// ...
}
可以看到最終會(huì)調(diào)用到 nodeExecutor.execute(work)
修肠,而這里的 nodeExecutor
也就是前面說(shuō)的傳給 process()
的 BuildOperationAwareExecutionAction
的實(shí)例,來(lái)看看其 execute()
户盯。
public void execute(Node node) {
// ...
delegate.execute(node);
// ...
}
這里實(shí)際上是調(diào)用了 InvokeNodeExecutorsAction
的 execute()
嵌施。
public void execute(Node node) {
for (NodeExecutor nodeExecutor : nodeExecutors) {
if (nodeExecutor.execute(node, projectExecutionServices)) {
return;
}
}
throw new IllegalStateException("Unknown type of node: " + node);
}
可以看到它只是遍歷調(diào)用了傳遞進(jìn)來(lái)的 nodeExecutor
的 execute()
;這里的 nodeExecutors
是通過(guò)反射調(diào)用了 GradleScopeServices
的 createLocalTaskNodeExecutor()
莽鸭。
// GradleScopeServices.java
LocalTaskNodeExecutor createLocalTaskNodeExecutor() {
return new LocalTaskNodeExecutor();
}
即 LocalTaskNodeExecutor
的實(shí)例吗伤,來(lái)看看其 execute()
的源碼。
// LocalTaskNodeExecutor.java
public boolean execute(Node node, ProjectExecutionServiceRegistry services) {
if (node instanceof LocalTaskNode) {
LocalTaskNode localTaskNode = (LocalTaskNode) node;
TaskInternal task = localTaskNode.getTask();
TaskStateInternal state = task.getState();
// 判斷任務(wù)是否已經(jīng)執(zhí)行過(guò)硫眨,如果執(zhí)行過(guò)足淆,則直接返回
if (state.getExecuted()) {
return true;
}
TaskExecutionContext ctx = new DefaultTaskExecutionContext(localTaskNode);
// 這里又通過(guò)反射找 TaskExecuter
TaskExecuter taskExecuter = services.getProjectService((ProjectInternal) task.getProject(), TaskExecuter.class);
assert taskExecuter != null;
// 這里就是執(zhí)行 task 的入口
taskExecuter.execute(task, state, ctx);
localTaskNode.getPostAction().execute(task);
return true;
} else {
return false;
}
}
它首先判斷 task 是否有執(zhí)行過(guò),如果有執(zhí)行過(guò)則直接返回礁阁;如果沒有執(zhí)行過(guò)巧号,則調(diào)用 TaskExecuter
的 execute()
執(zhí)行 task。taskExecuter
是通過(guò)反射調(diào)用的 ProjectExecutionServices
的 createTaskExecuter()
姥闭。
// ProjectExecutionServices.java
TaskExecuter createTaskExecuter(TaskExecutionModeResolver repository,
BuildCacheController buildCacheController,
TaskInputsListener inputsListener,
TaskActionListener actionListener,
OutputChangeListener outputChangeListener,
ClassLoaderHierarchyHasher classLoaderHierarchyHasher,
TaskSnapshotter taskSnapshotter,
FileCollectionFingerprinterRegistry fingerprinterRegistry,
BuildOperationExecutor buildOperationExecutor,
AsyncWorkTracker asyncWorkTracker,
BuildOutputCleanupRegistry cleanupRegistry,
ExecutionHistoryStore executionHistoryStore,
OutputFilesRepository outputFilesRepository,
BuildScanPluginApplied buildScanPlugin,
FileCollectionFactory fileCollectionFactory,
PropertyWalker propertyWalker,
TaskExecutionGraphInternal taskExecutionGraph,
TaskExecutionListener taskExecutionListener,
TaskListenerInternal taskListenerInternal,
TaskCacheabilityResolver taskCacheabilityResolver,
WorkExecutor<AfterPreviousExecutionContext, CachingResult> workExecutor,
ReservedFileSystemLocationRegistry reservedFileSystemLocationRegistry,
ListenerManager listenerManager
) {
boolean buildCacheEnabled = buildCacheController.isEnabled();
boolean scanPluginApplied = buildScanPlugin.isBuildScanPluginApplied();
// 這個(gè) executer 才是真正執(zhí)行 task 的
TaskExecuter executer = new ExecuteActionsTaskExecuter(
buildCacheEnabled,
scanPluginApplied,
taskSnapshotter,
executionHistoryStore,
buildOperationExecutor,
asyncWorkTracker,
actionListener,
taskCacheabilityResolver,
fingerprinterRegistry,
classLoaderHierarchyHasher,
workExecutor,
listenerManager
);
// 下面這些都是包裝
executer = new ValidatingTaskExecuter(executer, reservedFileSystemLocationRegistry);
executer = new SkipEmptySourceFilesTaskExecuter(inputsListener, executionHistoryStore, cleanupRegistry, outputChangeListener, executer);
executer = new ResolveBeforeExecutionOutputsTaskExecuter(taskSnapshotter, executer);
if (buildCacheEnabled || scanPluginApplied) {
executer = new StartSnapshotTaskInputsBuildOperationTaskExecuter(buildOperationExecutor, executer);
}
executer = new ResolveAfterPreviousExecutionStateTaskExecuter(executionHistoryStore, executer);
executer = new CleanupStaleOutputsExecuter(cleanupRegistry, outputFilesRepository, buildOperationExecutor, outputChangeListener, executer);
executer = new FinalizePropertiesTaskExecuter(executer);
executer = new ResolveTaskExecutionModeExecuter(repository, fileCollectionFactory, propertyWalker, executer);
executer = new SkipTaskWithNoActionsExecuter(taskExecutionGraph, executer);
executer = new SkipOnlyIfTaskExecuter(executer);
executer = new CatchExceptionTaskExecuter(executer);
executer = new EventFiringTaskExecuter(buildOperationExecutor, taskExecutionListener, taskListenerInternal, executer);
return executer;
}
真正執(zhí)行 task 的是 ExecuteActionsTaskExecuter
丹鸿,其他都是對(duì)其進(jìn)行的包裝,在執(zhí)行 task 前做一些預(yù)處理操作棚品,從下往上挑關(guān)鍵的說(shuō)靠欢。
2.2.4.1 EventFiringTaskExecuter
首先來(lái)看看 EventFiringTaskExecuter
的 execute()
。
// EventFiringTaskExecuter.java
public TaskExecuterResult execute(final TaskInternal task, final TaskStateInternal state, final TaskExecutionContext context) {
return buildOperationExecutor.call(new CallableBuildOperation<TaskExecuterResult>() {
@Override
public TaskExecuterResult call(BuildOperationContext operationContext) {
TaskExecuterResult result = executeTask(operationContext);
// ...
return result;
}
private TaskExecuterResult executeTask(BuildOperationContext operationContext) {
// ...
// 1. 調(diào)用 TaskExecutionListener 的 beforeExecute()
taskExecutionListener.beforeExecute(task);
// ...
// 2. 執(zhí)行下一個(gè) execute()
TaskExecuterResult result = delegate.execute(task, state, context);
// ...
// 3. 調(diào)用 TaskExecutionListener 的 afterExecute()
taskExecutionListener.afterExecute(task, state);
// ...
}
});
}
可以看到铜跑,這里主要是增加事件回調(diào)门怪。在 Task
執(zhí)行前調(diào)用 TaskExecutionListener
的 beforeExecute()
,在 Task
執(zhí)行后調(diào)用 TaskExecutionListener
的 afterExecute()
锅纺。
2.2.4.2 CatchExceptionTaskExecuter
再來(lái)看看 CatchExceptionTaskExecuter
的 execute()
掷空。
// CatchExceptionTaskExecuter.java
public TaskExecuterResult execute(TaskInternal task, TaskStateInternal state, TaskExecutionContext context) {
try {
return delegate.execute(task, state, context);
} catch (RuntimeException e) {
state.setOutcome(new TaskExecutionException(task, e));
return TaskExecuterResult.WITHOUT_OUTPUTS;
}
}
這里主要是給 task 執(zhí)行加上 try{}catch{}
。
2.2.4.3 SkipOnlyIfTaskExecuter
再來(lái)看看 SkipOnlyIfTaskExecuter
的 execute()
伞广。
// SkipOnlyIfTaskExecuter.java
public TaskExecuterResult execute(TaskInternal task, TaskStateInternal state, TaskExecutionContext context) {
boolean skip;
try {
skip = !task.getOnlyIf().isSatisfiedBy(task);
} catch (Throwable t) {
state.setOutcome(new GradleException(String.format("Could not evaluate onlyIf predicate for %s.", task), t));
return TaskExecuterResult.WITHOUT_OUTPUTS;
}
if (skip) {
state.setOutcome(TaskExecutionOutcome.SKIPPED);
return TaskExecuterResult.WITHOUT_OUTPUTS;
}
return executer.execute(task, state, context);
}
這里主要是判斷 task 的 onlyIf
條件是否滿足執(zhí)行拣帽,onlyIf
類似于 java
的 if
語(yǔ)句疼电,只有當(dāng)判斷條件為真的時(shí)候才會(huì)執(zhí)行 task嚼锄。
舉個(gè)栗子方便理解。在 root project 的 build.gradle
文件里面添加如下代碼蔽豺。
subprojects { Project p ->
Task hello = p.task("hello") {
doLast {
println("execute hello task!")
}
}
}
sync 后運(yùn)行 ./gradlew hello
区丑,結(jié)果如下。
這里分別執(zhí)行了 app 和 app2 的 hello task,然后修改 build.gradle
增加 onlyIf
判斷沧侥。
subprojects { Project p ->
Task hello = p.task("hello") {
doLast {
println("execute hello task!")
}
}
// 只有當(dāng)是 app 的時(shí)候才執(zhí)行
hello.onlyIf { hello.project.name == "app" }
}
sync 后再次運(yùn)行 ./gradlew hello
可霎,結(jié)果如下,可以看到相較于上面少了 :app2:hello
的執(zhí)行宴杀,說(shuō)明 onlyIf
生效了癣朗。
2.2.4.4 SkipTaskWithNoActionsExecuter
來(lái)看看 SkipTaskWithNoActionsExecuter
的 execute()
。
// SkipTaskWithNoActionsExecuter.java
public TaskExecuterResult execute(TaskInternal task, TaskStateInternal state, TaskExecutionContext context) {
if (!task.hasTaskActions()) {
boolean upToDate = true;
for (Task dependency : taskExecutionGraph.getDependencies(task)) {
if (!dependency.getState().getSkipped()) {
upToDate = false;
break;
}
}
state.setActionable(false);
state.setOutcome(upToDate ? TaskExecutionOutcome.UP_TO_DATE : TaskExecutionOutcome.EXECUTED);
return TaskExecuterResult.WITHOUT_OUTPUTS;
}
return executer.execute(task, state, context);
}
這里是跳過(guò)那些沒有 action 的 task旺罢,沒有 action 說(shuō)明 task 不需要執(zhí)行旷余。
2.2.4.5 ResolveTaskExecutionModeExecuter
來(lái)看看 ResolveTaskExecutionModeExecuter
的 execute()
。
// ResolveTaskExecutionModeExecuter.java
public TaskExecuterResult execute(final TaskInternal task, TaskStateInternal state, final TaskExecutionContext context) {
Timer clock = Time.startTimer();
// 1. 解析 task 屬性
TaskProperties properties = DefaultTaskProperties.resolve(propertyWalker, fileCollectionFactory, task);
context.setTaskProperties(properties);
// 2. 解析 task 的 Execution Mode
TaskExecutionMode taskExecutionMode = executionModeResolver.getExecutionMode(task, properties);
TaskOutputsInternal outputs = task.getOutputs();
context.setTaskExecutionMode(taskExecutionMode);
// ...
}
這里主要做了兩件事情:
- 解析
Task
的屬性扁达,比如輸入正卧、輸出等; - 獲取
Task
的Execution Mode
跪解;
過(guò)程一有點(diǎn)多炉旷,先說(shuō)過(guò)程二。這里的 executionModeResolver
是通過(guò)反射調(diào)用 ProjectExecutionServices
的 createExecutionModeResolver()
叉讥。
TaskExecutionModeResolver createExecutionModeResolver(
StartParameter startParameter
) {
return new DefaultTaskExecutionModeResolver(startParameter);
}
來(lái)看看 DefaultTaskExecutionModeResolver
的 getExecutionMode()
窘行。
// DefaultTaskExecutionModeResolver.java
public TaskExecutionMode getExecutionMode(TaskInternal task, TaskProperties properties) {
AndSpec<? super TaskInternal> upToDateSpec = task.getOutputs().getUpToDateSpec();
// 如果沒有聲明 outputs 并且沒有指定 upToDateSpec
if (!properties.hasDeclaredOutputs() && upToDateSpec.isEmpty()) {
if (task.hasTaskActions()) {
if (requiresInputChanges(task)) {
DeprecationLogger.nagUserOfDeprecated("Using the incremental task API without declaring any outputs", "Please declare output files for your task or use `TaskOutputs.upToDateWhen()`.");
} else {
return TaskExecutionMode.NO_OUTPUTS_WITH_ACTIONS;
}
} else {
return TaskExecutionMode.NO_OUTPUTS_WITHOUT_ACTIONS;
}
}
if (startParameter.isRerunTasks()) {
return TaskExecutionMode.RERUN_TASKS_ENABLED;
}
if (!upToDateSpec.isSatisfiedBy(task)) {
return TaskExecutionMode.UP_TO_DATE_WHEN_FALSE;
}
return TaskExecutionMode.INCREMENTAL;
}
這個(gè) TaskExecutionMode
究竟是啥玩意呢?來(lái)看看其源碼图仓。
public enum TaskExecutionMode {
INCREMENTAL(null, true, true),
NO_OUTPUTS_WITHOUT_ACTIONS("Task has not declared any outputs nor actions.", false, false),
NO_OUTPUTS_WITH_ACTIONS("Task has not declared any outputs despite executing actions.", false, false),
RERUN_TASKS_ENABLED("Executed with '--rerun-tasks'.", true, false),
UP_TO_DATE_WHEN_FALSE("Task.upToDateWhen is false.", true, false);
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
private final Optional<String> rebuildReason;
private final boolean taskHistoryMaintained;
private final boolean allowedToUseCachedResults;
TaskExecutionMode(@Nullable String rebuildReason, boolean taskHistoryMaintained, boolean allowedToUseCachedResults) {
this.rebuildReason = Optional.ofNullable(rebuildReason);
this.taskHistoryMaintained = taskHistoryMaintained;
this.allowedToUseCachedResults = allowedToUseCachedResults;
}
// 返回原因
public Optional<String> getRebuildReason() {
return rebuildReason;
}
// 這個(gè)方法標(biāo)記了是否需要記錄執(zhí)行歷史
public boolean isTaskHistoryMaintained() {
return taskHistoryMaintained;
}
// 這里方法決定了是否加載緩存來(lái)替代執(zhí)行 task
public boolean isAllowedToUseCachedResults() {
return allowedToUseCachedResults;
}
}
TaskExecutionMode
有兩個(gè)比較重要的方法 isTaskHistoryMaintained()
和 isAllowedToUseCachedResults()
抽高,它們影響到了 Task
的執(zhí)行流程。
再看下過(guò)程一是如何解析 Task
屬性的透绩。先來(lái)看看DefaultTaskProperties
的 resolve()
翘骂。
// DefaultTaskProperties.java
public static TaskProperties resolve(PropertyWalker propertyWalker, FileCollectionFactory fileCollectionFactory, TaskInternal task) {
String beanName = task.toString();
GetInputFilesVisitor inputFilesVisitor = new GetInputFilesVisitor(beanName, fileCollectionFactory);
GetOutputFilesVisitor outputFilesVisitor = new GetOutputFilesVisitor(beanName, fileCollectionFactory);
GetInputPropertiesVisitor inputPropertiesVisitor = new GetInputPropertiesVisitor(beanName);
GetLocalStateVisitor localStateVisitor = new GetLocalStateVisitor(beanName, fileCollectionFactory);
GetDestroyablesVisitor destroyablesVisitor = new GetDestroyablesVisitor(beanName, fileCollectionFactory);
ValidationVisitor validationVisitor = new ValidationVisitor();
try {
// 主要是這個(gè)方法
TaskPropertyUtils.visitProperties(propertyWalker, task, new CompositePropertyVisitor(
inputPropertiesVisitor,
inputFilesVisitor,
outputFilesVisitor,
validationVisitor,
destroyablesVisitor,
localStateVisitor
));
} catch (Exception e) {
throw new TaskExecutionException(task, e);
}
// 把解析出來(lái)的屬性存到 DefaultTaskProperties里面
return new DefaultTaskProperties(
task.toString(),
inputPropertiesVisitor.getPropertyValuesSupplier(),
inputFilesVisitor.getFileProperties(),
outputFilesVisitor.getFileProperties(),
outputFilesVisitor.hasDeclaredOutputs(),
localStateVisitor.getFiles(),
destroyablesVisitor.getFiles(),
validationVisitor.getTaskPropertySpecs());
}
主要是調(diào)用的 TaskPropertyUtils.visitProperties()
,來(lái)看看其源碼帚豪。
// TaskPropertyUtils.java
public static void visitProperties(PropertyWalker propertyWalker, final TaskInternal task, final PropertyVisitor visitor) {
StrictErrorsOnlyContext validationContext = new StrictErrorsOnlyContext(task);
propertyWalker.visitProperties(task, validationContext, visitor);
// ...
}
這里的 propertyWalker
是通過(guò)反射調(diào)用的 ExecutionGlobalServices
的 createPropertyWalker()
碳竟。
// ExecutionGlobalServices.java
PropertyWalker createPropertyWalker(TaskScheme taskScheme) {
return taskScheme.getInspectionScheme().getPropertyWalker();
}
而 taskScheme
是通過(guò)反射調(diào)用的 ExecutionGlobalServices
的 createTaskScheme()
。
// ExecutionGlobalServices.java
TaskScheme createTaskScheme(InspectionSchemeFactory inspectionSchemeFactory, InstantiatorFactory instantiatorFactory) {
InstantiationScheme instantiationScheme = instantiatorFactory.decorateScheme();
InspectionScheme inspectionScheme = inspectionSchemeFactory.inspectionScheme(
ImmutableSet.of(
Input.class,
InputFile.class,
InputFiles.class,
InputDirectory.class,
OutputFile.class,
OutputFiles.class,
OutputDirectory.class,
OutputDirectories.class,
Destroys.class,
LocalState.class,
Nested.class,
Console.class,
ReplacedBy.class,
Internal.class,
OptionValues.class
),
ImmutableSet.of(
Classpath.class,
CompileClasspath.class,
Incremental.class,
Optional.class,
PathSensitive.class,
SkipWhenEmpty.class
),
instantiationScheme);
return new TaskScheme(instantiationScheme, inspectionScheme);
}
注意下傳給 inspectionScheme()
的第一個(gè)參數(shù)狸臣,是很多的注解莹桅,解析屬性會(huì)用到它們,后面再說(shuō)烛亦。先看下 InspectionSchemeFactory.InspectionSchemeImpl
的 getPropertyWalker()
诈泼。
// InspectionSchemeFactory.java
private static class InspectionSchemeImpl implements InspectionScheme {
private final DefaultPropertyWalker propertyWalker;
public InspectionSchemeImpl(List<TypeAnnotationHandler> typeHandlers, List<PropertyAnnotationHandler> propertyHandlers, Collection<Class<? extends Annotation>> propertyModifiers, TypeAnnotationMetadataStore typeAnnotationMetadataStore, CrossBuildInMemoryCacheFactory cacheFactory) {
propertyWalker = new DefaultPropertyWalker(metadataStore);
}
@Override
public PropertyWalker getPropertyWalker() {
return propertyWalker;
}
}
即 DefaultPropertyWalker
的實(shí)例,來(lái)看看其源碼煤禽。
public class DefaultPropertyWalker implements PropertyWalker {
private final RuntimeBeanNodeFactory nodeFactory;
public DefaultPropertyWalker(TypeMetadataStore typeMetadataStore) {
this.nodeFactory = new RuntimeBeanNodeFactory(typeMetadataStore);
}
@Override
public void visitProperties(Object bean, ParameterValidationContext validationContext, PropertyVisitor visitor) {
Queue<RuntimeBeanNode<?>> queue = new ArrayDeque<RuntimeBeanNode<?>>();
// node 為 RootRuntimeBeanNode
queue.add(nodeFactory.createRoot(bean));
while (!queue.isEmpty()) {
RuntimeBeanNode<?> node = queue.remove();
node.visitNode(visitor, queue, nodeFactory, validationContext);
}
}
}
// RuntimeBeanNodeFactory.java
public RuntimeBeanNode<?> createRoot(Object bean) {
return new RootRuntimeBeanNode(bean, metadataStore.getTypeMetadata(bean.getClass()));
}
這里的 node
是 RootRuntimeBeanNode
铐达,來(lái)看看其 visitNode()
。
// AbstractNestedRuntimeBeanNode.java
protected void visitProperties(PropertyVisitor visitor, final Queue<RuntimeBeanNode<?>> queue, final RuntimeBeanNodeFactory nodeFactory, ParameterValidationContext validationContext) {
TypeMetadata typeMetadata = getTypeMetadata();
typeMetadata.collectValidationFailures(getPropertyName(), validationContext);
for (PropertyMetadata propertyMetadata : typeMetadata.getPropertiesMetadata()) {
// 找屬性對(duì)應(yīng)的 PropertyAnnotationHandler
PropertyAnnotationHandler annotationHandler = typeMetadata.getAnnotationHandlerFor(propertyMetadata);
if (annotationHandler.shouldVisit(visitor)) {
String propertyName = getQualifiedPropertyName(propertyMetadata.getPropertyName());
PropertyValue value = new BeanPropertyValue(getBean(), propertyMetadata.getGetterMethod());
// 這里最終會(huì)調(diào)用 注解對(duì)應(yīng)的 PropertyAnnotationHandler 的 visitPropertyValue()
annotationHandler.visitPropertyValue(propertyName, value, propertyMetadata, visitor, new BeanPropertyContext() {
@Override
public void addNested(String propertyName, Object bean) {
queue.add(nodeFactory.create(AbstractNestedRuntimeBeanNode.this, propertyName, bean));
}
});
}
}
}
還記得前面很多注解的參數(shù)嗎檬果,其實(shí)解析屬性就是解析這些注解所修飾的東西瓮孙。每個(gè)注解都會(huì)對(duì)應(yīng)一個(gè) PropertyAnnotationHandler
唐断。拿 InputFile
舉個(gè)栗子,它對(duì)應(yīng)的是 InputFilePropertyAnnotationHandler
杭抠,來(lái)看看其 visitPropertyValue()
脸甘。
// AbstractInputFilePropertyAnnotationHandler.java
public void visitPropertyValue(String propertyName, PropertyValue value, PropertyMetadata propertyMetadata, PropertyVisitor visitor, BeanPropertyContext context) {
// ...
// 調(diào)用了 visitor 的 visitInputFileProperty(),visitor 即前面 DefaultTaskProperties.resolve() 里面?zhèn)魅氲?GetInputFilesVisitor
visitor.visitInputFileProperty(
propertyName,
propertyMetadata.isAnnotationPresent(Optional.class),
propertyMetadata.isAnnotationPresent(SkipWhenEmpty.class),
propertyMetadata.isAnnotationPresent(Incremental.class),
fileNormalizer,
value,
getFilePropertyType()
);
}
這里調(diào)用到了 visitor
的 visitInputFileProperty()
偏灿,它是前面 DefaultTaskProperties.resolve()
里面?zhèn)魅氲?GetInputFilesVisitor
實(shí)例丹诀,來(lái)看看其 visitInputFileProperty()
。
public void visitInputFileProperty(final String propertyName, boolean optional, boolean skipWhenEmpty, boolean incremental, @Nullable Class<? extends FileNormalizer> fileNormalizer, PropertyValue value, InputFilePropertyType filePropertyType) {
// 解析 input file 是 directory 還是 file
FileCollection actualValue = FileParameterUtils.resolveInputFileValue(fileCollectionFactory, filePropertyType, value);
// 加到集合中
specs.add(new DefaultInputFilePropertySpec(
propertyName,
FileParameterUtils.normalizerOrDefault(fileNormalizer),
new PropertyFileCollection(ownerDisplayName, propertyName, "input", actualValue),
value,
skipWhenEmpty,
incremental
));
if (skipWhenEmpty) {
hasSourceFiles = true;
}
}
2.2.4.6 SkipEmptySourceFilesTaskExecuter
再來(lái)看看 SkipEmptySourceFilesTaskExecuter
的 execute()
翁垂。
// SkipEmptySourceFilesTaskExecuter.java
public TaskExecuterResult execute(TaskInternal task, TaskStateInternal state, final TaskExecutionContext context) {
TaskProperties properties = context.getTaskProperties();
FileCollection sourceFiles = properties.getSourceFiles();
// 如果有 source files 但是 source files 是空的
if (properties.hasSourceFiles() && sourceFiles.isEmpty()) {
AfterPreviousExecutionState previousExecution = context.getAfterPreviousExecution();
ImmutableSortedMap<String, FileCollectionFingerprint> outputFiles = previousExecution == null
? ImmutableSortedMap.<String, FileCollectionFingerprint>of()
: previousExecution.getOutputFileProperties();
if (outputFiles.isEmpty()) {
// 沒有 outputs忿墅,則標(biāo)記為 NO_SOURCE
state.setOutcome(TaskExecutionOutcome.NO_SOURCE);
} else {
outputChangeListener.beforeOutputChange();
OutputsCleaner outputsCleaner = new OutputsCleaner(new Predicate<File>() {
@Override
public boolean test(File file) {
return buildOutputCleanupRegistry.isOutputOwnedByBuild(file);
}
}, new Predicate<File>() {
@Override
public boolean test(File dir) {
return buildOutputCleanupRegistry.isOutputOwnedByBuild(dir);
}
});
for (FileCollectionFingerprint outputFingerprints : outputFiles.values()) {
try {
outputsCleaner.cleanupOutputs(outputFingerprints);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
if (outputsCleaner.getDidWork()) {
state.setOutcome(TaskExecutionOutcome.EXECUTED);
} else {
state.setOutcome(TaskExecutionOutcome.NO_SOURCE);
}
}
taskInputsListener.onExecute(task, Cast.cast(FileCollectionInternal.class, sourceFiles));
executionHistoryStore.remove(task.getPath());
return TaskExecuterResult.WITHOUT_OUTPUTS;
} else {
taskInputsListener.onExecute(task, Cast.cast(FileCollectionInternal.class, properties.getInputFiles()));
}
return executer.execute(task, state, context);
}
這里是處理那些有設(shè)置 sourc files 但是 source files 為空的 Task
,source files 為空說(shuō)明 Task
沒有需要處理的資源沮峡。
2.2.4.7 ValidatingTaskExecuter
再來(lái)看看 ValidatingTaskExecuter
的 execute()
疚脐。
// ValidatingTaskExecuter.java
public TaskExecuterResult execute(TaskInternal task, TaskStateInternal state, TaskExecutionContext context) {
List<String> messages = Lists.newArrayList();
FileResolver resolver = ((ProjectInternal) task.getProject()).getFileResolver();
final TaskValidationContext validationContext = new DefaultTaskValidationContext(resolver, reservedFileSystemLocationRegistry, messages);
// 做一些屬性的校驗(yàn)操作
context.getTaskProperties().validate(validationContext);
if (!messages.isEmpty()) {
List<String> firstMessages = messages.subList(0, Math.min(5, messages.size()));
report(task, firstMessages, state);
return TaskExecuterResult.WITHOUT_OUTPUTS;
}
return executer.execute(task, state, context);
}
這里是在 Task
執(zhí)行前做一些校驗(yàn)。
2.2.5 執(zhí)行 Task
最后會(huì)執(zhí)行到 ExecuteActionsTaskExecuter
的 execute()
邢疙,這里才是正真執(zhí)行 Task
的地方棍弄,先來(lái)看看它的源碼。
// ExecuteActionsTaskExecuter.java
public TaskExecuterResult execute(TaskInternal task, TaskStateInternal state, TaskExecutionContext context) {
// 創(chuàng)建一個(gè) TaskExecution 實(shí)例
TaskExecution work = new TaskExecution(task, context, executionHistoryStore, fingerprinterRegistry, classLoaderHierarchyHasher);
// 調(diào)用 workExecutor 的 execute疟游,最終會(huì)調(diào)用 getWork().execute()呼畸,即 TaskExecution 的 execute()
CachingResult result = workExecutor.execute(new AfterPreviousExecutionContext() {
@Override
public UnitOfWork getWork() {
return work;
}
});
// ...
}
這里的 workExecutor
是通過(guò)反射調(diào)用的 ExecutionGradleServices
的 createWorkExecutor()
。
// ExecutionGradleServices.java
public WorkExecutor<AfterPreviousExecutionContext, CachingResult> createWorkExecutor(
BuildCacheCommandFactory buildCacheCommandFactory,
BuildCacheController buildCacheController,
BuildScanPluginApplied buildScanPlugin,
BuildCancellationToken cancellationToken,
BuildInvocationScopeId buildInvocationScopeId,
ExecutionStateChangeDetector changeDetector,
ClassLoaderHierarchyHasher classLoaderHierarchyHasher,
ValueSnapshotter valueSnapshotter,
OutputChangeListener outputChangeListener,
OutputFilesRepository outputFilesRepository,
TimeoutHandler timeoutHandler
) {
return new DefaultWorkExecutor<AfterPreviousExecutionContext, CachingResult>(
// 注意這里傳入的 Step 實(shí)例颁虐,最終會(huì)調(diào)用到 ExecuteStep 的 execute()
new CaptureStateBeforeExecutionStep(classLoaderHierarchyHasher, valueSnapshotter,
new ResolveCachingStateStep(buildCacheController, buildScanPlugin.isBuildScanPluginApplied(),
new MarkSnapshottingInputsFinishedStep<UpToDateResult>(
new ResolveChangesStep<UpToDateResult>(changeDetector,
new SkipUpToDateStep<IncrementalChangesContext>(
new RecordOutputsStep<IncrementalChangesContext>(outputFilesRepository,
new StoreSnapshotsStep<IncrementalChangesContext>(
new BroadcastChangingOutputsStep<IncrementalChangesContext, CurrentSnapshotResult>(outputChangeListener,
new CacheStep(buildCacheController, buildCacheCommandFactory,
new SnapshotOutputsStep<IncrementalChangesContext>(buildInvocationScopeId.getId(),
new CreateOutputsStep<IncrementalChangesContext, Result>(
new CatchExceptionStep<IncrementalChangesContext>(
new TimeoutStep<IncrementalChangesContext>(timeoutHandler,
new CancelExecutionStep<IncrementalChangesContext>(cancellationToken,
new ResolveInputChangesStep<IncrementalChangesContext>(
new CleanupOutputsStep<InputChangesContext, Result>(
new ExecuteStep<InputChangesContext>()
)
)
)
)
)
)
)
)
)
)
)
)
)
)
)
)
);
}
即 DefaultWorkExecutor
的實(shí)例蛮原,注意這里傳入的 Step
,后面會(huì)用到另绩。先來(lái)看看 DefaultWorkExecutor
的 execute()
儒陨。
// DefaultWorkExecutor.java
public R execute(C context) {
return executeStep.execute(context);
}
這里直接調(diào)用了 executeStep
的 execute()
,即上面?zhèn)魅氲?Step
的 execute()
笋籽,跟隨調(diào)用鏈發(fā)現(xiàn)它最終會(huì)調(diào)用到 ExecuteStep
的 execute()
蹦漠,來(lái)看看其源碼。
// ExecuteStep.java
public Result execute(C context) {
// 前面你說(shuō)了 getWork() 即 TaskExecution车海,這里調(diào)用了它的 execute()
UnitOfWork work = context.getWork();
ExecutionOutcome outcome = context.getInputChanges()
.map(inputChanges -> determineOutcome(work.execute(inputChanges), inputChanges.isIncremental()))
.orElseGet(() -> determineOutcome(work.execute(null), false));
return new Result() {
@Override
public Try<ExecutionOutcome> getOutcome() {
return Try.successful(outcome);
}
};
}
這里會(huì)調(diào)用 TaskExecution
的 execute()
笛园,來(lái)看看其源碼。
// TaskExecution(ExecuteActionsTaskExecuter.java的內(nèi)部類)
public WorkResult execute(@Nullable InputChangesInternal inputChanges) {
task.getState().setExecuting(true);
try {
// 1. 調(diào)用 TaskActionListener 的 beforeActions()
actionListener.beforeActions(task);
// 2. 調(diào)用 executeActions()
executeActions(task, inputChanges);
return task.getState().getDidWork() ? WorkResult.DID_WORK : WorkResult.DID_NO_WORK;
} finally {
task.getState().setExecuting(false);
// 3. 調(diào)用 TaskActionListener 的 afterActions()
actionListener.afterActions(task);
}
}
private void executeActions(TaskInternal task, @Nullable InputChangesInternal inputChanges) {
boolean hasTaskListener = listenerManager.hasListeners(TaskActionListener.class) || listenerManager.hasListeners(TaskExecutionListener.class);
Iterator<InputChangesAwareTaskAction> actions = new ArrayList<>(task.getTaskActions()).iterator();
// 遍歷 actions侍芝,逐個(gè)調(diào)用 executeAction()
while (actions.hasNext()) {
InputChangesAwareTaskAction action = actions.next();
task.getState().setDidWork(true);
task.getStandardOutputCapture().start();
boolean hasMoreWork = hasTaskListener || actions.hasNext();
// 調(diào)用 executeAction()
executeAction(action.getDisplayName(), task, action, inputChanges, hasMoreWork);
}
}
private void executeAction(String actionDisplayName, TaskInternal task, InputChangesAwareTaskAction action, @Nullable InputChangesInternal inputChanges, boolean hasMoreWork) {
if (inputChanges != null) {
action.setInputChanges(inputChanges);
}
buildOperationExecutor.run(new RunnableBuildOperation() {
@Override
public void run(BuildOperationContext context) {
// ...
// 調(diào)用action 的execute()
action.execute(task);
// ...
}
});
}
這里的邏輯十分的清晰:
- 首先調(diào)用
TaskActionListener
的beforeActions()
研铆; - 然后遍歷
Task
所有的Action
,逐個(gè)調(diào)用其execute()
(執(zhí)行Task
實(shí)際上就是執(zhí)行Task
里面所有的Action
)州叠; - 執(zhí)行完
Task
后會(huì)調(diào)用TaskActionListener
的afterActions()
棵红。
執(zhí)行完 Task
后就會(huì)回到 DefaultGradleLauncher
的 runWork()
。
private void runWork() {
// ...
// 如果有失敗的留量,則拋出異常
if (!taskFailures.isEmpty()) {
throw new MultipleBuildFailures(taskFailures);
}
// 執(zhí)行成功則將狀態(tài)標(biāo)記為 RunTasks
stage = Stage.RunTasks;
}
這里最后會(huì)將狀態(tài)標(biāo)記為 RunTasks
窄赋,至此 Gradle 構(gòu)建流程的 RunTasks
就分析完了哟冬。