一. task選擇
到了這個階段,gradle開始計算task入口是哪個? 選擇的邏輯是這樣:
如果使用者收入了task,比如這樣的指令'gradle pmd',那麼就執行pmd這個task
如果使用者沒有輸入task,比如直接輸入'gradle',那麼看有沒有預設的task
如果沒有預設的task,那就執行help這個task。大家可以試下直接輸入gradle,看看輸出什麼内容。
接下來看源代碼。
檔案路徑:subprojects\core\src\main\java\org\gradle\initialization\DefaultGradleLauncher.java
<code>private</code> <code>void</code> <code>doBuildStages(Stage upTo) {</code>
<code> </code><code>...</code>
<code> </code><code>// After this point, the GradleLauncher cannot be reused</code>
<code> </code><code>stage = Stage.Build;</code>
<code> </code><code>// Populate task graph</code>
<code> </code><code>buildOperationExecutor.run(</code><code>"Calculate task graph"</code><code>, </code><code>new</code> <code>Runnable() {</code>
<code> </code><code>@Override</code>
<code> </code><code>public</code> <code>void</code> <code>run() {</code>
<code> </code><code>buildConfigurationActionExecuter.select(gradle);</code>
<code> </code><code>if</code> <code>(gradle.getStartParameter().isConfigureOnDemand()) {</code>
<code> </code><code>buildListener.projectsEvaluated(gradle);</code>
<code> </code><code>}</code>
<code> </code><code>}</code>
<code> </code><code>});</code>
<code> </code><code>}</code>
檔案路徑:
subprojects\core\src\main\java\org\gradle\execution\DefaultBuildConfigurationActionExecuter.java
<code>public</code> <code>class</code> <code>DefaultBuildConfigurationActionExecuter </code><code>implements</code> <code>BuildConfigurationActionExecuter {</code>
<code> </code><code>...</code>
<code> </code><code>public</code> <code>void</code> <code>select(GradleInternal gradle) {</code>
<code> </code><code>List<BuildConfigurationAction> processingBuildActions = CollectionUtils.flattenCollections(BuildConfigurationAction.</code><code>class</code><code>, configurationActions, taskSelectors);</code>
<code> </code><code>configure(processingBuildActions, gradle, </code><code>0</code><code>);</code>
<code> </code><code>private</code> <code>void</code> <code>configure(</code><code>final</code> <code>List<BuildConfigurationAction> processingConfigurationActions, </code><code>final</code> <code>GradleInternal gradle, </code><code>final</code> <code>int</code> <code>index) {</code>
<code> </code><code>if</code> <code>(index >= processingConfigurationActions.size()) {</code>
<code> </code><code>return</code><code>;</code>
<code> </code><code>}</code>
<code> </code><code>BuildConfigurationAction action = processingConfigurationActions.get(index);</code>
<code> </code><code>System.out.println(</code><code>"DefaultBuildConfigurationActionExecuter action: "</code> <code>+ action + </code><code>" index: "</code> <code>+ index);</code>
<code> </code><code>/*processingConfigurationActions.get(index)*/</code><code>action.configure(</code><code>new</code> <code>BuildExecutionContext() {</code>
<code> </code><code>public</code> <code>GradleInternal getGradle() {</code>
<code> </code><code>return</code> <code>gradle;</code>
<code> </code><code>public</code> <code>void</code> <code>proceed() {</code>
<code> </code><code>configure(processingConfigurationActions, gradle, index + </code><code>1</code><code>);</code>
<code>}</code>
這個地方的寫法挺奇怪的,它的想法是周遊processingConfigurationActions裡面的每個action,然後執行它的configure方法,是以它用了遞歸。
但是個人覺得直接用循環不是更簡單直接嗎?
先不去管這些,processingConfigurationActions裡面有3個成員,他們繼承自同一接口BuildConfigurationAction。
<code>org.gradle.execution.ExcludedTaskFilteringBuildConfigurationAction</code><code>@3ee68eb2</code> <code>index: </code><code>0</code>
<code>org.gradle.execution.DefaultTasksBuildExecutionAction</code><code>@49cd08f9</code> <code>index: </code><code>1</code>
<code>org.gradle.execution.TaskNameResolvingBuildConfigurationAction</code><code>@4eace42b</code> <code>index: </code><code>2</code>
他們3個分别處理的事情不一樣。
a. ExcludedTaskFilteringBuildConfigurationAction用來處理不執行的task,如果使用者有配置的話。
代碼如下:
subprojects\core\src\main\java\org\gradle\execution\ExcludedTaskFilteringBuildConfigurationAction.java
<code>/**</code>
<code> </code><code>* A {@link BuildConfigurationAction} which filters excluded tasks.</code>
<code> </code><code>*/</code>
<code>public</code> <code>class</code> <code>ExcludedTaskFilteringBuildConfigurationAction </code><code>implements</code> <code>BuildConfigurationAction {</code>
<code> </code><code>public</code> <code>void</code> <code>configure(BuildExecutionContext context) {</code>
<code> </code><code>GradleInternal gradle = context.getGradle();</code>
<code> </code><code>Set<String> excludedTaskNames = gradle.getStartParameter().getExcludedTaskNames();</code>
<code> </code><code>if</code> <code>(!excludedTaskNames.isEmpty()) {</code>
<code> </code><code>final</code> <code>Set<Spec<Task>> filters = </code><code>new</code> <code>HashSet<Spec<Task>>();</code>
<code> </code><code>for</code> <code>(String taskName : excludedTaskNames) {</code>
<code> </code><code>filters.add(taskSelector.getFilter(taskName));</code>
<code> </code><code>gradle.getTaskGraph().useFilter(Specs.intersect(filters));</code>
<code> </code><code>context.proceed();</code>
b. DefaultTasksBuildExecutionAction用來處理預設的task,如果使用者有輸入task,那麼就使用使用者輸入的。比如使用者輸入'gradle pmd',那麼使用的task就是pmd
如果使用者沒有輸入task,那麼就使用預設的task
如果預設task也沒有,則使用help task,比如使用者直接輸入'gradle'
subprojects\core\src\main\java\org\gradle\execution\DefaultTasksBuildExecutionAction.java
<code>public</code> <code>class</code> <code>DefaultTasksBuildExecutionAction </code><code>implements</code> <code>BuildConfigurationAction {</code>
<code> </code><code>StartParameter startParameter = context.getGradle().getStartParameter();</code>
<code> </code><code>System.out.println(</code><code>"DefaultTasksBuildExecutionAction configure. startParameter: "</code> <code>+ startParameter);</code>
<code> </code><code>//判斷是否有輸入task?</code>
<code> </code><code>for</code> <code>(TaskExecutionRequest request : startParameter.getTaskRequests()) {</code>
<code> </code><code>if</code> <code>(!request.getArgs().isEmpty()) {</code>
<code> </code><code>context.proceed();</code>
<code> </code><code>return</code><code>;</code>
<code> </code><code>//沒有輸入task,嘗試使用預設task和help task</code>
<code> </code><code>// Gather the default tasks from this first group project</code>
<code> </code><code>ProjectInternal project = context.getGradle().getDefaultProject();</code>
<code> </code><code>//so that we don't miss out default tasks</code>
<code> </code><code>projectConfigurer.configure(project);</code>
<code> </code><code>List<String> defaultTasks = project.getDefaultTasks();</code>
<code> </code><code>if</code> <code>(defaultTasks.size() == </code><code>0</code><code>) {</code>
<code> </code><code>defaultTasks = Collections.singletonList(ProjectInternal.HELP_TASK);</code>
<code> </code><code>LOGGER.info(</code><code>"No tasks specified. Using default task {}"</code><code>, GUtil.toString(defaultTasks));</code>
<code> </code><code>System.out.println(</code><code>"No tasks specified. Using default task {}"</code> <code>+ </code><code>"-"</code> <code>+ GUtil.toString(defaultTasks));</code>
<code> </code><code>} </code><code>else</code> <code>{</code>
<code> </code><code>LOGGER.info(</code><code>"No tasks specified. Using project default tasks {}"</code><code>, GUtil.toString(defaultTasks));</code>
<code> </code><code>System.out.println(</code><code>"No tasks specified. Using project default tasks {}"</code> <code>+ </code><code>" - "</code> <code>+ GUtil.toString(defaultTasks));</code>
<code> </code><code>startParameter.setTaskNames(defaultTasks);</code>
c. TaskNameResolvingBuildConfigurationAction
把輸入的task(如果沒有輸入,則使用預設task或者 help)添加到executer裡面,為真正執行做準備。
代碼路徑:
subprojects\core\src\main\java\org\gradle\execution\TaskNameResolvingBuildConfigurationAction.java
<code> </code><code>* A {@link BuildConfigurationAction} which selects tasks which match the provided names. For each name, selects all tasks in all</code>
<code> </code><code>* projects whose name is the given name.</code>
<code>public</code> <code>class</code> <code>TaskNameResolvingBuildConfigurationAction </code><code>implements</code> <code>BuildConfigurationAction {</code>
<code> </code><code>System.out.println(</code><code>"TaskNameResolvingBuildConfigurationAction configure 1"</code><code>);</code>
<code> </code><code>TaskGraphExecuter executer = gradle.getTaskGraph();</code>
<code> </code><code>List<TaskExecutionRequest> taskParameters = gradle.getStartParameter().getTaskRequests();</code>
<code> </code><code>for</code> <code>(TaskExecutionRequest taskParameter : taskParameters) {</code>
<code> </code><code>System.out.println(</code><code>"TaskNameResolvingBuildConfigurationAction configure 2"</code><code>);</code>
<code> </code><code>List<TaskSelector.TaskSelection> taskSelections = commandLineTaskParser.parseTasks(taskParameter);</code>
<code> </code><code>for</code> <code>(TaskSelector.TaskSelection taskSelection : taskSelections) {</code>
<code> </code><code>LOGGER.info(</code><code>"Selected primary task '{}' from project {}"</code><code>, taskSelection.getTaskName(), taskSelection.getProjectPath());</code>
<code> </code><code>System.out.println(</code><code>"Selected primary task '{}' from project {}"</code> <code>+ taskSelection.getTaskName() + </code><code>"-"</code><code>+ taskSelection.getProjectPath());</code>
<code> </code><code>executer.addTasks(taskSelection.getTasks());</code>
二. 通知projectsEvaluated
<code>if</code> <code>(gradle.getStartParameter().isConfigureOnDemand()) {</code>
<code> </code><code>buildListener.projectsEvaluated(gradle);</code>
到此為止,所有的準備工作都已經做好了,接下就要真正的執行這個task了。
配置檔案加載
gradle檔案加載以及相應的plugin 類加載
要執行的task選擇
下一篇文章講task的執行。
本文轉自rongwei84n 51CTO部落格,原文連結:http://blog.51cto.com/483181/1930223,如需轉載請自行聯系原作者