【问题标题】:How to use Gradle "platforms" to align dependency versions in a multi-project setup?如何使用 Gradle“平台”在多项目设置中对齐依赖版本?
【发布时间】:2020-07-19 21:02:53
【问题描述】:

我正在尝试学习如何在多项目设置中使用“平台”来对齐项目之间的依赖版本。到目前为止,我已经看到:

  1. https://docs.gradle.org/6.2.1/userguide/platforms.html
  2. https://docs.gradle.org/6.2.1/userguide/dependency_management_terminology.html#sub::terminology_platform
  3. https://docs.gradle.org/6.2.1/userguide/dependency_version_alignment.html#sec:virtual_platform
  4. https://docs.gradle.org/6.2.1/userguide/dependency_constraints.html#sec:adding-constraints-transitive-deps
  5. https://docs.gradle.org/6.2.1/userguide/java_platform_plugin.html
  6. ... 以及一些试图找到示例的外部站点,例如 https://dzone.com/articles/gradle-goodness-use-bill-of-materials-bom-as-depen

我了解如何在项目中声明约束。我想我也了解如何为此目的使用 BOM。但是,我想为此目的使用“强制平台项目”,但这里有很多东西我不明白:

  1. 我是否必须使用“java 平台”插件?我们有非 Java 项目。我们的配置不太适合“api”和“运行时”存储桶。
  2. 即使我们都是 Java,对于任何一个项目,我们都不能为其“api”和“运行时”提供单独的版本。虽然我确实了解这在某些情况下可能提供的控制级别,但我不明白这些是如何协同工作以确保项目获得指定的依赖关系的。
  3. Gradle 如何知道使用平台的项目与平台规范之间要匹配哪些配置的约束? 我想我看到了定义“api”和平台中其他约束的示例,我“理解”了项目将通过声明 api platform(project(':platform')) 来引用它。我希望 Gradle 不会试图通过简单的名称匹配来将“api”与“api”匹配。我需要多个不同的依赖项配置来与同一个平台“配置”保持一致,无论它被称为什么。

总的来说,我没有找到足够的信息来对它的作用或工作原理有信心。有人可以填写空白或指向一些显示比上述更多示例和详细信息的文件吗?目前我不明白我应该为那个平台项目(它的build.gradle)实际写什么和/或如何从我们现有的项目中正确引用它。

谢谢!

更新 1:在https://discuss.gradle.org/t/can-someone-tell-me-what-i-am-doing-wrong-to-align-dependency-versions-across-projects/35601 发布了一个最小的实验来测试我(缺乏)对此的理解......

【问题讨论】:

    标签: gradle gradle-dependencies gradle-multi-project-build gradle-groovy-dsl


    【解决方案1】:

    我是否必须使用“java平台”插件?

    没有。如果您有非 Java 项目,则不应使用 Java 平台插件。正如插件名称所示,它适用于 Java 项目。

    Gradle 为 Java 项目提供官方平台插件,但除此之外的任何东西,例如 C++/Swift,您都需要推出自己的插件/平台实现。您可以参考source code 来帮助您实施。

    即使我们都是 Java,对于任何一个项目,我们都不能为其“api”和“运行时”提供单独的版本

    您不需要为每个配置设置单独的版本。 api 扩展自 implementationruntimeClasspath (runtimeOnly) 从 implementation 扩展。所以声明api 的依赖就足够了。参考依赖图here

    Gradle 如何知道在使用平台的项目和平台规范之间需要匹配哪些配置约束?

    通过您在项目中指定它的方式以及 Java 平台插件的平台实现。例如,给定以下平台:

    // my-platform
    
    plugins {
        `java-platform`
    }
    
    dependencies {
        constraints {
            api("commons-httpclient:commons-httpclient:3.1")
        }
    }
    

    我可以在项目中执行以下任何操作:

    dependencies {
        api(platform(":my-platform"))
        implementation(platform(":my-platform"))
        annotationProcessor(platform(":my-platform"))
    }
    

    我希望 Gradle 不会尝试通过简单的名称匹配将“api”与“api”匹配

    根据使用情况进行匹配。请参阅this 行和these 行。 api 只是 Gradle 为其插件选择的配置名称,请参阅 here。他们确实可以选择任何名称,但更有可能选择api/runtime 以保持与他们所拥有的相似。

    您会在平台上找到的大多数文档都是针对 Java 开发人员的。我相信这主要是因为平台的概念受到Maven's BOM的极大启发

    如果你真的想知道 Gradle 是如何在平台上做事的,那么要么痛苦地检查源代码,要么编写一个使用该平台的简单 Gradle 插件,然后使用GradleRunner 并使用断点进行调试。示例插件可能是:

    public class ExamplePlatformPlugin implements Plugin<Project> {
    
        @Override
        public void apply(Project project) {
            project.getRepositories().mavenCentral();
    
            DependencyHandler dependencies = project.getDependencies();
    
            // api(platform(""org.springframework.boot:spring-boot-dependencies:2.2.6.RELEASE"")
            Dependency springBootPlatform = dependencies.platform("org.springframework.boot:spring-boot-dependencies:2.2.6.RELEASE");
            dependencies.add(JavaPlugin.API_CONFIGURATION_NAME, springBootPlatform);
    
            // api("org.apache.commons:commons-lang3")
            dependencies.add(JavaPlugin.API_CONFIGURATION_NAME, "org.apache.commons:commons-lang3");
        }
    }
    

    【讨论】:

    • 谢谢!您为源代码提供的链接非常有用。我自己应该记得的。不过,仍然缺少细节。不过,这种“api 扩展实现”业务与我曾经从事过或将要从事的任何业务都不匹配。项目将他们的 API 公开为他们使用的一个子集,而不是超集,并且需要“实现”他们的 API(完全相反)。在你回答之前,我在discuss.gradle.org/t/… 发布了一个最小的实验来尝试一些东西 - 你可以看看吗?
    猜你喜欢
    • 1970-01-01
    • 2019-03-30
    • 1970-01-01
    • 2018-05-02
    • 1970-01-01
    • 1970-01-01
    • 2022-06-11
    • 2014-01-13
    • 2017-02-01
    相关资源
    最近更新 更多