Как создать буферы протокола Google и Kotlin с помощью Gradle?

Я пытаюсь создать проект, который использует как буферы протокола Google, так и Kotlin, используя Gradle. Я хочу, чтобы прото файлы компилировались в источник 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. Впоследствии я вижу, что нет исходных файлов Java, поэтому кажется, что прото-компилятор вообще не вызывается.

Если я удаляю строку apply plugin: 'kotlin', то ./gradlew assemble успешно генерирует источник Java, но, конечно, мой источник Kotlin никогда не компилируется.

Как исправить мой build.gradle, чтобы я мог вызвать свой код protobuf из Kotlin?

Ответ 1

Мне удалось заставить это работать, добавив две строки в мой build.gradle.

Первая строка добавляет каталог, в котором прото-компилятор генерирует Java-код в каталоги :compileKotlin ищет источник Java:

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

Второе гарантирует, что код Java (re) сгенерирован перед вызовом :compileKotlin:

compileKotlin.dependsOn ':generateProto'

Ответ 2

Для Kotlin и Android:

android {

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

Для каждого типа сборки необходимо добавить дополнительный исходный каталог. В этом примере есть два типа сборки: debug и release.

Если вы используете 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 -plugin 0.8.0, protobuf 3.2.x и grpc 1.x ему не нужно возиться с порядком задачи.

Ответ 3

если вы работаете с несколькими типами сборки и ароматами в android и используете protobuf-lite ниже с kotlin.

например, у меня есть debug и release с demo и prod, которые создадут варианты demoDebug, demoRelease и prodDebug и prodRelease.

затем используйте

`

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'
      }
    }

`

связать разные компиляцииKotlin с помощью 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')
}