Search code examples
kotlingradleandroidxdatastore

Androidx Proto datastore gradle setup


I'm trying to get the new (alpha) android datastore using protobuf support configured in gradle using Kotlin DSL (build.gradle.kts). The first attempts are not generating any java source classes from the xxx.proto (made-up name) file that is present. The protobuf plugin is generating the correct android tasks, but running them generates nothing, so obviously the default setup is not finding the directory my initial xxx.proto file is located in. The existing doc is thin on gradle setup, especially for Kotlin Gradle DSL (most all the gradle doc from google so far is for groovy), and my initial attempts at defining the location of the xxx.proto file are not working.

Does anyone have or has anyone seen working gradle config that specifies a custom source directory for .proto file(s) using Kotlin (build.gradle.kts)?


Solution

  • Got it working after some experimentation and floundering, but a hack is involved. If anyone can suggest improvements, it would be appreciated. In case this is useful here are the config snippets from the working setup. Module is kotlin 1.4.21-2 multiplatform with android, ios64, and jvm targets, with more planned. It has the KMP default setup for source directories:

    src directories

    The .proto file is in src/androidMain/proto subdirectory.

    build.gradle.kts snippets are below. All the changes are in the android block, except for the plugin of course:

    plugins {
        id("com.android.library")
        kotlin("multiplatform")
        id("kotlinx-atomicfu")
        kotlin("plugin.serialization") version Versions.kotlinVersion
        id("com.google.protobuf") version "0.8.14"
    }
    ...
    kotlin {
    ... no changes here
    }
    ...
    android {
        ...
        sourceSets {
            ...
            getByName("main") {
                manifest.srcFile("src/androidMain/AndroidManifest.xml")
                java.srcDirs("src/androidMain/kotlin")
                assets.srcDirs(File("src/commonMain/resources"))
    
                withGroovyBuilder {
                    "proto" {
                       "srcDir" ("src/androidMain/proto")
                   }
                }
            }
        }
        protobuf {
            protoc {
                artifact = "com.google.protobuf:protoc:4.0.0-rc-2"
            }
            plugins {
                id("javalite") { artifact = "com.google.protobuf:protoc-gen-javalite:3.0.0" }
            }
            generateProtoTasks {
                all().forEach { task ->
                    task.builtins {
                        id("java") {
                            option("lite")
                        }
                    }
                    task.plugins{
                    }
                }
            }
        }
        dependencies {
            api("com.google.protobuf:protobuf-javalite:4.0.0-rc-2")
            implementation("androidx.datastore:datastore:1.0.0-alpha05")
            ...
        } 
    }
    

    Note the withGroovyBuilder hack in the android sourceset - the srcdir definition is required for the plugin to find the .proto file I had, but in the current version of the plugin I couldn't figure out the correct Kotlin DSL syntax. Seems like the plugin needs to define a Kotlin extension function to make this work better.

    It would be really nice if instead of requiring this stuff, that the datastore stuff could use the protobuf serialization available with kotlinx.serialization, and skip this java code generation step in gradle all together. But I'm sure that's down the road...

    Anyway, thanks in advance if anyone has improvements etc...