关于我对Gradle的翻译,以Github上的项目及http://gradledoc.qiniudn.com 上的文档为准。如发现翻译有误的地方,将首先在以上两个地方更新。因时间精力问题,博客中发表的译文基本不会同步修改。
另外,目前Gradle1.12版本的文档已经翻译完并进入校稿阶段,校稿的方式为到该项目https://github.com/msdx/gradledoc 提交issue或是pull request。校稿的结果不只是在此版本更新,也会用于改善Gradle下一版本(2.0)文档的翻译。
本章内容描述了一个新的 孵化中的 功能,是由“ivy-publish
”插件提供的 Ivy 发布支持。最终这个新的发布支持的发布功能将会取代Upload
任务的发布功能。
如果你正在查找关于使用 Upload
任务的原始的Ivy发布支持的文档,请查阅 第五十一章, 发布构件。
本章内容主要描述了如何发布使用 Apache Ivy 格式的构建构件,通常是发布到一个用于其他构建或项目的消费的仓库。发布的内容是一个或多个在构建中创建的构件,以及一个描述了这些构件以及它们的依赖的Ivy 模块描述文件(通常是 ivy.xml
)。
使用已发布的 Ivy 模块就可以在Gradle(参见 第五十章, 依赖管理)或其他了解Ivy 格式的工具中使用。
ivy-publish
”插件这种使用 Ivy 格式发布的能力是由 “ivy-publish
”插件提供的。
“publishing
” 插件在project上创建了一个名为 “publishing
”的 PublishingExtension
类型的扩展。这个扩展提供了两个容器,一个叫publications,一个叫repositories。“ivy-publish
”适用于IvyPublication
publications 和 IvyArtifactRepository
仓库。
示例 64.1. 应用“ivy-publish”插件
build.gradle
apply plugin: 'ivy-publish'
应用“ivy-publish
”插件将会执行以下操作:
publishing
”插件IvyPublication
自动创建 GenerateIvyDescriptor
任务(见第 64.2 节,“发布”)。IvyPublication
(见第 64.2 节,“发布”)和IvyArtifactRepository
(见第 64.3 节,“仓库”)的组件自动创建 PublishToIvyRepository
任务。如果你不熟悉项目构件和配置,你应该读一下第五十一章,发布,里面对这些概念进行了介绍。这一章还介绍了使用另一种不同的机制的“发布构件”。这里描述的发布功能最终将取代那一功能。
发布对象描述了要被创建的发布内容的结构和配置。publications是通过任务发布到仓库中的,并且发布对象的配置明确决定了会发布哪些内容。一个项目的所有publications会在 PublishingExtension.getPublications()
容器中定义。每一个发布
为了能让“ivy-publish
”插件起作用的,一个 IvyPublication
必须被添加到publications集里。这个publication决定了实际上哪些构件会被发布,以及在关联的Ivy模块描述文件中所包含的详细信息。通过添加组件,自定义构件,以及直接修改生成的模块描述文件,可以配置一个publication。
向Ivy仓库发布一个Gradle项目的最简单的方式是指定一个要发布的 SoftwareComponent
。目前可用于publication的组件都有:
表64.1. 软件组件
名称 | 提供者 | 构件 | 依赖 |
java |
Java 插件 | 生成的 jar 文件 | “runtime”配置的依赖 |
web |
War 插件 | 生成的 war 文件 | 没有依赖 |
在以下示例中,工件和运行时依赖都来自于由 Java Plugin
添加的 “java” 组件。
示例 64.2. 将一个 java 模块发布到 Ivy
build.gradle
publications { ivyJava(IvyPublication) { from components.java } }
我们还可以显式地配置要被包含在publication的构件。这些构件通常是以原始数据文件,或者是 AbstractArchiveTask
的实例(如Jar, Zip)的方式来提供。
对于每个自定义的项目,在发布时可以指定name
、extension
、type
、classifier
和conf
的值。注意,每个构件必须有一个唯一的 name/classifier/extension 组合。
如下所示配置自定义构件︰
示例64.3. 发布额外的构件到Ivy
build.gradle
task sourceJar(type: Jar) { from sourceSets.main.java classifier "source" } publishing { publications { ivy(IvyPublication) { from components.java artifact(sourceJar) { type "source" conf "runtime" } } } }
关于如何自定义构件的更详细的文档,请参阅IvyPublication
。
生成的Ivy模块描述符文件包含了用于标识该模块的
标记。默认标识的值取自以下这些项目属性︰
organisation
- Project.getGroup()
module
- Project.getName()
revision
- Project.getVersion()
status
- Project.getStatus()
重写默认标识值是很简单︰只需要配置IvyPublication
时指定organisation
、module
或revision
属性。
示例 64.4. 自定义发布标识
build.gradle
publishing { publications { ivy(IvyPublication) { organisation 'org.gradle.sample' module 'project1-sample' revision '1.1' descriptor.status = 'milestone' from components.java } } }
Gradle 将处理 organization, module 和 revision(以及 artifact 名称, extension 和 classifier)的任何有效的Unicode 字符。唯一明确禁止使用的是“\
”,“/
”以及所有的ISO控制字符。这些提供的值会在发布之前进行验证。
有时候,从项目信息生成的模块描述文件可能需要在发布之前进行一些调整。“ivy-publish
”插件提供了一个hook以允许这一类的修改。
示例 64.5. 自定义模块描述符文件
build.gradle
publications { ivyCustom(IvyPublication) { descriptor.withXml { asNode().info[0].appendNode('description', 'A demonstration of ivy descriptor customization') } } }
在这个例子中,我们添加了一个“description”元素到生成的Ivy依赖描述符中,而这个hook,允许你去对这个生成的描述符的任何方面进行修改。例如,你可以使用一个用于产生构建的实际版本去替换一个依赖的版本范围。
相关的 API 参考文档,请参阅IvyModuleDescriptor.withXml()
。
如果有需要的话,你也可以修改所创建的描述符的几乎任何方面。这意味着,用这样的方式,可能会把这个描述符修改为不再是有效的Ivy模块描述符,所以必须谨慎使用这个功能。
已发布模块的标识符(organisation,module,revision)则是一个例外;不能使用“withXML”hook 来修改描述符中的这些值。
有时候从你的 Gradle 构建中发布多个模块会很有用,而不是创建一个单独的 Gradle 子项目。一个例子是为您的library 分别发布一个单独的 API 和它的实现的 jar。使用 Gradle 的话很简单︰
示例 64.6. 从一个单一的项目发布多个模块
build.gradle
task apiJar(type: Jar) { baseName "publishing-api" from sourceSets.main.output exclude '**/impl/**' } publishing { publications { impl(IvyPublication) { organisation 'org.gradle.sample.impl' module 'project2-impl' revision '2.3' from components.java } api(IvyPublication) { organisation 'org.gradle.sample' module 'project2-api' revision '2' } } }
如果一个项目定义了多个要发布的内容,Gradle 将把每一个都发布到定义的仓库。如上文所述,每个发布的内容都必须给定一个唯一的标识。
发布的内容都会被发布到仓库中用于发布的仓库是通过PublishingExtension.getRepositories()
容器来定义的。
示例 64.7. 声明用于发布的仓库
build.gradle
repositories { ivy { url "$buildDir/repo" // change to point to your repo, e.g. http://my.org/repo } }
定义用于发布的仓库的DSL和定义用于查找依赖的仓库的DSL一样(RepositoryHandler
)。然而,在Ivy发布的场景中,只有通过 ivy()
方法创建的仓库才可以作为发布的指定地方。例如,你不能把一个 IvyPublication
发布到一个Maven仓库中。
对每一个在 publishing.publications
和 publishing.repositories
容器中分别组合的IvyPublication
和 IvyArtifactRepository
,“ivy-publish
” 插件自动为它们创建了一个 PublishToIvyRepository
任务。
这个创建的任务使用“publish«PUBLICATION 名称»PublicationTo«REPOSITORY 名称»Repository
”的方式来命名。因此,在下面的例子中,创建了一个 PublishToIvyRepository
任务,名字叫做“publishIvyJavaPublicationToIvyRepository
”。
示例 64.8. 选择要发布的特定出版物
build.gradle
apply plugin: 'java' apply plugin: 'ivy-publish' group = 'org.gradle.sample' version = '1.0' publishing { publications { ivyJava(IvyPublication) { from components.java } } repositories { ivy { url "$buildDir/repo" // change to point to your repo, e.g. http://my.org/repo } } }
gradle publishIvyJavaPublicationToIvyRepository
的输出结果
> gradle publishIvyJavaPublicationToIvyRepository :generateDescriptorFileForIvyJavaPublication :compileJava UP-TO-DATE :processResources UP-TO-DATE :classes UP-TO-DATE :jar :publishIvyJavaPublicationToIvyRepository BUILD SUCCESSFUL Total time: 1 secs
publish
” 生命周期任务这个“publish
插件(即“ivy-publish
” 插件隐式应用的)添加了一个 叫做“publish
”的生命周期任务,可以用于发布所有出版物到所有适用的仓库中。
更具体而言,执行这个任务将会执行在项目中的所有 PublishToIvyRepository
任务。这通常是执行发布的最方便的方法。
示例 64.9. 通过“publish”生命周期任务发布所有出版物
gradle publish
的输出结果
> gradle publish :generateDescriptorFileForIvyJavaPublication :compileJava UP-TO-DATE :processResources UP-TO-DATE :classes UP-TO-DATE :jar :publishIvyJavaPublicationToIvyRepository :publish BUILD SUCCESSFUL Total time: 1 secs
有时候,我们会需要在不发布你的模块到Ivy仓库的情况下,生成Ivy模块描述符文件(通常是ivy.xml
)。因为描述符文件的生成是由一个单独的任务执行的,所以这很容易做到。
“ivy-publish
”插件自动为每一个注册的 IvyPublication
连接了一个GenerateIvyDescriptor
任务。这个任务被指定为一个基于发布的名称的名字:“generateDescriptorFileFor«发布名称»Publication
”。因此,在上面的例子中,发布的名称叫“ivyJava
”,那么这个任务的名称就会是“generateDescriptorFileForIvyJavaPublication
”。
你可以通过在生成任务上设置destination
属性,指定生成的Ivy文件位置。默认情况下这个文件将会生成到build/publications/«发布名称»/ivy.xml
。
示例 64.10. 生成Ivy模块描述符文件
build.gradle
model {
tasks.generateDescriptorFileForIvyCustomPublication {
destination = file("$buildDir/generated-ivy.xml")
}
}
gradle generateDescriptorFileForIvyCustomPublication
的输出结果
> gradle generateDescriptorFileForIvyCustomPublication :generateDescriptorFileForIvyCustomPublication BUILD SUCCESSFUL Total time: 1 secs
“ivy-publish
”插件利用了后期插件配置的一些实验性的支持,并且在配置发布扩展之前,不会构造GenerateIvyDescriptor
任务。确保当你尝试访问GenerateIvyDescriptor
任务时,发布插件已经配置好的最简单的方式是,将访问的代码放在publishing
代码块中,如上面的例子中所示。
这同样适用于任何发布相关的任务的访问,像PublishToIvyRepository
。这些任务应该从publishing
代码块内引用。
下面的例子演示了如何使用在多项目构建中进行发布。每个项目发布一个 java 组件,以及配置额外的源码构件。自定描述符,以包含每一个项目的项目描述。
示例 64.11. 发布一个 java 模块
build.gradle
subprojects { apply plugin: 'java' apply plugin: 'ivy-publish' version = '1.0' group = 'org.gradle.sample' repositories { mavenCentral() } task sourceJar(type: Jar) { from sourceSets.main.java classifier "source" } } project(":project1") { description = "The first project" dependencies { compile 'junit:junit:4.11', project(':project2') } } project(":project2") { description = "The second project" dependencies { compile 'commons-collections:commons-collections:3.1' } } subprojects { publishing { repositories { ivy { url "${rootProject.buildDir}/repo" // change to point to your repo, e.g. http://my.org/repo } } publications { ivy(IvyPublication) { from components.java artifact(sourceJar) { type "source" conf "runtime" } descriptor.withXml { asNode().info[0].appendNode('description', description) } } } } }
其结果是将为每个项目发表以下构件︰
ivy-1.0.xml
。project1-1.0.jar
。project1-1.0-source.jar
。当project1
发布时,产生的模块描述符(即ivy.xml
文件)将是……
注意:在这个例子的Ivy模块描述符中的«发布时间戳»
将是描述符文件生成时的时间戳。
示例 64.12. 生成 ivy.xml的示例
output-ivy.xml
version="2.0">
organisation="org.gradle.sample" module="project1" revision="1.0" status="integration" publication="«PUBLICATION-TIME-STAMP»">
The first project
name="default" visibility="public" extends="runtime"/>
name="runtime" visibility="public"/>
name="project1" type="jar" ext="jar" conf="runtime"/>
name="project1" type="source" ext="jar" conf="runtime" m:classifier="source" xmlns:m="http://ant.apache.org/ivy/maven"/>
org="junit" name="junit" rev="4.11" conf="runtime->default"/>
org="org.gradle.sample" name="project2" rev="1.0" conf="runtime->default"/>
“ivy-publish
”插件的功能,如上文所述是不完整的,因为这一功能仍然在孵化中。在即将到来的 Gradle 版本中,功能将会扩展到包括(但不仅限于)︰
module
、organisation
等)。module descriptor
中方便依赖报告的自定义。