0

I am trying to build a GIT repository to store common protocol buffers. What I am trying to do is minimizing the common boilerplate code across different projects.

I am thinking something like the following structure. Hence, when an application include my source as a "git submodule", it can include only "necessary proto + Language".

rootProject
  |-- proto-1
  |     |--src
  |     |   |-- main
  |     |         |-- proto
  |     |               |-- proto-a.proto
  |     |               `-- proto-a.proto
  |     |-- Java
  |     |     |-- build.gradle.kts
  |     |-- Kotlin
  |     |     |-- build.gradle.kts  
  |     |-- JavaScript
  |           |-- build.gradle.kts
  |-- proto-2
  |     |--src
  |     |   |-- main
  |     |         |-- proto
  |     |               |-- proto-c.proto
  |     |               `-- proto-d.proto
  |     |-- Java
  |     |     |-- build.gradle.kts
  |     |-- Python
  |     |     |-- build.gradle.kts  
  |---- settings.gradle
  `---- build.gradle.kts

The above code works well, if I define protobuf and sourceSets for each build.gradle.kts, like

protobuf {
    generateProtoTasks {
        all().forEach {
            it.builtins {
                id("kotlin")
            }
        }
    }
}
sourceSets {
    main {
        proto {
            srcDir("../src/main/proto")
        }
    }
}

However, as you may see, the above code is duplicate across build.gradle.kts. If I can set up the above code in the rootpage build.gradle.kts, I think it will be very easy to use it.

This is my current build.gradle.kts for the root project. (Surely, this is incomplete)

allprojects {
    apply(plugin = "java")
    apply(plugin = "com.google.protobuf")

    repositories {
        maven {
            setUrl("https://nexus.yanolja.in/repository/maven-public/")
        }
    }

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

subprojects {
    apply(plugin = "java")
    val implementation by configurations
    dependencies {
        implementation("com.google.protobuf:protobuf-java:3.22.0")
    }
}
    val mainSource = project.the<SourceSetContainer>().findByName(SourceSet.MAIN_SOURCE_SET_NAME)
    mainSource?.allSource?.srcDir("../src/main/proto")

1 Answers1

0

This is a use-case for Gradle's convention plugins.

You can define those either in included builds or in buildSrc.

├── buildSrc
│   ├── build.gradle.kts
│   ├── settings.gradle.kts
│   ├── src
│   │   ├── main
│   │   │   └── kotlin
│   │   │       ├── myproject.protobuf.gradle.kts
// buildSrc/build.gradle.kts
plugins {
    `kotlin-dsl`
}

repositories {
    gradlePluginPortal() // so that external plugins can be resolved in dependencies section
}

dependencies {
    implementation("com.google.protobuf:protobuf-gradle-plugin:0.9.2") //depend on the protobuf plugin
}

Move all the logic you want in those projects that use protobuf into the convention plugin, using regular buildscript syntax.

// buildSrc/src/main/kotlin/myproject.protobuf.gradle.kts
plugins {
   java
   id("com.google.protobuf") 
}

repositories {
    maven {
        setUrl("https://nexus.yanolja.in/repository/maven-public/")
    }
}

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

dependencies {
    implementation("com.google.protobuf:protobuf-java:3.22.0")
}

val mainSource = project.the<SourceSetContainer>().findByName(SourceSet.MAIN_SOURCE_SET_NAME)
mainSource?.allSource?.srcDir("../src/main/proto")

Now you can just apply the convention plugin to your builds, via the plugin block.

plugins {
    id("myproject.protobuf")
}
Leonard Brünings
  • 12,408
  • 1
  • 46
  • 66