在 Gradle 中,如何生成具有解析为实际使用版本的动态依赖项的 POM 文件?

Posted

技术标签:

【中文标题】在 Gradle 中,如何生成具有解析为实际使用版本的动态依赖项的 POM 文件?【英文标题】:In Gradle, how can I generate a POM file with dynamic dependencies resolved to the actual version used? 【发布时间】:2014-01-24 10:09:14 【问题描述】:

dependencies 
    testCompile(group: 'junit', name: 'junit', version: '4.+')

这是从上面的依赖中生成的。

<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.+</version>
        <scope>test</scope>
    </dependency>
</dependencies>

我希望将+ 解析为如下所示的应计版本。

<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
</dependencies>

Maven Publishing 上的 Gradle 指南章节谈到了这样做,但没有提到如何做。

使用这个钩子,您可以修改 POM 的任何方面。例如,您可以将依赖项的版本范围替换为用于生成构建的实际版本。

解决方案

使用 Peter Niederwieser 的回答中的信息,我创建了一个任务,该任务读取包含动态依赖项的 POM,并用已解决依赖项的新 pom 覆盖它。

/**
 * Reads and Overwrites POM file resolving dynamic dependencies
 */
task cleanPom(dependsOn: writeNewPom) << 
    // Get existing pom file
    Node xml = new XmlParser().parse(pomFileLocation)

    // Generate map of resolved versions
    Map resolvedVersionMap = new HashMap()
    Set<ResolvedArtifact> resolvedArtifacts = configurations.compile.getResolvedConfiguration().getResolvedArtifacts()
    resolvedArtifacts.addAll(configurations.testCompile.getResolvedConfiguration().getResolvedArtifacts())
    resolvedArtifacts.each 
        resolvedVersionMap.put(it.getName(), it.getModuleVersion().getId().getVersion())
    

    // Update dependencies with resolved versions
    xml.dependencies.first().each 
        Node artifactId = it.get("artifactId").first()
        def artifactName = artifactId.value().first()
        def artifactVersion = resolvedVersionMap.get(artifactName)

        Node version = it.get("version").first()
        version.value = artifactVersion
    

    // Overwrite existing pom file
    new XmlNodePrinter(new PrintWriter(new FileWriter(pomFileLocation))).print(xml)

【问题讨论】:

你为什么不使用我链接到的示例中显示的pom.withXml() 挂钩? @PeterNiederwieser 我目前正在使用旧的“maven”插件来创建 POM 文件,此代码将修改我已经创建的 POM。我假设 pom.withXml() 是新 incubating 'maven-publish' 插件的一部分。 旧插件有一个类似的钩子(和示例)。使用旧插件还有一个更简单的解决方案,因为它允许在对象级别操作 POM(在同一示例中进行了演示)。 @PeterNiederwieser 谢谢,有时间我将不得不重新访问并更新此内容。 【参考方案1】:

这需要一些努力来编写代码。两个主要部分是:

使用Configuration#getIncomingConfiguration#getResolvedConfiguration API 查询已解析的版本 使用 Groovy 的 XMlParser API 操作 POM(假设使用了新的 maven-publish 插件)

有关Configuration API 的信息可以在Gradle Build Language Reference 中找到,它进一步链接到Javadoc。 完整的 Gradle 发行版包含一个演示 POM 操作的tiny sample。有关 XmlParser 的信息可以在 Groovy 文档中找到。

【讨论】:

【参考方案2】:

我已经尝试将其集成到一个可以应用的插件中,具体代码在这里:https://github.com/nebula-plugins/nebula-publishing-plugin/blob/master/src/main/groovy/nebula/plugin/publishing/maven/ResolvedMavenPlugin.groovy

它可以通过 jcenter() 通过 'com.netflix.nebula:nebula-publishing-plugin:1.9.1' 包含。

【讨论】:

【参考方案3】:

Peter 建议的pom.withXml() 的解决方案如下所示:

publishing 
  publications 
    mavenCustom(MavenPublication) 
        from components.java
            pom.withXml 
                // Generate map of resolved versions
                Map resolvedVersionMap = [:]
                Set<ResolvedArtifact> resolvedArtifacts = configurations.compile.getResolvedConfiguration().getResolvedArtifacts()
                resolvedArtifacts.addAll(configurations.testCompile.getResolvedConfiguration().getResolvedArtifacts())
                resolvedArtifacts.each 
                    ModuleVersionIdentifier mvi = it.getModuleVersion().getId();
                    resolvedVersionMap.put("$mvi.getGroup():$mvi.getName()", mvi.getVersion())
                

              // Update dependencies with resolved versions
              def hasDependencies = !asNode().dependencies.isEmpty()
              if (hasDependencies) 
                  asNode().dependencies.first().each 
                      def groupId = it.get("groupId").first().value().first()
                      def artifactId = it.get("artifactId").first().value().first()
                      it.get("version").first().value = resolvedVersionMap.get("$groupId:$artifactId")
              
          
      
   

【讨论】:

这适用于 android 项目吗?我收到错误“错误:无法获取 SoftwareComponentInternal 集的未知属性‘java’。”从components.java就行了。以前我使用的是 mavenDeployer:docs.gradle.org/current/userguide/maven_plugin.html。我怎样才能将它们一起使用? 我以前从未使用过Android,但是您是否在gradle文件中应用了java-plugin?

以上是关于在 Gradle 中,如何生成具有解析为实际使用版本的动态依赖项的 POM 文件?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 spring boot 插件 2.0.x 从一个具有不同依赖项的 gradle 项目生成 2 个 jars

如何使用spring boot plugin 2.0.x从一个具有不同依赖项的gradle项目生成2个jar

如何使用Gradle为Android项目生成Eclipse和Intellij项目文件

如何使用 Gradle 为 Android 项目生成 Eclipse 和 Intellij 项目文件

使用 Gradle Kotlin DSL 配置 Jooq 时如何修复“未解析的引用:jdbc”

Gradle详细解析