Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 16 additions & 9 deletions gradle-plugin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ kotlin {
explicitApi()

jvmToolchain(17)

compilerOptions.optIn.add("kotlinx.rpc.internal.InternalRpcApi")
}

tasks.withType<KotlinCompile>().configureEach {
Expand All @@ -29,7 +31,9 @@ tasks.withType<KotlinCompile>().configureEach {
}

dependencies {
implementation(libs.kotlin.gradle.plugin)
compileOnly(libs.kotlin.gradle.plugin)
compileOnly(libs.android.gradle.plugin)
compileOnly(libs.android.gradle.plugin.api)

testImplementation(libs.kotlin.gradle.plugin)
testImplementation(gradleTestKit())
Expand All @@ -43,16 +47,19 @@ dependencies {
}

tasks.test {
val forwardOutput: Boolean = (properties.getOrDefault("gradle.test.forward.output", "false")
as String).toBooleanStrictOrNull() ?: false
useJUnitPlatform()

systemProperty("gradle.test.forward.output", forwardOutput)
val protocGen = gradle.includedBuild("protoc-gen")
dependsOn(protocGen.task(":grpc:publishAllPublicationsToBuildRepoRepository"))
dependsOn(protocGen.task(":protobuf:publishAllPublicationsToBuildRepoRepository"))

useJUnitPlatform()
val compilerPlugin = gradle.includedBuild("compiler-plugin")
dependsOn(compilerPlugin.task(":compiler-plugin-cli:publishAllPublicationsToBuildRepoRepository"))
dependsOn(compilerPlugin.task(":compiler-plugin-k2:publishAllPublicationsToBuildRepoRepository"))
dependsOn(compilerPlugin.task(":compiler-plugin-backend:publishAllPublicationsToBuildRepoRepository"))
dependsOn(compilerPlugin.task(":compiler-plugin-common:publishAllPublicationsToBuildRepoRepository"))

val includedBuild = gradle.includedBuild("protoc-gen")
dependsOn(includedBuild.task(":grpc:publishAllPublicationsToBuildRepoRepository"))
dependsOn(includedBuild.task(":protobuf:publishAllPublicationsToBuildRepoRepository"))
dependsOn(":publishAllPublicationsToBuildRepoRepository")
}

// This block is needed to show plugin tasks on --dry-run
Expand Down Expand Up @@ -103,7 +110,7 @@ generateSource(
text = """
package kotlinx.rpc

const val KOTLIN_VERSION: String = "${libs.versions.kotlin.lang.get()}"
const val RPC_VERSION: String = "${libs.versions.kotlinx.rpc.get()}"

const val BUILD_REPO: String = "${File(globalRootDir).resolve("build/repo").absolutePath}"
""".trimIndent(),
Expand Down
11 changes: 5 additions & 6 deletions gradle-plugin/src/main/kotlin/kotlinx/rpc/Extensions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,13 @@ public open class RpcExtension @Inject internal constructor(objects: ObjectFacto
internal val protocApplied = AtomicBoolean(false)

internal val protocInternal by lazy {
if (protocApplied.get()) {
if (protocApplied.compareAndSet(false, true)) {
objects.newInstance<DefaultProtocExtension>().apply {
callbacks.forEach { it.execute(this) }
}
} else {
error("Illegal access to protoc extension during DefaultProtocExtension.init")
}

protocApplied.set(true)
objects.newInstance<DefaultProtocExtension>().apply {
callbacks.forEach { it.execute(this) }
}
}

private val callbacks = mutableListOf<Action<ProtocExtension>>()
Expand Down
22 changes: 22 additions & 0 deletions gradle-plugin/src/main/kotlin/kotlinx/rpc/RpcGradlePlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@ package kotlinx.rpc

import kotlinx.rpc.protoc.configurePluginProtections
import kotlinx.rpc.protoc.createProtoExtensions
import org.gradle.api.GradleException
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.create

@Suppress("unused")
public class RpcGradlePlugin : Plugin<Project> {
override fun apply(target: Project) {
checkKGPIsInTheClasspath()

target.extensions.create<RpcExtension>("rpc")

applyCompilerPlugin(target)
Expand All @@ -28,3 +31,22 @@ public class RpcGradlePlugin : Plugin<Project> {
target.plugins.apply(CompilerPluginCli::class.java)
}
}

private fun checkKGPIsInTheClasspath() {
try {
Class.forName("org.jetbrains.kotlin.gradle.plugin.KotlinCompilerPluginSupportPlugin")
} catch (_: ClassNotFoundException) {
throw GradleException(
"""
Kotlin Gradle plugin is not applied to the project.
Please ensure that Kotlin Gradle plugin is applied to the project in the plugins block:

plugins {
kotlin("jvm") version "..." // or
kotlin("multiplatform") version "..." // or
kotlin("android") version "..."
}
""".trimIndent()
)
}
}
27 changes: 5 additions & 22 deletions gradle-plugin/src/main/kotlin/kotlinx/rpc/buf/BufExtensions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,10 @@

package kotlinx.rpc.buf

import kotlinx.rpc.buf.tasks.BufAllTasks
import kotlinx.rpc.buf.tasks.BufAllTasksImpl
import kotlinx.rpc.buf.tasks.BufExecTask
import kotlinx.rpc.buf.tasks.BufGenerateTask
import kotlinx.rpc.buf.tasks.BufTasks
import kotlinx.rpc.buf.tasks.BufTasksImpl
import kotlinx.rpc.protoc.ProtoTasks
import kotlinx.rpc.protoc.ProtocPlugin
import kotlinx.rpc.protoc.protoTasks
import org.gradle.api.Action
import org.gradle.api.Project
import org.gradle.api.model.ObjectFactory
Expand Down Expand Up @@ -104,13 +101,6 @@ public open class BufExtension @Inject internal constructor(objects: ObjectFacto
* Allows registering custom Buf tasks that can operate on the generated workspace.
*/
public open class BufTasksExtension @Inject internal constructor(internal val project: Project) {
/**
* Returns a collection of all `buf` tasks registered in the project.
*/
public fun all(): BufAllTasks {
return BufAllTasksImpl(project, project.tasks.withType(BufExecTask::class.java))
}

/**
* Registers a custom Buf task that operates on the generated workspace.
*
Expand All @@ -123,11 +113,11 @@ public open class BufTasksExtension @Inject internal constructor(internal val pr
kClass: KClass<T>,
name: String,
configure: Action<T> = Action {},
): BufTasks<T> {
): ProtoTasks<T> {
@Suppress("UNCHECKED_CAST")
customTasks.add(Definition(name, kClass, configure))

return all().matchingType(kClass)
return project.protoTasks.matchingType(kClass)
}

/**
Expand All @@ -141,7 +131,7 @@ public open class BufTasksExtension @Inject internal constructor(internal val pr
public inline fun <reified T : BufExecTask> registerWorkspaceTask(
name: String,
configure: Action<T> = Action {},
): BufTasks<T> {
): ProtoTasks<T> {
return registerWorkspaceTask(T::class, name, configure)
}

Expand All @@ -161,13 +151,6 @@ public open class BufTasksExtension @Inject internal constructor(internal val pr
* @see [BUF_GEN_YAML]
*/
public open class BufGenerateExtension @Inject internal constructor(internal val project: Project) {
/**
* Returns a collection of all `buf generate` tasks registered in the project.
*/
public fun allTasks(): BufTasks<BufGenerateTask> {
return BufTasksImpl(project, project.tasks.withType(BufGenerateTask::class.java), BufGenerateTask::class)
}

/**
* `--include-imports` option.
*
Expand Down
72 changes: 17 additions & 55 deletions gradle-plugin/src/main/kotlin/kotlinx/rpc/buf/tasks/BufExecTask.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ package kotlinx.rpc.buf.tasks
import kotlinx.rpc.buf.BUF_EXECUTABLE_CONFIGURATION
import kotlinx.rpc.buf.BufExtension
import kotlinx.rpc.buf.execBuf
import kotlinx.rpc.protoc.PROTO_GROUP
import kotlinx.rpc.rpcExtension
import org.gradle.api.DefaultTask
import org.gradle.api.Project
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.Property
Expand All @@ -26,71 +24,35 @@ import kotlin.reflect.KClass
import kotlinx.rpc.buf.BUF_GEN_YAML
import kotlinx.rpc.buf.BUF_YAML
import kotlinx.rpc.buf.BufTasksExtension
import kotlinx.rpc.protoc.DefaultProtoTask
import kotlinx.rpc.protoc.ProtoTask
import org.gradle.api.logging.LogLevel
import org.gradle.api.provider.SetProperty
import org.gradle.api.tasks.Classpath
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.InputFiles
import org.gradle.api.tasks.SkipWhenEmpty
import javax.inject.Inject

/**
* Abstract base class for `buf` tasks.
*/
public abstract class BufExecTask @Inject constructor(
@Internal
public val properties: Properties
) : DefaultTask() {
init {
group = PROTO_GROUP
}
properties: ProtoTask.Properties,
) : DefaultProtoTask(properties) {
// unsued, but required for Gradle to properly recognise inputs
@get:InputFiles
@get:SkipWhenEmpty
internal abstract val protoFiles: ListProperty<File>

// list of buf task dependencies of the same type
@get:Internal
internal abstract val bufTaskDependencies: SetProperty<String>
// unsued, but required for Gradle to properly recognise inputs
@get:InputFiles
internal abstract val importProtoFiles: ListProperty<File>

@get:InputFile
internal abstract val bufExecutable: Property<File>

@get:Input
internal abstract val debug: Property<Boolean>

/**
* Properties of the buf task.
*
* Can be used with [BufTasks] to filter tasks.
*/
public open class Properties internal constructor(
/**
* Whether the task is for a test source set.
*/
public val isTest: Boolean,
/**
* Name of the [kotlinx.rpc.protoc.ProtoSourceSet] this task is associated with.
*/
public val sourceSetName: String,
)

/**
* Properties of the buf task for android source sets.
*
* Can be used with [BufTasks] to filter tasks.
*/
public class AndroidProperties internal constructor(
isTest: Boolean,
sourceSetName: String,
/**
* Name of the android flavor this task is associated with.
*/
public val flavor: String,
/**
* Name of the android build type this task is associated with.
*/
public val buildType: String,
/**
* Name of the android variant this task is associated with.
*/
public val variant: String,
) : Properties(isTest, sourceSetName)

/**
* The `buf` command to execute.
*
Expand Down Expand Up @@ -151,7 +113,7 @@ public abstract class BufExecTask @Inject constructor(
public inline fun <reified T : BufExecTask> Project.registerBufExecTask(
name: String,
workingDir: Provider<File>,
properties: BufExecTask.Properties,
properties: ProtoTask.Properties,
noinline configuration: T.() -> Unit,
): TaskProvider<T> = registerBufExecTask(T::class, name, workingDir, properties, configuration)

Expand All @@ -160,12 +122,12 @@ internal fun <T : BufExecTask> Project.registerBufExecTask(
clazz: KClass<T>,
name: String,
workingDir: Provider<File>,
properties: BufExecTask.Properties,
properties: ProtoTask.Properties,
configuration: T.() -> Unit = {},
): TaskProvider<T> = tasks.register(name, clazz, properties).apply {
configure {
val executableConfiguration = configurations.getByName(BUF_EXECUTABLE_CONFIGURATION)
bufExecutable.set(executableConfiguration.singleFile)
val executableConfiguration = configurations.named(BUF_EXECUTABLE_CONFIGURATION)
bufExecutable.set(project.provider { executableConfiguration.get().singleFile })
this.workingDir.set(workingDir)

val buf = provider { rpcExtension().protoc.get().buf }
Expand Down
Loading
Loading