18

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

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

毕业项目给我

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的工件,它们是空的,因为这实际上不是一个项目,只是子目录apicore是正确的 Java 项目。

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

4

3 回答 3

19

您可以尝试使用他们在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' 
} 
于 2012-07-02T14:37:56.040 回答
2

从 Gradle 6.7 开始,Gradle 用户手册建议不要使用“跨项目配置”功能使用subprojectsand来配置子项目allprojects

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

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

Gradle 推荐的组织构建逻辑的方法是使用它的插件系统。插件应该定义子项目的类型。事实上,Gradle 核心插件的建模方式相同——例如,Java 插件配置一个通用的 java 项目,而Java 库插件在内部应用Java 插件并配置特定于 Java 库的方面。同样,Application Plugin应用和配置Java PluginDistribution Plugin

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

我们建议将约定插件的源代码和测试放在项目根目录的特殊 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插件,这并不会买太多。您正在用另一个替换一个插件包含。但是,一旦您最终获得比这更多的共享构建逻辑,它就开始在跨项目一致性和减少重复代码方面获得回报。

于 2020-12-27T03:01:58.243 回答
1

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

project.getBuildFile().exists()
于 2021-02-04T10:42:05.910 回答