使用空项目进行多项目构建



将多项目 Gradle 结构应用于我们的项目时,我的 settings.gradle 如下所示:

include "source:compA:api"
include "source:compA:core"
include "source:compB"

Gradle 项目给我

Root project 'tmp'
--- Project ':source'
     +--- Project ':source:compA'
     |    +--- Project ':source:compA:api'
     |    --- Project ':source:compA:core'
     --- Project ':source:compB'

这正是目录结构!
在我的根目录中,我有一个build.gradle,它将java插件应用于所有子项目:

subprojects {
    apply plugin: 'java'
}

在构建时,我最终有 :source:compA 的工件是空的,因为这实际上不是一个项目,只是子目录 api核心是适当的 Java 项目。

避免空工件的最佳方法是什么?

您可以尝试使用他们在 Gradle 自己的 settings.gradle 文件中使用的技巧。请注意每个子项目如何位于'subprojects/${projectName}'文件夹中,但subprojects文件夹本身不是项目。

因此,在您的情况下,您可以执行以下操作:

include "source:compA-api"
include "source:compA-core"
include "source:compB"
project(':source:compA-api').projectDir = new File(settingsDir, 'source/compA/api')
project(':source:compA-core').projectDir = new File(settingsDir, 'source/compA/core')

我故意省略了compAapi之间的冒号,以确保source:compA不会被评估为项目容器。

或者,您可以尝试通过执行以下操作来排除source:compA项目,使其无法应用java插件:

def javaProjects() { 
  return subprojects.findAll { it.name != 'compA' }
} 
configure(javaProjects()) { 
  apply plugin: 'java' 
} 

编辑:或者,您可以尝试这样的事情(根据自己的喜好进行调整):

def javaProjects() { 
  return subprojects.findAll { new File(it.projectDir, "src").exists() }
} 
configure(javaProjects()) { 
  apply plugin: 'java' 
} 
从 Gradle

6.7 开始,Gradle 用户手册建议不要使用 subprojectsallprojects 使用"跨项目配置"功能来配置子项目:

在子项目之间共享构建逻辑的另一种不鼓励的方法是通过subprojects {}allprojects {} DSL构造进行跨项目配置。通过交叉配置,可以将生成逻辑注入到子项目中,这在查看子项目的生成脚本时并不明显,因此更难理解特定子项目的逻辑。从长远来看,交叉配置通常会变得复杂,条件逻辑越来越多,维护负担也越来越重。交叉配置还会在项目之间引入配置-时间耦合,这可能会阻止按需配置等优化正常工作。

建议的方法是改用约定插件来定义共同特征:

Gradle 推荐的组织构建逻辑的方式是使用其插件系统。插件应该定义子项目的类型。事实上,Gradle 核心插件的建模方式相同 - 例如,Java 插件配置一个通用的 Java 项目,而 Java 库插件在内部应用 Java 插件并另外配置特定于 Java 库的各个方面。同样,应用程序插件应用并配置 Java 插件和分发插件。

您可以通过应用和配置核心和外部插件来编写自定义构建逻辑,并创建自定义插件来定义新的项目类型并配置特定于您的项目或组织的约定。对于本节开头的每个示例特征,我们可以编写一个插件来封装给定类型的子项目共有的逻辑。

我们建议将约定插件的源代码和测试放在项目根目录的特殊 buildSrc 目录中。有关 buildSrc 的更多信息,请参阅使用 buildSrc 来组织构建逻辑。

<小时 />

在您的特定情况下,您可以遵循 Gradle 示例中给出的方法:

├── buildSrc
│   ├── build.gradle
│   ├── src
│   │   ├── main
│   │   │   └── groovy
│   │   │       ├── source.java-conventions.gradle

buildSrc/build.gradle文件将仅包含以下groovy-gradle-plugin

plugins {
    id 'groovy-gradle-plugin'
}

buildSrc/src/main/groovy/source.java-conventions.gradle将包含 Java 项目的通用逻辑。 在您的示例中,您刚刚拥有 Java 插件的应用程序,但您将添加不会与非 Java 项目共享的 Java 插件的任何其他通用性:

plugins {
    id 'groovy-gradle-plugin'
}

然后,每个 Java 项目都将包含约定插件:

plugins {
    id 'source.java-conventions'
}

请注意,如果从字面上看,唯一常见的是java插件,这并没有多大好处;您正在用另一个插件替换一个插件包含。 但是,一旦你最终有了比这更多的共享构建逻辑,它就会开始在跨项目一致性和减少重复代码方面得到回报。

我有两种情况。 空的父目录被视为项目。 我们可以进行一些检查以忽略该项目。

project.getBuildFile().exists()

最新更新