1. 写在前面
在 Gradle源码分析(四)一文中,我们分析了Gradle构建流程的
TaskGraph
阶段,这里将分析RunTasks
阶段(gradle 源码版本为 5.6.4)。
2. RunTasks
2.1 整体实现
这里我整理了 RunTasks
阶段的一些主要操作,并绘制了调用链的时序图。如果对源码不感兴趣的同学只需要看这一部分的内容即可。
2.1.1 时序图
2.1.2 主要操作
RunTasks
阶段 Gradle 主要做了下面这些事情。
- 处理 --dry-run;
- 回调传给
whenReady()
的闭包; - 创建线程和
ExecutorWorker
; - 执行 task 前的预处理;
- 调用
TaskActionListener
的beforeAction()
,遍历Task
的Action
,并调用其execute()
,调用TaskActionListener
的afterAction()
。
2.2 源码分析
2.2.1 处理 --dry-run
RunTasks
的过程发生在 DefaultGradleLauncher
的 runWork()
中,先来看看其源码。
// DefaultGradleLauncher.java
private void runWork() {
// ...
List<Throwable> taskFailures = new ArrayList<Throwable>();
buildExecuter.execute(gradle, taskFailures);
// ...
}
这里调用了 buildExecuter
的 execute()
,而 buildExecuter
是通过反射调用GradleScopeServices
的createBuildExecuter()
生成的。
// GradleScopeServices.java
BuildWorkExecutor createBuildExecuter(StyledTextOutputFactory textOutputFactory, IncludedBuildControllers includedBuildControllers, BuildOperationExecutor buildOperationExecutor) {
return new BuildOperationFiringBuildWorkerExecutor(
new IncludedBuildLifecycleBuildWorkExecutor(
new DefaultBuildWorkExecutor(
// 记住这两个 BuildExecutionAction
asList(new DryRunBuildExecutionAction(textOutputFactory),
new SelectedTaskExecutionAction())),
includedBuildControllers),
buildOperationExecutor);
}
这里有两个比较重要的 BuildExecutionAction
,暂时先记住它们:
DryRunBuildExecutionAction
SelectedTaskExecutionAction
上面的代码最终会调用到 DefaultBuildWorkExecutor
的 execute()
,来看看其源码。
// DefaultBuildWorkExecutor.java
public void execute(GradleInternal gradle, Collection<? super Throwable> failures) {
execute(gradle, 0, failures);
}
// 和 TaskGraph 阶段的 BuildConfigurationAction 执行差不多
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);
}
这里遍历执行了传给 DefaultBuildWorkExecutor
构造器的 BuildConfigurationAction
的 execute()
,也就是前面提到的 DryRunBuildExecutionAction
和 SelectedTaskExecutionAction
。来看看 DryRunBuildExecutionAction
的 execute()
做了什么。
// DryRunBuildExecutionAction.java
public void execute(BuildExecutionContext context, Collection<? super Throwable> taskFailures) {
GradleInternal gradle = context.getGradle();
// 判断是否有指定参数 -m 或者 --dry-run
if (gradle.getStartParameter().isDryRun()) {
for (Task task : gradle.getTaskGraph().getAllTasks()) {
// 如果有指定,则直接拦截task的执行,改为打印 task 的 name 以及执行顺序
textOutputFactory.create(DryRunBuildExecutionAction.class)
.append(((TaskInternal) task).getIdentityPath().getPath())
.append(" ")
.style(StyledTextOutput.Style.ProgressStatus)
.append("SKIPPED")
.println();
}
} else {
// 3. 如果没有配置,则执行下一个 BuildExecutionAction 的 execute()
context.proceed();
}
}
可以看到 DryRunBuildExecutionAction
的作用是拦截 task 的执行过程。
- 首先通过
StartParameter
获取到是否有指定-m
或者--dry-run
参数; - 如果有指定该参数,则拦截 tasks 的执行,改为遍历所有待执行的 tasks,逐个打印其 path;
- 如果没有指定该参数,则执行下一个
BuildExecutionAction
的execute()
。
来看看 ./gradlew clean --dry-run
的效果图。
2.2.2 回调传给 whenReady() 的闭包
接下来会执行到 SelectedTaskExecutionAction
的 execute()
,来看看其源码。
// SelectedTaskExecutionAction.java
public void execute(BuildExecutionContext context, Collection<? super Throwable> taskFailures) {
GradleInternal gradle = context.getGradle();
TaskExecutionGraphInternal taskGraph = gradle.getTaskGraph();
// 是否有指定参数 --continue,如果为true,在失败的时候依旧会继续执行
if (gradle.getStartParameter().isContinueOnFailure()) {
taskGraph.setContinueOnFailure(true);
}
taskGraph.addTaskExecutionGraphListener(new BindAllReferencesOfProjectsToExecuteListener());
// 执行 tasks
taskGraph.execute(taskFailures);
}
这里首先会看是否有指定 --continue
,该参数表示在执行失败的时候是否继续执行 tasks,然后调用 DefaultTaskExecutionGraph
的 execute()
准备 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的有向无环图已经生成
ensurePopulated();
if (!hasFiredWhenReady) {
ProjectStateRegistry projectStateRegistry = gradleInternal.getServices().get(ProjectStateRegistry.class);
// 2. 调用 TaskExecutionGraphListener 的 graphPopulated()
projectStateRegistry.withLenientState(new Runnable() {
@Override
public void run() {
buildOperationExecutor.run(new NotifyTaskGraphWhenReady(DefaultTaskExecutionGraph.this, graphListeners.getSource(), gradleInternal));
}
});
hasFiredWhenReady = true;
}
try {
// 3. 调用 DefaultPlanExecutor的process()
planExecutor.process(executionPlan, failures,
new BuildOperationAwareExecutionAction(
buildOperationExecutor.getCurrentOperation(),
new InvokeNodeExecutorsAction(nodeExecutors, projectExecutionServices)
)
);
}
// ...
}
这里首先调用了 ensurePopulated()
确保 task 的有向无环图已经生成,然后会调用 NotifyTaskGraphWhenReady
的 run()
,来看看其源码。
// NotifyTaskGraphWhenReady(DefaultTaskExecutionGraph的内部类)
public void run(BuildOperationContext context) {
graphListener.graphPopulated(taskExecutionGraph);
}
这里会调用 TaskExecutionGraphListener
的 graphPopulated()
;为什么提这个方法,这就得看看 DefaultTaskExecutionGraph
的 whenReady()
了,这也是编写 gradle 脚本经常使用的一个方法。
// 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()
的动作实际上是被封装成了 TaskExecutionGraphListener
,所以调用 TaskExecutionGraphListener
的 graphPopulated()
即回调了传给 whenReady()
的动作。
接着调用了 planExecutor
的 process()
,注意这里传递的参数 BuildOperationAwareExecutionAction
,后面会使用到。
2.2.3 创建线程和 ExecutorWorker
planExecutor
是通过反射调用的 ExecutionGradleServices
的 createPlanExecutor()
。
// ExecutionGradleServices.java
PlanExecutor createPlanExecutor(
ParallelismConfigurationManager parallelismConfigurationManager,
ExecutorFactory executorFactory,
WorkerLeaseService workerLeaseService,
BuildCancellationToken cancellationToken,
ResourceLockCoordinationService coordinationService) {
// 这个参数gradle并行构建的时候会有用 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
的实例,来看看其 process()
的源码。
// DefaultPlanExecutor.java
public void process(ExecutionPlan executionPlan, Collection<? super Throwable> failures, Action<Node> nodeExecutor) {
// 创建线程池
ManagedExecutor executor = executorFactory.create("Execution worker for '" + executionPlan.getDisplayName() + "'");
try {
WorkerLease parentWorkerLease = workerLeaseService.getCurrentWorkerLease();
// org.gradle.parallel=true 的时候会开启多个 ExecutorWorker 并行构建
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) {
// 创建多个 ExecutorWorker 并行构建
for (int i = 1; i < executorCount; i++) {
executor.execute(new ExecutorWorker(executionPlan, nodeExecutor, parentWorkerLease, cancellationToken, coordinationService));
}
}
这里会创建线程池 ManagedExecutor
和任务 ExecutorWorker
,在开启了 org.gradle.parallel
的情况下,会创建多个线程和任务并行执行。
2.2.4 task 执行前的预处理
接着会调用到 ExecutorWorker
的 run()
,来看看其源码。
// ExecutorWorker(DefaultPlanExecutor.java的内部类)
public void run() {
WorkerLease childLease = parentWorkerLease.createChild();
while (true) {
// 调用 executeNextNode()
boolean nodesRemaining = executeNextNode(childLease, new Action<Node>() {
@Override
public void execute(Node work) {
nodeExecutor.execute(work);
// ...
}
});
if (!nodesRemaining) {
// 没有任务执行了。
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) {
// 是否取消执行
if (cancellationToken.isCancellationRequested()) {
executionPlan.cancelExecution();
}
nodesRemaining.set(executionPlan.hasNodesRemaining());
// 没有任务执行了,则标记为结束
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 {
// 执行 ExecutorWorker里面创建的 Action 匿名内部类实例的 execute()
nodeExecutor.execute(selected);
} catch (Throwable e) {
selected.setExecutionFailure(e);
}
}
}
// ...
}
可以看到最终会调用到 nodeExecutor.execute(work)
,而这里的 nodeExecutor
也就是前面说的传给 process()
的 BuildOperationAwareExecutionAction
的实例,来看看其 execute()
。
public void execute(Node node) {
// ...
delegate.execute(node);
// ...
}
这里实际上是调用了 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);
}
可以看到它只是遍历调用了传递进来的 nodeExecutor
的 execute()
;这里的 nodeExecutors
是通过反射调用了 GradleScopeServices
的 createLocalTaskNodeExecutor()
。
// GradleScopeServices.java
LocalTaskNodeExecutor createLocalTaskNodeExecutor() {
return new LocalTaskNodeExecutor();
}
即 LocalTaskNodeExecutor
的实例,来看看其 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();
// 判断任务是否已经执行过,如果执行过,则直接返回
if (state.getExecuted()) {
return true;
}
TaskExecutionContext ctx = new DefaultTaskExecutionContext(localTaskNode);
// 这里又通过反射找 TaskExecuter
TaskExecuter taskExecuter = services.getProjectService((ProjectInternal) task.getProject(), TaskExecuter.class);
assert taskExecuter != null;
// 这里就是执行 task 的入口
taskExecuter.execute(task, state, ctx);
localTaskNode.getPostAction().execute(task);
return true;
} else {
return false;
}
}
它首先判断 task 是否有执行过,如果有执行过则直接返回;如果没有执行过,则调用 TaskExecuter
的 execute()
执行 task。taskExecuter
是通过反射调用的 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();
// 这个 executer 才是真正执行 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;
}
真正执行 task 的是 ExecuteActionsTaskExecuter
,其他都是对其进行的包装,在执行 task 前做一些预处理操作,从下往上挑关键的说。
2.2.4.1 EventFiringTaskExecuter
首先来看看 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. 调用 TaskExecutionListener 的 beforeExecute()
taskExecutionListener.beforeExecute(task);
// ...
// 2. 执行下一个 execute()
TaskExecuterResult result = delegate.execute(task, state, context);
// ...
// 3. 调用 TaskExecutionListener 的 afterExecute()
taskExecutionListener.afterExecute(task, state);
// ...
}
});
}
可以看到,这里主要是增加事件回调。在 Task
执行前调用 TaskExecutionListener
的 beforeExecute()
,在 Task
执行后调用 TaskExecutionListener
的 afterExecute()
。
2.2.4.2 CatchExceptionTaskExecuter
再来看看 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 执行加上 try{}catch{}
。
2.2.4.3 SkipOnlyIfTaskExecuter
再来看看 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
条件是否满足执行,onlyIf
类似于 java
的 if
语句,只有当判断条件为真的时候才会执行 task。
举个栗子方便理解。在 root project 的 build.gradle
文件里面添加如下代码。
subprojects { Project p ->
Task hello = p.task("hello") {
doLast {
println("execute hello task!")
}
}
}
sync 后运行 ./gradlew hello
,结果如下。
这里分别执行了 app 和 app2 的 hello task,然后修改 build.gradle
增加 onlyIf
判断。
subprojects { Project p ->
Task hello = p.task("hello") {
doLast {
println("execute hello task!")
}
}
// 只有当是 app 的时候才执行
hello.onlyIf { hello.project.name == "app" }
}
sync 后再次运行 ./gradlew hello
,结果如下,可以看到相较于上面少了 :app2:hello
的执行,说明 onlyIf
生效了。
2.2.4.4 SkipTaskWithNoActionsExecuter
来看看 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);
}
这里是跳过那些没有 action 的 task,没有 action 说明 task 不需要执行。
2.2.4.5 ResolveTaskExecutionModeExecuter
来看看 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
;
过程一有点多,先说过程二。这里的 executionModeResolver
是通过反射调用 ProjectExecutionServices
的 createExecutionModeResolver()
。
TaskExecutionModeResolver createExecutionModeResolver(
StartParameter startParameter
) {
return new DefaultTaskExecutionModeResolver(startParameter);
}
来看看 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;
}
这个 TaskExecutionMode
究竟是啥玩意呢?来看看其源码。
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;
}
// 这个方法标记了是否需要记录执行历史
public boolean isTaskHistoryMaintained() {
return taskHistoryMaintained;
}
// 这里方法决定了是否加载缓存来替代执行 task
public boolean isAllowedToUseCachedResults() {
return allowedToUseCachedResults;
}
}
TaskExecutionMode
有两个比较重要的方法 isTaskHistoryMaintained()
和 isAllowedToUseCachedResults()
,它们影响到了 Task
的执行流程。
再看下过程一是如何解析 Task
属性的。先来看看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 {
// 主要是这个方法
TaskPropertyUtils.visitProperties(propertyWalker, task, new CompositePropertyVisitor(
inputPropertiesVisitor,
inputFilesVisitor,
outputFilesVisitor,
validationVisitor,
destroyablesVisitor,
localStateVisitor
));
} catch (Exception e) {
throw new TaskExecutionException(task, e);
}
// 把解析出来的属性存到 DefaultTaskProperties里面
return new DefaultTaskProperties(
task.toString(),
inputPropertiesVisitor.getPropertyValuesSupplier(),
inputFilesVisitor.getFileProperties(),
outputFilesVisitor.getFileProperties(),
outputFilesVisitor.hasDeclaredOutputs(),
localStateVisitor.getFiles(),
destroyablesVisitor.getFiles(),
validationVisitor.getTaskPropertySpecs());
}
主要是调用的 TaskPropertyUtils.visitProperties()
,来看看其源码。
// 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
是通过反射调用的 ExecutionGlobalServices
的 createPropertyWalker()
。
// ExecutionGlobalServices.java
PropertyWalker createPropertyWalker(TaskScheme taskScheme) {
return taskScheme.getInspectionScheme().getPropertyWalker();
}
而 taskScheme
是通过反射调用的 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()
的第一个参数,是很多的注解,解析属性会用到它们,后面再说。先看下 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
的实例,来看看其源码。
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
,来看看其 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()) {
// 找属性对应的 PropertyAnnotationHandler
PropertyAnnotationHandler annotationHandler = typeMetadata.getAnnotationHandlerFor(propertyMetadata);
if (annotationHandler.shouldVisit(visitor)) {
String propertyName = getQualifiedPropertyName(propertyMetadata.getPropertyName());
PropertyValue value = new BeanPropertyValue(getBean(), propertyMetadata.getGetterMethod());
// 这里最终会调用 注解对应的 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));
}
});
}
}
}
还记得前面很多注解的参数吗,其实解析属性就是解析这些注解所修饰的东西。每个注解都会对应一个 PropertyAnnotationHandler
。拿 InputFile
举个栗子,它对应的是 InputFilePropertyAnnotationHandler
,来看看其 visitPropertyValue()
。
// AbstractInputFilePropertyAnnotationHandler.java
public void visitPropertyValue(String propertyName, PropertyValue value, PropertyMetadata propertyMetadata, PropertyVisitor visitor, BeanPropertyContext context) {
// ...
// 调用了 visitor 的 visitInputFileProperty(),visitor 即前面 DefaultTaskProperties.resolve() 里面传入的 GetInputFilesVisitor
visitor.visitInputFileProperty(
propertyName,
propertyMetadata.isAnnotationPresent(Optional.class),
propertyMetadata.isAnnotationPresent(SkipWhenEmpty.class),
propertyMetadata.isAnnotationPresent(Incremental.class),
fileNormalizer,
value,
getFilePropertyType()
);
}
这里调用到了 visitor
的 visitInputFileProperty()
,它是前面 DefaultTaskProperties.resolve()
里面传入的 GetInputFilesVisitor
实例,来看看其 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
再来看看 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,则标记为 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);
}
这里是处理那些有设置 sourc files 但是 source files 为空的 Task
,source files 为空说明 Task
没有需要处理的资源。
2.2.4.7 ValidatingTaskExecuter
再来看看 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);
// 做一些属性的校验操作
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
执行前做一些校验。
2.2.5 执行 Task
最后会执行到 ExecuteActionsTaskExecuter
的 execute()
,这里才是正真执行 Task
的地方,先来看看它的源码。
// ExecuteActionsTaskExecuter.java
public TaskExecuterResult execute(TaskInternal task, TaskStateInternal state, TaskExecutionContext context) {
// 创建一个 TaskExecution 实例
TaskExecution work = new TaskExecution(task, context, executionHistoryStore, fingerprinterRegistry, classLoaderHierarchyHasher);
// 调用 workExecutor 的 execute,最终会调用 getWork().execute(),即 TaskExecution 的 execute()
CachingResult result = workExecutor.execute(new AfterPreviousExecutionContext() {
@Override
public UnitOfWork getWork() {
return work;
}
});
// ...
}
这里的 workExecutor
是通过反射调用的 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 实例,最终会调用到 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
的实例,注意这里传入的 Step
,后面会用到。先来看看 DefaultWorkExecutor
的 execute()
。
// DefaultWorkExecutor.java
public R execute(C context) {
return executeStep.execute(context);
}
这里直接调用了 executeStep
的 execute()
,即上面传入的 Step
的 execute()
,跟随调用链发现它最终会调用到 ExecuteStep
的 execute()
,来看看其源码。
// ExecuteStep.java
public Result execute(C context) {
// 前面你说了 getWork() 即 TaskExecution,这里调用了它的 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);
}
};
}
这里会调用 TaskExecution
的 execute()
,来看看其源码。
// TaskExecution(ExecuteActionsTaskExecuter.java的内部类)
public WorkResult execute(@Nullable InputChangesInternal inputChanges) {
task.getState().setExecuting(true);
try {
// 1. 调用 TaskActionListener 的 beforeActions()
actionListener.beforeActions(task);
// 2. 调用 executeActions()
executeActions(task, inputChanges);
return task.getState().getDidWork() ? WorkResult.DID_WORK : WorkResult.DID_NO_WORK;
} finally {
task.getState().setExecuting(false);
// 3. 调用 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,逐个调用 executeAction()
while (actions.hasNext()) {
InputChangesAwareTaskAction action = actions.next();
task.getState().setDidWork(true);
task.getStandardOutputCapture().start();
boolean hasMoreWork = hasTaskListener || actions.hasNext();
// 调用 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) {
// ...
// 调用action 的execute()
action.execute(task);
// ...
}
});
}
这里的逻辑十分的清晰:
- 首先调用
TaskActionListener
的beforeActions()
; - 然后遍历
Task
所有的Action
,逐个调用其execute()
(执行Task
实际上就是执行Task
里面所有的Action
); - 执行完
Task
后会调用TaskActionListener
的afterActions()
。
执行完 Task
后就会回到 DefaultGradleLauncher
的 runWork()
。
private void runWork() {
// ...
// 如果有失败的,则抛出异常
if (!taskFailures.isEmpty()) {
throw new MultipleBuildFailures(taskFailures);
}
// 执行成功则将状态标记为 RunTasks
stage = Stage.RunTasks;
}
这里最后会将状态标记为 RunTasks
,至此 Gradle 构建流程的 RunTasks
就分析完了。