在 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#getIncoming
或Configuration#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 项目文件