standalone pb plugin working!
This commit is contained in:
parent
59891678a5
commit
0f6677e0b1
12 changed files with 613 additions and 353 deletions
|
|
@ -37,6 +37,7 @@ dependencies {
|
||||||
testImplementation("io.kotest:kotest-property-jvm:$kotestVersion")
|
testImplementation("io.kotest:kotest-property-jvm:$kotestVersion")
|
||||||
testImplementation("io.kotest:kotest-assertions-json:$kotestVersion")
|
testImplementation("io.kotest:kotest-assertions-json:$kotestVersion")
|
||||||
testImplementation("io.mockk:mockk:1.12.0")
|
testImplementation("io.mockk:mockk:1.12.0")
|
||||||
|
|
||||||
//</editor-fold>
|
//</editor-fold>
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
package dev.adamko.gradle.pbandg
|
||||||
|
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.file.Directory
|
||||||
|
import org.gradle.api.file.ProjectLayout
|
||||||
|
import org.gradle.api.provider.Provider
|
||||||
|
|
||||||
|
object Constants {
|
||||||
|
const val PBG_SETTINGS_NAME = "pbAndG"
|
||||||
|
const val PBG_TASK_GROUP = PBG_SETTINGS_NAME// "pb-and-g"
|
||||||
|
const val PBG_LIBS_CONF_NAME = "protobufLibrary"
|
||||||
|
const val PBG_TASK_COMPILE = "protobufCompile"
|
||||||
|
|
||||||
|
val Project.pbAndGBuildDir: Provider<Directory>
|
||||||
|
get() = layout.pbAndGBuildDir
|
||||||
|
|
||||||
|
val ProjectLayout.pbAndGBuildDir: Provider<Directory>
|
||||||
|
get() = buildDirectory.dir(PBG_TASK_GROUP)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
package dev.adamko.gradle.pbandg
|
||||||
|
|
||||||
|
import dev.adamko.gradle.pbandg.settings.PBAndGSettings
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.artifacts.Configuration
|
||||||
|
|
||||||
|
|
||||||
|
class ProtobufCompilerDependency(
|
||||||
|
project: Project,
|
||||||
|
pluginSettings: PBAndGSettings,
|
||||||
|
private val conf: Configuration = project.configurations.create("protobufCompiler") {
|
||||||
|
this.description = "Define a single dependency that provides the protoc.exe for this system"
|
||||||
|
isVisible = false
|
||||||
|
isCanBeConsumed = false
|
||||||
|
isCanBeResolved = true
|
||||||
|
isTransitive = false
|
||||||
|
|
||||||
|
defaultDependencies {
|
||||||
|
add(pluginSettings.dependency.get())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
) : Configuration by conf
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
package dev.adamko.gradle.pbandg.pattern
|
||||||
|
|
||||||
|
import org.gradle.api.Plugin
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.kotlin.dsl.configure
|
||||||
|
import org.gradle.kotlin.dsl.hasPlugin
|
||||||
|
import org.gradle.kotlin.dsl.withType
|
||||||
|
import org.gradle.plugins.ide.idea.GenerateIdeaModule
|
||||||
|
import org.gradle.plugins.ide.idea.IdeaPlugin
|
||||||
|
import org.gradle.plugins.ide.idea.model.IdeaModel
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IntelliJ requires source dirs are configured first.
|
||||||
|
*
|
||||||
|
* https://github.com/google/protobuf-gradle-plugin/blob/master/src/main/groovy/com/google/protobuf/gradle/Utils.groovy#L128
|
||||||
|
*/
|
||||||
|
class IntelliJPattern : Plugin<Project> {
|
||||||
|
|
||||||
|
fun isIdeaPluginPresent(project: Project) = project.plugins.hasPlugin(IdeaPlugin::class)
|
||||||
|
|
||||||
|
override fun apply(project: Project) {
|
||||||
|
|
||||||
|
if (!isIdeaPluginPresent(project)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val genSrcDir = project.layout.buildDirectory.dir("protobuf/generated-sources")
|
||||||
|
val ktGenSrc = genSrcDir.map { it.dir("kotlin") }
|
||||||
|
val jGenSrc = genSrcDir.map { it.dir("java") }
|
||||||
|
|
||||||
|
project.mkdir(ktGenSrc)
|
||||||
|
project.mkdir(jGenSrc)
|
||||||
|
|
||||||
|
project.plugins.withType<IdeaPlugin> {
|
||||||
|
project.extensions.configure<IdeaModel> {
|
||||||
|
this.module.generatedSourceDirs.add(ktGenSrc.get().asFile)
|
||||||
|
this.module.generatedSourceDirs.add(jGenSrc.get().asFile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
project.tasks.withType<GenerateIdeaModule> {
|
||||||
|
doFirst {
|
||||||
|
project.mkdir(ktGenSrc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
package dev.adamko.gradle.pbandg.pattern
|
||||||
|
|
||||||
|
import dev.adamko.gradle.pbandg.task.ProtobufCompileTask
|
||||||
|
import org.gradle.api.Plugin
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.tasks.SourceSet
|
||||||
|
import org.gradle.kotlin.dsl.dependencies
|
||||||
|
import org.gradle.kotlin.dsl.findByType
|
||||||
|
import org.gradle.kotlin.dsl.getByName
|
||||||
|
import org.gradle.kotlin.dsl.withType
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension
|
||||||
|
|
||||||
|
class KotlinProjectConfiguration : Plugin<Project> {
|
||||||
|
|
||||||
|
override fun apply(project: Project) {
|
||||||
|
addSourceSets(project)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addSourceSets(project: Project) {
|
||||||
|
|
||||||
|
project.extensions.findByType<KotlinJvmProjectExtension>()?.apply {
|
||||||
|
|
||||||
|
val srcSet = project.extensions.getByName<SourceSet>(SourceSet.MAIN_SOURCE_SET_NAME)
|
||||||
|
|
||||||
|
project.tasks
|
||||||
|
.withType<ProtobufCompileTask>()
|
||||||
|
.map { it.generatedSources.get() }
|
||||||
|
.forEach { generatedSourcesDir ->
|
||||||
|
project.logger.lifecycle("-------\nadding generated sources $generatedSourcesDir\n-------")
|
||||||
|
|
||||||
|
srcSet.java {
|
||||||
|
srcDir(generatedSourcesDir.dir("java"))
|
||||||
|
srcDir(generatedSourcesDir.dir("kotlin"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
package dev.adamko.gradle.pbandg.pattern
|
||||||
|
|
||||||
|
|
||||||
|
import dev.adamko.gradle.pbandg.settings.PBAndGSettings
|
||||||
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.artifacts.Configuration
|
||||||
|
import org.gradle.api.artifacts.ExternalModuleDependency
|
||||||
|
import org.gradle.api.file.DirectoryProperty
|
||||||
|
import org.gradle.api.file.RegularFileProperty
|
||||||
|
import org.gradle.api.provider.Provider
|
||||||
|
import org.gradle.api.tasks.Internal
|
||||||
|
import org.gradle.api.tasks.OutputDirectory
|
||||||
|
import org.gradle.api.tasks.TaskAction
|
||||||
|
import org.gradle.kotlin.dsl.getByType
|
||||||
|
|
||||||
|
|
||||||
|
abstract class ProtocPrepareTask : DefaultTask() {
|
||||||
|
|
||||||
|
@Internal
|
||||||
|
val protocPluginConfig: Provider<PBAndGSettings> = project.provider {
|
||||||
|
project.extensions.getByType<PBAndGSettings>()
|
||||||
|
}
|
||||||
|
|
||||||
|
@get:OutputDirectory
|
||||||
|
val outputDirectory: DirectoryProperty = project.objects.directoryProperty()
|
||||||
|
.convention(protocPluginConfig.flatMap { it.protocWorkingDir })
|
||||||
|
|
||||||
|
@Internal
|
||||||
|
val protocOutput: RegularFileProperty = project.objects.fileProperty()
|
||||||
|
|
||||||
|
@Internal
|
||||||
|
val protocDependency: Provider<ExternalModuleDependency> =
|
||||||
|
protocPluginConfig.flatMap { it.dependency }
|
||||||
|
|
||||||
|
init {
|
||||||
|
super.setGroup("protobuf")
|
||||||
|
outputs.dir(outputDirectory)
|
||||||
|
}
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
fun action() {
|
||||||
|
|
||||||
|
val protocDep: Configuration = project.configurations.create("protoc") {
|
||||||
|
isVisible = false
|
||||||
|
isCanBeConsumed = false
|
||||||
|
isCanBeResolved = true
|
||||||
|
isTransitive = false
|
||||||
|
|
||||||
|
defaultDependencies {
|
||||||
|
add(protocDependency.get())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.lifecycle("Downloading protoc")
|
||||||
|
val resolvedProtocDep = protocDep.singleFile
|
||||||
|
logger.lifecycle("Downloaded $resolvedProtocDep")
|
||||||
|
|
||||||
|
project.sync {
|
||||||
|
from(resolvedProtocDep)
|
||||||
|
into(outputDirectory)
|
||||||
|
logger.lifecycle("Syncing from $resolvedProtocDep to ${outputDirectory.asFile.get().canonicalPath}")
|
||||||
|
protocOutput.set(outputDirectory.asFileTree.singleFile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,86 @@
|
||||||
|
package dev.adamko.gradle.pbandg
|
||||||
|
|
||||||
|
import dev.adamko.gradle.pbandg.settings.PBAndGSettings
|
||||||
|
import dev.adamko.gradle.pbandg.task.ProtobufCompileTask
|
||||||
|
import dev.adamko.gradle.pbandg.task.ProtobufPrepareLibrariesTask
|
||||||
|
import dev.adamko.gradle.pbandg.task.options.ProtocOutput.JavaOutput
|
||||||
|
import dev.adamko.gradle.pbandg.task.options.ProtocOutput.KotlinOutput
|
||||||
|
|
||||||
|
//plugins {
|
||||||
|
// `kotlin-dsl`
|
||||||
|
//}
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
base
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO investigate builtBy and sourceDirectorySet?
|
||||||
|
// project.objects.fileCollection().builtBy()
|
||||||
|
// val pbSrcSet = project.objects.sourceDirectorySet("protobuf", "protobuf")
|
||||||
|
|
||||||
|
//if (plugins.hasPlugin(IdeaPlugin::class)) {
|
||||||
|
// apply(IntelliJPattern())
|
||||||
|
//}
|
||||||
|
//if (plugins.hasPlugin("org.jetbrains.kotlin.jvm")) {
|
||||||
|
// apply(KotlinProjectConfiguration())
|
||||||
|
//}
|
||||||
|
|
||||||
|
val pbAndGSettings =
|
||||||
|
project.extensions.create(Constants.PBG_SETTINGS_NAME, PBAndGSettings::class, project)
|
||||||
|
|
||||||
|
//val protocDep = ProtobufCompilerDependency(project, pbAndGSettings)
|
||||||
|
val protocDep = project.configurations.create("protobufCompiler") {
|
||||||
|
this.description = "Define a single dependency that provides the protoc.exe for this system"
|
||||||
|
isVisible = false
|
||||||
|
isCanBeConsumed = false
|
||||||
|
isCanBeResolved = true
|
||||||
|
isTransitive = false
|
||||||
|
|
||||||
|
defaultDependencies {
|
||||||
|
add(pbAndGSettings.dependency.get())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val protobufLibraryDependencies: Configuration =
|
||||||
|
project.configurations.create(Constants.PBG_LIBS_CONF_NAME) {
|
||||||
|
isVisible = true
|
||||||
|
isCanBeConsumed = false
|
||||||
|
isCanBeResolved = true
|
||||||
|
isTransitive = false
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
project.dependencies {
|
||||||
|
protobufLibraryDependencies("com.google.protobuf:protobuf-javalite:3.19.1")
|
||||||
|
// implementation("com.google.protobuf:protobuf-javalite:3.19.1")
|
||||||
|
// implementation("com.google.protobuf:protobuf-kotlin-lite:3.19.1")
|
||||||
|
}
|
||||||
|
|
||||||
|
val protobufPrepareLibrariesTask =
|
||||||
|
project.tasks.register<ProtobufPrepareLibrariesTask>("protobufPrepareLibraries") {
|
||||||
|
librarySources.set(protobufLibraryDependencies)
|
||||||
|
}
|
||||||
|
|
||||||
|
//project.dependencies {
|
||||||
|
// protobufLibraryDependencies("com.google.protobuf:protobuf-javalite:3.19.1")
|
||||||
|
//// implementation("com.google.protobuf:protobuf-javalite:3.19.1")
|
||||||
|
//// implementation("com.google.protobuf:protobuf-kotlin-lite:3.19.1")
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
/** Convert `.proto` files to Kotlin */
|
||||||
|
val pbCompileTask = project.tasks.register<ProtobufCompileTask>(Constants.PBG_TASK_COMPILE) {
|
||||||
|
dependsOn(protocDep, protobufPrepareLibrariesTask)
|
||||||
|
|
||||||
|
protobufLibraryDirectories.add(protobufPrepareLibrariesTask.flatMap { it.librariesDirectory })
|
||||||
|
|
||||||
|
protocOutputs += KotlinOutput()
|
||||||
|
protocOutputs += JavaOutput()
|
||||||
|
|
||||||
|
val exe = protocDep.singleFile
|
||||||
|
logger.lifecycle("protoc.exe: $exe")
|
||||||
|
protocExecutable.set(exe)
|
||||||
|
}
|
||||||
|
|
||||||
|
project.tasks.assemble { dependsOn(pbCompileTask) }
|
||||||
|
|
@ -0,0 +1,103 @@
|
||||||
|
package dev.adamko.gradle.pbandg.settings
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.function.Supplier
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.artifacts.ExternalModuleDependency
|
||||||
|
import org.gradle.api.file.DirectoryProperty
|
||||||
|
import org.gradle.api.provider.Property
|
||||||
|
import org.gradle.api.provider.Provider
|
||||||
|
import org.gradle.kotlin.dsl.create
|
||||||
|
import org.gradle.kotlin.dsl.property
|
||||||
|
import org.gradle.nativeplatform.platform.Architecture
|
||||||
|
import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform
|
||||||
|
import org.gradle.nativeplatform.platform.internal.DefaultOperatingSystem
|
||||||
|
|
||||||
|
abstract class PBAndGSettings(private val project: Project) {
|
||||||
|
|
||||||
|
val protocWorkingDir: DirectoryProperty =
|
||||||
|
project.objects.directoryProperty()
|
||||||
|
.convention(project.rootProject.layout.projectDirectory.dir(".gradle/protoc"))
|
||||||
|
|
||||||
|
val protocVersion: Property<String> =
|
||||||
|
project.objects.property(String::class).convention("3.19.1")
|
||||||
|
|
||||||
|
val protocGroup: Property<String> =
|
||||||
|
project.objects.property(String::class).convention("com.google.protobuf")
|
||||||
|
|
||||||
|
val protocArtifactName: Property<String> =
|
||||||
|
project.objects.property(String::class).convention("protoc")
|
||||||
|
|
||||||
|
val protocArtifactExtension: Property<String> =
|
||||||
|
project.objects.property(String::class).convention("exe")
|
||||||
|
|
||||||
|
val operatingSystemProvider: Property<Supplier<DefaultOperatingSystem>> =
|
||||||
|
project.objects.property<Supplier<DefaultOperatingSystem>>()
|
||||||
|
.convention { DefaultNativePlatform.getCurrentOperatingSystem() }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should return one of
|
||||||
|
*
|
||||||
|
* * `linux`
|
||||||
|
* * `osx`
|
||||||
|
* * `windows`
|
||||||
|
*/
|
||||||
|
val operatingSystemName: Property<String> =
|
||||||
|
project.objects
|
||||||
|
.property<String>()
|
||||||
|
.convention(operatingSystemProvider.map { it.get().toFamilyName() })
|
||||||
|
|
||||||
|
private val architectureProvider: Provider<Architecture> =
|
||||||
|
project.provider { DefaultNativePlatform.getCurrentArchitecture() }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should return one of
|
||||||
|
*
|
||||||
|
* * `aarch_64`
|
||||||
|
* * `ppcle_64`
|
||||||
|
* * `x86_32`
|
||||||
|
* * `x86_64`
|
||||||
|
*/
|
||||||
|
val architectureName: Property<String> =
|
||||||
|
project.objects
|
||||||
|
.property<String>()
|
||||||
|
.convention(architectureProvider.map { it.name.replace("-", "_") })
|
||||||
|
|
||||||
|
private val classifierProvider: Provider<String> =
|
||||||
|
project.provider { "${operatingSystemName.get()}-${architectureName.get()}" }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default: concatenate [operatingSystemName] and [architectureName]
|
||||||
|
*
|
||||||
|
* Should return one of:
|
||||||
|
*
|
||||||
|
* * `linux-aarch_64`
|
||||||
|
* * `linux-ppcle_64`
|
||||||
|
* * `linux-x86_64`
|
||||||
|
* * `osx-x86_32`
|
||||||
|
* * `osx-x86_64`
|
||||||
|
* * `windows-x86_32`
|
||||||
|
*/
|
||||||
|
val classifier: Property<String> =
|
||||||
|
project.objects
|
||||||
|
.property<String>()
|
||||||
|
.convention(classifierProvider)
|
||||||
|
|
||||||
|
|
||||||
|
private val dependencyProvider: Provider<ExternalModuleDependency> =
|
||||||
|
project.provider {
|
||||||
|
project.dependencies.create(
|
||||||
|
group = protocGroup.get(),
|
||||||
|
name = protocArtifactName.get(),
|
||||||
|
version = protocVersion.get(),
|
||||||
|
classifier = classifierProvider.get(),
|
||||||
|
ext = protocArtifactExtension.get(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val dependency: Property<ExternalModuleDependency> =
|
||||||
|
project.objects
|
||||||
|
.property<ExternalModuleDependency>()
|
||||||
|
.convention(dependencyProvider)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,153 @@
|
||||||
|
package dev.adamko.gradle.pbandg.task
|
||||||
|
|
||||||
|
import dev.adamko.gradle.pbandg.Constants
|
||||||
|
import dev.adamko.gradle.pbandg.Constants.pbAndGBuildDir
|
||||||
|
import dev.adamko.gradle.pbandg.task.options.ProtocOutput
|
||||||
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.DomainObjectSet
|
||||||
|
import org.gradle.api.file.Directory
|
||||||
|
import org.gradle.api.file.DirectoryProperty
|
||||||
|
import org.gradle.api.file.RegularFileProperty
|
||||||
|
import org.gradle.api.provider.ListProperty
|
||||||
|
import org.gradle.api.provider.Property
|
||||||
|
import org.gradle.api.tasks.Input
|
||||||
|
import org.gradle.api.tasks.InputFile
|
||||||
|
import org.gradle.api.tasks.InputFiles
|
||||||
|
import org.gradle.api.tasks.OutputDirectory
|
||||||
|
import org.gradle.api.tasks.TaskAction
|
||||||
|
import org.gradle.kotlin.dsl.property
|
||||||
|
|
||||||
|
abstract class ProtobufCompileTask : DefaultTask() {
|
||||||
|
|
||||||
|
@get:InputFile
|
||||||
|
abstract val protocExecutable: RegularFileProperty
|
||||||
|
|
||||||
|
@get:OutputDirectory
|
||||||
|
val generatedSources: DirectoryProperty = project.objects.directoryProperty()
|
||||||
|
.convention(project.pbAndGBuildDir.map { it.dir("generated-sources") })
|
||||||
|
|
||||||
|
@get:InputFiles
|
||||||
|
abstract val protobufLibraryDirectories: ListProperty<Directory>
|
||||||
|
|
||||||
|
@get:Input
|
||||||
|
abstract val protocOutputs: DomainObjectSet<ProtocOutput>
|
||||||
|
// = project.objects.domainObjectSet(ProtocOutput::class.java)
|
||||||
|
|
||||||
|
@get:InputFile
|
||||||
|
abstract val protoFile: RegularFileProperty
|
||||||
|
|
||||||
|
@get:Input
|
||||||
|
val cliParamProtoPath: Property<String> =
|
||||||
|
project.objects.property<String>().convention("--proto_path=")
|
||||||
|
|
||||||
|
init {
|
||||||
|
group = Constants.PBG_TASK_GROUP
|
||||||
|
}
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
fun compile() {
|
||||||
|
|
||||||
|
val workDir = temporaryDir
|
||||||
|
project.delete(workDir)
|
||||||
|
|
||||||
|
project.exec {
|
||||||
|
executable(protocExecutable.asFile.get())
|
||||||
|
workingDir(workDir)
|
||||||
|
|
||||||
|
// prepare directories
|
||||||
|
project.mkdir(workingDir)
|
||||||
|
project.mkdir(generatedSources)
|
||||||
|
|
||||||
|
val mapOutputsToOutputDir =
|
||||||
|
protocOutputs.associateWith { workingDir.resolve(it.outputDirectoryName) }
|
||||||
|
mapOutputsToOutputDir.values.forEach { project.mkdir(it) }
|
||||||
|
|
||||||
|
// set args
|
||||||
|
mapOutputsToOutputDir
|
||||||
|
.map { (opt, dir) ->
|
||||||
|
"${opt.cliParam}=${opt.protocOptions}:${dir}"
|
||||||
|
}
|
||||||
|
.also { args(it) }
|
||||||
|
|
||||||
|
val protoPath = cliParamProtoPath.get()
|
||||||
|
val libArgs = protobufLibraryDirectories.get().map { "$protoPath${it.asFile}" }
|
||||||
|
args(libArgs)
|
||||||
|
|
||||||
|
val targetProtoFile = protoFile.get().asFile
|
||||||
|
args("$protoPath${targetProtoFile.parentFile}")
|
||||||
|
args("$targetProtoFile")
|
||||||
|
}
|
||||||
|
|
||||||
|
// sync compiled files
|
||||||
|
project.sync {
|
||||||
|
from(workDir)
|
||||||
|
into(generatedSources)
|
||||||
|
includeEmptyDirs = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// clean up temp-dir
|
||||||
|
project.delete(workDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
{
|
||||||
|
group = "protobuf"
|
||||||
|
dependsOn(protobufCompiler, protoLibsTask)
|
||||||
|
|
||||||
|
standardOutput = System.out
|
||||||
|
|
||||||
|
executable(protobufCompiler.singleFile)
|
||||||
|
workingDir(temporaryDirFactory)
|
||||||
|
|
||||||
|
val outDir = project.layout.buildDirectory.dir("protobuf/generated-sources")
|
||||||
|
outputs.dir(outDir)
|
||||||
|
|
||||||
|
val protoLibsDir: Provider<File> = protoLibsTask.map { it.destinationDir }
|
||||||
|
|
||||||
|
val javaOut = workingDir.resolve("java")
|
||||||
|
val kotlinOut = workingDir.resolve("kotlin")
|
||||||
|
val protoFile by project.objects.fileProperty()
|
||||||
|
.convention(project.layout.projectDirectory.file("src/main/proto/FactorioServerLogRecord.proto"))
|
||||||
|
|
||||||
|
val protoFileParent = project.provider { protoFile.asFile.parentFile }
|
||||||
|
|
||||||
|
val isLiteEnabled: Boolean by project.objects.property<Boolean>().convention(true)
|
||||||
|
|
||||||
|
doFirst {
|
||||||
|
project.delete(workingDir)
|
||||||
|
|
||||||
|
project.mkdir(outDir)
|
||||||
|
project.mkdir(javaOut)
|
||||||
|
project.mkdir(kotlinOut)
|
||||||
|
|
||||||
|
val liteOpt: String = when (isLiteEnabled) {
|
||||||
|
true -> "lite:"
|
||||||
|
false -> ""
|
||||||
|
}
|
||||||
|
|
||||||
|
args(
|
||||||
|
parseSpaceSeparatedArgs(
|
||||||
|
"""
|
||||||
|
--proto_path=${protoLibsDir.get()}
|
||||||
|
--proto_path=${protoFileParent.get()}
|
||||||
|
--java_out=$liteOpt$javaOut
|
||||||
|
--kotlin_out=$liteOpt$kotlinOut
|
||||||
|
$protoFile
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
doLast {
|
||||||
|
project.sync {
|
||||||
|
from(workingDir)
|
||||||
|
into(outDir)
|
||||||
|
}
|
||||||
|
project.delete(workingDir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
package dev.adamko.gradle.pbandg.task
|
||||||
|
|
||||||
|
import dev.adamko.gradle.pbandg.Constants
|
||||||
|
import dev.adamko.gradle.pbandg.Constants.pbAndGBuildDir
|
||||||
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.artifacts.Configuration
|
||||||
|
import org.gradle.api.file.DirectoryProperty
|
||||||
|
import org.gradle.api.provider.Property
|
||||||
|
import org.gradle.api.tasks.InputFiles
|
||||||
|
import org.gradle.api.tasks.OutputDirectory
|
||||||
|
import org.gradle.api.tasks.TaskAction
|
||||||
|
import org.gradle.kotlin.dsl.property
|
||||||
|
|
||||||
|
/** Download protobuf libs */
|
||||||
|
abstract class ProtobufPrepareLibrariesTask : DefaultTask() {
|
||||||
|
|
||||||
|
@get:InputFiles
|
||||||
|
val librarySources: Property<Configuration> = project.objects.property()
|
||||||
|
|
||||||
|
@OutputDirectory
|
||||||
|
val librariesDirectory: DirectoryProperty = project.objects.directoryProperty()
|
||||||
|
.convention(project.pbAndGBuildDir.map { it.dir("libs") })
|
||||||
|
|
||||||
|
init {
|
||||||
|
group = Constants.PBG_TASK_GROUP
|
||||||
|
description = "Download and extract protobuf libs"
|
||||||
|
}
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
fun doTask() {
|
||||||
|
project.sync {
|
||||||
|
includeEmptyDirs = false
|
||||||
|
from(librarySources.map { conf -> conf.map { project.zipTree(it) } })
|
||||||
|
into(librariesDirectory)
|
||||||
|
include("**/*.proto")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
package dev.adamko.gradle.pbandg.task.options
|
||||||
|
|
||||||
|
import dev.adamko.gradle.pbandg.Constants.pbAndGBuildDir
|
||||||
|
import java.io.Serializable
|
||||||
|
import org.gradle.api.file.Directory
|
||||||
|
import org.gradle.api.file.ProjectLayout
|
||||||
|
import org.gradle.api.provider.Provider
|
||||||
|
|
||||||
|
|
||||||
|
interface ProtocOutput : Serializable {
|
||||||
|
val cliParam: String
|
||||||
|
val protocOptions: String
|
||||||
|
val outputDirectoryName: String
|
||||||
|
|
||||||
|
fun outputDirectory(layout: ProjectLayout): Provider<Directory> {
|
||||||
|
return layout.pbAndGBuildDir.map { it.dir(outputDirectoryName) }
|
||||||
|
}
|
||||||
|
|
||||||
|
data class KotlinOutput(
|
||||||
|
override val protocOptions: String = "lite",
|
||||||
|
override val outputDirectoryName: String = "kotlin",
|
||||||
|
) : ProtocOutput {
|
||||||
|
override val cliParam: String = "--kotlin_out"
|
||||||
|
}
|
||||||
|
|
||||||
|
data class JavaOutput(
|
||||||
|
override val protocOptions: String = "lite",
|
||||||
|
override val outputDirectoryName: String = "java",
|
||||||
|
) : ProtocOutput {
|
||||||
|
override val cliParam: String = "--java_out"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,21 +1,6 @@
|
||||||
import java.util.function.Supplier
|
|
||||||
import org.gradle.api.DefaultTask
|
|
||||||
import org.gradle.api.Plugin
|
|
||||||
import org.gradle.api.Project
|
|
||||||
import org.gradle.api.provider.Property
|
|
||||||
import org.gradle.api.tasks.TaskAction
|
|
||||||
import org.gradle.kotlin.dsl.provideDelegate
|
|
||||||
import org.gradle.kotlin.dsl.configure
|
|
||||||
import org.gradle.kotlin.dsl.create
|
|
||||||
import org.gradle.kotlin.dsl.property
|
|
||||||
import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform
|
|
||||||
import org.gradle.nativeplatform.platform.internal.DefaultOperatingSystem
|
|
||||||
import org.gradle.plugins.ide.idea.model.IdeaModel
|
|
||||||
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension
|
|
||||||
import org.jetbrains.kotlin.util.parseSpaceSeparatedArgs
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("dev.adamko.factoriowebmap.archetype.kotlin-jvm")
|
id("dev.adamko.factoriowebmap.archetype.kotlin-jvm")
|
||||||
|
id("dev.adamko.gradle.pbandg.pb-and-g")
|
||||||
`kotlin-dsl`
|
`kotlin-dsl`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -24,343 +9,9 @@ val buildDir: Directory = layout.buildDirectory.dir(projectId).get()
|
||||||
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
protobufLibrary("com.google.protobuf:protobuf-javalite:3.19.1")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.protobufCompile {
|
||||||
open class ProtocPlugin : Plugin<Project> {
|
protoFile.set(layout.projectDirectory.file("src/main/proto/FactorioServerLogRecord.proto"))
|
||||||
|
|
||||||
override fun apply(project: Project) {
|
|
||||||
|
|
||||||
configureIntelliJ(project)
|
|
||||||
|
|
||||||
val protocConfig =
|
|
||||||
project.extensions.create("protocPluginConfig", ProtocPluginConfig::class, project)
|
|
||||||
|
|
||||||
val protobufCompiler: Configuration = project.configurations.create("protobufCompiler") {
|
|
||||||
isVisible = false
|
|
||||||
isCanBeConsumed = false
|
|
||||||
isCanBeResolved = true
|
|
||||||
isTransitive = false
|
|
||||||
|
|
||||||
defaultDependencies {
|
|
||||||
add(protocConfig.dependency.get())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val protobufLib: Configuration = project.configurations.create("protobufLib") {
|
|
||||||
isVisible = true
|
|
||||||
isCanBeConsumed = false
|
|
||||||
isCanBeResolved = true
|
|
||||||
isTransitive = false
|
|
||||||
}
|
|
||||||
|
|
||||||
project.dependencies {
|
|
||||||
protobufLib("com.google.protobuf:protobuf-javalite:3.19.1")
|
|
||||||
// implementation("com.google.protobuf:protobuf-javalite:3.19.1")
|
|
||||||
implementation("com.google.protobuf:protobuf-kotlin-lite:3.19.1")
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Download protobuf libs */
|
|
||||||
val protoLibsTask = project.tasks.register<Sync>("protobufLibs") {
|
|
||||||
group = "protobuf"
|
|
||||||
description = "Download and extract protobuf libs"
|
|
||||||
includeEmptyDirs = false
|
|
||||||
dependsOn(protobufLib)
|
|
||||||
|
|
||||||
val protoLibDir by project.objects.directoryProperty()
|
|
||||||
.convention(project.layout.buildDirectory.dir("protobuf/libs"))
|
|
||||||
into(protoLibDir)
|
|
||||||
|
|
||||||
protobufLib
|
|
||||||
.map { project.zipTree(it) }
|
|
||||||
.forEach {
|
|
||||||
logger.lifecycle("protoc lib - $it")
|
|
||||||
from(it) {
|
|
||||||
include("**/*.proto")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO investigate builtBy and sourceDirectorySet?
|
|
||||||
// project.objects.fileCollection().builtBy()
|
|
||||||
// val pbSrcSet = project.objects.sourceDirectorySet("protobuf", "protobuf")
|
|
||||||
|
|
||||||
|
|
||||||
/** Convert `.proto` files to Kotlin */
|
|
||||||
val pbCompileTask = project.tasks.register<Exec>("protobufCompile") {
|
|
||||||
group = "protobuf"
|
|
||||||
dependsOn(protobufCompiler, protoLibsTask)
|
|
||||||
|
|
||||||
standardOutput = System.out
|
|
||||||
|
|
||||||
executable(protobufCompiler.singleFile)
|
|
||||||
workingDir(temporaryDirFactory)
|
|
||||||
|
|
||||||
val outDir = project.layout.buildDirectory.dir("protobuf/generated-sources")
|
|
||||||
outputs.dir(outDir)
|
|
||||||
|
|
||||||
val protoLibsDir: Provider<File> = protoLibsTask.map { it.destinationDir }
|
|
||||||
|
|
||||||
val javaOut = workingDir.resolve("java")
|
|
||||||
val kotlinOut = workingDir.resolve("kotlin")
|
|
||||||
val protoFile by project.objects.fileProperty()
|
|
||||||
.convention(project.layout.projectDirectory.file("src/main/proto/FactorioServerLogRecord.proto"))
|
|
||||||
|
|
||||||
val protoFileParent = project.provider { protoFile.asFile.parentFile }
|
|
||||||
|
|
||||||
val isLiteEnabled: Boolean by project.objects.property<Boolean>().convention(true)
|
|
||||||
|
|
||||||
doFirst {
|
|
||||||
project.delete(workingDir)
|
|
||||||
|
|
||||||
project.mkdir(outDir)
|
|
||||||
project.mkdir(javaOut)
|
|
||||||
project.mkdir(kotlinOut)
|
|
||||||
|
|
||||||
val liteOpt: String = when (isLiteEnabled) {
|
|
||||||
true -> "lite:"
|
|
||||||
false -> ""
|
|
||||||
}
|
|
||||||
|
|
||||||
args(
|
|
||||||
parseSpaceSeparatedArgs(
|
|
||||||
"""
|
|
||||||
--proto_path=${protoLibsDir.get()}
|
|
||||||
--proto_path=${protoFileParent.get()}
|
|
||||||
--java_out=$liteOpt$javaOut
|
|
||||||
--kotlin_out=$liteOpt$kotlinOut
|
|
||||||
$protoFile
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
doLast {
|
|
||||||
project.sync {
|
|
||||||
from(workingDir)
|
|
||||||
into(outDir)
|
|
||||||
}
|
|
||||||
project.delete(workingDir)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
project.tasks.assemble { dependsOn(pbCompileTask) }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Setup source dirs */
|
|
||||||
private fun configureIntelliJ(project: Project) {
|
|
||||||
|
|
||||||
val genSrcDir = project.layout.buildDirectory.dir("protobuf/generated-sources")
|
|
||||||
val ktGenSrc = genSrcDir.map { it.dir("kotlin") }
|
|
||||||
val jGenSrc = genSrcDir.map { it.dir("java") }
|
|
||||||
|
|
||||||
project.mkdir(ktGenSrc)
|
|
||||||
|
|
||||||
project.extensions.findByType<KotlinJvmProjectExtension>()?.apply {
|
|
||||||
project.logger.lifecycle("-------\nadding generated sources $ktGenSrc\n-------")
|
|
||||||
|
|
||||||
project.sourceSets.named("main") {
|
|
||||||
this.java.srcDir(ktGenSrc)
|
|
||||||
this.java.srcDir(jGenSrc)
|
|
||||||
}
|
|
||||||
|
|
||||||
// sourceSets.main.get().kotlin.srcDir(ktGenSrc)
|
|
||||||
|
|
||||||
// sourceSets.main.configure {
|
|
||||||
// this.kotlin.srcDir(ktGenSrc)
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
project.plugins.withType<IdeaPlugin> {
|
|
||||||
project.extensions.configure<IdeaModel> {
|
|
||||||
this.module.generatedSourceDirs.add(ktGenSrc.get().asFile)
|
|
||||||
this.module.generatedSourceDirs.add(jGenSrc.get().asFile)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* IntelliJ requires source dirs are configured first.
|
|
||||||
*
|
|
||||||
* https://github.com/google/protobuf-gradle-plugin/blob/master/src/main/groovy/com/google/protobuf/gradle/Utils.groovy#L128
|
|
||||||
*/
|
|
||||||
project.tasks.withType<GenerateIdeaModule> {
|
|
||||||
doFirst {
|
|
||||||
project.mkdir(ktGenSrc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class ProtocPluginConfig(private val project: Project) {
|
|
||||||
|
|
||||||
val protocWorkingDir: DirectoryProperty =
|
|
||||||
project.objects.directoryProperty()
|
|
||||||
.convention(project.rootProject.layout.projectDirectory.dir(".gradle/protoc"))
|
|
||||||
|
|
||||||
val protocVersion: Property<String> =
|
|
||||||
project.objects.property(String::class).convention("3.19.1")
|
|
||||||
|
|
||||||
val protocGroup: Property<String> =
|
|
||||||
project.objects.property(String::class).convention("com.google.protobuf")
|
|
||||||
|
|
||||||
val protocArtifactName: Property<String> =
|
|
||||||
project.objects.property(String::class).convention("protoc")
|
|
||||||
|
|
||||||
val protocArtifactExtension: Property<String> =
|
|
||||||
project.objects.property(String::class).convention("exe")
|
|
||||||
|
|
||||||
val operatingSystemProvider: Property<Supplier<DefaultOperatingSystem>> =
|
|
||||||
project.objects.property<Supplier<DefaultOperatingSystem>>()
|
|
||||||
.convention { DefaultNativePlatform.getCurrentOperatingSystem() }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Should return one of
|
|
||||||
*
|
|
||||||
* * `linux`
|
|
||||||
* * `osx`
|
|
||||||
* * `windows`
|
|
||||||
*/
|
|
||||||
val operatingSystemName: Property<String> =
|
|
||||||
project.objects
|
|
||||||
.property<String>()
|
|
||||||
.convention(operatingSystemProvider.map { it.get().toFamilyName() })
|
|
||||||
|
|
||||||
private val architectureProvider: Provider<Architecture> =
|
|
||||||
project.provider { DefaultNativePlatform.getCurrentArchitecture() }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Should return one of
|
|
||||||
*
|
|
||||||
* * `aarch_64`
|
|
||||||
* * `ppcle_64`
|
|
||||||
* * `x86_32`
|
|
||||||
* * `x86_64`
|
|
||||||
*/
|
|
||||||
val architectureName: Property<String> =
|
|
||||||
project.objects
|
|
||||||
.property<String>()
|
|
||||||
.convention(architectureProvider.map { it.name.replace("-", "_") })
|
|
||||||
|
|
||||||
private val classifierProvider: Provider<String> =
|
|
||||||
project.provider { "${operatingSystemName.get()}-${architectureName.get()}" }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default: concatenate [osFamilyNameProvider] and [architectureProvider]
|
|
||||||
*
|
|
||||||
* Should return one of:
|
|
||||||
*
|
|
||||||
* * `linux-aarch_64`
|
|
||||||
* * `linux-ppcle_64`
|
|
||||||
* * `linux-x86_64`
|
|
||||||
* * `osx-x86_32`
|
|
||||||
* * `osx-x86_64`
|
|
||||||
* * `windows-x86_32`
|
|
||||||
*/
|
|
||||||
val classifier: Property<String> =
|
|
||||||
project.objects
|
|
||||||
.property<String>()
|
|
||||||
.convention(classifierProvider)
|
|
||||||
|
|
||||||
|
|
||||||
private val dependencyProvider: Provider<ExternalModuleDependency> =
|
|
||||||
project.provider {
|
|
||||||
project.dependencies.create(
|
|
||||||
group = protocGroup.get(),
|
|
||||||
name = protocArtifactName.get(),
|
|
||||||
version = protocVersion.get(),
|
|
||||||
classifier = classifierProvider.get(),
|
|
||||||
ext = protocArtifactExtension.get(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val dependency: Property<ExternalModuleDependency> =
|
|
||||||
project.objects
|
|
||||||
.property<ExternalModuleDependency>()
|
|
||||||
.convention(dependencyProvider)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class ProtocPrepareTask : DefaultTask() {
|
|
||||||
|
|
||||||
@Internal
|
|
||||||
val protocPluginConfig: Provider<ProtocPluginConfig> = project.provider {
|
|
||||||
project.extensions.getByType<ProtocPluginConfig>()
|
|
||||||
}
|
|
||||||
|
|
||||||
@get:OutputDirectory
|
|
||||||
val outputDirectory: DirectoryProperty = project.objects.directoryProperty()
|
|
||||||
.convention(protocPluginConfig.flatMap { it.protocWorkingDir })
|
|
||||||
|
|
||||||
@Internal
|
|
||||||
val protocOutput: RegularFileProperty = project.objects.fileProperty()
|
|
||||||
|
|
||||||
@Internal
|
|
||||||
val protocDependency: Provider<ExternalModuleDependency> =
|
|
||||||
protocPluginConfig.flatMap { it.dependency }
|
|
||||||
|
|
||||||
init {
|
|
||||||
super.setGroup("protobuf")
|
|
||||||
outputs.dir(outputDirectory)
|
|
||||||
}
|
|
||||||
|
|
||||||
@TaskAction
|
|
||||||
fun action() {
|
|
||||||
|
|
||||||
val protocDep: Configuration = project.configurations.create("protoc") {
|
|
||||||
isVisible = false
|
|
||||||
isCanBeConsumed = false
|
|
||||||
isCanBeResolved = true
|
|
||||||
isTransitive = false
|
|
||||||
|
|
||||||
defaultDependencies {
|
|
||||||
add(protocDependency.get())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.lifecycle("Downloading protoc")
|
|
||||||
val resolvedProtocDep = protocDep.singleFile
|
|
||||||
logger.lifecycle("Downloaded $resolvedProtocDep")
|
|
||||||
|
|
||||||
project.sync {
|
|
||||||
from(resolvedProtocDep)
|
|
||||||
into(outputDirectory)
|
|
||||||
logger.lifecycle("Syncing from $resolvedProtocDep to ${outputDirectory.asFile.get().canonicalPath}")
|
|
||||||
protocOutput.set(outputDirectory.asFileTree.singleFile)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class ProtocGenerationTask : DefaultTask() {
|
|
||||||
|
|
||||||
@TaskAction
|
|
||||||
fun generate() {
|
|
||||||
logger.lifecycle("generating protoc...")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
apply<ProtocPlugin>()
|
|
||||||
|
|
||||||
configure<ProtocPluginConfig> {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
val logSS = tasks.create("logSourceSets") {
|
|
||||||
group = "protobuf"
|
|
||||||
|
|
||||||
doLast {
|
|
||||||
sourceSets.forEach { set ->
|
|
||||||
logger.lifecycle("SourceSet name: ${set.name}")
|
|
||||||
set.allSource.forEach { src ->
|
|
||||||
logger.lifecycle("location: ${src.toRelativeString(rootProject.projectDir)}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.lifecycle("-------\nIdeaModel generated source dirs: ${project.idea.module.generatedSourceDirs.joinToString()}\n-------")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.named("protobufCompile") { finalizedBy(logSS) }
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue