3

当使用maven-publish(incubating, I know) 发布时,compile依赖项被添加到生成 POM(在runtime范围内),但testCompile依赖项被忽略。

如何将testCompile依赖项作为test作用域放入生成的 POM 中?

4

3 回答 3

2

我用了几个小时来找到一种很好的方法来选择工件或出版物应该使用的构建配置,但没有运气。我的发现是,实现它的唯一方法是修改生成的 POM XML,如下所示:

// build.gradle

publishing {
    repositories { /* skipped for brevity */ }

    publications {
        core(MavenPublication) {
            from components.java
            artifactId project.name

            artifact sourcesJar {
                classifier 'sources'
            }
        }

        generators(MavenPublication) {
            from components.java
            artifactId "${project.name}-generators"

            artifacts = [ generatorsJar ]
            artifact generatorsSourcesJar {
                classifier 'sources'
            }

            pom.withXml { pomXml -> replaceDependenciesWith('generatorsBase', pomXml) }
        }
    }
}

void replaceDependenciesWith(String configurationName, XmlProvider pomXml) {
    Node configurationDependencies = new Node(null, 'dependencies')
    project.configurations.getByName(configurationName).allDependencies.each { dep ->
        Node dependency = new Node(null, 'dependency')
        dependency.appendNode('groupId', dep.group)
        dependency.appendNode('artifactId', dep.name)
        dependency.appendNode('version', dep.version)
        dependency.appendNode('scope', 'compile')
        configurationDependencies.append(dependency)
    }
    pomXml.asNode().dependencies*.replaceNode(configurationDependencies)
}

以上在 Gradle 3.3 上工作


评论 Groovy 的类似 XML 构建器的语法

我还尝试使用 Groovy 的类似 XML 构建器的语法,但不幸的是,错误的上下文附加到传递给replaceNode方法的闭包,因此它不起作用。内联时,它获得与publications {}闭包相同的上下文,而当提取到方法时,version dep.version没有按预期工作)。

// Does not work!
void replaceDependenciesWith(String configurationName, Node pomXmlNode) {
    pomXmlNode.dependencies*.replaceNode {
        dependencies {
            project.configurations.getByName(configurationName).allDependencies.each { dep ->
                dependency {
                    groupId dep.group
                    artifactId dep.name
                    version dep.version
                    scope 'compile'
                }
            }
        }
    }
}
于 2017-06-17T14:58:19.330 回答
1

POM 仅在发布工件时使用;它与工件一起上传到 Maven 存储库。因此,POM 只需要运行时依赖。

Gradle 执行独立于您的部署插件的测试,因此它不使用 POM 文件。

假设您使用的是 Java 插件,它会添加test源集。这反过来又创建了 testCompile 任务。

现在,Gradle 假设您的运行时依赖项将与您的编译时依赖项相同,如果您不进行其他配置。但是,它只考虑main源集。这就是为什么您的 POM 不包含 test依赖项的原因。

因此,总而言之,配置您的测试依赖项类似于以下内容。然后,快乐地生活,知道发布的工件不会包含您的测试代码或其依赖项。

dependencies {
    testCompile 'org.springframework:spring-test:4.+'
}

如果您遇到特殊情况,即在无法访问测试源代码的机器上执行测试,请更详细地描述您的要求。应该可以为测试代码设置一个单独的输出工件,以便它可以发布,但我仍然认为您不应该将它发布在与main源集相同的包(或 POM)中。

于 2015-03-03T11:38:51.547 回答
0

当我需要修改 POM xml 时,我无法使用 groovy 语言的任何功能。而且我不得不像krzychu 的回答一样直接依赖 API 。

否则 xml 闭包没有像我预期的那样应用,构建失败并带有一些警告,或者没有正确应用闭包导致无效的 pom.xml 。

但是最近,在仔细阅读了groovy 的闭包文档后,我注意到可以将 aresolutionStrategy应用于闭包,以帮助运行时找到正确的上下文(隐含的 this)。

默认的解决策略是Closure.OWNER_FIRST,这解释了为什么我publications在一些试验中遇到了关于应用闭包的错误。从他们的文档中,我尝试将策略设置为Closure.DELEGATE_FIRST,事实证明这按预期工作。

但是请注意,闭包必须应用于 a Node,因此.children()返回一个列表,.last()返回一个Node您可以通过.plus(...)方法或其别名添加另一个节点的 a +

publishing {
    publications {
        core(MavenPublication) {
            pom.withXml {
                def dependenciesNode = 
                    asNode().dependencyManagement
                            .first()
                            .dependencies
                            .first()

                dependenciesNode.children().last().plus( {
                    resolveStrategy = Closure.DELEGATE_FIRST
                    dependency {
                        'groupId'('org.springframework.boot')
                        'artifactId'('spring-boot-dependencies')
                        'version'(rootProject.'spring-boot.version')
                        'type'('pom')
                        'scope'('import')
                    }
                })
            }
        }
    }
}

找到正确的语法就像大海捞针,这里有一些链接(1)(2)(3)帮助我找到了resolutionStrategy.

于 2019-10-21T10:16:10.490 回答