【问题标题】:In Buildship: how can I substitute a Gradle project with a built jar?在 Buildship 中:如何用构建的 jar 替换 Gradle 项目?
【发布时间】:2018-04-11 16:33:30
【问题描述】:

我希望能够让 Eclipse 忽略一个 Gradle 项目,而是使用它的预构建版本。

背景

我有一个用 Scala 编写的“解析器”项目,还有十几个用 Java 编写的项目。我的工具集中最薄弱的环节是 Scala IDE。我使用这个插件来编辑和编译 Scala 代码,但不幸的是,它在混合语言项目中严重破坏了 Java (JDT) 工具*。

  • 特别是:调用层次结构缺少结果、搜索崩溃等。此外,Scala IDE 似乎已经失去了资金,而且这些问题听起来相当根本,所以我不会屏息等待这些问题得到解决。

对于 Maven (m2e),我有一个非常满意的解决方法:

  1. 构建为 .jar 放入我的本地 .m2 存储库:

    cd parser; mvn install
    
  2. 在 Eclipse 中,关闭“解析器”项目

“像魔法一样”,m2e 只是拿起了最近“安装”的 .jar 并使用它来代替已关闭的项目。

一个很棒的答案是如何让 Gradle 做到这一点!

但我所希望的只是满足这些要求的任何解决方案......

要求

  1. 我可以在必要时打开项目parser(很少), 通过 Gradle 命令行编辑和构建更改。 完成后我会关闭它。
  2. 其他项目使用我本地 .m2 存储库中构建的 .jar。 (如果他们总是这样做就好了。)
  3. 更改不得影响不使用 Eclipse 的其他人
  4. (理想情况下)其他 Eclipse 用户可以使用更改

方法

@lance-java 的good answer 提出了一个类似的问题,并提出了一些一般性建议。我认为我可以排除这些想法:

与 lance-java 的想法 #4 类似的东西听起来是可行的。转述……

  • “使用eclipse plugin [结合] Buildship,例如使用whenMerged 挂钩来调整生成的.classpath [所有Java项目 ]。”

    更新:[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 用作项目依赖项,仅作为常规依赖项,在本地 .m2 存储库中挑选?
  • 没错,我想删除对项目parser(Gradle默认添加)的引用,并将其替换为parser-1.0.0-SNAPSHOT.jar之类的东西。
  • 更新:我刚刚发现一个big clue 试图从 .m2 目录中包含 .jars 可能有问题。也许我必须避免maven-publish 和/或将 jar 复制到其他地方。
  • 我明天会尝试一个正确的答案,但我认为它并不复杂(如果我理解正确的话)

标签: java gradle scala-ide gradle-eclipse


【解决方案1】:

所以解决方案有点复杂。添加'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 }
                }
            }
        }
    }

所以这有两个部分:

  1. 使用“plusConfigurations”感觉有点绕。我最终这样做了,因为我看不到如何直接构造 class Library 类路径条目。然而,无论如何,这很可能是正确实现“瞬态依赖”所必需的。 (见问题的结尾。)
  2. Gradle 开发人员在this discussion 中向我提供了阻止 Buildship 从运行时类路径中删除 .jar(从而偏离 Gradle 命令行启动)的技巧。

用法

解决方案如我所愿。每次修改这个库中的一些代码时,我都会在命令行上执行以下任务(除了构建解析器 jar 之外,它还执行了一些其他代码和资源生成步骤):

./gradlew generateEclipse

然后在 Eclipse 中,我按下“Gradle -> Refresh Gradle Projects”的键盘快捷键,构建。

和谐恢复了。 :-)

  • 导航到parser 的(预建)源代码。
  • 如果我需要编辑源代码,我可以打开parser项目进行编辑。 Scala-IDE 在这方面仍然做得很好。
  • 完成后,我执行命令,关闭项目,我的 Java 工具就很开心了。

【讨论】:

    【解决方案2】:

    parser 项目中

    您应该将maven-publish 插件与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'
    

    如果我对您的情况的理解很好,那应该可以解决问题。

    【讨论】:

    • 谢谢!我认为这是一个 gradle 范围的更改,这将影响每个人(包括那些使用 IntelliJ 或 vi 并进行命令行构建的人)。因此需要 3(和可选 4)——因为我理想情况下正在寻找一个只修补 Eclipse 用户的 IDE 问题的修复程序。因此,如果我理解正确,它的缺点是需要其他团队成员也执行此额外步骤,对吗?
    • 还请注意我昨天的第二条评论:我发现了一个big clue 关于我正在击中的“砖墙”。我认为 Buildship 正在从运行时类路径中删除我的 .m2 存储库中的任何 jars(大概是为了避免在安装时 Buildship 和 m2e(eclipse-gradle 和 eclipse-maven)之间的讨厌的交互。所以考虑到这一点,我当前想法是:也许只是添加构建的.jar的基本复制任务来“发布”它,并添加一个eclipse { }块来引用它?
    • 更改不得影响不使用 Eclipse 的其他人 但是源代码是版本化的,不是吗?因此,无论 ide 是什么,它都应该开箱即用
    • 是的,它在 git 中。其他人的正常工作流程通常只是gradlew build。如果他们自己编辑了parser 模块,或者git pull 其他人的修改修改了它,这个命令是否仍然有效?
    • 使用上述解决方案,每个用户都必须确保在本地 .m2 存储库中有一个新的 parser jar,因此在拉取或本地修改项目后,gradle publishToMavenLocal是必要的
    猜你喜欢
    • 2015-12-13
    • 1970-01-01
    • 2016-08-06
    • 1970-01-01
    • 2019-01-19
    • 2023-04-08
    • 2016-09-03
    • 1970-01-01
    • 2014-08-05
    相关资源
    最近更新 更多