在 Buildship 中:如何用构建的 jar 替换 Gradle 项目?
In Buildship: how can I substitute a Gradle project with a built jar?
我希望能够让 Eclipse 忽略一个 Gradle 项目,而是使用它的预构建版本。
背景
我有一个用 Scala 编写的项目 "parser",还有十几个用 Java 编写的项目。我的工具集中最弱的 link 是 Scala IDE。我使用这个插件来编辑和编译 Scala 代码,但不幸的是它在混合语言项目中严重破坏了 Java (JDT) 工具*。
- 具体来说:调用层次结构缺少结果、搜索崩溃等。此外,Scala IDE 似乎已经失去了资金,而且这些问题听起来相当基础,所以我不会屏住呼吸等待这些问题得到解决。
使用 Maven (m2e) 我有一个我很满意的解决方法:
构建为 .jar
放入我的本地 .m2 存储库:
cd parser; mvn install
在 Eclipse 中,关闭 "parser" 项目
"Like magic",m2e 只是选择了最新的 'installed' .jar 并用它代替关闭的项目。
一个很棒的答案是如何让 Gradle 做到这一点!
然而我所希望的是满足这些的任何解决方案...
要求
- 我可以在必要时(很少)打开项目
parser
,
通过 Gradle 命令行编辑和构建更改。
完成后我会关闭它。
- 其他项目使用我本地 .m2 存储库中构建的 .jar。
(如果他们总是这样做就好了。)
- 更改不得影响其他不使用 Eclipse 的人
- (理想情况下)更改可以被其他 Eclipse 用户使用
方法
@lance-java 在 提出了一个类似的问题,其中包含一些一般性建议。我认为我可以排除这些想法:
- composite build support / 多个回购。其他团队成员认为单独构建这个项目没有意义,因为它与其他项目集成得非常紧密。
- dependency substitution rules - 似乎不符合要求 3.
lance-java 的第 4 个想法听起来很可行。释义...
"use the eclipse plugin [in conjunction with] Buildship, e.g. using the whenMerged hook to tweak the generated .classpath
[of all the Java projects]."
更新:[4 月 18 日]:我有 hit a brick wall 这种方法。 Buildship 没有将构建的 .jar 放到运行时类路径中。 (更新 2:现在已解决 - 请参阅我的回答。)
问题
主要问题:我如何构建一个解决方案,才能真正起作用并避免任何重大陷阱?
请注意,项目本身有一些依赖项,具体而言:
dependencies {
compile 'org.scala-lang:scala-library:2.12.4'
compileOnly 'com.google.code.findbugs:jsr305:1.3.9'
antlr 'org.antlr:antlr4:4.5.3'
}
所以一个子问题可能是:如何在不重复定义的情况下将它们拉入其他项目? (如果这不能自动工作。)
在parser
项目中
你应该使用 maven-publish
plugin with the publishToMavenLocal
任务
apply plugin: 'maven-publish'
group = 'your.company'
version = '1.0.0'
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
pom.withXml {
def root = asNode()
root.appendNode('name', 'Your parser project name')
root.appendNode('description', 'Your parser project description')
}
}
}
}
每次修改时,如有必要,只需更改版本号,然后使用 gradle publishToMavenLocal
在其他 java 项目中使用 parser
只需使用 parser
作为常规依赖项:
repositories {
mavenLocal()
...
}
compile 'your.company:parser:1.0.0'
如果我对你的情况的理解很好,应该可以解决问题。
所以解决方案有点复杂。添加 'maven-publish'
以创建库后,我执行以下操作以强制 Eclipse 使用预构建的库:
subprojects {
// Additional configuration to manipulate the Eclipse classpaths
configurations {
parserSubstitution
}
dependencies {
parserSubstitution module("com.example:parser:${project.version}")
}
apply plugin: 'eclipse'
eclipse {
classpath {
plusConfigurations += [ configurations.pseLangSubstitution ]
file {
whenMerged { cp ->
// Get Gradle to add the depedency upon
// parser-xxx.jar via 'plusConfigurations' above.
// Then this here if we have a dependency on Project(':parser')
// - If so, remove it (completing the project -> jar substitution).
// - If not, remove the .jar dependency: it wasn't needed.
def usesParser = entries.removeAll {
it instanceof ProjectDependency && it.path.startsWith('/parser')
}
def parserJar =
cp.entries.find { it instanceof Library && it.path.contains('parser-') }
if (usesParser) {
// This trick stops Buildship deleting it from the runtime classpath
parserJar ?. entryAttributes ?. remove("gradle_used_by_scope")
} else {
cp.entries.remove { parserJar }
}
}
}
}
所以这个有两个部分:
- 使用'plusConfigurations'感觉有点迂回。我最终这样做是因为我看不到如何直接构造
class Library
类路径条目。然而,这很可能是正确实施 'transient dependencies' 所必需的。 (见题末。)
- Gradle 开发人员在 this discussion.
用法
解决方案如我所愿。每次修改这个库中的一些代码时,我都会在命令行上执行我的以下任务(除了构建解析器 jar 之外,它还会执行一些其他代码和资源生成步骤):
./gradlew generateEclipse
然后在 Eclipse 中按 "Gradle -> Refresh Gradle Projects"、Build.
的键盘快捷键
和谐又恢复了。 :-)
- 导航到
parser
的(预构建)源。
- 如果我需要编辑源代码,我可以打开
parser
项目并进行编辑。 Scala-IDE 在这方面仍然做得很好。
- 当我完成后,我执行命令,关闭项目,我的 Java 工具很高兴。
我希望能够让 Eclipse 忽略一个 Gradle 项目,而是使用它的预构建版本。
背景
我有一个用 Scala 编写的项目 "parser",还有十几个用 Java 编写的项目。我的工具集中最弱的 link 是 Scala IDE。我使用这个插件来编辑和编译 Scala 代码,但不幸的是它在混合语言项目中严重破坏了 Java (JDT) 工具*。
- 具体来说:调用层次结构缺少结果、搜索崩溃等。此外,Scala IDE 似乎已经失去了资金,而且这些问题听起来相当基础,所以我不会屏住呼吸等待这些问题得到解决。
使用 Maven (m2e) 我有一个我很满意的解决方法:
构建为
.jar
放入我的本地 .m2 存储库:cd parser; mvn install
在 Eclipse 中,关闭 "parser" 项目
"Like magic",m2e 只是选择了最新的 'installed' .jar 并用它代替关闭的项目。
一个很棒的答案是如何让 Gradle 做到这一点!
然而我所希望的是满足这些的任何解决方案...
要求
- 我可以在必要时(很少)打开项目
parser
, 通过 Gradle 命令行编辑和构建更改。 完成后我会关闭它。 - 其他项目使用我本地 .m2 存储库中构建的 .jar。 (如果他们总是这样做就好了。)
- 更改不得影响其他不使用 Eclipse 的人
- (理想情况下)更改可以被其他 Eclipse 用户使用
方法
@lance-java 在
- composite build support / 多个回购。其他团队成员认为单独构建这个项目没有意义,因为它与其他项目集成得非常紧密。
- dependency substitution rules - 似乎不符合要求 3.
lance-java 的第 4 个想法听起来很可行。释义...
"use the eclipse plugin [in conjunction with] Buildship, e.g. using the whenMerged hook to tweak the generated
.classpath
[of all the Java projects]."更新:[4 月 18 日]:我有 hit a brick wall 这种方法。 Buildship 没有将构建的 .jar 放到运行时类路径中。 (更新 2:现在已解决 - 请参阅我的回答。)
问题
主要问题:我如何构建一个解决方案,才能真正起作用并避免任何重大陷阱?
请注意,项目本身有一些依赖项,具体而言:
dependencies {
compile 'org.scala-lang:scala-library:2.12.4'
compileOnly 'com.google.code.findbugs:jsr305:1.3.9'
antlr 'org.antlr:antlr4:4.5.3'
}
所以一个子问题可能是:如何在不重复定义的情况下将它们拉入其他项目? (如果这不能自动工作。)
在parser
项目中
你应该使用 maven-publish
plugin with the publishToMavenLocal
任务
apply plugin: 'maven-publish'
group = 'your.company'
version = '1.0.0'
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
pom.withXml {
def root = asNode()
root.appendNode('name', 'Your parser project name')
root.appendNode('description', 'Your parser project description')
}
}
}
}
每次修改时,如有必要,只需更改版本号,然后使用 gradle publishToMavenLocal
在其他 java 项目中使用 parser
只需使用 parser
作为常规依赖项:
repositories {
mavenLocal()
...
}
compile 'your.company:parser:1.0.0'
如果我对你的情况的理解很好,应该可以解决问题。
所以解决方案有点复杂。添加 'maven-publish'
以创建库后,我执行以下操作以强制 Eclipse 使用预构建的库:
subprojects {
// Additional configuration to manipulate the Eclipse classpaths
configurations {
parserSubstitution
}
dependencies {
parserSubstitution module("com.example:parser:${project.version}")
}
apply plugin: 'eclipse'
eclipse {
classpath {
plusConfigurations += [ configurations.pseLangSubstitution ]
file {
whenMerged { cp ->
// Get Gradle to add the depedency upon
// parser-xxx.jar via 'plusConfigurations' above.
// Then this here if we have a dependency on Project(':parser')
// - If so, remove it (completing the project -> jar substitution).
// - If not, remove the .jar dependency: it wasn't needed.
def usesParser = entries.removeAll {
it instanceof ProjectDependency && it.path.startsWith('/parser')
}
def parserJar =
cp.entries.find { it instanceof Library && it.path.contains('parser-') }
if (usesParser) {
// This trick stops Buildship deleting it from the runtime classpath
parserJar ?. entryAttributes ?. remove("gradle_used_by_scope")
} else {
cp.entries.remove { parserJar }
}
}
}
}
所以这个有两个部分:
- 使用'plusConfigurations'感觉有点迂回。我最终这样做是因为我看不到如何直接构造
class Library
类路径条目。然而,这很可能是正确实施 'transient dependencies' 所必需的。 (见题末。) - Gradle 开发人员在 this discussion.
用法
解决方案如我所愿。每次修改这个库中的一些代码时,我都会在命令行上执行我的以下任务(除了构建解析器 jar 之外,它还会执行一些其他代码和资源生成步骤):
./gradlew generateEclipse
然后在 Eclipse 中按 "Gradle -> Refresh Gradle Projects"、Build.
的键盘快捷键和谐又恢复了。 :-)
- 导航到
parser
的(预构建)源。 - 如果我需要编辑源代码,我可以打开
parser
项目并进行编辑。 Scala-IDE 在这方面仍然做得很好。 - 当我完成后,我执行命令,关闭项目,我的 Java 工具很高兴。