tried moving protobuf plugin to separate project, but IntelliJ doesn't like it

This commit is contained in:
Adam 2021-10-30 20:24:58 +02:00
parent 978b515682
commit 59891678a5
4 changed files with 260 additions and 185 deletions

View file

@ -1,3 +1,5 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins { plugins {
`kotlin-dsl` `kotlin-dsl`
kotlin("jvm") version "1.5.31" kotlin("jvm") version "1.5.31"
@ -20,3 +22,12 @@ dependencies {
implementation("com.github.node-gradle:gradle-node-plugin:3.1.1") implementation("com.github.node-gradle:gradle-node-plugin:3.1.1")
} }
tasks.withType<KotlinCompile>().configureEach {
kotlinOptions.freeCompilerArgs += listOf(
"-Xopt-in=kotlin.OptIn",
"-Xopt-in=kotlin.ExperimentalStdlibApi",
"-Xopt-in=kotlin.time.ExperimentalTime",
"-Xopt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
)
}

View file

@ -1,16 +1,14 @@
import org.gradle.nativeplatform.platform.internal.ArchitectureInternal
import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform
plugins { plugins {
kotlin("jvm") version "1.5.31" kotlin("jvm") version "1.5.31"
`kotlin-dsl` `kotlin-dsl`
`java-gradle-plugin` `java-gradle-plugin`
`maven-publish`
} }
gradlePlugin { gradlePlugin {
plugins { plugins {
create("Protobuf & Gradle") { create("ProtobufAndGradle") {
id = "dev-adamko.pb-and-g" id = "dev.adamko.pb-and-g"
implementationClass = "dev.adamko.gradle.pbandg.ProtocPluginKt" implementationClass = "dev.adamko.gradle.pbandg.ProtocPluginKt"
description = description =
"Protobuf & Gradle. Wrapper for protoc to generate code from Proto Buffer files." "Protobuf & Gradle. Wrapper for protoc to generate code from Proto Buffer files."
@ -18,6 +16,9 @@ gradlePlugin {
} }
} }
group = "dev.adamko.gradle.pbandg"
version = "0.0.1-SNAPSHOT"
val protocConfiguration: Configuration by configurations.creating { val protocConfiguration: Configuration by configurations.creating {
// A configuration meant for consumers that need the implementation of this component // A configuration meant for consumers that need the implementation of this component
@ -25,10 +26,13 @@ val protocConfiguration: Configuration by configurations.creating {
isCanBeConsumed = false isCanBeConsumed = false
} }
val protobufVersion = "3.19.0" val protobufVersion = "3.19.1"
val protocVersion = "3.9.2" val protocVersion = "3.9.2"
dependencies { dependencies {
implementation(platform("org.jetbrains.kotlin:kotlin-bom"))
implementation(kotlin("stdlib"))
implementation(platform("com.google.protobuf:protobuf-bom:$protobufVersion")) implementation(platform("com.google.protobuf:protobuf-bom:$protobufVersion"))
implementation("com.google.protobuf:protobuf-java:$protobufVersion") implementation("com.google.protobuf:protobuf-java:$protobufVersion")
@ -45,9 +49,6 @@ dependencies {
implementation("io.grpc:protoc-gen-grpc-kotlin:1.2.0") implementation("io.grpc:protoc-gen-grpc-kotlin:1.2.0")
implementation("javax.annotation:javax.annotation-api:1.3.2") implementation("javax.annotation:javax.annotation-api:1.3.2")
//
// implementation(npm("protoc-gen-ts", "0.15.0"))
implementation( implementation(
group = "com.google.protobuf", group = "com.google.protobuf",
@ -67,93 +68,10 @@ dependencies {
ext = "exe", ext = "exe",
) )
// protocConfiguration("com.google.protobuf:protoc:3.9.2@exe")
} }
// https://github.com/protocolbuffers/protobuf/tree/master/protoc-artifacts
// The name of a published protoc artifact is in the format:
// protoc-<version>-<os>-<arch>.exe
// e.g., protoc-3.6.1-linux-x86_64.exe
// Note that artifacts for Linux/macOS also have the .exe suffix, but they are not windows binaries.
val os: OperatingSystem = DefaultNativePlatform.getCurrentOperatingSystem()
val arch: ArchitectureInternal = DefaultNativePlatform.getCurrentArchitecture()
repositories { repositories {
mavenCentral() mavenCentral()
// ivy {
// url = project.repositories.mavenCentral().url
//
// patternLayout {
//
// // com/google/protobuf/protoc/3.9.2/protoc-3.9.2-linux-aarch_64.exe
// artifact("[organisation]/[module]/[revision]/[artifact]-[revision]-${os.name}-${arch.name}.[ext]")
//
//// artifact("3rd-party-artifacts/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]")
//// artifact("company-artifacts/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]")
//// ivy("ivy-files/[organisation]/[module]/[revision]/ivy.xml")
//// artifact("[organisation]/[module]/[revision]/[artifact]-[revision].[ext]")
// setM2compatible(true)
// metadataSources {
// artifact()
// }
// }
// }
} }
tasks.register<Sync>("protocExecCopy") {
group = project.name
// from(protocConfiguration.artifacts)
from(protocConfiguration.resolve())
into(project.layout.buildDirectory.dir("protocCopy"))
}
//tasks.register("dlPc") {
// group = project.name
//
// val downloadDir = this.temporaryDir
//
// outputs.dir(downloadDir)
//
// doLast {
//
//// downloadDir.mkdirs()
//
// val protocArtifactFileExt = "exe"
//
// val osFamilyName = DefaultNativePlatform.host().operatingSystem.toFamilyName()
//
// val arch: String =
// DefaultNativePlatform.getCurrentArchitecture()
// .name
// .replace("-", "_")
//
// val artifact = "protoc-$protocVersion-${osFamilyName}-${arch}.$protocArtifactFileExt"
//
// val uri = uri(
// ArtifactRepositoryContainer.MAVEN_CENTRAL_URL
// + "com/google/protobuf/protoc/$protocVersion/$artifact"
// )
// // actual:
// // https://repo.maven.apache.org/maven2/com/google/protobuf/protoc/3.9.2/protoc-3.9.2-windows-x86_64.exe
// // https://repo.maven.apache.org/maven2/com/google/protobuf/protoc/3.9.2/protoc-3.9.2-windows-x86-64.exe
//
// ant.invokeMethod(
// "get", mapOf(
// "src" to uri,
// "dest" to downloadDir.canonicalPath,
// "verbose" to true,
// )
// )
// }
//
//}
//

View file

@ -1,67 +1,217 @@
package dev.adamko.gradle.pbandg package dev.adamko.gradle.pbandg
import java.io.File
import java.util.function.Supplier
import org.gradle.api.DefaultTask import org.gradle.api.DefaultTask
import org.gradle.api.Plugin import org.gradle.api.Plugin
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.ExternalDependency import org.gradle.api.artifacts.ExternalDependency
import org.gradle.api.artifacts.ExternalModuleDependency
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.plugins.ExtensionAware import org.gradle.api.plugins.ExtensionAware
import org.gradle.api.provider.Property import org.gradle.api.provider.Property
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.Exec
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.OutputDirectory
import org.gradle.api.tasks.Sync
import org.gradle.api.tasks.TaskAction import org.gradle.api.tasks.TaskAction
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.domainObjectContainer import org.gradle.kotlin.dsl.domainObjectContainer
import org.gradle.kotlin.dsl.create import org.gradle.kotlin.dsl.create
import org.gradle.kotlin.dsl.defaultDependencies
import org.gradle.kotlin.dsl.dependencies
import org.gradle.kotlin.dsl.findByType
import org.gradle.kotlin.dsl.getByType
import org.gradle.kotlin.dsl.create
import org.gradle.kotlin.dsl.getValue
import org.gradle.kotlin.dsl.withType import org.gradle.kotlin.dsl.withType
import org.gradle.kotlin.dsl.property import org.gradle.kotlin.dsl.property
import org.gradle.kotlin.dsl.provideDelegate
import org.gradle.kotlin.dsl.register
import org.gradle.nativeplatform.platform.Architecture
import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform
import org.gradle.nativeplatform.platform.internal.DefaultOperatingSystem
import org.gradle.plugins.ide.idea.GenerateIdeaModule
import org.gradle.plugins.ide.idea.IdeaPlugin
import org.gradle.plugins.ide.idea.model.IdeaModel
import org.jetbrains.kotlin.util.parseSpaceSeparatedArgs
class ProtocPlugin : Plugin<Project> { open class ProtocPlugin : Plugin<Project> {
override fun apply(project: Project) { override fun apply(project: Project) {
val protocConfig = configureIntelliJ(project)
project.extensions.create("protocConfig", ProtocConfigExtension::class.java)
val protocDeps = project.configurations.create("pbAndG") { val protocConfig =
project.extensions.create("protocPluginConfig", ProtocPluginConfig::class, project)
val protobufCompiler: Configuration = project.configurations.create("protobufCompiler") {
isVisible = false isVisible = false
isCanBeConsumed = false isCanBeConsumed = false
isCanBeResolved = true isCanBeResolved = true
description = "protoc dependencies" isTransitive = false
defaultDependencies { defaultDependencies {
// deps += project.dependencies.create("com.google.protobuf:protoc:3.19.0") add(protocConfig.dependency.get())
add(protocConfig.dependencyProvider())
} }
} }
val generatorsContainer = val protobufLib: Configuration = project.configurations.create("protobufLib") {
project.objects.domainObjectContainer(ProtocGenerationTask::class.java) isVisible = true
protocConfig.extensions.add("generate", generatorsContainer) isCanBeConsumed = false
isCanBeResolved = true
isTransitive = false
project.extensions.add("asd", project.provider {
DefaultNativePlatform.getCurrentOperatingSystem().toFamilyName()
})
project.tasks.withType<ProtocGenerationTask> {
// .getDataFiles()?.from(protocDeps)
} }
// project.getPlugins().withType(org.gradle.api.plugins.JavaPlugin::class) { javaPlugin -> project.dependencies {
// val sourceSets: SourceSetContainer = protobufLib("com.google.protobuf:protobuf-javalite:3.19.1")
// project.getExtensions().getByType(SourceSetContainer::class.java) // implementation("com.google.protobuf:protobuf-javalite:3.19.1")
// val main: SourceSet = sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME) // implementation("com.google.protobuf:protobuf-kotlin-lite:3.19.1")
// main.getJava().setSrcDirs(Arrays.asList("src")) }
// }
/** 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) }
} }
/**
* 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
*/
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)
}
}
project.tasks.withType<GenerateIdeaModule> {
doFirst {
project.mkdir(ktGenSrc)
}
}
}
} }
abstract class ProtocPluginConfig(private val project: Project) {
abstract class ProtocConfigExtension(private val project: Project) : ExtensionAware { val protocWorkingDir: DirectoryProperty =
project.objects.directoryProperty()
.convention(project.rootProject.layout.projectDirectory.dir(".gradle/protoc"))
val protocVersion: Property<String> = val protocVersion: Property<String> =
project.objects.property(String::class).convention("3.9.2") project.objects.property(String::class).convention("3.19.1")
val protocGroup: Property<String> = val protocGroup: Property<String> =
project.objects.property(String::class).convention("com.google.protobuf") project.objects.property(String::class).convention("com.google.protobuf")
@ -72,77 +222,73 @@ abstract class ProtocConfigExtension(private val project: Project) : ExtensionAw
val protocArtifactExtension: Property<String> = val protocArtifactExtension: Property<String> =
project.objects.property(String::class).convention("exe") project.objects.property(String::class).convention("exe")
var osFamilyNameProvider: () -> String = { val operatingSystemProvider: Property<Supplier<DefaultOperatingSystem>> =
DefaultNativePlatform.getCurrentOperatingSystem().toFamilyName() project.objects.property<Supplier<DefaultOperatingSystem>>()
} .convention { DefaultNativePlatform.getCurrentOperatingSystem() }
var architectureProviderMapper: (String) -> String = { /**
it.replace("-", "_") * Should return one of
} *
* * `linux`
* * `osx`
* * `windows`
*/
val operatingSystemName: Property<String> =
project.objects
.property<String>()
.convention(operatingSystemProvider.map { it.get().toFamilyName() })
var architectureProvider: () -> String = { private val architectureProvider: Provider<Architecture> =
DefaultNativePlatform.getCurrentArchitecture() project.provider { DefaultNativePlatform.getCurrentArchitecture() }
.name
.let(architectureProviderMapper)
}
var classifierProvider: () -> String = { /**
"${osFamilyNameProvider()}-${architectureProvider()}" * 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("-", "_") })
var dependencyProvider: () -> ExternalDependency = { private val classifierProvider: Provider<String> =
project.dependencies.create( project.provider { "${operatingSystemName.get()}-${architectureName.get()}" }
group = protocGroup.get(),
name = protocArtifactName.get(),
version = protocVersion.get(),
classifier = classifierProvider(),
ext = protocArtifactExtension.get(),
)
}
val generators = project.objects.domainObjectContainer(ProtocGenerationConfig::class) /**
* 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 ProtocGenerationConfig
abstract class ProtocGenerationTask : DefaultTask() {
@TaskAction
fun generate() {
logger.lifecycle("generating protoc...")
}
}
//class ProtocDownloadExe : DefaultTask() {
//
////@Input
//val protocVersion = "3.9.2"
//val protocArtifactFileExt = "exe"
//
//
// @TaskAction
// fun download() {
//
// val baseUri = project.repositories.mavenCentral().url
//
// val os: OperatingSystem = DefaultNativePlatform.getCurrentOperatingSystem()
// val arch: ArchitectureInternal = DefaultNativePlatform.getCurrentArchitecture()
//
// val artifact = "protoc-$protocVersion-${os.name}-${arch.name}.$protocArtifactFileExt"
//
// ant.invokeMethod(
// "get", mapOf(
// "src" to baseUri.resolve("/com/google/protobuf/protoc/3.9.2/protoc-3.9.2-linux-aarch_64.exe"),
// "dest" to project.layout.buildDirectory.dir("protoc-artifact"),
// "verbose" to true,
// )
// )
//
//
// }
//
//}

View file

@ -1,7 +1,7 @@
rootProject.name = "factorio-web-map" rootProject.name = "factorio-web-map"
includeBuild("modules/protoc-gradle-plugin") //includeBuild("modules/protoc-gradle-plugin")
include( include(
":modules:mod", ":modules:mod",