首页 > 代码库 > 17. Gradle编译其他应用代码流程(五) - 设置Task过程

17. Gradle编译其他应用代码流程(五) - 设置Task过程

接上一篇 15. Gradle编译其他应用代码流程(四) - Configure过程 继续分析


一. task选择

到了这个阶段,gradle开始计算task入口是哪个? 选择的逻辑是这样:

  1. 如果用户收入了task,比如这样的指令‘gradle pmd‘,那么就执行pmd这个task

  2. 如果用户没有输入task,比如直接输入‘gradle‘,那么看有没有默认的task

  3. 如果没有默认的task,那就执行help这个task。大家可以试下直接输入gradle,看看输出什么内容。


接下来看源代码。

文件路径:subprojects\core\src\main\java\org\gradle\initialization\DefaultGradleLauncher.java

private void doBuildStages(Stage upTo) {
        ...

        // After this point, the GradleLauncher cannot be reused
        stage = Stage.Build;

        // Populate task graph
        buildOperationExecutor.run("Calculate task graph", new Runnable() {
            @Override
            public void run() {
                buildConfigurationActionExecuter.select(gradle);
                if (gradle.getStartParameter().isConfigureOnDemand()) {
                    buildListener.projectsEvaluated(gradle);
                }
            }
        });

        ...
    }


文件路径:

subprojects\core\src\main\java\org\gradle\execution\DefaultBuildConfigurationActionExecuter.java

public class DefaultBuildConfigurationActionExecuter implements BuildConfigurationActionExecuter {
    ...
    public void select(GradleInternal gradle) {
        List<BuildConfigurationAction> processingBuildActions = CollectionUtils.flattenCollections(BuildConfigurationAction.class, configurationActions, taskSelectors);
        configure(processingBuildActions, gradle, 0);
    }

    ...

    private void configure(final List<BuildConfigurationAction> processingConfigurationActions, final GradleInternal gradle, final int index) {
        if (index >= processingConfigurationActions.size()) {
            return;
        }
        BuildConfigurationAction action  = processingConfigurationActions.get(index);
        System.out.println("DefaultBuildConfigurationActionExecuter action: " + action + " index: " + index);
        /*processingConfigurationActions.get(index)*/action.configure(new BuildExecutionContext() {
            public GradleInternal getGradle() {
                return gradle;
            }

            public void proceed() {
                configure(processingConfigurationActions, gradle, index + 1);
            }

        });
    }
}


这个地方的写法挺奇怪的,它的想法是遍历processingConfigurationActions里面的每个action,然后执行它的configure方法,所以它用了递归。

但是个人觉得直接用循环不是更简单直接吗?


先不去管这些,processingConfigurationActions里面有3个成员,他们继承自同一接口BuildConfigurationAction。

org.gradle.execution.ExcludedTaskFilteringBuildConfigurationAction@3ee68eb2 index: 0
org.gradle.execution.DefaultTasksBuildExecutionAction@49cd08f9 index: 1
org.gradle.execution.TaskNameResolvingBuildConfigurationAction@4eace42b index: 2


他们3个分别处理的事情不一样。

a. ExcludedTaskFilteringBuildConfigurationAction用来处理不执行的task,如果用户有配置的话。

代码如下:

文件路径:

subprojects\core\src\main\java\org\gradle\execution\ExcludedTaskFilteringBuildConfigurationAction.java

/**
 * A {@link BuildConfigurationAction} which filters excluded tasks.
 */
public class ExcludedTaskFilteringBuildConfigurationAction implements BuildConfigurationAction {
    ...

    public void configure(BuildExecutionContext context) {
        GradleInternal gradle = context.getGradle();
        Set<String> excludedTaskNames = gradle.getStartParameter().getExcludedTaskNames();
        if (!excludedTaskNames.isEmpty()) {
            final Set<Spec<Task>> filters = new HashSet<Spec<Task>>();
            for (String taskName : excludedTaskNames) {
                filters.add(taskSelector.getFilter(taskName));
            }
            gradle.getTaskGraph().useFilter(Specs.intersect(filters));
        }

        context.proceed();
    }
}


b. DefaultTasksBuildExecutionAction用来处理默认的task,如果用户有输入task,那么就使用用户输入的。比如用户输入‘gradle pmd‘,那么使用的task就是pmd

如果用户没有输入task,那么就使用默认的task

如果默认task也没有,则使用help task,比如用户直接输入‘gradle‘

文件路径:

subprojects\core\src\main\java\org\gradle\execution\DefaultTasksBuildExecutionAction.java

public class DefaultTasksBuildExecutionAction implements BuildConfigurationAction {
    ...

    public void configure(BuildExecutionContext context) {
        StartParameter startParameter = context.getGradle().getStartParameter();
        System.out.println("DefaultTasksBuildExecutionAction configure. startParameter: " + startParameter);

        //判断是否有输入task?
        for (TaskExecutionRequest request : startParameter.getTaskRequests()) {
            if (!request.getArgs().isEmpty()) {
                context.proceed();
                return;
            }
        }

        //没有输入task,尝试使用默认task和help task
        // Gather the default tasks from this first group project
        ProjectInternal project = context.getGradle().getDefaultProject();

        //so that we don‘t miss out default tasks
        projectConfigurer.configure(project);

        List<String> defaultTasks = project.getDefaultTasks();
        if (defaultTasks.size() == 0) {
            defaultTasks = Collections.singletonList(ProjectInternal.HELP_TASK);
            LOGGER.info("No tasks specified. Using default task {}", GUtil.toString(defaultTasks));
            System.out.println("No tasks specified. Using default task {}" + "-" + GUtil.toString(defaultTasks));
        } else {
            LOGGER.info("No tasks specified. Using project default tasks {}", GUtil.toString(defaultTasks));
            System.out.println("No tasks specified. Using project default tasks {}" + " - " + GUtil.toString(defaultTasks));
        }

        startParameter.setTaskNames(defaultTasks);
        context.proceed();
    }
}


c. TaskNameResolvingBuildConfigurationAction

把输入的task(如果没有输入,则使用默认task或者 help)添加到executer里面,为真正执行做准备。

代码路径:

subprojects\core\src\main\java\org\gradle\execution\TaskNameResolvingBuildConfigurationAction.java

/**
 * A {@link BuildConfigurationAction} which selects tasks which match the provided names. For each name, selects all tasks in all
 * projects whose name is the given name.
 */
public class TaskNameResolvingBuildConfigurationAction implements BuildConfigurationAction {
    ...

    public void configure(BuildExecutionContext context) {
    	System.out.println("TaskNameResolvingBuildConfigurationAction configure 1");
        GradleInternal gradle = context.getGradle();
        TaskGraphExecuter executer = gradle.getTaskGraph();

        List<TaskExecutionRequest> taskParameters = gradle.getStartParameter().getTaskRequests();
        for (TaskExecutionRequest taskParameter : taskParameters) {
        	System.out.println("TaskNameResolvingBuildConfigurationAction configure 2");
            List<TaskSelector.TaskSelection> taskSelections = commandLineTaskParser.parseTasks(taskParameter);
            for (TaskSelector.TaskSelection taskSelection : taskSelections) {
                LOGGER.info("Selected primary task ‘{}‘ from project {}", taskSelection.getTaskName(), taskSelection.getProjectPath());
                System.out.println("Selected primary task ‘{}‘ from project {}" + taskSelection.getTaskName() + "-"+ taskSelection.getProjectPath());
                executer.addTasks(taskSelection.getTasks());
            }
        }

        context.proceed();
    }

}



二. 通知projectsEvaluated

if (gradle.getStartParameter().isConfigureOnDemand()) {
    buildListener.projectsEvaluated(gradle);
}


到此为止,所有的准备工作都已经做好了,接下就要真正的执行这个task了。

  1. 配置文件加载

  2. gradle文件加载以及相应的plugin 类加载

  3. 要执行的task选择


下一篇帖子讲task的执行。



本文出自 “www.bogo.com” 博客,请务必保留此出处http://483181.blog.51cto.com/473181/1930223

17. Gradle编译其他应用代码流程(五) - 设置Task过程