Gradle 对 Maven POM Profile 的支持

目录

简介

Maven Profile 提供了在特定条件下(例如,如果设置了特定的系统属性)自定义构建时元数据的能力。一个典型的用例是为不同的运行时环境(例如 Linux 与 Windows)应用特定的配置。例如,正在构建的项目可能需要在这些不同的平台上使用不同的依赖。

在 Gradle 项目中实现构建时 Profile #

仔细想想,Maven Profile 在逻辑上只不过是有限的 if 语句。Gradle 不需要为此提供特殊的构造。为什么会这样呢?Gradle 使用编程语言(而不是 XML)来定义构建模型。这使您可以充分利用编程语言中的表达能力来定义配置的某些部分的条件。Gradle 的模型更丰富、更灵活,可以更精细地表达 Maven Profile 通常用于实现的各种目的。一个非常简单且常用的模式是将条件逻辑拆分为不同的脚本插件,以使条件构建逻辑尽可能模块化和可维护。以下代码片段演示了这样的实现

if (project.hasProperty('env') && project.getProperty('env') == 'prod') {
    apply from: 'gradle/production.gradle'
} else {
    apply from: 'gradle/development.gradle'
}

以上方法允许根据您需要的任何情况临时表达不同的配置。这类似于 Maven Profile 的方法,但更简洁、更灵活。

表达变体的条件配置的另一种方法是将变体作为一等公民。 AndroidC/C++ Gradle 插件采用了这种方法。这表明 Gradle 团队认为对于大多数场景来说,更好的方法是将构建定义中的变体作为一等公民,而不是以条件方式表达的东西。这种“变体即一等公民”的方法正在添加到 基于 JVM 的插件 中,以适应诸如 JDK 兼容性之类的变体,并深入嵌入到 Gradle 的依赖管理引擎中。

使用依赖于 Profile 的 Maven 依赖 #

我们已经讨论了 Maven Profile 在配置构建中的作用以及 Gradle 中的替代方法。由于 Gradle 支持依赖于基于 POM 的构件,我们还必须考虑 Maven Profile 如何影响依赖解析。

一些已发布的 Maven 构件,尤其是在公共 Maven 中央仓库中,依赖于其 POM Profile 中声明的信息来进行依赖解析过程。这种做法被 认为是一种应该避免的反模式,因为它会影响构建的可重现性。然而,它在实践中被使用,Gradle 1.12 引入了对一些影响依赖解析的 Profile 用法的支持。

Gradle 中支持的 Profile 标准 #

Gradle 考虑以下两个激活标准

  1. 默认激活的 Profile(Gradle 1.12 及更高版本可用)
  2. 在缺少系统属性时激活的 Profile(Gradle 2.0 及更高版本可用)

让我们看一些示例,演示这两种用例。

默认激活的 Profile #

Profile 可以被认为是默认激活的。此行为由激活元素 activeByDefault 控制。让我们考虑已发布的 POM 文件的以下 Profile 部分

<project>
    ...
    <profiles>
        <profile>
            <id>profile-1</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <dependencies>
                <dependency>
                    <groupId>org.apache.commons</groupId>
                    <artifactId>commons-lang3</artifactId>
                    <version>3.3.2</version>
                </dependency>
            </dependencies>
        </profile>
    </profiles>
</project>

我们可以看到元素 activeByDefault 设置为 true。在 Gradle 解析相应的构件时,名为 profile-1 的 Profile 将变为激活状态。此 Profile 声明了依赖 org.apache.commons:commons-lang3:3.3.2 作为传递性依赖。反过来,Gradle 将负责解析此依赖。

在缺少系统属性时激活的 Profile #

除了 activeByDefault 之外,另一种方法是通过缺少特定的系统属性来触发 Profile 的激活。让我们看一下另一个 POM 文件,该文件使用了这种类型的 Profile 激活

<project>
    ...
    <profiles>
        <profile>
            <id>profile-2</id>
            <property>
                <name>!env.type</name>
            </property>
        </profile>
    </profiles>
</project>

只要未定义系统属性 env.type,此 POM 文件将激活名为 profile-2 的 Profile。

Profile 的替代依赖解析方法 #

我们已经了解了 Maven Profile 如何用于表达构建配置中的变体,以及当使用 Maven 构件(该构件使用 Profile 作为其运行时定义的一部分)时,这如何影响 Gradle 依赖解析。我们还了解了下一代 Gradle 插件(Android、C/C++)如何采用不同的方法来处理变体,使其成为一等公民,并且这个概念也正在应用于 Gradle 对通用 JVM 语言的支持。这也会对依赖解析产生深刻的影响,类似于 Maven Profile 如何影响依赖解析。

将变体作为构建模型中的一等公民的一个重要好处是,可以利用此信息来提供变体感知的依赖解析。例如,当为具有调试符号的 x86 架构构建二进制文件时,应使用声明的依赖项的 x86 变体,最好是包含调试符号的变体(如果可用)。这将自动为整个传递性依赖图强制执行。在软件构建和依赖管理中,存在无数的变体情况。

Gradle 的创始人兼 Gradle 公司 CEO Hans Dockter 最近发布了 2014 Gradle 路线图,您将在其中看到变体感知的依赖管理是当前正在进行的关键项目。预计在未来一年中,您将看到 Gradle 在这个领域推出新的功能。

讨论