standalone pb plugin working!

This commit is contained in:
Adam 2021-10-31 08:52:40 +01:00
parent 59891678a5
commit 0f6677e0b1
12 changed files with 613 additions and 353 deletions

View file

@ -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>
}

View file

@ -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)
}

View file

@ -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

View file

@ -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)
}
}
}
}

View file

@ -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"))
}
}
}
}
}

View file

@ -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)
}
}
}

View file

@ -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) }

View file

@ -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)
}

View file

@ -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)
}
}
*/

View file

@ -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")
}
}
}

View file

@ -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"
}
}

View file

@ -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) }