Gradle 使用两个主要目录来执行和管理其工作

author gradle 2

1. Gradle User Home 目录

默认情况下,Gradle User Home (~/.gradleC:\Users\<USERNAME>\.gradle) 存储全局配置属性、初始化脚本、缓存和日志文件。

它可以通过环境变量 GRADLE_USER_HOME 设置。

请勿与 GRADLE_HOME 混淆,后者是 Gradle 的可选安装目录。

其大致结构如下

├── caches              (1)
│   ├── 4.8         (2)
│   ├── 4.9             (2)
│   ├── ⋮
│   ├── jars-3      (3)
│   └── modules-2       (3)
├── daemon          (4)
│   ├── ⋮
│   ├── 4.8
│   └── 4.9
├── init.d              (5)
│   └── my-setup.gradle
├── jdks                (6)
│   ├── ⋮
│   └── jdk-14.0.2+12
├── wrapper
│   └── dists           (7)
│       ├── ⋮
│       ├── gradle-4.8-bin
│       ├── gradle-4.9-all
│       └── gradle-4.9-bin
└── gradle.properties   (8)
1 全局缓存目录(用于存储非项目特定的所有内容)。
2 特定版本缓存(例如,支持增量构建)。
3 共享缓存(例如,用于依赖项的 artifacts)。
4 Gradle Daemon 的注册表和日志。
5 全局初始化脚本
6 工具链支持下载的 JDK。
7 Gradle Wrapper 下载的分发版。
8 全局Gradle 配置属性

清理缓存和分发版

Gradle 会自动清理其用户主目录。

默认情况下,当 Gradle daemon 停止或关闭时,清理工作在后台运行。

如果使用 --no-daemon,它会在构建会话结束后在前台运行。

以下清理策略会定期应用(默认情况下,每 24 小时一次)

  • 会检查所有 caches/<GRADLE_VERSION>/ 目录中的特定版本缓存是否仍在使用。

    如果没有,发布版本目录会在闲置 30 天后删除,快照版本会在闲置 7 天后删除。

  • 会检查 caches/ 中的共享缓存(例如 jars-*)是否仍在使用。

    如果没有 Gradle 版本仍在使用它们,它们将被删除。

  • 会检查当前 Gradle 版本在 caches/ 中使用的共享缓存文件(例如 jars-3modules-2)的最后访问时间。

    根据文件是可以在本地重新创建还是从远程仓库下载,它们将分别在 7 天或 30 天后删除。

  • 会检查 wrapper/dists/ 中的 Gradle 分发版是否仍在使用,即是否存在相应的特定版本缓存目录。

    未使用的分发版将被删除。

配置缓存和分发版的清理

可以配置各种缓存的保留期限。

缓存分为五类

  1. 发布版 Wrapper 分发版: 与发布版本对应的分发版和相关的特定版本缓存(例如 4.6.28.0)。

    未使用版本的默认保留期限为 30 天。

  2. 快照版 Wrapper 分发版: 与快照版本对应的分发版和相关的特定版本缓存(例如 7.6-20221130141522+0000)。

    未使用版本的默认保留期限为 7 天。

  3. 下载的资源: 从远程仓库下载的共享缓存(例如,缓存的依赖项)。

    未使用资源的默认保留期限为 30 天。

  4. 创建的资源: Gradle 在构建期间创建的共享缓存(例如,artifact 转换)。

    未使用资源的默认保留期限为 7 天。

  5. 构建缓存: 本地构建缓存(例如,build-cache-1)。

    未使用构建缓存条目的默认保留期限为 7 天。

每个类别的保留期限可以通过 Gradle User Home 中的初始化脚本独立配置

gradleUserHome/init.d/cache-settings.gradle.kts
beforeSettings {
    caches {
        releasedWrappers.setRemoveUnusedEntriesAfterDays(45)
        snapshotWrappers.setRemoveUnusedEntriesAfterDays(10)
        downloadedResources.setRemoveUnusedEntriesAfterDays(45)
        createdResources.setRemoveUnusedEntriesAfterDays(10)
        buildCache.setRemoveUnusedEntriesAfterDays(5)
    }
}
gradleUserHome/init.d/cache-settings.gradle
beforeSettings { settings ->
    settings.caches {
        releasedWrappers.removeUnusedEntriesAfterDays = 45
        snapshotWrappers.removeUnusedEntriesAfterDays = 10
        downloadedResources.removeUnusedEntriesAfterDays = 45
        createdResources.removeUnusedEntriesAfterDays = 10
        buildCache.removeUnusedEntriesAfterDays = 5
    }
}

调用缓存清理的频率也是可配置的。

有三种可能的设置

  1. DEFAULT: 清理在后台定期执行(目前每 24 小时一次)。

  2. DISABLED: 永不清理 Gradle User Home。

    这在使用临时性 Gradle User Home 或希望将清理延迟到某个明确时间点的情况下非常有用。

  3. ALWAYS: 在每次构建会话结束时执行清理。

    这在希望确保清理已发生后再进行下一步操作的情况下非常有用。

    然而,这会在构建期间(而不是在后台)执行缓存清理,这可能会耗费大量资源,因此此选项仅应在必要时使用。

要禁用缓存清理

gradleUserHome/init.d/cache-settings.gradle.kts
beforeSettings {
    caches {
        cleanup = Cleanup.DISABLED
    }
}
gradleUserHome/init.d/cache-settings.gradle
beforeSettings { settings ->
    settings.caches {
        cleanup = Cleanup.DISABLED
    }
}
缓存清理设置只能通过初始化脚本配置,并且应放置在 Gradle User Home 的 init.d 目录下。这有效地将缓存清理的配置与这些设置适用的 Gradle User Home 关联起来,并限制了来自不同项目的不同冲突设置应用于同一目录的可能性。

多个 Gradle 版本共享一个 Gradle User Home

多个 Gradle 版本共享一个 Gradle User Home 是很常见的。

如上所述,Gradle User Home 中的缓存是特定于版本的。不同版本的 Gradle 只会对与其相关的特定版本缓存执行维护。

另一方面,有些缓存是在不同版本之间共享的(例如,依赖项 artifact 缓存或 artifact 转换缓存)。

从 Gradle 8.0 版本开始,可以配置缓存清理设置以使用自定义保留期限。然而,旧版本有固定的保留期限(7 天或 30 天,取决于缓存)。这些共享缓存可能会被具有不同缓存 artifact 保留设置的 Gradle 版本访问。

这意味着

  • 如果保留期限自定义,所有执行清理的版本将具有相同的保留期限。共享一个 Gradle User Home 对多个版本没有影响。

  • 如果为 Gradle 8.0 或更高版本自定义了使用比之前固定期限更短的保留期限,也不会有影响。

    了解这些设置的 Gradle 版本将比之前固定的保留期限更早清理 artifact,而旧版本实际上不会参与共享缓存的清理。

  • 如果为 Gradle 8.0 或更高版本自定义了使用比之前固定期限更长的保留期限,旧版本的 Gradle 可能会比配置的时间更早清理共享缓存。

    在这种情况下,如果希望为较新版本保持这些共享缓存条目更长的保留期限,它们将无法与旧版本共享一个 Gradle User Home。它们将需要使用一个单独的目录。

与 8.0 版本之前的 Gradle 版本共享 Gradle User Home 的另一个考虑因素是,用于配置缓存保留设置的 DSL 元素在早期版本中不可用,因此在版本之间共享的任何初始化脚本中都必须考虑到这一点。这可以通过有条件地应用与版本兼容的脚本轻松处理。

与版本兼容的脚本应位于 init.d 目录之外的其他位置(例如子目录),这样它就不会自动应用。

为了以版本安全的方式配置缓存清理

gradleUserHome/init.d/cache-settings.gradle.kts
if (GradleVersion.current() >= GradleVersion.version("8.0")) {
    apply(from = "gradle8/cache-settings.gradle.kts")
}
gradleUserHome/init.d/cache-settings.gradle
if (GradleVersion.current() >= GradleVersion.version('8.0')) {
    apply from: "gradle8/cache-settings.gradle"
}

与版本兼容的缓存配置脚本

gradleUserHome/init.d/gradle8/cache-settings.gradle.kts
beforeSettings {
    caches {
        releasedWrappers { setRemoveUnusedEntriesAfterDays(45) }
        snapshotWrappers { setRemoveUnusedEntriesAfterDays(10) }
        downloadedResources { setRemoveUnusedEntriesAfterDays(45) }
        createdResources { setRemoveUnusedEntriesAfterDays(10) }
        buildCache { setRemoveUnusedEntriesAfterDays(5) }
    }
}
gradleUserHome/init.d/gradle8/cache-settings.gradle
beforeSettings { settings ->
    settings.caches {
        releasedWrappers.removeUnusedEntriesAfterDays = 45
        snapshotWrappers.removeUnusedEntriesAfterDays = 10
        downloadedResources.removeUnusedEntriesAfterDays = 45
        createdResources.removeUnusedEntriesAfterDays = 10
        buildCache.removeUnusedEntriesAfterDays = 5
    }
}

缓存标记

从 Gradle 8.1 版本开始,Gradle 支持使用 CACHEDIR.TAG 文件标记缓存。

它遵循缓存目录标记规范中描述的格式。此文件的目的是允许工具识别不需要搜索或备份的目录。

默认情况下,Gradle User Home 中的 cacheswrapper/distsdaemonjdks 目录会用此文件标记。

配置缓存标记

缓存标记功能可以通过 Gradle User Home 中的初始化脚本配置

gradleUserHome/init.d/cache-settings.gradle.kts
beforeSettings {
    caches {
        // Disable cache marking for all caches
        markingStrategy = MarkingStrategy.NONE
    }
}
gradleUserHome/init.d/cache-settings.gradle
beforeSettings { settings ->
    settings.caches {
        // Disable cache marking for all caches
        markingStrategy = MarkingStrategy.NONE
    }
}
缓存标记设置只能通过初始化脚本配置,并且应放置在 Gradle User Home 的 init.d 目录下。这有效地将缓存标记的配置与这些设置适用的 Gradle User Home 关联起来,并限制了来自不同项目的不同冲突设置应用于同一目录的可能性。

2. 项目根目录

项目根目录包含您项目的所有源文件。

它还包含 Gradle 生成的文件和目录,例如 .gradlebuild

前者通常会提交到版本控制,而后者是 Gradle 用于支持增量构建等功能的临时文件。

典型的项目根目录结构如下所示

├── .gradle                 (1)
│   ├── 4.8             (2)
│   ├── 4.9                 (2)
│   └── ⋮
├── build               (3)
├── gradle
│   └── wrapper             (4)
├── gradle.properties   (5)
├── gradlew                 (6)
├── gradlew.bat         (6)
├── settings.gradle.kts     (7)
├── subproject-one      (8)
|   └── build.gradle.kts    (9)
├── subproject-two      (8)
|   └── build.gradle.kts    (9)
└── ⋮
1 Gradle 生成的项目特定缓存目录。
2 特定版本缓存(例如,支持增量构建)。
3 此项目的构建目录,Gradle 在其中生成所有构建 artifact。
4 包含Gradle Wrapper 的 JAR 文件和配置。
5 项目特定Gradle 配置属性
6 使用Gradle Wrapper 执行构建的脚本。
7 项目的settings 文件,其中定义了子项目列表。
8 通常,一个项目组织成一个或多个子项目。
9 每个子项目都有自己的 Gradle 构建脚本。

项目缓存清理

从 4.10 版本开始,Gradle 会自动清理项目特定缓存目录。

构建项目后,.gradle/8.14/ 中的特定版本缓存目录会定期(最多每 24 小时一次)检查是否仍在使用。如果 7 天内未使用,则会删除。