如何使用 Gradle 构建 Google 协议缓冲区和 Kotlin?

How to build Google protocol buffers and Kotlin using Gradle?

我正在尝试构建一个使用 Google 协议缓冲区和使用 Gradle 的 Kotlin 的项目。我希望将原型文件编译成 Java 源代码,然后从我的 Kotlin 代码中调用它。

我的源文件是这样排列的:

src/main/proto/*.proto
src/main/kotlin/*.kt
src/test/kotlin/*.kt

这是我的 build.gradle 文件:

version '1.0-SNAPSHOT'

apply plugin: 'kotlin'
apply plugin: 'java'
apply plugin: 'com.google.protobuf'

repositories {
    mavenCentral()
    maven { url "http://dl.bintray.com/kotlin/kotlin-eap-1.1" }
}


buildscript {
    ext.kotlin_version = '1.1-M02'

    repositories {
        mavenCentral()
        maven { url "http://dl.bintray.com/kotlin/kotlin-eap-1.1" }
    }

    dependencies {
        classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.0'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

protobuf {
    protoc {
        artifact = 'com.google.protobuf:protoc:3.0.0'
    }
}

dependencies {
    compile 'com.google.protobuf:protobuf-java:3.0.0'
    compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    testCompile 'junit:junit:4.12'
}

当我 运行 ./gradlew assemble 时,我在 :compileKotlin 期间遇到了一堆 "Unresolved reference" 错误。之后我可以看到没有生成 Java 个源文件,所以看起来根本没有调用 proto 编译器。

如果我删除 apply plugin: 'kotlin' 行,那么 ./gradlew assemble 会成功生成 Java 源代码,但是我的 Kotlin 源代码当然不会被编译。

如何修复我的 build.gradle 以便我可以从 Kotlin 调用我的 protobuf 代码?

我可以通过在 build.gradle.

中添加两行来实现它

第一行将 proto 编译器生成 Java 代码的目录添加到 :compileKotlin 查找 Java 的目录 source:

sourceSets.main.java.srcDirs += 'build/generated/source/proto/main/java'

第二个确保在调用 :compileKotlin 之前(重新)生成 Java 代码:

compileKotlin.dependsOn ':generateProto'

对于 Kotlin 和 Android:

android {

    sourceSets {
        debug.java.srcDirs += 'build/generated/source/proto/debug/java'
        release.java.srcDirs += 'build/generated/source/proto/release/java'
    }
}

必须为每种构建类型添加一个额外的源目录。在此示例中,有两种构建类型:debugrelease.

如果您使用的是 grpc,则必须为每个构建类型添加另一行:

android {

    sourceSets {
        debug.java.srcDirs += 'build/generated/source/proto/debug/java'
        debug.java.srcDirs += 'build/generated/source/proto/debug/grpc'
        release.java.srcDirs += 'build/generated/source/proto/release/java'
        release.java.srcDirs += 'build/generated/source/proto/release/grpc'
    }
}

至少对于 Kotlin 1.0.6、protobuf-gradle-plugin0.8.0、protobuf 3.2.x 和 grpc 1.x,任务顺序不需要 fiddle .

如果您在 android 中使用多种构建类型和风格,并且使用下面的 protobuf-lite 和 kotlin。

例如,我有 debugrelease 使用 demoprod 构建,它将创建 demoDebugdemoReleaseprodDebugprodRelease 变体。

然后使用

`

android{
    sourceSets {
        debug.java.srcDirs += 'build/generated/source/proto/demoDebug/javalite'
        debug.java.srcDirs += 'build/generated/source/proto/prodDebug/javalite'
        release.java.srcDirs += 'build/generated/source/proto/demoRelease/javalite'
        release.java.srcDirs += 'build/generated/source/proto/prodRelease/javalite'
      }
    }

`

将不同的 compileKotlin 与 generateProto 联系起来

tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
  if (getName() == 'compileDemoDebugKotlin')
    dependsOn(':app:generateDemoDebugProto')
  if (getName() == 'compileDemoReleaseKotlin')
    dependsOn(':app:generateDemoReleaseProto')
  if (getName() == 'compileProdDebugKotlin')
    dependsOn(':app:generateProdDebugProto')
  if (getName() == 'compileProdReleaseKotlin')
    dependsOn(':app:generateProdReleaseProto')
}

对于 gradle 设置:

plugins {
    id 'com.android.application'
    id 'kotlin-android'
    id 'com.google.protobuf' version "0.8.17"
}

然后在底部build.gradle

protobuf {
    protoc {
        artifact = "com.google.protobuf:protoc:3.10.0"
    }

    // Generates the java Protobuf-lite code for the Protobufs in this project. See
    // https://github.com/google/protobuf-gradle-plugin#customizing-protobuf-compilation
    // for more information.
    generateProtoTasks {
        all().each { task ->
            task.builtins {
                java {
                    option 'lite'
                }
            }
        }
    }
}