天天看點

17. Gradle編譯其他應用代碼流程(五) - 設定Task過程

一. 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&lt;BuildConfigurationAction&gt; 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&lt;BuildConfigurationAction&gt; 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 &gt;= 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&lt;String&gt; excludedTaskNames = gradle.getStartParameter().getExcludedTaskNames();</code>

<code>        </code><code>if</code> <code>(!excludedTaskNames.isEmpty()) {</code>

<code>            </code><code>final</code> <code>Set&lt;Spec&lt;Task&gt;&gt; filters = </code><code>new</code> <code>HashSet&lt;Spec&lt;Task&gt;&gt;();</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&lt;String&gt; 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&lt;TaskExecutionRequest&gt; 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&lt;TaskSelector.TaskSelection&gt; 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,如需轉載請自行聯系原作者