溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

17. Gradle編譯其他應(yīng)用代碼流程(五) - 設(shè)置Task過程

發(fā)布時(shí)間:2020-06-24 10:59:47 來源:網(wǎng)絡(luò) 閱讀:1011 作者:rongwei84n 欄目:開發(fā)技術(shù)

接上一篇 15. Gradle編譯其他應(yīng)用代碼流程(四) - Configure過程 繼續(xù)分析


一. task選擇

到了這個(gè)階段,gradle開始計(jì)算task入口是哪個(gè)? 選擇的邏輯是這樣:

  1. 如果用戶收入了task,比如這樣的指令'gradle pmd',那么就執(zhí)行pmd這個(gè)task

  2. 如果用戶沒有輸入task,比如直接輸入'gradle',那么看有沒有默認(rèn)的task

  3. 如果沒有默認(rèn)的task,那就執(zhí)行help這個(gè)task。大家可以試下直接輸入gradle,看看輸出什么內(nèi)容。


接下來看源代碼。

文件路徑: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);
            }

        });
    }
}


這個(gè)地方的寫法挺奇怪的,它的想法是遍歷processingConfigurationActions里面的每個(gè)action,然后執(zhí)行它的configure方法,所以它用了遞歸。

但是個(gè)人覺得直接用循環(huán)不是更簡(jiǎn)單直接嗎?


先不去管這些,processingConfigurationActions里面有3個(gè)成員,他們繼承自同一接口BuildConfigurationAction。

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


他們3個(gè)分別處理的事情不一樣。

a. ExcludedTaskFilteringBuildConfigurationAction用來處理不執(zhí)行的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用來處理默認(rèn)的task,如果用戶有輸入task,那么就使用用戶輸入的。比如用戶輸入'gradle pmd',那么使用的task就是pmd

如果用戶沒有輸入task,那么就使用默認(rèn)的task

如果默認(rèn)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,嘗試使用默認(rèn)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(如果沒有輸入,則使用默認(rèn)task或者 help)添加到executer里面,為真正執(zhí)行做準(zhǔn)備。

代碼路徑:

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


到此為止,所有的準(zhǔn)備工作都已經(jīng)做好了,接下就要真正的執(zhí)行這個(gè)task了。

  1. 配置文件加載

  2. gradle文件加載以及相應(yīng)的plugin 類加載

  3. 要執(zhí)行的task選擇


下一篇帖子講task的執(zhí)行。



向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI