接上一篇 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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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。

1
2
3
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
 * 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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
 * 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

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

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

  1. 配置文件加载

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

  3. 要执行的task选择

下一篇帖子讲task的执行。

本文转自rongwei84n 51CTO博客,原文链接:http://blog.51cto.com/483181/1930223,如需转载请自行联系原作者

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

  1. android uefi 编译报错,【Android SDM660开机流程】- UEFI XBL 代码流程分析

    [Android SDM660开机流程]- UEFI XBL 代码流程分析 一.UEFI XBL 1.1 boot_images代码目录 1.2 UEFI代码运行流程 1.3 SEC (安全验证) 1 ...

  2. 全志 android 编译,全志A20启动代码流程分析 ——Android

    现在的CPU都固化了内部 ROM,内部 ROM中有一般都有一段程序,一般有如下几个功能: 1,初始化,部分外设,如USB,SDCARD 2,初始化DDR(内存)和NandFlash 3,加载boot( ...

  3. 全志android 编译,全志A20启动代码流程分析 ——Android

    现在的CPU都固化了内部 ROM,内部 ROM中有一般都有一段程序,一般有如下几个功能: 1,初始化,部分外设,如USB,SDCARD 2,初始化DDR(内存)和NandFlash 3,加载boot( ...

  4. Camera camx代码结构、编译、代码流程简介

    文章目录 一.camx 代码结构 二.camx 编译 三.camx 代码流程分析 转载链接: https://juejin.cn/post/6870358276425875463 https://ww ...

  5. java离线编译_离线代码编译器用吐了,那这五款在线编译器你可以来试试了。...

    在云计算时代,使用旧的离线编译器和IDE并不是那么无聊.当然离线是很棒的,但是我们必须在每种系统上手动安装不同的编译器,这需要很大的空间,而且要将代码移植到多个系统上也不容易.但是使用在线编译器或ID ...

  6. 【错误记录】Android Studio 中编写 Gradle 编译脚本时没有 Groovy 代码提示 ( Cannot find declaration to go to )

    文章目录 一.报错信息 二.解决方案 一.报错信息 在 Android Studio 工程中 , 编辑 build.gradle 脚本时 , 无法进行代码提示 ; 按住 Ctrl 键 , 点击相应的属 ...

  7. 3-uboot-spl代码流程

    [uboot] (第三章)uboot流程--uboot-spl代码流程 2016年10月28日 16:24:14 阅读数:2077 以下例子都以project X项目tiny210(s5pv210平台 ...

  8. gradle编译打包过程 之 ProcessAndroidResources的源码分析

    首先,如何查看gradle源码,我们在项目里依赖com.android.tools.build:gradle即可,如下: compile gradleApi() compile 'com.androi ...

  9. apt 根据注解,编译时生成代码

    apt: @Retention后面的值,设置的为CLASS,说明就是编译时动态处理的.一般这类注解会在编译的时候,根据注解标识,动态生成一些类或者生成一些xml都可以,在运行时期,这类注解是没有的~~ ...

最新文章

  1. 神舟台式计算机图片,扩展性媲美台式机!神舟战神K780G拆机图赏
  2. 用类模拟C风格的赋值+返回值
  3. 软件项目经理需具备什么样的技术水平?
  4. java中读取某路径下的文本内容
  5. jquery知识巩固
  6. java etcd api_在java中如何使用etcd的v2 和v3 api获取配置,并且对配置的变化进行监控和监听...
  7. Postgresql添加/删除触发器示例
  8. CentOS7安装Gnome GUI图形界面
  9. C#关于委托(基础)
  10. python交互式程序设计导论小测验答案_最新网课答案2021学堂在线Python 交互式程序设计导论...
  11. 考研数学(二)知识点回顾及笔记(第五章 定积分及应用)
  12. 精益生产管理专家——安岷老师
  13. 360网上商城:链接生态与终端
  14. 爬虫-爬取中国诗歌网中中国好诗栏目 - 统计词汇出现频数 - 副本
  15. Export encrypted key
  16. 女孩子适合软件测试这个行业吗?【工作内容、薪资、加班、怎么转行、职业规划】全面解析女生适不适合软件测试。
  17. 社区说 | Flutter 工程那些事儿
  18. C语言_回文字符串的判断
  19. 美橙互联短信服务——发送注册短信并验证
  20. 济南近郊出游——线路指南

热门文章

  1. spirng底层实现原理
  2. 'int' object has no attribute 'backward'报错 使用Pytorch编写 Hinge loss函数
  3. mysql datasource.url_SpringBoot配置数据源DataSource
  4. 单击选定单元格后输入新内容_2015年计算机一级msoffice考前简答题练习
  5. IntObjectHashMap和HashMap的区别?
  6. [Ext JS 4] 实战之Chart, Column Chart 定制颜色
  7. Teamcenter - Index search 找不到相关物件的解决方法
  8. android动态调试防止,Android应用防止so注入防止动态调试参考代码
  9. MATLAB图像处理之图像边缘提取
  10. huffman算法c语言程序,哈夫曼算法构造代码