Gradle 翻译:User Guide

完成翻译部分

基于 Gradle 2.8

  • Chapter 1. Introduction
  • Chapter 2. Overview
  • Chapter 3. Tutorials
  • Chapter 4. Installing Gradle
  • Chapter 6. Build Script Basics
  • Chapter 7. Java Quickstart
  • Chapter 8. Dependency Management Basics

Chapter 1. Introduction

Gradle 做为构建系统,是 Java(JVM) 世界的一大飞跃

  • 一种非常灵活的通用构建工具, 像 Ant
  • 可切换的,基于约定的构建框架
  • 支持多项目构建
  • 支持依赖关系管理(基于Apache Ivy)
  • 支持现有的 Maven 或 Ivy 仓库
  • 支持传递性依赖管理,而不需要远程仓库或者是 pom.xml 和 ivy.xml 配置文件
  • 支持 Ant 任务
  • 基于 Groovy 的构建脚本
  • 有丰富的领域模型来描述构建

Chapter 2. Overview

2.1. 特性

特性清单

声明式和基于约定的构建
Gradle 的核心,基于 Groovy 的 Domain Specific Language(DSL)语言,有丰富的拓展性。Gradle 提供了可以自由组合的可声明的语言元素,进行声明式构建。这些元素提供了对 Java,Groovy,OSGi,Web 和 Scala 等项目的基于约定构建的支持。这种声明式语言是可拓展的,你可以加入新的语言元素或者继承已经有的,因而提供了简洁,可维护的,易于理解的构建。

基于依赖编程的语言
这种声明式语言,在整个构建任务图的顶端,能够可以影响到构建的每一个细节。针对特定的需求,灵活地适配。

对构建的组织
Gradle 的敏捷性和丰富性,允许你在构建中使用通用的设计原则。例如,可以很轻松地组合可复用的构建逻辑代码。但是,不必要的内联内容是不合适的。不要强行把某些原本属于一体的部分进行分离(在你的整个项目的层次结构中)。避免某些部分的改动过多,使得你的构建进入维护性的噩梦。最后可以创造出一个组织良好,易于维护,易于理解的构建。

深层次的 API
Gradle 在整个构建的的生命周期中,嵌入了一些钩子(回调)。可以进行配置和控制核心的一些可执行行为。

多项目构建
Gradle 支持多项目构建。项目依赖关系是关键。能偶像在问题领域中描述的那样,做出项目依赖关系的模型。

Gradle 支持部分构建。你可以单独构建子项目,Gradle 只会关心该子项目依赖的其他依赖项目。可以对依赖于某个子项目的其他所有子项目进行重新构建。对于大型项目的构建,增量构建的方式可以大大节约时间。

多种方式管理依赖
Gradle 对不同方式的依赖管理了方便的支持。无论是远程 Maven 或 Ivy 仓库,jars 或者在本地的文件目录,都能够对这些的依赖的传递进行管理。

一体化构建工具
Gradle 支持对任何 Ant 项目导入,在运行时会把这些 Ant targets 转化成原生的 Gradle tasks。在 Gradle 的 build.xml 文件里,可以依赖、继承这些任务,声明这些任务的依赖关系。同样也对项目属性,路径等也进行了整合。

Gradle 对已经存在的 Maven 或 Ivy 仓库基础设施发布和检索依赖提供了完全的支持。不久将会提供一种转化器,在运行时把 Maven 项目导入的 pom.xml 文件转成 Gradle 脚本。

易于集成
Gradle 可以适应任何的项目结构。因此可以在产品逐步发展完善的同一个分支里,进行 Gradle 的构建。建议写测试来确保这些生产出来的产品和期望中的是相似的。可以在集成的时候尽可能地减少混乱而更加可靠。这是遵循小步重构的最佳实践。

Groovy 作为构建脚本
Gradle 的脚本由 Groovy 语言实现。但和其他的方式不一样,并没有简单地把动态语言的原生的脚本功能暴露出来。这会引起构建难以维护。这个 Gradle 设计的首要目标是作为一种语言来使用,而不是一种固定的框架。Groovy 可以将现实中的叙述和一些抽象概念(你或 Gradle 提供)融合起来。所有的 Gradle API 都是有 Groovy 实现的。

The Gradle wrapper
The Gradle wrapper 允许在没有安装 Gradle 的机器上执行 Gradle 构建。对于一些正在集成的服务器非常有用。减轻了一些开源项目的构建的障碍。对于客户机器不需要管理员权限去访问。强制使用某个版本的 Gradle,最小化不同版本 Gradle 支持不一致带来的问题

免费开源的代码
Gradle 是一个开源项目,使用 ASL 证书

2.2. 为什么使用 Groovy?

在构建脚本的使用中,内部的 DSL(基于动态语言) 比 XML 好。这么多的动态语言,使用 Groovy 和 Gradle 操作的上下环境有关。尽管 Gradle 目标做一个通用的构建工具,但只要还是 Java 项目。这些项目中开发人员更加熟悉 Java。对于所有人员来说,需要让脚本更加透明。

基于此,为什么不使用 Java 语言作为脚本,这可以为团队提高最高的透明性,最小的学习成本。但是 Java 的局限性,这样的话构建脚本就不够漂亮,表达性不强。像 Python,Groovy 或者 Ruby 在这方面做得更好。选择 Groovy 因为它为 Java 开发者最好的透明性。它的语法基础、类型系统和包结构等 Java 一样。Groovy 提供了不仅仅这些。

Chapter 3. Tutorials

3.1. 开始

  • Chapter 4. Installing Gradle
  • Chapter 6. Build Script Basics
  • Chapter 7. Java Quickstart
  • Chapter 8. Dependency Management Basics

Chapter 4. Installing Gradle

Installing Gradle

  • 需要 JDK 或者 JRE, 自带 Groovy 库
  • 配置环境变量 GRADLE_HOME

Chapter 6. Build Script Basics

6.1. Projects and tasks

Gradle 的一切基于两个基本概念:项目(projects)和任务(tasks)

每个 Gradle 构建都有一个或多个项目(projects)组成。一个项目怎么展示基于这个项目在 Gradle 中做了什么。例如,一个项目可以展示为 JAR 库或者 Web 应用。可以展示为一个 ZIP 压缩包,集成了其他项目产生的 JARs。一个项目并不一定需要展示为准备编译的内容,也可以是它准备要拿来做什么,比如部署应用到应用环境中。Gradle 基于约定构建的支持添加了许多的概念,用来定义一个项目是什么。

每一个项目都是有一个或者多个任务(tasks)组成。一个任务展示的是一个构建中的原子工作。它可以是编译一些类,创建 JAR,生成 Javadoc,或者发布某些文档到仓库中。

6.2. Hello world

通过使用 gradle 命令来运行 Gradle。该命令会在当前目录搜索 build.gradle 文件。这个文件可以称作构建脚本(build script),严格来说是构建配置脚本。这个构建脚本定义了一个项目和它的任务。

Example 6.1. Your first build script

build.gradle

task hello {
	doLast {
		println 'Hello world!'	
	}
}

在终端中,进入包含该构建脚本的目录执行 gradle -q hello

Example 6.2. Execution of a build script

Output of gradle -q hello

	> gradle -q hello
	Hello world!

该编译脚本定义了一个单独的任务 hello,并且添加了 aciton。当运行 gradle hello,Gradle 执行 hello 任务,该任务会执行到提供的 action。一个 action 就是一个简单的容器,包含了一些 Groovy 的执行代码。

这些就像 Ant 的 targets。这些任务和 Ant targets 是等价的,但是功能更强大。

6.3. 定义任务的快捷方式

更简洁的方式定义任务

Example 6.3. A task definition shortcut

build.gradle

task hello << {
    println 'Hello world!'
}

这个同样定义了一个名为 hello 的任务

6.4. 构建脚本代码

Gradle 构建脚本提供了 Groovy 的强大功能。

Example 6.4. Using Groovy in Gradle’s tasks

build.gradle

ask upper << {
    String someString = 'mY_nAmE'
    println "Original: " + someString 
    println "Upper case: " + someString.toUpperCase()
}

使用 gradle -q upper 的输出

> gradle -q upper
Original: mY_nAmE
Upper case: MY_NAME

Example 6.5. Using Groovy in Gradle’s tasks

build.gradle

task count << {
    4.times { print "$it " }
}

使用 gradle -q upper 的输出

> gradle -q count
0 1 2 3

6.5. 任务依赖

可以声明一个任务依赖于其他任务

Example 6.6. Declaration of task that depends on other task

build.gradle

task hello << {
    println 'Hello world!'
}
task intro(dependsOn: hello) << {
    println "I'm Gradle"
}

使用 gradle -q intro 的输出

> gradle -q intro
Hello world!
I'm Gradle

添加依赖的时候,相应的任务并不需要存在

Example 6.7. Lazy dependsOn - the other task does not exist (yet)

build.gradle

task taskX(dependsOn: 'taskY') << {
    println 'taskX'
}
task taskY << {
    println 'taskY'
}

使用 gradle -q intro 的输出

> gradle -q taskX
taskY
taskX

taskX 和 taskY 的依赖关系在 taskY 被定义前声明。这对多项目构建非常重要。任务依赖更详细的讨论在 Section 14.4, “Adding dependencies to a task”

注意的是,在相关的任务还未定义的情况下是不能使用快捷注解的 Section 6.8, “Shortcut notations”

6.6. 动态任务

使用 Groovy ,还可以动态创建任务

Example 6.8. Dynamic creation of a task

build.gradle

4.times { counter ->
    task "task$counter" << {
        println "I'm task number $counter"
    }
}

使用 gradle -q task1 的输出

> gradle -q task1
I'm task number 1

6.7. 操作已经存在的任务

已经创建的任务,可以通过API。例如,可以使用这种方式在运行时动态添加依赖到任务中。而 Ant 并不允许。

Example 6.9. Accessing a task via API - adding a dependency

build.gradle

4.times { counter ->
    task "task$counter" << {
        println "I'm task number $counter"
    }
}
task0.dependsOn task2, task3

使用 gradle -q task0 的输出

> gradle -q task0
I'm task number 2
I'm task number 3
I'm task number 0

只能在已经存在的任务中添加行为

Example 6.10. Accessing a task via API - adding behaviour

build.gradle

task hello << {
    println 'Hello Earth'
}
hello.doFirst {
    println 'Hello Venus'
}
hello.doLast {
    println 'Hello Mars'
}
hello << {
    println 'Hello Jupiter'
}

使用 gradle -q hello 的输出

> gradle -q hello
Hello Venus
Hello Earth
Hello Mars
Hello Jupiter

doFirstdoLast 可以多次执行。会添加到任务的 action 列表的头部或者尾部,按列表的顺序执行。操作符 <<
doLast 的简写

6.8. 快捷标注

对已经存在的任务有方便的标注用来访问。每个任务都可以看成构建脚本的属性

Example 6.11. Accessing task as a property of the build script

build.gradle

task hello << {
    println 'Hello world!'
}
hello.doLast {
    println "Greetings from the $hello.name task."
}

使用 gradle -q hello 的输出

> gradle -q hello
Hello world!
Greetings from the hello task.

6.9. 额外项目属性

可以添加属性到任务中。为了添加一个名为 myProperty 的属性,需要设置 ext.myProperty 一个初始化值。从那一刻起,属性就可以被读取和设置,就像一个预定义的任务属性

Example 6.12. Adding extra properties to a task

build.gradle

task myTask {
    ext.myProperty = "myValue"
}

task printTaskProperties << {
    println myTask.myProperty
}

使用 gradle -q printTaskProperties 的输出

> gradle -q printTaskProperties
myValue

额外属性不局限于任务,具体见 Section 13.4.2, “Extra properties”

6.11. 使用方法

Gradle 可组织构建逻辑,第一层次是获得方法

Example 6.14. Using methods to organize your build logic

build.gradle

task checksum << {
    fileList('../antLoadfileResources').each {File file ->
        ant.checksum(file: file, property: "cs_$file.name")
        println "$file.name Checksum: ${ant.properties["cs_$file.name"]}"
    }
}

task loadfile << {
    fileList('../antLoadfileResources').each {File file ->
        ant.loadfile(srcFile: file, property: file.name)
        println "I'm fond of $file.name"
    }
}

File[] fileList(String dir) {
    file(dir).listFiles({file -> file.isFile() } as FileFilter).sort()
}

使用 gradle -q printTaskProperties 的输出

> gradle -q loadfile
I'm fond of agile.manifesto.txt
I'm fond of gradle.manifesto.txt

有写方法是多项目构建中所有子项目都可以访问的。Gradle 提供了非常方便的方式去组织构建逻辑 Chapter 62, Organizing Build Logic

6.12. 默认任务

可以定义一个或多个的默认任务

Example 6.15. Defining a default task

build.gradle

defaultTasks 'clean', 'run'

task clean << {
    println 'Default Cleaning!'
}

task run << {
    println 'Default Running!'
}

task other << {
    println "I'm not a default task!"
}

使用 gradle -q 的输出

> gradle -q
Default Cleaning!
Default Running!

这个和运行 gradle clean run 等价。在多项目构建中,所有子项目均由默认任务。如果子项目没有明确的默认任务,如果有父项目,使用父项目的默认任务。

6.13. Configure by DAG

Gradle 分成配置阶段和运行阶段(Chapter 58, The Build Lifecycle)。在配置阶段结束后,Gradle 会知道所有要执行的任务。Gradle 提供了钩子去使用这些信息。一个用例是需要检查发布的任务是否包含在要执行的任务中。基于此,可以为某些变量分配值。

在接下来的例子,distribution 和 release 任务基于 version 变量的值

Example 6.16. Different outcomes of build depending on chosen tasks

build.gradle

task distribution << {
    println "We build the zip with version=$version"
}

task release(dependsOn: 'distribution') << {
    println 'We release now'
}

gradle.taskGraph.whenReady {taskGraph ->
    if (taskGraph.hasTask(release)) {
        version = '1.0'
    } else {
        version = '1.0-SNAPSHOT'
    }
}

使用 gradle -q release 的输出

> gradle -q release
We build the zip with version=1.0
We release now

重要的地方有, whenReady 在 release 任务执行前影响 release 任务。这个方法当 release 任务不是首要任务(primary task)的时候也会工作。

Chapter 7. Java Quickstart

7.1. Java 插件

Gradle 是一种通用的构建工具,但需要我们编写构建脚本。

所有的 Java 项目都有相似的构建过程:需要编译 Java 源码,运行一些单元测试,创建 JAR 文件来包含 class 文件。Gradle 通过插件(plugin)的使用来解决这些问题。插件是一种对 Gradle 的拓展,可以用来配置项目,尤其是预配置了一些非常有用的任务。Gradle 携带了大量的插件,其中 Java plugin 添加了一些任务,用来编译和测试 Java 源码,最后打包进 JAR 文件。

Java 插件是基于约定的。这意味着插件为项目的各个方面的内容定义了默认值,比如 Java 源代码文件路径。如果在 Java 项目里遵循这些约定,通常不需要在构建脚本做太多的工作,就可以得到有用的构建。如果不想遵循约定,也可以自定义项目。事实上,对 Java 项目最大的支持就是实现这些插件,如果不想使用也是可以构建 Java 项目的。

####7.2. A basic Java project

为了使用 Java 插件,需要在构建脚本添加一句:

Example 7.1. Using the Java plugin

build.gradle

apply plugin: 'java'

这些代码在所有发行版的 Gradle 都可以找到,samples/java/quickstart

这句代码会应用 Java 插件到项目中,并且添加大量的任务

Gradle 希望在 src/main/java 文件夹下找到源代码,在 src/test/java 下找到测试代码。另外,任何在 src/main/resources 下的文件都会被当成资源打包进 JAR 文件中,并且任务在 src/test/resource 下的文件都可以用来运行测试。所有的输出文件都会在构建目录下,JAR 文件会在 build/libs 目录下。

7.2.1 构建项目

Java 插件在项目中添加了许多的任务,然后只有少量的任务是我们在构建项目中使用到的。最长使用到的任务是 build task。当我们运行 gradle build 命令后,Gradle 会编译和测试代码,最后创建 JAR 文件去包含主要的类和资源。

可以使用 gradle tasks 命令列出一个项目中的所有任务

Example 7.2. Building a Java project

运行 gradle build 的输出

> gradle build
:compileJava
:processResources
:classes
:jar
:assemble
:compileTestJava
:processTestResources
:testClasses
:test
:check
:build

BUILD SUCCESSFUL

Total time: 1 secs

其他有用的任务有

clean
删除 build 目录,移除所有构建的文件

assemble
编译和打包代码,但不运行单元测试。其他的插件对这个任务做了更多的功能。例如使用 War 插件,同时会构建 WAR 文件。

check
编译和测试代码。其他的插件会对该任务添加更多的检查。比如使用 checkstyle 插件,这个任务会在源代码上运行 Checkstyle

7.2.2. 外部依赖

通常一个 Java 项目会依赖外部的 JAR 文件。为了引用这些文件,需要告诉 Gradle 哪里去找到它们。在 Gradle,这些 JAR 文件等文档都放在仓库(repository)中。一个仓库可以被用来获取项目依赖的文档,或者发布项目的文档,或者两者兼具。比如,使用 Maven 仓库:

Example 7.3. Adding Maven repository

build.gradle

repositories {
    mavenCentral()
}

现在添加一些依赖,现在声明一些产品源码的编译时依赖,还有使用 junit 作为测试的编译时依赖

Example 7.4. Adding dependencies

build.gradle

dependencies {
    compile group: 'commons-collections', name: 'commons-collections', version: '3.2'
    testCompile group: 'junit', name: 'junit', version: '4.+'
}

可以在 Chapter 8,Dependency Management Basics 中找到更多

7.2.3. 定制项目

Java 插件为项目提供了大量的属性。这些属性包含了默认值,可以有效地开始编译。如果这些值不适合可以很简单地改变它们下面的例子会为 Java 项目定义版本号,并且为 JAR 的 mainifest 添加属性

Example 7.5. Customization of MANIFEST.MF

build.gradle

sourceCompatibility = 1.5
version = '1.0'
jar {
    manifest {
        attributes 'Implementation-Title': 'Gradle Quickstart',
                   'Implementation-Version': version
    }
}

Java 插件添加的任务为常规任务,和我们在构建文件中声明的任务是一样的。这意味着可以像之前的章节那样,为这些任务设置属性,添加行为,改变之间的依赖或者完全地替换。例如对 test 任务的配置,添加系统属性,在测试执行之后会用到:

Example 7.6. Adding a test system property

build.gradle

test {
    systemProperties 'property': 'value'
}
7.2.4. 发布 JAR 文件

通常需要告诉 Gradle 哪里发布这些 JAR 文件。在 Gradle,这些 JAR 文件需要被发布到仓库中。比如发布到本地的目录。也可以发布到远程地址,或者多个地址。

Example 7.7. Publishing the JAR file

build.gradle

uploadArchives {
    repositories {
       flatDir {
           dirs 'repos'
       }
    }
}

发布这些文件,需要运行 gradle uploadArchives

7.2.5. 创建 Eclipse 项目

如果要创建 Eclipse 特有的描述文件,比如 .project 文件,需要添加一个另外的插件:

Example 7.8. Eclipse plugin

build.gradle

apply plugin: 'eclipse'

然后可以执行 gradle eclipse 命令去生成 Eclipse 项目文件。更多关于 Eclipse 任务可以在 Chapter 38,The Eclipse Plugins中找到。

7.2.6. 总结

下面是例子的完整构建脚本:

Example 7.9. Java example - complete build file

build.gradle

apply plugin: 'java'
apply plugin: 'eclipse'

sourceCompatibility = 1.5
version = '1.0'
jar {
    manifest {
        attributes 'Implementation-Title': 'Gradle Quickstart',
                   'Implementation-Version': version
    }
}

repositories {
    mavenCentral()
}

dependencies {
    compile group: 'commons-collections', name: 'commons-collections', version: '3.2'
    testCompile group: 'junit', name: 'junit', version: '4.+'
}

test {
    systemProperties 'property': 'value'
}

uploadArchives {
    repositories {
       flatDir {
           dirs 'repos'
       }
    }
}

7.3. Java 的多项目构建

现在看典型的多项目构建。下面是一个项目的布局:

Example 7.10. Multi-project build - hierarchical layout

Build layout

multiproject/
  api/
  services/webservice/
  shared/
  services/shared/ 

该案例的代码在 samples/java/mutiproject 目录中

这里一共有四个项目,项目 api 产生 JAR 文件,里面有一个客户端,用来支持 XML webservice 的 Java 客户端。项目 webservice 是一个 web 项目用来返回 XML。项目 shared 包含了一些代码,既使用了 api 也使用了 webservices。项目 services/shared 有一些代码依赖于项目 shared。

7.3.1. 定义多项目构建

为了定义多项目构建,需要创建一个 settings file。这个设置文件放置在源码树的根目录。必须被命名为 setting.gradle。在这个例子中,有一简单的层次布局,下面是相关的设置文件

Example 7.11. Multi-project build - settings.gradle file

setting.gradle

include "shared", "api", "services:webservice", "services:shared"

可以在 Chapter 59,Muti-project Builds 找到更多的设置文件。

7.3.2. 通用配置

对于所有的多项目构建,有一些配置是通用的。在我们的例子中,会在根项目中定义一些通用配置,使用一种被成为 configuration injection 的技术。在这里,根项目就像一个容器,subprojects 方法作为容器的元素罗列在其中-这个例子的项目-和特殊的配置。所以我们可以简单地定义所有文档的清单内容,和一些通用依赖:

Example 7.12. Multi-project build - common configuration

build.gradle

subprojects {
    apply plugin: 'java'
    apply plugin: 'eclipse-wtp'

    repositories {
       mavenCentral()
    }

    dependencies {
        testCompile 'junit:junit:4.12'
    }

    version = '1.0'

    jar {
        manifest.attributes provider: 'gradle'
    }
}

这个例子为每个子项目都应用了 Java 插件,这意味着那些 Java 插件中的熟悉和方法在每个 subproject 中都可以使用。当根项目运行 gradle build,在所有子项目都可以进行编译、测试和打包成 JAR。

同时要注意,这些插件也只有在子项目中起作用,所以根构建不会在根目录下找 Java 源文件代码,只有在子项目中寻找。

7.3.3. 项目间的依赖

可以在同一个构建中添加项目间的依赖,例如,一个项目的 JAR 被用来编译另一个项目。在 api 构建文件我们会添加项目 shared 的依赖。因为这个依赖的存在,Gradle 会确保 项目 shared 总是在项目 api 之前得到构建。

7.3.4. 创建发布

可以添加一个 distribution,用来搭载客户端:

Example 7.14. Multi-project build - distribution file

api/build.gradle

task dist(type: Zip) {
    dependsOn spiJar
    from 'src/dist'
    into('libs') {
        from spiJar.archivePath
        from configurations.runtime
    }
}

artifacts {
   archives dist
}

7.4. 接下来?

这个章节简要的说明了构建一个基本的 Java 项目所需做的事情。这个章节并不全面。还有更多事情可以做。这些可以在 Chapter 23,The Java Plugin 中找到。可以在 sample/java 目录下找到一些案例。

Chapter 8. Dependency Management Basics

8.1. 什么是依赖管理

简要地说,依赖管理分成两个部分。首先,Gradle 需要知道你项目中构建或者运行时需要的东西,用来找到它们。我们把这些文件成为项目的依赖(dependencies)。其次,Gradle 需要构建和上传项目产生的东西。我们称这些输出的文件为一个项目的出版物(publications)。更详细地了解:

大部分项目都没有完全独立。它们需要其他项目的构建好的文件进行编译或者测试等。例如,为了在项目中使用 Hibernate 框架,需要包含一些 Hibernate 的 jars 在 classpath中。为了运行测试,也需要包含一些其他的 jars 在 test classpath 中,例如特别的 JDBC driver 或者 Ehcache jars。

这些是项目依赖将会用到的文件。Gradle 要求我们描述这个项目依赖了什么,这样它才能专心去寻找这些依赖,并且使它们在构建的时候可用。这些依赖可能需要从远程的 Maven 或 Ivy 仓库中下载,或者放在本地的目录中,或者需要同一个多项目构建中提前构建好。我们称这个过程为 dependency resolution

要注意的是,上面的特性比使用 Ant 更优秀。使用 Ant,我们只能精确地表述要加载的 jars 的绝对或者相对路径。使用 Gradle,可以简单地声明这些依赖的名称,还有那些地方可以获取到这些依赖。可以从 Ant 找到相似的功能,比如添加 Apache Ivy,但是 Gradle 做得更好。

经常情况下,依赖的项目也会有各自的依赖。例如,Hibernate 核心需要一些其他的库放在 classpath,当运行构建的时候需要用到。所以,当 Gradle 为项目运行测试,它也需要找到这些依赖并且使它们可用。称这些为依赖传递(transitive dependencies)。

大部分项目的首要目标是构建一些文件能够在外部被其他项目使用。例如,如果生产了一个 Java 库,需要构建一个 jar,可能还需要 source jar 和一些文档,然后发布到其他地方。

这些外部文件组成了一个项目的出版物。Gradle 同样关注了这些重要的工作。需要声明项目的出版物,然后 Gradle 构建它们并且发布到某些地方。确切的说法,“publishing”基于你想要做什么。想要复制一些文件到本地目录,或者上传到远程的 Maven 或 Ivy 仓库。或者在同一个多项目构建中在另一个项目中使用这些文件。把这样的过程成为出版(publication)。

8.2. 依赖声明

依赖声明的基础脚本

Example 8.1. Declaring dependencies

build.gradle

apply plugin: 'java'

repositories {
    mavenCentral()
}

dependencies {
    compile group: 'org.hibernate', name: 'hibernate-core', version: '3.6.7.Final'
    testCompile group: 'junit', name: 'junit', version: '4.+'
}

构建脚本为这个项目做了很多事情。手写,它陈述了 Hibernate core 3.6.7.Final需要项目在编译的时候需要用到,言外之意,Hibernate core 和它的依赖在运行时也需要用到。构建脚本也陈述了 junit >= 4.0 版本在项目测试的时候需要用到。这些也让 Gradle 在 Maven 中心仓库寻找任何需要的依赖。接下来是详细内容:

8.3. 依赖配置

在 Gradle 中依赖都被整合到配置里(configuraiton)。一个配置被简单地命名为依赖的集合。我们可以把这些称为依赖配置(denpendency configurations)。可以使用他们去声明项目的外部依赖。也可以使用去声明项目的出版。

Java 插件提供了大量的标准配置。这些配置展示了 Java 插件使用到的 classpath。有一些罗列在下面,可以在 Table 23.5, “Java plugin - dependency configurations”. 找到更详细的内容。

compile
项目产品代码的依赖

runtime
项目运行时产品 classes 文件需要的依赖。默认情况下,也包含了编译时依赖

testComplie
项目测试代码需要的依赖。默认情况下,也包含了编译产品的代码后生成的类文件和编译时依赖。

testRuntime
运行测试时需哟啊的依赖。默认情况下,包含了上面三个过程的依赖。

8.4. 外部依赖

有许多种依赖类型可以声明。一种类型是外部依赖(external denpendency)。这些依赖的文件在当前构建的外部被构建好,然后存储到某些仓库中,如 Maven central,或者公司的 Maven 或 Ivy 仓库,或者本地文件目录。

定义一个外部依赖,需要添加依赖配置:

Example 8.2. Definition of an external dependency

build.gradle

dependencies {
    compile group: 'org.hibernate', name: 'hibernate-core', version: '3.6.7.Final'
}

更多关于依赖的定义和工作方式,需要在 Section 52.4, “How to declare your dependencies”. 寻找。

8.5. 仓库

Gradle 是如何找到外部依赖的文件?Gradle 在仓库(repository)中寻找。一个仓库就是一些列文件的集合,通过 group,name 和 version 来进行管理。Gradle 能够理解不同类型仓库的格式,例如 Maven 和 Ivy,还有其他访问仓库的方式,比如使用本地文件系统或者通过 HTTP。

默认情况下,Gradle 不定义任何仓库,所以在声明外部依赖前,需要去定义至少一个仓库。

Example 8.4. Usage of Maven central repository

build.gradle

repositories {
    mavenCentral()
}

Example 8.5. Usage of a remote Maven repository

build.gradle

repositories {
    maven {
        url "http://repo.mycompany.com/maven2"
    }
}

Example 8.6. Usage of a remote Ivy directory

build.gradle

repositories {
    ivy {
        url "http://repo.mycompany.com/repo"
    }
}

同样可以使用本地的文件系统。可以是 Maven 和 Ivy 仓库。

Example 8.7. Usage of a local Ivy directory

build.gradle

repositories {
    ivy {
        // URL can refer to a local directory
        url "../local-repo"
    }
}

一个项目可以有多个仓库。Gradle 会在每一个仓库中寻找依赖直到被确定,在第一个可以找到该依赖的仓库时停止。如果需要更多关于仓库的定义和工作,需要阅读 Section 52.6, “Repositories”

8.6. 发布产品

依赖配置同样被使用到发布文件。我们称这些文件为 publication artifacts,或者直接成为 artifacts

产检为定义一个项目的产品做了很好的工作,所以不需要特别的操作去告诉 Gradle 发布它们需要做什么。只需要告诉 Gradle 哪里去发布。可以通过 uploadArchives task 来接触这些仓库。下面是发布到远程的 Ivy 仓库的例子:

Example 8.8. Publishing to an Ivy repository

build.gradle

uploadArchives {
    repositories {
        ivy {
            credentials {
                username "username"
                password "pw"
            }
            url "http://repo.mycompany.com"
        }
    }
}

现在,当我们执行 gradle uploadArchives,Gradle 会构建并上传 Jar 文件。Gradle 同样会自动创建并上传 ivy.xml 文件。

也可以发布到 Maven 仓库。语法略有不同。注意的是需要应用 Maven 插件。Gradle 同样会创建并上传 pom.xml 文件。

Example 8.9. Publishing to a Maven repository

build.gradle

apply plugin: 'maven'

uploadArchives {
    repositories {
        mavenDeployer {
            repository(url: "file://localhost/tmp/myRepo/")
        }
    }
}

更多的内容,要看 Chapter 53, Publishing artifacts