如何在Gradle中以编程方式添加传递性依赖项?

huangapple go评论80阅读模式
英文:

How can I programmatically add transitive dependencies in Gradle?

问题

我对Gradle还比较陌生,正在评估在我目前的雇主的Scala项目中从SBT切换到Gradle的潜在好处。因此,我不打算立即将整个构建转换为Gradle,但似乎可以动态地基于Gradle构建(目前主要是编译器标志和具有全局版本的依赖项)。这样,我既不会不必要地增加同事的认知负担,同时也不会使我的构建落后于或与POM文件中的“标准”配置发生冲突。

这是我的当前build.gradle文件(到目前为止,我只开始处理依赖项):

def dependencyVersions = [:]
new XmlSlurper().parse('pom.xml').dependencyManagement.dependencies.dependency.each {
    dependencyVersions["${it.groupId}:${it.artifactId}"] = it.version.text()
}

allprojects {
    group = 'my.org'
    version = 'latest-SNAPSHOT'
}

subprojects {
    apply plugin: 'java'
    apply plugin: 'scala'

    repositories {
        mavenLocal()
        maven {
            url = uri('https://repo.maven.apache.org/maven2')
        }
    }

    dependencies {
        implementation 'org.scala-lang:scala-library:2.13.3'

        // ... Global deps ...

        new XmlSlurper().parse("$projectDir/pom.xml").dependencies.dependency.each {
            if(it.groupId.text() == 'my.org') {
                add('implementation', project(":${it.artifactId}"))
            } else {
                def version = it.version.text() ? it.version.text() : dependencyVersions["${it.groupId}:${it.artifactId}"]
                def dep = "${it.groupId}:${it.artifactId}:${version}"
                def scope = it.scope.text() ? it.scope.text() : 'compile'
                if(scope == 'compile')
                    add('implementation', dep)
                else if(scope == 'test') {
                    add('testImplementation', dep)
                } else {
                    throw new Exception("Unrecognized dependency scope: $scope")
                }
            }
        }
    }

    sourceCompatibility = '1.8'

    tasks.withType(JavaCompile) {
        options.encoding = 'UTF-8'
    }
}

上述代码几乎能够正常工作。直接依赖项已按预期添加,但问题在于传递依赖项在编译时不可用。我该如何配置子项目,以使任何传递依赖项都能够解析并添加到子项目中呢?

英文:

I'm pretty (very) new to Gradle and I am evaluating the potential benefits of switching from SBT to Gradle in a Scala project at my current employer. As such I'm not looking to convert an entire build to Gradle right away but it seems it should be possible to dynamically base the Gradle build (atm, primarily compiler flags and dependencies with global versions). This way I don't unnecessarily increase the cognitive load on my colleagues but at the same time I don't run the risk of my build lagging behind or conflicting with the "canonical" configuration in the pom-files.

This is my current build.gradle (so far I have only started to tackle dependencies):

def dependencyVersions = [:]
new XmlSlurper().parse('pom.xml').dependencyManagement.dependencies.dependency.each {
dependencyVersions["${it.groupId}:${it.artifactId}"] = it.version.text()
}
allprojects {
group = 'my.org'
version = 'latest-SNAPSHOT'
}
subprojects {
apply plugin: 'java'
apply plugin: 'scala'
repositories {
mavenLocal()
maven {
url = uri('https://repo.maven.apache.org/maven2')
}
}
dependencies {
implementation 'org.scala-lang:scala-library:2.13.3'
// ... Global deps ...
new XmlSlurper().parse("$projectDir/pom.xml").dependencies.dependency.each {
if(it.groupId.text() == 'my.org') {
add('implementation', project(":${it.artifactId}"))
} else {
def version = it.version.text() ? it.version.text() : dependencyVersions["${it.groupId}:${it.artifactId}"]
def dep = "${it.groupId}:${it.artifactId}:${version}"
def scope = it.scope.text() ? it.scope.text() : 'compile'
if(scope == 'compile')
add('implementation', dep)
else if(scope == 'test') {
add('testImplementation', dep)
} else {
throw new Exception("Unrecognized dependency scope: $scope")
}
}
}
}
sourceCompatibility = '1.8'
tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}
}

The above almost works. Direct dependencies are added as they should be but the problem is that transitive dependencies are not available at compile-time. How can I configure the subproject such that any transitive dependencies are resolved and added to the subprojects as well?

答案1

得分: 1

如果您打算将模块/子项目用作另一个子项目/项目的依赖项或库,那么您应该使用Java Library 插件,而不是Java 插件

使用 Java Library 插件,您将可以访问api配置。您可以在API 和实现分离文档中了解更多关于implementationapi的信息。

因此,您的 Gradle 文件可以如下所示:

dependencies {
    api 'org.scala-lang:scala-library:2.13.3'
    
    // ... 全局依赖 ...
    
    new XmlSlurper().parse("$projectDir/pom.xml").dependencies.dependency.each {
        if(it.groupId.text() == 'my.org') {
            add('api', project(":${it.artifactId}"))
        } else {
            def version = it.version.text() ? it.version.text() : dependencyVersions["${it.groupId}:${it.artifactId}"]
            def dep = "${it.groupId}:${it.artifactId}:${version}"
            def scope = it.scope.text() ? it.scope.text() : 'compile'
            if(scope == 'compile')
                add('api', dep)
            else if(scope == 'test') {
                add('testImplementation', dep)
            } else {
                throw new Exception("Unrecognized dependency scope: $scope")
            }
        }
    }
}

唯一不同的是从 implementation 切换到 api

英文:

If you are intending for a module/subproject to be consumed as a dependency or library from another subproject/project, then you should use the Java Library plugin instead of the Java plugin

With the Java Library plugin, you will have access to the api configuration. You can read more about implementation vs api in API and implementation separation docs.

So your Gradle file could be:

dependencies {
implementation 'org.scala-lang:scala-library:2.13.3'
// ... Global deps ...
new XmlSlurper().parse("$projectDir/pom.xml").dependencies.dependency.each {
if(it.groupId.text() == 'my.org') {
add('api', project(":${it.artifactId}"))
} else {
def version = it.version.text() ? it.version.text() : dependencyVersions["${it.groupId}:${it.artifactId}"]
def dep = "${it.groupId}:${it.artifactId}:${version}"
def scope = it.scope.text() ? it.scope.text() : 'compile'
if(scope == 'compile')
add('api', dep)
else if(scope == 'test') {
add('testImplementation', dep)
} else {
throw new Exception("Unrecognized dependency scope: $scope")
}
}
}
}

The only thing different here is switching from implementation to api.

huangapple
  • 本文由 发表于 2020年8月10日 02:39:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/63330012.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定