英文:
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 和实现分离文档中了解更多关于implementation
与api
的信息。
因此,您的 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
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论