发布到Maven仓库

原文地址:Chapter 36. Maven Publishing (new) ,基于Gradle Build Tool 3.4.1的,后期可能会修改。文章最后面写了一下自己的总结。

译文

本章描述的是通过”maven-publish”插件来支持发布到Maven功能。最终这种新的发布方式会替换掉通过Upload task的发布方式。

本章描述怎样发布构建的内容(artifacts)到Apache Maven仓库。一个模块发布到Maven仓库以后可以供MavenGradle以及其它支持Maven仓库格式的工具使用。

36.1. “maven-publish” 插件

“maven-publish” 插件提供了发布Maven格式的功能。

“publishing” 插件创建一个类型为PublishingExtension名称为publishing的参数,这个参数里面提供了publications容器和repositories容器。”maven-publish” 依赖的是MavenPublicationMavenArtifactRepository。(意思是”maven-publish”是在”publishing”上再一次的封装)

应用”maven-publish”插件的例子。

// build.gradle
apply plugin: 'maven-publish'

应用”Maven Plugin”需要做如下事情:

  • 使用”publishing”插件 (没看明白,觉得意思就是需要apply plugin: 'maven-publish')
  • 创建一个规则自动为每一个MavenPublication创建GenerateMavenPom任务
  • 创建一个规则自动的为每一个MavenPublicationMavenArtifactRepository的组合创建一个PublishToMavenRepository任务
  • 创建一个规则自动的为每一个MavenPublication创建PublishToMavenLocal任务

PS:这里说的似乎有点绕,MavenPublication相当于是需要发布的内容,而MavenArtifactRepository则相当于是发布的仓库。”maven-pluign”主要是做三件事:GenerateMavenPom可以用来生成pom文件;PublishToMavenRepository可以用来发布到指定仓库,本地某个路径或者远程的服务器;PublishToMavenLocal则是用来发布到本地的.m2仓库(例如我自己电脑的地址是/Users/Egos/.m2)

36.2. Publications

Publication对象描述的是一次发布的结构和配置。Publications通过任务发布到仓库,Publication对象的配置则精确地确定哪些内容需要发布。所有的发布配置信息定义在PublishingExtension.getPublications()容器中,在一个项目中每一个发布到都有一个唯一的名字。

对于”maven-publish”插件有哪些影响,需要创建一个MavenPublication,这个发布决定了哪些内容需要发布以及包含在POM文件中的详细信息。发布时可以通过增加模块、自定义构建的内容以及修改生成的POM文件来配置。

36.2.1. 发布一个软件模块

最简单的发布一个Gradle项目到Maven仓库的方法就是指定一个软件模版去发布。目前已经支持的模版有。

NameProvided ByArtifactsDependencies
javaThe Java PluginGenerated jar fileDependencies from ‘runtime’ configuration
webThe War PluginGenerated war fileNo dependencies

下面的例子,构建内容和运行的依赖都来自在Java插件中定义的java信息。

// build.gradle
publishing {
    publications {
        mavenJava(MavenPublication) {
            from components.java
        }
    }
}

PS:什么意思呢?上面一句from components.java代表了使用默认的配置,从上表可以看出会生成jar文件,同时需要运行时的一些依赖。

36.2.2. 发布一个自定义构建内容

可以通过配置artifact明确的指定需要生成的内容。通常会提供原始的文件或者AbstractArchiveTask对应的实例(例如:Jar,Zip等等)。

对于每一个自定义的构建内容,可以指定扩展名和分类信息(classifier)。注意只有一个发布的构建内容可以拥有空的分类信息(classifier),并且所有的构建信息必须拥有唯一的分类信息(classifier)和扩展名的组合。

如下配置自定义的构建内容:

// build.gradle
task sourceJar(type: Jar) {
    from sourceSets.main.allJava
}

publishing {
    publications {
        mavenJava(MavenPublication) {
            from components.java

            artifact sourceJar {
                classifier "sources"
            }
        }
    }
}

PS:什么意思呢? 插件自身可以支持发布出去生成的文件是jarwar,但是这并不能满足所有的情况,所以可以自定义构建内容,比如:aar等等。怎么自定义呢?创建相应的任务以及在publications中使用artifact就可以了。

36.2.3. 在生成的POM中区别值

生成的POM文件的值包含了如下的属性:

  • groupId Project.getGroup()
  • artifactId Project.getName()
  • version Project.getVersion()

覆盖默认的标识属性非常的简单:只需要在MavenPublication配置时指定groupId,artifactId,version就行。

// build.gradle
publishing {
    publications {
        maven(MavenPublication) {
            groupId 'org.gradle.sample'
            artifactId 'project1-sample'
            version '1.1'

            from components.java
        }
    }
}

Maven限制了groupIdartifactId在一个有限的字符集([A-Za-z0-9_\\-.]+),并且Gradle也遵循这样的限制。对于version(以及构建内容中的extensionclassifier),只需要是有效的Unicode字符就行。唯一明确禁止的Unicode字符是”\”,”/”和ISO控制字符。会在publication之前对字符进行校验。

36.2.4. 修改生成的POM文件

生成的POM文件可能在发布之前需要修改。”maven-publish”插件提供了一个hook来允许这样的修改。

// build.gradle
publications {
    mavenCustom(MavenPublication) {
        pom.withXml {
            asNode().appendNode('description',
                                'A demonstration of maven POM customization')
        }
    }
}

上面例子在生成的POM文件中增加了一个description元素。使用hook可以修改POM中任意的元素。例如:你可以将依赖关系的版本范围替换成生成构建的实际版本。

可以修改POM中的任意元素,这也意味着可以将POM修改成非法的POM,所以需要小心的使用这个功能。

发布模块的唯一标识属性(groupId,artifactId,version)是一个例外,这个元素不能通过withXMLhook来修改。

36.2.5. 发布多个模块

有时候使用Gradle不创建多个子项目发布多个模块是非常有用的。

下面的例子是在一个项目中使用Gradle发布多个模块。

task apiJar(type: Jar) {
    baseName "publishing-api"
    from sourceSets.main.output
    exclude '**/impl/**'
}

publishing {
    publications {
        impl(MavenPublication) {
            groupId 'org.gradle.sample.impl'
            artifactId 'project2-impl'
            version '2.3'

            from components.java
        }
        api(MavenPublication) {
            groupId 'org.gradle.sample'
            artifactId 'project2-api'
            version '2'

            artifact apiJar
        }
    }
}

如果一个工程定义了多个发布信息,Gradle会将每一个发布信息发布到指定的仓库。每一个发布需要给定一个唯一的标示。

36.3. Repositories

发布信息(Publications)最终会发布到仓库,发布的仓库信息定义在PublishingExtension.getRepositories()中。

下面是定义一个发布的仓库

// build.gradle
publishing {
    repositories {
        maven {
            // change to point to your repo, e.g. http://my.org/repo
            url "$buildDir/repo"
        }
    }
}

The DSL used to declare repositories for publication is the same DSL that is used to declare repositories to consume dependencies from, RepositoryHandler. However, in the context of Maven publication only MavenArtifactRepository repositories can be used for publication.

上面一句是对于Repositories的描述,理解不了。自己理解的意思是使用Maven publication只能发布在Maven仓库中。

36.4. 发布到maven仓库的一个例子

“maven-publish”插件会自动的为每一个各自声明在publishing.publicationsMavenPublication和声明在publishing.repositoriesMavenArtifactRepository的组合创建一个PublishToMavenRepository任务。

创建的任务的名字格式是publish«PUBNAME»PublicationTo«REPONAME»Repository

// build.gradle
apply plugin: 'java'
apply plugin: 'maven-publish'

group = 'org.gradle.sample'
version = '1.0'

publishing {
    publications {
        mavenJava(MavenPublication) {
            from components.java
        }
    }
}
publishing {
    repositories {
        maven {
            // change to point to your repo, e.g. http://my.org/repo
            url "$buildDir/repo"
        }
    }
}
// Output of gradle publish
> gradle publish
:generatePomFileForMavenJavaPublication
:compileJava
:processResources NO-SOURCE
:classes
:jar
:publishMavenJavaPublicationToMavenRepository
:publish

BUILD SUCCESSFUL

Total time: 1 secs

在这个例子中,一个类型是PublishToMavenRepository,名称是publishMavenJavaPublicationToMavenRepository的任务会被创建,这个任务会被连接到发布任务的生命周期中。执行gradle publish会生成POM文件以及生成要发布的所有的构建内容,并将生成的构建内容传输到相应的仓库。

36.5. 发布到本地maven仓库

为了于本地maven集成,有时候将模块发布在本地的.m2仓库是非常有用的。Maven称之为“安装”模块。”maven-publish”插件会自动的为每一个声明在publishing.publications的内容创建一个PublishToMavenLocal任务。每一个这样的任务都会被连接到publishToMavenLocal的生命周期中。不需要在publishing.repositories中写mavenLocal

创建的任务的名字格式是publish«PUBNAME»PublicationToMavenLocal

PS:网上很多的开源插件有一些没有发布到本地的方法,对于一些需要修改代码进行调试等,发布到本地还是非常方便的。

36.6. 不发布的情况下生成pom文件

有时候在不发布的情况下修改POM文件是非常有用的,因为POM文件的生成是一个单独的任务,所以非常容易实现。

生成POM文件的任务类型是GenerateMavenPom,名称是基于发布任务generatePomFileFor«PUBNAME»Publication。因此在下面的例子中,发布的名称是mavenCustom,所以生成POM文件的名称是generatePomFileForMavenCustomPublication

// 不发布的情况下生成POM文件
model {
    tasks.generatePomFileForMavenCustomPublication {
        destination = file("$buildDir/generated-pom.xml")
    }
}
> gradle generatePomFileForMavenCustomPublication
:generatePomFileForMavenCustomPublication

BUILD SUCCESSFUL

Total time: 1 secs

打包android library到本地的例子

// android-artifacts.gradle
apply plugin: "maven-publish"

task androidJavadocs(type: Javadoc) {
    source = android.sourceSets.main.java.srcDirs
    ext.androidJar = "${android.sdkDirectory}/platforms/${android.compileSdkVersion}/android.jar"
    classpath += files(ext.androidJar)
}

task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
    classifier = 'javadoc'
    from androidJavadocs.destinationDir
}

afterEvaluate { project ->
    tasks.all { Task task ->
        if (task.name.equalsIgnoreCase('publishPatchLibPublicationToMavenLocal')) {
            task.dependsOn tasks.getByName('assemble')
        }
    }
}

publishing {
    publications {
        PatchLib(MavenPublication) {

            artifactId project.getName()
            groupId group
            version version

            // artifact 打成aar
            artifact("$buildDir/outputs/aar/${project.getName()}-release.aar")
            artifact androidJavadocsJar
        }
    }
}
// publish«PUBNAME»PublicationToMavenLocal
task pushlishLibToLocal(dependsOn: ['build', 'publish PatchLibPublicationToMavenLocal']) {
    group = 'patch'
}

使用的时候只需要在需要打包到本地的lib工程的build.gradle目录中。

apply plugin: 'com.android.library'

...
version "1.0.0" // 需要一个version传到android-artifacts.gradle,每一个需要打包的可能不一样
group APP_PACKAGE_NAME  // 同上

apply from: file('../gradle/android-artifacts.gradle')

打包Java library到本地的例子

Java library 就会更简单一点了,因为有一个模版,上面文章已经有介绍了。

// java-artifacts.gradle

apply plugin: 'maven-publish'

sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7

afterEvaluate { project ->
    tasks.all { Task task ->
        if (task.name.equalsIgnoreCase('publishPatchLibPublicationToMavenLocal')) {
            task.dependsOn tasks.getByName('assemble')
        }
    }
}

publishing {
    publications {
        PatchLib(MavenPublication) {
            from components.java
            groupId = group
            artifactId = project.getName()
            version = VERSION_NAME_DEV
        }
    }
}

// 发布在本地仓库
// 会自动创建'publishXXXXXPublicationToMavenLocal'  'XXXXX' 是 publishing->publications-> PatchLib
task pushlishLibToLocal(dependsOn: ['build', 'publishPatchLibPublicationToMavenLocal']) {
    group = 'patch'
}

总结

将项目模块(Android LibraryJava Library以及Groovy Plugins等等)构建、打包发到Maven仓库(包括本地的Maven仓库)是一件很有意义的事情。对于公司来说,方便多个小组之间的调用、以及维护管理,同时也使代码看起来不会显的过于臃肿,也避免了一些网络不好的情况(公司内网还是相对快一点)。这篇文件介绍的’maven-publish’插件是一个已经可以直接使用的插件,个人觉得目前这个插件的主要作用是将构建内容发布在本地(.m2目录)。这样对于修改一些开源的框架还是蛮有作用的,以及将项目中的Library模块先发布在本地然后再依赖调用,也可以减少打包的时间。

对于需要打包发布在远程仓库的,最好还是使用“maven”插件“signing”插件,当然还有可能发布在ivy仓库等,需要根据实际的需求来选择。所有的发布都可以在官方文档中找到。想要系统的学习Gradle插件还是得花点时间看看userguide

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值