全面理解Gradle - 执行时序
vide1025
7年前
<h3>什么是Gradle?</h3> <p>一个像 Ant 一样的非常灵活的通用构建工具</p> <p>一种可切换的, 像 maven 一样的基于合约构建的框架</p> <p>支持强大的多工程构建</p> <p>支持强大的依赖管理(基于 ApacheIvy )</p> <p>支持已有的 maven 和 ivy 仓库</p> <p>支持传递性依赖管理, 而不需要远程仓库或者 pom.xml 或者 ivy 配置文件</p> <p>优先支持 Ant 式的任务和构建</p> <p>基于 groovy 的构建脚本</p> <p>有丰富的领域模型来描述你的构建</p> <h3>如何学习Gradle?</h3> <ul> <li>学习 Groovy( <a href="/misc/goto?guid=4959755818033572024" rel="nofollow,noindex">http://docs.groovy-lang.org/</a> )</li> <li>学习 Gradle DSL( <a href="/misc/goto?guid=4959714813931452605" rel="nofollow,noindex">https://docs.gradle.org/current/javadoc/org/gradle/api/Project.html</a> )</li> <li>学习 Android DSL和Task( <a href="/misc/goto?guid=4959650644642179328" rel="nofollow,noindex">http://google.github.io/android-gradle-dsl/current/index.html</a> )</li> </ul> <h3>使用Gradle wrapper</h3> <p>如果你本地安装了Gradle,那么你就可以使用gradle命令来直接构建。如果本地没有安装,那么可以通过gradle wrapper来构建,Linux和MAC使用./gradlew,而Windows上面则使用gradlew,还可以在 gradle/gradle-wrapper.properties 中配置 Gradle 版本。</p> <h3>Gradle脚本的执行时序</h3> <p>Gradle脚本的执行分为三个过程:</p> <ul> <li> <p>初始化</p> <p>分析有哪些module将要被构建,为每个module创建对应的 project实例。这个时候settings.gradle文件会被解析。</p> </li> <li> <p>配置:处理所有的模块的 build 脚本,处理依赖,属性等。这个时候每个模块的build.gradle文件会被解析并配置,这个时候会构建整个task的链表(这里的链表仅仅指存在依赖关系的task的集合,不是数据结构的链表)。</p> </li> <li> <p>执行:根据task链表来执行某一个特定的task,这个task所依赖的其他task都将会被提前执行。</p> </li> </ul> <p>下面我们根据一个实际的例子来详细说明。这里我们仍然采用VirtualAPK这个开源项目来做演示,它的地址是: <a href="/misc/goto?guid=4959750224245156431" rel="nofollow,noindex">https://github.com/didi/VirtualAPK</a> 。</p> <p>我们以它的宿主端为例,宿主端有如下几个模块:</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/4cdcf084d63657035266346e9cbc83c3.png"></p> <p>其实buildSrc是virtualapk-gradle-plugin,为了便于调试我将其重命名为buildSrc。他们的依赖关系如下:</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/97c2ca7eb7aa214988fdcf41e0cabc6f.png"></p> <p>解释一下,app模块依赖CoreLibrary和buildSrc,CoreLibrary又依赖AndroidStub。为了大家更好理解,下面加一下log。</p> <pre> <code class="language-javascript">/***** Settings.gradle *****/ println "settings start" include ':app' include ':CoreLibrary' include ':AndroidStub' println "settings end"</code></pre> <pre> <code class="language-javascript">/***** VirtualAPK.gradle *****/ println "virtualapk start" allprojects { repositories { mavenCentral() jcenter() } } task clean(type: Delete) { delete rootProject.buildDir } println "virtualapk end"</code></pre> <pre> <code class="language-javascript">/***** app.gradle *****/ println "app config start" apply plugin: 'com.android.application' apply plugin: 'com.didi.virtualapk.host' dependencies { compile project (":CoreLibrary") } project.afterEvaluate { println "app evaluate start" println "app evaluate end" } println "app config end"</code></pre> <pre> <code class="language-javascript">/***** CoreLibrary.gradle *****/ apply plugin: 'com.android.library' println "corelib config start" dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:22.2.0' provided project(':AndroidStub') } apply from: 'upload.gradle' println "corelib config end"</code></pre> <pre> <code class="language-javascript">/***** AndroidStub.gradle *****/ println "androidstub config start" dependencies { compile 'com.android.support:support-annotations:22.2.0' } println "androidstub config end"</code></pre> <pre> <code class="language-javascript">/***** buildSrc *****/ public class VAHostPlugin implements Plugin<Project> { @Override public void apply(Project project) { println "VAHostPlugin config start" project.afterEvaluate { println "VAHostPlugin evaluate start" project.android.applicationVariants.each { ApplicationVariant variant -> generateDependencies(variant) backupHostR(variant) backupProguardMapping(variant) } println "VAHostPlugin evaluate end" } println "VAHostPlugin config end" } }</code></pre> <p>现在随便执行一个task,比如 ./gradlew clean ,那么将会输出如下日志,大家对比着日志,应该能明白Gradle脚本的执行顺序了吧。</p> <pre> <code class="language-javascript">VirtualAPK renyugang$ ./gradlew clean settings start settings end virtualapk start virtualapk end androidstub config start androidstub config end Incremental java compilation is an incubating feature. corelib config start corelib config end app config start VAHostPlugin config start VAHostPlugin config end app config end VAHostPlugin evaluate start VAHostPlugin evaluate end app evaluate start app evaluate end :clean :AndroidStub:clean :CoreLibrary:clean :app:clean BUILD SUCCESSFUL Total time: 12.381 secs</code></pre> <p>可以看到,Gradle执行的时候遵循如下顺序:</p> <p>1. 首先解析settings.gradle来获取模块信息,这是初始化阶段;</p> <p>2. 然后配置每个模块,配置的时候并不会执行task;</p> <p>3. 配置完了以后,有一个重要的回调 project.afterEvaluate ,它表示所有的模块都已经配置完了,可以准备执行task了;</p> <p>4. 执行指定的task。</p> <p>备注:如果注册了多个 project.afterEvaluate 回调,那么执行顺序等同于注册顺序。在上面的例子中,由于buildSrc中的回调注册较早,所以它也先执行。</p> <p> </p> <p> </p> <p>来自:http://blog.csdn.net/singwhatiwanna/article/details/78797506</p> <p> </p>