【问题标题】:Gradle multi project, how to deal with different rootDirsGradle多项目,如何处理不同的rootDirs
【发布时间】:2017-03-22 07:41:14
【问题描述】:

我的公司目前正在为其 Java 项目从 Ant 切换到 Gradle,但我坚持使用干净整洁的设置。假设我为一家为客户构建网站的公司工作,这些客户通常使用相同的根库(核心项目),但有一些特定的代码,这些代码放在子项目中。每个客户,我们建立一个新的子项目,这取决于核心项目。未来客户数量会增加。

目前我们有三个项目:

  • 一个核心项目。这应该单独运行,因为我们希望能够为此单独进行单元测试。
  • 两个子项目依赖于核心项目,但有一些自己的项目特定于该项目。

我成功地将整个 ant 构建转换为核心项目的 gradle 构建。我的想法是在核心中包含所有功能和项目结构,而仅在子项目中实际需要额外的功能。

这是我们文件夹结构的简短示例:

-- core
    - build.gradle
    - settings.gradle
    -- repository (our external jars used)
    -- Implementation
      -- source_code
        -- all the core project folders
      -- Projects
        -- Client A
          - build.gradle
          - settings.gradle
          -- more project specific folders
        -- Client B
          - build.gradle
          - settings.gradle
          -- more project specific folders

我经常使用 $rootDir 变量。核心的 settings.gradle 的一小部分如下所示:

project(':CoreProjectA').projectDir = new File(rootDir, 'Implementation/Source_code/Core/coreA')
project(':CoreProjectB').projectDir = new File(rootDir, 'Implementation/Source_code/Core/CoreB')

但还有更多。另外,在核心 build.gradle 中,我这样引用我们的存储库:

repositories {
   //All sub-projects will now refer to the same 'libs' directory
    flatDir {
        dirs "$rootDir/repository/lib/jaxb"
        //many more dirs here
    }
}

现在,当我从核心项目进行 gradle 构建时,这一切都很好。 我打算将下一段代码放在每个客户的子项目 build.gradle 中:

apply from: '../../../build.gradle'

当我从 Client A 文件夹运行 gradle 构建时,我的 rootDir 显然已经改变,现在,我的所有路径都无法在任何地方找到。

有什么方法可以以一种干净整洁的方式进行设置吗?这样以后每个添加的子项目都可以始终使用相同的结构吗?还是我必须为每个子项目完全赋予其自己的 build.gradle 和 settings.gradle?

我知道最后一个选项可行,但开销很大,而且对我来说似乎一点也不干净......

提前致谢!

【问题讨论】:

    标签: java gradle build.gradle


    【解决方案1】:

    我最近处理了一个类似的配置,所以让我解释一下我是如何构建 Gradle 基础架构的。由于您提到了很多要求,我希望我会错过其中的任何一个,您可以将我的方案应用于您的问题。

    一般

    我们实际上使用构建系统(如 Gradle)来让它们处理任何依赖项(项目、模块、任务)。那么,如果我们可以在 Gradle 中简单地定义依赖关系,我们为什么要在文件系统层次结构之类的东西中定义它呢?

    我会尽可能避免使用路径(约定优于配置),并尝试在构建脚本和依赖项中坚持使用 Gradle 项目。

    此外,如果您在核心 gradle.build 中定义依赖项,则应该只调用此 gradle 文件,即使您只想构建一个子项目。您的 apply from: '../../../build.gradle' 破坏了整个 Gradle 逻辑。相反,您应该使用 gradle :sub1:build 之类的东西来仅构建第一个子项目。

    第一种方法(以核心作为根项目)

    文件系统结构:

    core/
        build.gradle
        settings.gradle
        src/
            ...
        sub1/
            src/
                ...
            build.gradle [optional]
        sub2/
            src/
                ...
            build.gradle [optional]
    

    核心settings.gradle:

    include 'sub1'
    include 'sub2'
    

    核心build.gradle:

    allprojects {
         apply plugin: 'java'
    
         repositories {
             // define repos for all projects
         }
    }
    
    subprojects {
         dependencies {
             // let subprojects depend on core
             compile rootProject
         }
    }
    
    project(':sub1') {
         // define anything you want (e.g. dependencies) just for this subproject
         // alternative: use build.gradle in subproject folder
    }
    

    第二种方法(所有项目独立)

    文件系统结构:

    core/
        src/
            ...
        build.gradle [optional]
    sub1/
        src/
            ...
        build.gradle [optional]
    sub2/
        src/
            ...
        build.gradle [optional]
    build.gradle
    settings.gradle
    

    settings.gradle:

    include 'core'
    include 'sub1'
    include 'sub2'
    

    根'build.gradle'

    subprojects {
        apply plugin: 'java'
    
        repositories {
            // define repos for all projects
        }
    }
    
    configure(subprojects.findAll {it.name != 'core'}) {
        dependencies {
            // Add dependency on core for sub1 and sub2
            compile project(':core')
        }
    }
    
    project(':sub1') {
         // define anything you want (e.g. dependencies) just for this subproject
         // alternative: use build.gradle in subproject folder
    }
    

    这种方法提供了极大的灵活性,因为每个依赖逻辑都由 Gradle 处理,您永远不必将任何内容复制到另一个位置。只需更改依赖关系即可。

    来源

    Gradle Tutorial on Multi-project Builds

    Question in Gradle Forum

    【讨论】:

    • 嘿,太好了,我目前没有时间研究它,但我明天一定会好好看看这个。感谢您的详细回答,我认为您找到了一个好地方,但我会让您知道!到目前为止非常感谢!
    • 嘿伙计,对不起,我还不能回复你。工作太忙了,还没来得及看。如果它对我有帮助,肯定会投票给你的答案是正确的!不过,一个快速的问题,在您的两个答案中,您的文件夹结构略有不同。我看到子项目就在 build.gradle 文件夹下。有必要吗?
    • 没有必要,但我会推荐它。您仍然可以像以前一样设置项目目录。顺便说一句,如果您只想“修复”您的结构,Nikitas 的回答会为您提供帮助,不过我的方法对如何组织多项目构建提供了更一般的解释。
    【解决方案2】:

    您的子项目中似乎有额外的settings.gradle。这让 Gradle 认为子项目是一个独立的项目。如果您从子项目中删除settings.gradle,Gradle 将在文件系统层次结构中查找它,将在核心项目中找到一个,将创建正确的多模块项目,并且所有路径都应该正常工作。

    因此,只需删除额外的 settings.gradle 文件,您的构建就会正常工作。在子项目中使用build.gradle 非常好。

    【讨论】:

      【解决方案3】:

      我要感谢 Nikita,尤其是 lukegv 的详细回答,但我最终采用了不同的方法。

      我不想每次我们有一个新项目时都有一个主要的 gradle 构建和扩展它。此外,如果我的同事想为其中一个项目创建构建,我想让他们保持简单和合乎逻辑。

      因此,我保留了上述结构。在根 gradle.settings 但更改了

      project(':CoreProjectA').projectDir = new File(rootDir, 'Implementation/Source_code/Core/coreA')
      project(':CoreProjectB').projectDir = new File(rootDir, 'Implementation/Source_code/Core/CoreB')
      

      进入:

      project(':CoreProjectA').projectDir = new File(customRootDir, 'Implementation/Source_code/Core/coreA')
      project(':CoreProjectB').projectDir = new File(customRootDir, 'Implementation/Source_code/Core/CoreB')
      

      在每个项目中,我都有一个 properties.gradle,其中填写了 customRootDir(相对于项目目录)。

      这一切都像一个魅力。我可以进入任何项目文件夹并生成构建,同时使用根目录的 build.gradle 的功能。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-17
        • 2015-07-08
        • 2015-08-10
        • 1970-01-01
        相关资源
        最近更新 更多