0%

Gradle学习(五) - 打包发布

发布到Maven仓库

Maven-Publish插件

Gradle将项目发布到Maven仓库需要借助插件,Maven-Publish便是官方推荐的一款插件。
Maven-Publish

发布项目

通过'maven-publish'引入插件
build.gradle

apply plugin: 'maven-publish'

发布到本地

build.gradle

apply plugin: 'java'
apply plugin: 'maven-publish'

group = 'cn.tac.test'
version = '1.0'

publishing {
    publications {
        mavenJava(MavenPublication) {
            from components.java
        }
    }
}
publishing {
    repositories {
        maven {
            url "$buildDir/repo"
        }
    }
}

在以上配置中

  • publishing{}是由插件为项目创建的扩展(PublishingExtension类型),这个扩展提供了两个block:publications{}(MavenPublication类型)和repositories{}(MavenArtifactRepository 类型),分别用于配置要发布的内容目标仓库(均可配置多个)。
  • mavenJava{}被称为发布组件Component,用于配置一项要发布的内容,components.java表示这个组件是通过Java插件添加的java组件,可以简单地理解为就是将当前java项目作为发布内容。
  • maven{}指定了一个要发布的目标仓库,当前指定了当前项目的build目录下的repo目录,即发布到本地

执行publishing -> publish,可以看到项目成功发布到了build/repo目录中。
build/repo

tips

  • 两个publishing{}块的内容也可以合在一起写
  • mavenJava只是一个命名,并无特殊含义,你也可以将其更换为别的名称,但不能与其它发布组件名称重复
  • mavenJava块中还可以配置要发布的artifact的groupidversion,如果不显式指定,则默认采用当前项目的配置

发布源码

在上一步的基础上

  1. 新增一个用于获取源码的task
  2. 配置发布组件,使其发布的同时额外发布一个包含源码的artifact

build.gradle

……
//这个task可以获取到源码
task sourceJar(type: Jar) {
    from sourceSets.main.allJava
}

publishing {
    publications {
        mavenJava(MavenPublication) {
            ……
            //配置额外发布的artifact
            artifact sourceJar {
                //这个字符串会作为artifact文件的后缀
                classifier "sources"
            }
        }
    }
}
……

执行task
sources

发布到远程仓库

只需要修改url指向远程仓库即可。同时由于远程仓库大多需要认证,因此通常需要通过credentials{}指定用户名和密码

build.gradle

……
publishing {
    repositories {
        maven {
            url "http://172.10.10.66:8081/nexus/content/repositories/releases/"
            credentials {
                username = "admin"
                password = "admin123"
            }
        }
    }
}
……

条件发布

这点相信会点groovy的同学都不会觉得难,用if/else就可以完成。例如下面的配置实现根据version后缀来决定是发布到snapshots还是releases仓库中

build.gralde

……
publishing {
    repositories {
        def NEXUS_URL = "http://172.10.10.66:8081/nexus/content/repositories/releases/"
        if (project.version.endsWith("SNAPSHOT")){
            NEXUS_URL = "http://172.10.10.66:8081/nexus/content/repositories/snapshots/"
        }
        maven {
            url NEXUS_URL
            credentials {
                username = "admin"
                password = "admin123"
            }
        }
    }
}
……

发布多项目

父项目的task执行的同时会执行其所有子项目的同一task(最常见的如build任务),因此多项目发布只需要配置好所有子项目的发布配置即可。

build.gradle

subprojects {
    apply plugin: 'java'
    apply plugin: 'maven-publish'

    group "cn.tac.test"
    version "1.0-SNAPSHOT"

    //因为父项目不需要发布,所以只需要配置子项目的发布配置即可
    publishing {
        publications {
            mavenJava(MavenPublication) {
                from components.java
            }
        }
    }
    publishing {
        repositories {
            maven {
                url "$buildDir/repo"
            }
        }
    }
}

执行task,可以看到每个子项目都发布到了其对应的build/repo中。

tips

  • 如果子模块之间互相有依赖,Gradle发布时会自动解析各模块的先后发布顺序,无需我们自己配置

常见问题

发布后pom.xml中项目的依赖scope为runtime的问题

在发布的时候发现,项目中通过complie依赖的第三方库或其它模块,在发布后由Gradle生成的pom.xml文件中,依赖的scope默认变成了runtime,而非我们期望的compile

<?xml version="1.0" encoding="UTF-8"?>
  ……
  <groupId>cn.tac.test</groupId>
  <artifactId>publishing</artifactId>
  <version>1.0-SNAPSHOT</version>
  <dependencies>
    <dependency>
      <groupId>cn.tac.test</groupId>
      <artifactId>module1</artifactId>
      <version>1.0-SNAPSHOT</version>
      <scope>runtime</scope>
    </dependency>
  </dependencies>
</project>

为了达到期望的效果,只需要在发布配置中通过withXML对pom进行修改即可
build.gradle

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

            pom.withXml {
                asNode().dependencies.'*'.findAll() {
                    it.scope.text() == 'runtime' && project.configurations.compile.allDependencies.find { dep ->
                        dep.name == it.artifactId.text()
                    }
                }.each() {
                    it.scope*.value = 'compile'
                }
            }
        }
    }
}

再次发布

<?xml version="1.0" encoding="UTF-8"?>
  ……
  <groupId>cn.tac.test</groupId>
  <artifactId>publishing</artifactId>
  <version>1.0-SNAPSHOT</version>
  <dependencies>
    <dependency>
      <groupId>cn.tac.test</groupId>
      <artifactId>module1</artifactId>
      <version>1.0-SNAPSHOT</version>
      <scope>compile</scope>
    </dependency>
  </dependencies>
</project>

tips