我知道有很多问题看起来很相似。我还花了几个小时来掌握Gradle多项目。但我仍然不明白这里的最佳做法是什么。顺便说一句,我使用Groovy作为我的编码语言,但引用Java的解释也同样好。
我开发了一个Eclipse Gradle项目"ProjectA",它特别有一个类IndexManager
,负责创建、打开和查询Lucene索引。
现在我正在开发一个新的EclipseGradle项目"ProjectB",它希望使用ProjectA中的IndexManager
类。
这并不意味着我希望这两个项目都是多项目的一部分。我不想每次编译ProjectB时都编译ProjectA的最新版本,而是希望ProjectB依赖于ProjectA的IndexManager
的特定版本。可以选择在将来升级到新版本。也就是说,就像从Maven或JCenter获得的依赖关系一样。。。
两个项目都有application
插件,因此ProjectA生成一个可执行的.jar文件,该文件的名称包含了该版本。但目前它只包含.class文件、资源文件和一个名为MANIFEST.MF的文件,其中包含"MANIFEST Version:1.0"一行。显然,它不包含.class文件所需的任何依赖项(例如Lucene jar文件)。
application
插件还允许您生成一个可运行的分发版:它包括一个可执行文件(事实上有两个,一个用于*nix/Cygwin,一个适用于Windows),以及运行它所需的所有.jar依赖项。
有人能解释一下我如何完成打包这个类IndexManager
(或者可能是ProjectA中的所有类),然后将它包含在ProjectB的build.gradle的dependencies
子句中…然后在ProjectB中的给定文件(Groovy或Java)中使用它的任务吗?
或者指出一些关于最佳行动方案的教程?
对此,我似乎找到了一个可能的答案,但发现有点不令人满意,那就是将要由多个项目使用的类(此处为IndexManager
)放入Gradle项目中,该项目专门设计为Groovy库。为此,您可以通过创建项目目录来启动它,然后:
$ gradle init --type groovy-library
可以从Cygwin提示符中执行,但据我所知,不能从Eclipse中执行。因此,您必须将它导入Eclipse。这个库项目中的build.gradle必须包含IndexManager
所需的依赖项,在本例中为:
compile 'org.apache.lucene:lucene-analyzers-common:6.+'
compile 'org.apache.lucene:lucene-queryparser:6.+'
compile 'org.apache.lucene:lucene-highlighter:6.+'
compile 'commons-io:commons-io:2.6'
compile 'org.apache.poi:poi-ooxml:4.0.0'
compile 'ch.qos.logback:logback-classic:1.2.1'
之后,我运行gradle jar
来创建.jar,其中包含这个IndexManager
类,最初在清单中没有任何花哨的东西(例如名称、版本)。我把这个.jar文件放在一个专用的本地目录中。
然后我创建了另一个Gradle项目来使用这个.jar文件,这里的关键依赖项是
compile files('D:/My Documents/software projects/misc/localJars/XGradleLibExp.jar' )
要使用此类的文件如下所示:
package core
import XGradleLibExp.IndexManager
class Test {
public static void main( args ) {
println "hello xxx"
Printer printer = new Printer()
IndexManager im = new IndexManager( printer )
def result = im.makeIndexFromDbaseTable()
println "call result $result"
}
}
class Printer {
def outPS = new PrintStream(System.out, true, 'UTF-8' )
}
我将IndexManager
设计为使用一个辅助类,该类具有属性outPS
。Groovy-duck-type意味着你只需要提供任何具有这样一个属性的东西,希望一切都能正常工作。
上面的安排没有运行:虽然你可以毫无错误地执行build
和installdist
,但执行分布式可执行文件的尝试失败了,因为上面6个compile
依赖行不存在于"consumer"项目的build.gradle中。当你把它们放在这个"消费者"Gradle项目的build.Gradle中时,它就起作用了。
毫无疑问,您可以将版本添加到生成的.jar文件中,从而保留旧版本以供"使用者"项目使用。我不明白的是,如何利用这种机制,使.jar所需的依赖项的下载和使用像我们习惯于从"真实存储库"中获得的东西一样自动。
PS在我今天的挣扎过程中,我似乎发现Gradle的"maven publish"插件与Gradle 5.+(我正在使用)不兼容。这可能相关,也可能不相关:有些人谈到使用"本地Maven存储库"。我不知道这是否是我问题的答案。。。等待一个über Gradle极客的输入…:)
您应该能够更新Eclipse模型以反映此项目到项目的依赖关系。它看起来像这样(在ProjectB的build.gradle中):
apply plugin: 'eclipse'
eclipse {
classpath.file.whenMerged {
entries << new org.gradle.plugins.ide.eclipse.model.ProjectDependency('/ProjectA')
}
project.file.whenMerged {
// add a project reference, which should show up in /ProjectB/.project's <projects> element
}
}
这些更改可能是对正在运行的数据模型的更改,因此它们实际上可能不会更改.classpath
和.project
文件。更多信息可以在这里找到:https://docs.gradle.org/current/dsl/org.gradle.plugins.ide.eclipse.model.EclipseModel.html
这里讨论这个问题:http://gradle.1045684.n5.nabble.com/Gradle-s-Eclipse-DSL-and-resolving-dependencies-to-workspace-projects-td4856525.html在这里打开了一个错误,但从未解决:https://issues.gradle.org/browse/GRADLE-1014