简体   繁体   English

相对于Gradle子项目的依赖关系,这些子项目也可以独立构建

[英]Dependencies relative to Gradle subprojects which are also buildable independently

Background 背景

I've inherited an old, extremely complicated Gradle-based Java project with many sub-projects. 我继承了一个古老的,极其复杂的基于Gradle的Java项目,其中包含许多子项目。 Many of these have closed-source *.jar libraries that should not leak to other (sub-)projects in order to avoid namespace clashes when multiple projects use different versions of the "same" library. 其中许多具有闭源*.jar库,这些库不应泄漏给其他(子)项目,以避免当多个项目使用不同版本的“相同”库时发生命名空间冲突。

I'm trying to update the project to use some new versions of some of these libraries and in general clean up the dependencies, since development has become extremely complicated. 我正在尝试更新项目,以使用其中某些库的某些新版本,并通常清理依赖项,因为开发变得极为复杂。 To make things worse, one project is nested as a Git submodule , which is supposed to be able to be built either independently or as a subproject of the main Gradle project I'm working with. 更糟糕的是,有一个项目是嵌套的Git的子模块 ,它应该是能够独立作为主要项目摇篮我工作的一个子项目,待建。

The Git submodule Git子模块

Here is a simplified structure analogous to the Git submodule/Gradle project/Gradle sub-project: 这是类似于Git子模块/ Gradle项目/ Gradle子项目的简化结构:

robotcontroller
+--.git
+--gradle
+--libs
+--planning
|  +--src
|  +--build.gradle
+--plugins
|  +--nao
|  |  +--libs
|  |  |  +--robocommons.jar
|  |  +--src
|  |  +--build.gradle
|  +--pepper
|  |  +--libs
|  |  |  +--graphadapter.jar
|  |  +--src
|  |  +--build.gradle
+--build.gradle
+--gradlew
+--gradlew.bat
+--settings.gradle

plugins/nao/build.gradle : plugins/nao/build.gradle

dependencies {
    compile project(':planning')
    // This is inside the subproject's "libs/" dir
    compile name: 'robocommons'
    compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.3'
}

[rootProject, this].each {
    it.repositories {
        flatDir {
            dirs "${rootDir}/plugins/nao/libs/"
        }
    }
}

plugins/pepper/build.gradle : plugins/pepper/build.gradle

dependencies {
    compile project(':planning')
    // This is inside the subproject's "libs/" dir
    compile name: 'graphadapter'
    compile group: 'com.google.guava', name: 'guava', version: '19.0'
}

[rootProject, this].each {
    it.repositories {
        maven {
            // Some proprietary, closed-source repo
        }
        flatDir {
            dirs "${rootDir}/plugins/pepper/libs/"
        }
    }
}   

plugins/build.gradle : plugins/build.gradle

dependencies {
    compile project(':plugins:nao')
    compile project(':plugins:pepper')
}

build.gradle : build.gradle

// Stuff like plugins here
...

allprojects {
  repositories {
    flatDir {
      dirs "${rootDir}/libs"
    }
    jcenter()

    maven {
        // Some other proprietary repo here
    }
  }

  dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'
  }
}

dependencies {
    compile subprojects
}

// Stuff like javadoc and sourceJar tasks
...

settings.gradle : settings.gradle

include 'planning'
include 'plugins'
include 'plugins:nao'
include 'plugins:pepper'

The "root" Git repository “根” Git存储库

The Gradle project and all of its sub-projects above not only need to be able to be built on their own, but the project is itself a sub-project of another Gradle project, which is in a different Git repository: Gradle项目及其上面的所有子项目不仅需要能够自己构建,而且该项目本身是另一个Gradle项目的子项目,该项目位于不同的Git存储库中:

complicatedrobotproject
+--.git
+--gradle
+--robotcontroller@SOMEREVISION // This is managed by the ".gitmodules" file
+--robocommons // A different, partially-compatible version of the source code used to make "robocommons.jar" is here
|  +--src
|  +--build.gradle
+--.gitmodules
+--build.gradle
+--gradlew
+--gradlew.bat
+--settings.gradle

build.gradle : build.gradle

allprojects {
    repositories {
        flatDir {
            dirs "${rootDir}/robotcontroller/libs"
        }
    }
}

dependencies {
    // some external dependencies
    ...
    compile project(":robotcontroller")
    compile project(":robocommons")

    // TEST
    testCompile group: 'junit', name: 'junit', version: '4.12'
}

settings.gradle : settings.gradle

include 'robocommons'
include 'robotcontroller:planning'
include 'robotcontroller:plugins'
include 'robotcontroller:plugins:nao'
include 'robotcontroller:plugins:pepper'

Problem 问题

In the example above, my immediate goal is to replace the source code found at complicatedrobotproject/robocommons with robocommons.jar . 在上面的示例中,我的近期目标是用robocommons.jar替换在complicatedrobotproject/robocommons找到的源代码。 However, the only way to build the project is with a modified version of the Git submodule robotcontroller that actually depends on that: 但是,构建项目的唯一方法是使用Git子模块robotcontroller的修改版本,该版本实际上取决于该版本:

robotcontroller/plugins/nao/build.gradle from revision SOMEREVISION : 修订版SOMEREVISION robotcontroller/plugins/nao/build.gradle SOMEREVISION

dependencies {
    compile name ':robocommons' // When building "complicatedrobotproject", this in fact links "robocommons" the directory, not "robocommons.jar"!
    compile project(':robotcontroller:planning')
    compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.3'
}

By adding :robotcontroller to the dependencies, the project complicatedrobotproject can be built, but robotcontroller cannot be built as a standalone Gradle project. 通过将:robotcontroller添加到依赖项中,可以构建complicatedrobotproject :robotcontroller项目,但不能将robotcontroller构建为独立的Gradle项目。 Taking that qualifier then makes the latter buildable at the expense of the former. 然后,采用该限定符可以使后者可构建,但要牺牲前者。 The classes present in robocommons.jar that are also present in the directory robocommons are largely but not completely equivalent. 存在于类robocommons.jar是也出现在目录robocommons很大程度上但不完全等同。 Ultimately, I want to replace both with a proper external dependency to eg compile group: 'com.complicatedrobots', name: 'robocommons', version: '2.0.3' , but that will require a lot of re-implementation, and I first need to sort out this dependency nightmare. 最终,我想用适当的外部依赖项来替换两者 ,例如compile group: 'com.complicatedrobots', name: 'robocommons', version: '2.0.3' ,但这将需要大量重新实现,而我首先需要解决这种依赖的噩梦。

My task is not to make the project make sense; 我的任务不是使项目有意义。 As much as this makes my head hurt, I just need both Git repositories to be buildable and also using a single version of robocommons across all Gradle projects, regardless of which Git repository is being built. 尽管这让我很robocommons ,但我只需要既可以构建Git仓库,又可以在所有Gradle项目中使用单个版本的robocommons ,无论构建哪个Git仓库。 I can't even think about the problem straight because every single possibility I think of blocks out some other thing that needs to work. 我什至无法直接考虑问题,因为我想到的每一种可能性都会阻止其他需要解决的问题。

I can't say I understand what's happening in that build and I feel your pain. 我不能说我了解该构建中正在发生的事情,并且我感到您的痛苦。 The first thing I would say is that composite builds may offer a pathway to a "normal", maintainable build, allowing you to keep robotcontroller as a separate project. 我要说的第一件事是, 复合构建可能会提供通往“正常”,可维护构建的途径,从而使您可以将robotcontroller保留为单独的项目。 If you go down this route, you will have to remove the `include ":robotcontroller" from the parent's settings.gradle file and replace it with the equivalent composite build configuration. 如果沿这条路线走,则必须从父级的settings.gradle文件中删除`include“:robotcontroller”并将其替换为等效的复合构建配置。

That said, I think you can get this working fairly easily, because most of the pieces appear to be in place. 就是说,我认为您可以很轻松地完成此工作,因为大部分内容似乎都已准备就绪。 I would do this: 我会这样做:

  1. Move all of those JARs currently in plugins/*/libs into robotcontroller/libs , adding a version to their file names 将当前在plugins / * / libs中的所有这些JAR移至robotcontroller / libs中 ,在其文件名中添加一个版本

  2. Update all the dependencies on those JARs so that they include the appropriate version 更新这些JAR上的所有依赖项,以便它们包含适当的版本

  3. Remove the /robocommons directory 删除/ robocommons目录

You see, robotcontroller/libs appears to already be set up as a flat directory repository in both robotcontroller and the parent project. 您会看到, robotcontroller / libs似乎已经在robotcontroller和父项目中都设置为平面目录存储库。 It seems to me that the only reason the problematic libraries are in project-specific directories is because they don't have version numbers in their names to distinguish them. 在我看来,有问题的库位于特定于项目的目录中的唯一原因是因为它们的名称中没有版本号来区分它们。 By adding the version number, you can keep them side by side in the same directory. 通过添加版本号,您可以将它们并排放置在同一目录中。

Does that make sense? 那有意义吗? Hope it helps anyway! 希望无论如何能有所帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM