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-assertions-json:$kotestVersion")
|
||||
testImplementation("io.mockk:mockk:1.12.0")
|
||||
|
||||
//</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 {
|
||||
id("dev.adamko.factoriowebmap.archetype.kotlin-jvm")
|
||||
id("dev.adamko.gradle.pbandg.pb-and-g")
|
||||
`kotlin-dsl`
|
||||
}
|
||||
|
||||
|
|
@ -24,343 +9,9 @@ val buildDir: Directory = layout.buildDirectory.dir(projectId).get()
|
|||
|
||||
|
||||
dependencies {
|
||||
protobufLibrary("com.google.protobuf:protobuf-javalite:3.19.1")
|
||||
}
|
||||
|
||||
|
||||
open class ProtocPlugin : Plugin<Project> {
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
tasks.protobufCompile {
|
||||
protoFile.set(layout.projectDirectory.file("src/main/proto/FactorioServerLogRecord.proto"))
|
||||
}
|
||||
|
||||
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