如何生成、编译、jar 和依赖一个 gradle 模块

How to generate, compile, jar, and depend on a gradle module

我有一个 Java Gradle 项目,它使用指定的 API OpenAPI。我使用了 org.openapi.generator 插件来生成源代码以及完整的 Gradle 模块。

我希望有一种方法可以定义生成、编译、jar 步骤,这样我就可以让其他模块依赖于生成的模块。

# api/build.gradle:
plugins {
    id 'java'
    id "org.openapi.generator" version "5.0.0"
}

repositories {
    mavenCentral()
}

dependencies {
    testImplementation group: 'junit', name: 'junit', version: '4.12'
}

compileJava.dependsOn "openApiGenerate"

openApiGenerate {
    generatorName = "java"
    inputSpec = "$projectDir/src/main/openapi/spec.yaml".toString()
    outputDir = "$buildDir/generated"
    apiPackage = "com.example.api"
    invokerPackage = "com.example.api.invoker"
    modelPackage = "com.example.api.model"
    configOptions = [
            dateLibrary: "java8",
            library    : "native"
    ]
    groupId = "com.example"
    id = "api"
}

gradlew api:openApiGenerate 生成(忽略无关文件):

api/build/generated/
├── build.gradle
├── pom.xml
├── settings.gradle
└── src
    ├── main/java/...
    └── test/java/...

有没有什么方法可以委托、包含或依赖项目中其他模块生成的这个模块?生成的模块具有可靠的group:artifact:version坐标。

即我希望能够在项目的其他地方指定 com.example:api:1.0


我已经通读了https://docs.gradle.org/current/userguide/composite_builds.html,因为它似乎接近我的预期,但我是Gradle的新手,而且有点深入。

我已经尝试覆盖 api/build.gradle 中的主要和测试源集,但我不喜欢必须从 api/build/generated/build.gradle.

中复制和粘贴依赖项

我找到了 https://docs.gradle.org/current/userguide/declaring_dependencies.html#sec:dependency-types,其中包含一个诱人的示例,但由于它是仅源依赖项而失败了。

dependencies {
    implementation files("$buildDir/classes") {
        builtBy 'compile'
    }
}

我查看了这个示例,但我如何依赖一个尚不存在的项目 (api/build/generated/)?

dependencies {
    implementation project(':shared')
}

好问题!我没有一个完美的答案,但希望以下内容仍然对您有所帮助。

建议的方法

我会将依赖于生成的 API 的模块的 builds 与生成的 build 完全分开API。此类构建之间的唯一联系应该是依赖声明。这意味着,您必须手动确保首先构建 API 生成项目,然后才构建依赖项目。

默认情况下,这意味着在构建依赖项目之前还要发布 API 模块。此默认设置的替代方法确实是复合构建——例如,允许您在发布之前先在本地测试新生成的 API。但是,在 creating/running 复合构建之前,每次打开 API 文档更改时,您都必须手动 运行 生成 API 生成构建。

例子

假设您有项目 A,这取决于生成的 API。它的 Gradle 构建将包含如下内容:

dependencies {
    implementation 'com.example:api:1.0'
}

在 运行ning A 的构建之前,您首先必须 运行

  1. ./gradlew openApiGenerate 来自您的 api 项目。
  2. ./gradlew publish 来自 api/build/generated/ 目录。

然后 A 的构建可以从发布存储库中获取已发布的依赖项。

或者,您可以在本地删除第 2 步,然后 运行 A 的构建具有额外的 Gradle CLI 选项:

./gradlew --include-build $path_to/api/build/generated/ …

减少体力劳动的想法

我对此思考了很多,但没有想出任何完整的解决方案——因此我上面的建议并不完美。让我仍然总结一下我对 可以如何 工作的想法。

  • 您将有一个 Gradle 生成生成 API – 类似于您的 api 项目。该构建也将提交给您的 VCS。
  • 该构建会发布生成的 API,即使它自己不会生成。相反,它会以某种方式委托给 openApiGenerate 任务生成的 Gradle 构建。授权必须通过 GradleBuild task.
    进行 这就是症结所在:所有关于依赖项和已发布工件的信息都必须通过 Gradle CLI 有效地检索。我怀疑目前是否可行。
  • 依赖于 API 的项目然后可以在复合构建中包含类似 api 的 Gradle 项目,而无需上述方法中的手动麻烦。

用我实际使用的内容扩展@Chriki 的回答:

  1. api/ 定义为带有空 api/settings.gradle 文件的自己的项目。

    这告诉 gradle 这是一个独立的项目。

  2. 定义 api 模块:

    # api/build.gradle
    plugins {
       id 'java'
       id "org.openapi.generator" version "5.0.0"
    }
    
    repositories {
       mavenCentral()
    }
    
    openApiGenerate {
       generatorName = "java"
       inputSpec = "$projectDir/src/main/openapi/specification.yaml"
       outputDir = "$buildDir/generated"
       apiPackage = "com.example.api"
       invokerPackage = "com.example.api.invoker"
       modelPackage = "com.example.api.model"
       configOptions = [
          dateLibrary: "java8",
          library    : "native"
       ]
       groupId = "com.example"
       id = "api"
       version = "1.0.0"
    }
    

    注意groupid(以及version)明确定义了它的maven坐标。

  3. 包含带有替换的构建,以便依赖者可以只使用它的 Maven 坐标:

    # settings.gradle
    
    includeBuild('api/build/generated') {
        dependencySubstitution {
            substitute module('com.example:api') with project(':')
        }
    }
    

    ... 在其他模块中:

    # app/build.gradle
    
    dependencies {
       implementation group: 'com.example', name: 'api'
    }
    

    ./gradlew --include-build api/build/generated 相比,它的主要优势在于 [my] IDE 也会 'link' 这一切。

  4. 生成 API 库:

     ./gradlew --project-dir api/ openApiGenerate
    
  5. Build/run主项目:

     ./gradlew build
     ./gradlew run