android技术

Gradle 源码分析(五)

2020-12-15  本文已影响0人  你怕是很皮哦

1. 写在前面

Gradle源码分析(四)一文中,我们分析了Gradle构建流程的 TaskGraph 阶段,这里将分析 RunTasks 阶段(gradle 源码版本为 5.6.4)。

2. RunTasks

2.1 整体实现

这里我整理了 RunTasks 阶段的一些主要操作,并绘制了调用链的时序图。如果对源码不感兴趣的同学只需要看这一部分的内容即可。

2.1.1 时序图

RunTasks时序图.png

2.1.2 主要操作

RunTasks 阶段 Gradle 主要做了下面这些事情。

  1. 处理 --dry-run;
  2. 回调传给 whenReady() 的闭包;
  3. 创建线程和 ExecutorWorker
  4. 执行 task 前的预处理;
  5. 调用 TaskActionListenerbeforeAction(),遍历 TaskAction ,并调用其 execute(),调用 TaskActionListenerafterAction()

2.2 源码分析

2.2.1 处理 --dry-run

RunTasks 的过程发生在 DefaultGradleLauncherrunWork() 中,先来看看其源码。

// DefaultGradleLauncher.java
private void runWork() {
    // ...
    List<Throwable> taskFailures = new ArrayList<Throwable>();
    buildExecuter.execute(gradle, taskFailures);
    // ...
}

这里调用了 buildExecuterexecute(),而 buildExecuter 是通过反射调用GradleScopeServicescreateBuildExecuter() 生成的。

// 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,暂时先记住它们:

上面的代码最终会调用到 DefaultBuildWorkExecutorexecute(),来看看其源码。

// 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 构造器的 BuildConfigurationActionexecute(),也就是前面提到的 DryRunBuildExecutionActionSelectedTaskExecutionAction。来看看 DryRunBuildExecutionActionexecute() 做了什么。

// 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 的执行过程。

  1. 首先通过 StartParameter 获取到是否有指定 -m 或者 --dry-run 参数;
  2. 如果有指定该参数,则拦截 tasks 的执行,改为遍历所有待执行的 tasks,逐个打印其 path;
  3. 如果没有指定该参数,则执行下一个 BuildExecutionActionexecute()

来看看 ./gradlew clean --dry-run 的效果图。

--dry-run效果图.png

2.2.2 回调传给 whenReady() 的闭包

接下来会执行到 SelectedTaskExecutionActionexecute(),来看看其源码。

// 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,然后调用 DefaultTaskExecutionGraphexecute() 准备 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 的有向无环图已经生成,然后会调用 NotifyTaskGraphWhenReadyrun(),来看看其源码。

// NotifyTaskGraphWhenReady(DefaultTaskExecutionGraph的内部类)
public void run(BuildOperationContext context) {
    graphListener.graphPopulated(taskExecutionGraph);
}

这里会调用 TaskExecutionGraphListenergraphPopulated();为什么提这个方法,这就得看看 DefaultTaskExecutionGraphwhenReady() 了,这也是编写 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,所以调用 TaskExecutionGraphListenergraphPopulated() 即回调了传给 whenReady() 的动作。

接着调用了 planExecutorprocess(),注意这里传递的参数 BuildOperationAwareExecutionAction,后面会使用到。

2.2.3 创建线程和 ExecutorWorker

planExecutor 是通过反射调用的 ExecutionGradleServicescreatePlanExecutor()

// 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 执行前的预处理

接着会调用到 ExecutorWorkerrun(),来看看其源码。

// 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);
    // ...
}

这里实际上是调用了 InvokeNodeExecutorsActionexecute()

public void execute(Node node) {
    for (NodeExecutor nodeExecutor : nodeExecutors) {
        if (nodeExecutor.execute(node, projectExecutionServices)) {
            return;
        }
    }
    throw new IllegalStateException("Unknown type of node: " + node);
}

可以看到它只是遍历调用了传递进来的 nodeExecutorexecute();这里的 nodeExecutors 是通过反射调用了 GradleScopeServicescreateLocalTaskNodeExecutor()

// 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 是否有执行过,如果有执行过则直接返回;如果没有执行过,则调用 TaskExecuterexecute() 执行 task。taskExecuter 是通过反射调用的 ProjectExecutionServicescreateTaskExecuter()

// 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

首先来看看 EventFiringTaskExecuterexecute()

// 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 执行前调用 TaskExecutionListenerbeforeExecute(),在 Task 执行后调用 TaskExecutionListenerafterExecute()

2.2.4.2 CatchExceptionTaskExecuter

再来看看 CatchExceptionTaskExecuterexecute()

// 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

再来看看 SkipOnlyIfTaskExecuterexecute()

// 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 类似于 javaif 语句,只有当判断条件为真的时候才会执行 task。

举个栗子方便理解。在 root project 的 build.gradle 文件里面添加如下代码。

subprojects { Project p ->
    Task hello = p.task("hello") {
        doLast {
            println("execute hello task!")
        }
    }
}

sync 后运行 ./gradlew hello ,结果如下。

没有onlyIf.png

这里分别执行了 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 生效了。

有onlyIf.png

2.2.4.4 SkipTaskWithNoActionsExecuter

来看看 SkipTaskWithNoActionsExecuterexecute()

// 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

来看看 ResolveTaskExecutionModeExecuterexecute()

// 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);
    // ...
}

这里主要做了两件事情:

  1. 解析 Task 的属性,比如输入、输出等;
  2. 获取 TaskExecution Mode

过程一有点多,先说过程二。这里的 executionModeResolver 是通过反射调用 ProjectExecutionServicescreateExecutionModeResolver()

TaskExecutionModeResolver createExecutionModeResolver(
    StartParameter startParameter
) {
    return new DefaultTaskExecutionModeResolver(startParameter);
}

来看看 DefaultTaskExecutionModeResolvergetExecutionMode()

// 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 属性的。先来看看DefaultTaskPropertiesresolve()

// 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 是通过反射调用的 ExecutionGlobalServicescreatePropertyWalker()

// ExecutionGlobalServices.java
PropertyWalker createPropertyWalker(TaskScheme taskScheme) {
    return taskScheme.getInspectionScheme().getPropertyWalker();
}

taskScheme 是通过反射调用的 ExecutionGlobalServicescreateTaskScheme()

// 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.InspectionSchemeImplgetPropertyWalker()

// 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()));
}

这里的 nodeRootRuntimeBeanNode,来看看其 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()
    );
}

这里调用到了 visitorvisitInputFileProperty(),它是前面 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

再来看看 SkipEmptySourceFilesTaskExecuterexecute()

// 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

再来看看 ValidatingTaskExecuterexecute()

// 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

最后会执行到 ExecuteActionsTaskExecuterexecute(),这里才是正真执行 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 是通过反射调用的 ExecutionGradleServicescreateWorkExecutor()

// 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,后面会用到。先来看看 DefaultWorkExecutorexecute()

// DefaultWorkExecutor.java
public R execute(C context) {
    return executeStep.execute(context);
}

这里直接调用了 executeStepexecute(),即上面传入的 Stepexecute(),跟随调用链发现它最终会调用到 ExecuteStepexecute(),来看看其源码。

// 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);
        }
    };
}

这里会调用 TaskExecutionexecute(),来看看其源码。

// 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);
            // ...
        }
    });
}

这里的逻辑十分的清晰:

  1. 首先调用 TaskActionListenerbeforeActions()
  2. 然后遍历 Task 所有的 Action ,逐个调用其 execute()(执行 Task实际上就是执行 Task 里面所有的 Action);
  3. 执行完 Task 后会调用 TaskActionListenerafterActions()

执行完 Task 后就会回到 DefaultGradleLauncherrunWork()

private void runWork() {
    // ...
    // 如果有失败的,则抛出异常
    if (!taskFailures.isEmpty()) {
        throw new MultipleBuildFailures(taskFailures);
    }
    // 执行成功则将状态标记为 RunTasks
    stage = Stage.RunTasks;
}

这里最后会将状态标记为 RunTasks,至此 Gradle 构建流程的 RunTasks 就分析完了。

上一篇 下一篇

猜你喜欢

热点阅读