Code generation with multiple distinct outputs

I have a tool that generates server and client source code based on an API definition (kind of like Swagger), and I’d like to wrap it up in a Gradle plugin that helps developers run the code generator. We’d like projects to publish various server/client definitions.

Today, our plugin uses a multi-project setup, where users must configure:

  • the project containing the API def
  • the projects that are targets of the source generation
  • for target projects, evaluationDependsOn and dependencies blocks

So we end up with, for every API in the multi-project build, something that looks like:

foo-api
foo-java-server
foo-java-client
+ other language outputs (e.g. typescript, go, rust)

I’d like to find a way to simplify the setup of this for our consumers. We could explore, but are unsure how:

  1. Multiple output jars from the same project (e.g. have just foo-api, somehow enable other projects to take a dependency on the server or client jars, and this seems to break publishing)
  2. Automatic project creation (seems like this won’t be a thing in Gradle)
  3. Some other approach we’re not considering?

Messing around with the new software model a bit I think I get pretty close, but I can’t figure out the incantation for the maven-publish plugin to publish the jars this generates:

plugins {
  id 'jvm-component'
  id 'java-lang'
}

apply plugin: 'maven-publish'

model {
  components {
    apiObjects(JvmLibrarySpec) {
      sources {
        java {
          source.srcDir 'src/generated/api-objects'
          dependencies {
             module 'jackson-databind' group 'com.fasterxml.jackson.core'
          }
        }
      }
    }
    retrofitClient(JvmLibrarySpec) {
      sources {
        java {
          source.srcDir 'src/generated/retrofit-client'
          dependencies {
            library 'apiObjects'
            module 'com.squareup.retrofit2:retrofit'
          }
        }
      }
    }
  }
}