`
wbj0110
  • 浏览: 1604642 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

Gradle学习系列之八——构建多个Project

阅读更多

请通过以下方式下载本系列文章的Github示例代码:

git clone https://github.com/davenkin/gradle-learning.git

 


 

Gradle为每个build.gradle都会创建一个相应的Project领域对象,在编写Gradle脚本时,我们实际上是在操作诸如Project这样的Gradle领域对象。在多Project的项目中,我们会操作多个Project领域对象。Gradle提供了强大的多Project构建支持。

要创建多Project的Gradle项目,我们首先需要在根(Root)Project中加入名为settings.gradle的配置文件,该文件应该包含各个子Project的名称。比如,我们有一个根Project名为root-project,它包含有两个子Project,名字分别为sub-project1和sub-project2,此时对应的文件目录结构如下:

复制代码
root-project/
   sub-project1/
      build.gradle
   sub-project2/
      build.gradle
build.gradle
settings.gradle
复制代码

 

root-project本身也有自己的build.gradle文件,同时它还拥有settings.gradle文件位于和build.gradle相同的目录下。此外,两个子Project也拥有他们
自己的build.gradle文件。

 

要将sub-project1和sub-project2加入到root-project的子Project中,我们需要在settings.gradle中加入:

include 'sub-project1', 'sub-project2'

 

接下来,我们来定义一个Task用于显示每个Project各自的名称。我们可以在每个build.gradle进行定义,但是这却是一种比较笨的方法,此时我们也完全没有享受到Gradle的多Project构建功能所带来的好处。在Gradle中,我们可以通过根Project的allprojects()方法将配置一次性地应用于所有的Project,当然也包括定义Task。比如,在root-project的build.gradle中,我们可以做以下定义:

复制代码
allprojects {
   apply plugin: 'idea'
   

   task allTask << {
      println project.name
   }
}
复制代码

 

以上Gradle脚本将闭包中的代码应用在所有的Project中,包括root-project本身。我们首先将应用了idea Plugin用于生成IntelliJ工程,其次我们定义了名为allTask的Task,该
Task应用于每个Project,作用是输出各个Project的名称。执行“gradle allTask”,命令行输出如下:

:allTask
root-project
:sub-project1:allTask
sub-project1
:sub-project2:allTask
sub-project2

 

我们看到,该allTask对于每个Project都执行了一次,在执行时输出了当前Project的名称。

 

除了allprojects()之外,Project还提供了subprojects()方法用于配置所有的子Project(不包含根Project)。比如,我们可以定义Task来只输出各个子Project的名字:

subprojects {
   task subTask << {
      println project.name
   }
}

 

执行“gradle subTask”,命令行输出如下:

:sub-project1:subTask
sub-project1
:sub-project2:subTask
sub-project2

 

此时的输出中不再包含root-project的名字。

 

上文中已经提到,在Gradle脚本中,我们实际上是在操作一些领域对象,因此我们可以将groovy的所有语言特性用在Gradle的领域对象上,比如我们可以对Project进行过滤:

configure(allprojects.findAll { it.name.startsWith('sub') }) {
   subTask << {
      println 'this is a sub project'
   }
}

 

在上面的代码中,我们先找到所有Project中名字以“sub”开头的Project,然后再对这些Project进行配置,在配置中,我们向这些Project的subTask中加入了一条额外的打印语句。
此时如果再执行“gradle subTask”,命令行输出如下:

:sub-project1:subTask
sub-project1
this is a sub project
:sub-project2:subTask
sub-project2
this is a sub project

 

到此为止,我们所有的Task定义工作都是在root-project中进行的,而sub-project1和sub-project2中的build.gradle文件依然什么都没有。事实上,我们可以将所有对子Project的配置
均放在根Project中进行。在上面的例子中,我们通过allprojects()和subprojects()将所有的子Project都包含在了配置之内,其实我们还可以对单个Project进行单独配置。比如,在root-project
的build.gradle中加入:

project(':sub-project1') {
   task forProject1 << {
      println 'for project 1'
   }
}

 

以上脚本向sub-project1中加入了名为forProject1的Task,在执行“gradle forProject1”时,终端输出如下:

:sub-project1:forProject1
for project 1

 

这里有一个问题:我们是在root-project下执行的命令,因此照理说Gradle会认为forProject1是定义在所有的Project上,而此时只有sub-project1才拥有该Task,Gradle应该抛出异常指示在root-project和sub-project2上找不到该Task才对,为什么它还是执行成功了呢?原因在于:只有当一个Task没有在任何Project中定义时,Gradle才会将其当做异常。否则,Gradle会在所有拥有该Task的Project上执行该Task。

一旦有了多个Project,他们之间便会存在着依赖关系。Gradle的Project之间的依赖关系是基于Task的,而不是整个Project的。

现在,让我们来看一个Project依赖的例子。比如sub-project1中有taskA和taskB,taskA依赖于taskB:

复制代码
task taskA << {
   println 'this is taskA from project 1'
}

task taskB << {
   println 'this is taskB from project 1'
}

taskA.dependsOn taskB
复制代码

 

在执行“gradle taskA”时,终端输出:

:sub-project1:taskB
this is taskB from project 2
:sub-project1:taskA
this is taskA from project 1

 

这个很容易理解,两个Task都是属于sub-project1的。但是,让我们再向其中加入一些复杂性。我们在sub-project2中定义taskC和taskD,然后使taskA再依赖于taskC,又使taskB依赖于taskD:

复制代码
//sub-project1:
taskA.dependsOn ':sub-project2:taskC'
taskB.dependsOn ':sub-project2:taskD'

//sub-project2:
task taskC << {
   println 'this is taskC from project 2'
}

task taskD << {
   println 'this is taskD from project 2'
}
复制代码

 

此时再执行“gradle taskA”,终端输出如下:

复制代码
:sub-project2:taskD
this is taskD from project 2
:sub-project1:taskB
this is taskB from project 1
:sub-project2:taskC
this is taskC from project 2
:sub-project1:taskA
this is taskA from project 1
复制代码

 

分析一下:taskA依赖于taskB,而taskB又依赖于taskD,所以sub-project1的taskD首先得到了执行,然后再执行sub-project1的taskB。之后,又由于taskA依赖于taskC,故Gradle
再次转向sub-project1执行taskC,最后才执行taskA。

分享到:
评论

相关推荐

    为什么说 Gradle 是 Android 进阶绕不去的坎 —— Gradle 系列(1).doc

    ale 插件: 提供具体构建逻辑,如 Android 插件负责处理 Android 项目的构建细节; Project: 表示一个独立的构建项目,可以包含多个子 ...通过逐步深入学习 Gradle 系列文章,你将能够更好地掌握这个强大的构建工具。

    gradle-6.5.7z

    每个项目都有自己的构建逻辑,可以包含多个子项目,形成项目树结构。 - **任务(Task)**: 任务是构建过程中的最小执行单元。它们定义了具体的构建动作,如编译代码、打包、运行测试等。Gradle允许自定义任务并创建...

    gradle用户手册中文版

    - Gradle支持Java项目的构建,包括编译、测试、打包等多个阶段。 - 提供了丰富的插件和内置任务来简化Java项目的构建过程。 2. **项目结构** - Java项目的典型结构包括源代码目录(`src/main/java`)、资源文件...

    掌握Java生态:Maven与Gradle的项目管理之道

    ### Java 生态中的 Maven 与 Gradle:项目管理之道 #### Java 语言概览 Java 作为一种被广泛采用的编程语言,在多个领域中都发挥着关键作用。它由 Sun Microsystems(现已被 Oracle 收购)在 1995 年首次推出。...

    GradleAndMaven:通过Gradle和Maven构建的多模块项目

    本文将深入探讨两种广泛使用的构建工具——Gradle和Maven,特别是它们在构建多模块项目中的应用。 **一、Maven** 1. **Maven简介**:Maven是由Apache Software Foundation开发的项目管理和综合工具。它基于项目...

    Gradle in Action

    - **多项目结构**:大型项目通常由多个子项目组成,每个子项目都有自己的 `build.gradle` 文件。 - **子项目引用**:可以在父项目中定义子项目,并通过路径引用子项目中的构建脚本。 - **依赖共享**:父项目可以定义...

    eclipse+gradle解决android 65k 方法问题

    在早期的 Android 应用开发中,开发者可能会遇到一个常见的问题——65K 方法数量限制。由于 Dalvik 虚拟机的设计限制,每个 APK 文件中的方法数不能超过 65536 个。当应用逐渐变得庞大,或者引入了大量第三方库时,...

    安卓Android源码——中国 象棋源码.rar

    6. **项目配置文件**:`project.properties`或`settings.gradle`,定义项目依赖和构建设置。 7. **README** 或其他文档:提供项目介绍、使用指南、版权信息等。 通过分析这个源码,开发者可以学习如何在Android平台...

    gradle-provider-api-example:通过Gradle的新PropertyProvider API演示惰性属性解析

    这些代码通常包括多个Gradle任务,展示了如何声明、配置和使用`Provider`对象。 总结起来,"gradle-provider-api-example"项目是为了帮助开发者理解和实践Gradle的Property/Provider API,它通过惰性属性解析优化了...

    安卓Android源码——PushTalk-master.zip

    6. **project.properties**(可能有):旧版Android项目中的构建配置文件,现在通常被gradle替代。 7. **assets** 目录(可能有):用于存放应用运行时需要的非资源文件,如数据库、配置文件等。 8. **libs** 目录...

    安卓Android源码——精典源码之查询工具源代码.zip

    【标题】"安卓Android源码——精典源码之查询工具源代码.zip" 提供的是一个关于Android系统中查询工具的源代码分析案例。这个压缩包包含了一系列与Android开发相关的文件,适合对Android源码有深入研究或者想要提升...

    安卓Android源码——程序启动界面Demo.zip

    这个压缩包包含了多个关键文件,下面将详细解释它们的作用以及如何通过这些文件构建一个启动界面。 1. **AndroidManifest.xml**:这是每个安卓应用的核心配置文件,它定义了应用的基本元数据,如应用名、图标、所需...

    安卓Android源码——Android 英语单词记忆程序源码.7z

    对于单词记忆应用,可能包含一个或多个单词库的文本文件,或者已经预加载的音频发音文件。 6. **bin**目录:在编译和构建过程中,编译后的class文件以及最终的APK文件会出现在这里。在开发阶段,你可以在此找到调试...

    安卓Android源码——365MobileSecretary v1.0.6(365手机助手AIDL).7z

    AIDL的使用意味着该应用可能有多个组件或服务需要跨进程通信,这是在大型或复杂Android应用中常见的设计模式。 【标签】"安卓 android" 指明了讨论的主题,即Android操作系统及其相关的开发工作。在这个环境下,...

    安卓Android源码——精典源码之开源项目Jchat编译以及源码分析含开发文档.zip

    通过以上步骤,你可以逐步了解并掌握Jchat项目的工作原理,同时,这个过程也将加深你对Android系统、网络编程、数据库管理、UI设计等多个方面的理解。源码分析是一个不断探索和学习的过程,实践与理论相结合,将使你...

    安卓Android源码——精典源码之引用第三方库的方法.zip

    本资料包“安卓Android源码——精典源码之引用第三方库的方法”旨在深入探讨如何在Android项目中集成和使用外部库。下面将详细阐述这一主题。 1. **依赖管理工具Gradle** Android项目主要使用Gradle作为构建工具...

    安卓Android源码——MyAppWeixin(仿微信界面).7z

    【标题】"安卓Android源码——...总的来说,这份源码为Android开发者提供了宝贵的学习机会,涵盖了从基础的界面设计到复杂的网络通信和数据管理等多个方面,对于提升开发者技能和理解Android应用开发流程非常有帮助。

    安卓Android源码——demo.zip

    【Android 源码分析——基于 demo.zip】 在 Android 开发中,理解源码是提升技术水平和解决问题的关键。本篇文章将深入探讨一个名为 "demo" 的 Android 项目,通过分析其压缩包内的文件结构和重要组件,来揭示 ...

    安卓Android源码——Android 英语单词记忆程序源码.zip

    在这个项目中,你可能会发现一个或多个包,每个包下包含对应的Activity、Adapter(用于数据绑定)以及其他辅助类,例如数据模型、网络请求类等。 6. **res**目录:资源文件夹存储了应用的所有非代码资源,如布局...

    安卓Android源码——版本检测与管理.zip

    在安卓(Android)系统开发中,版本检测与管理是至关重要的环节,它涉及到软件更新、兼容性测试以及用户隐私保护等多个方面。这份压缩包“安卓Android源码——版本检测与管理.zip”很可能是包含了关于如何在Android...

Global site tag (gtag.js) - Google Analytics