Skip to content

Commit 7b59c4d

Browse files
committed
Added full KMP support with proto source sets hierarchy and better plugin management
1 parent fa02074 commit 7b59c4d

File tree

47 files changed

+867
-390
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+867
-390
lines changed

gradle-conventions/src/main/kotlin/conventions-jvm.gradle.kts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ java {
2020
withSourcesJar()
2121
}
2222

23-
configureJavaCompatibility(8)
23+
if (project.name != "gradle-plugin") {
24+
configureJavaCompatibility(8)
25+
}
26+
2427
configureKotlinCompatibility("2.0.0")
2528

2629
kotlin {

gradle-conventions/src/main/kotlin/util/other/generateSource.kt

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,20 +40,28 @@ fun Project.generateSource(
4040
text: String,
4141
chooseSourceSet: NamedDomainObjectContainer<KotlinSourceSet>.() -> NamedDomainObjectProvider<KotlinSourceSet>,
4242
) {
43-
val sourcesDir = File(project.layout.buildDirectory.asFile.get(), "generated-sources/kotlin")
44-
45-
val generatePluginVersionTask =
46-
tasks.register<GenerateSourceTask>("generateSources_$name", name, text, sourcesDir)
47-
4843
withKotlinJvmExtension {
49-
chooseSourceSet(sourceSets).configure {
50-
kotlin.srcDir(generatePluginVersionTask.map { it.sourcesDir })
51-
}
44+
generateSource(sourceSets, name, text, chooseSourceSet)
5245
}
5346

5447
withKotlinKmpExtension {
55-
chooseSourceSet(sourceSets).configure {
56-
kotlin.srcDir(generatePluginVersionTask.map { it.sourcesDir })
57-
}
48+
generateSource(sourceSets, name, text, chooseSourceSet)
49+
}
50+
}
51+
52+
private fun Project.generateSource(
53+
sourceSets: NamedDomainObjectContainer<KotlinSourceSet>,
54+
name: String,
55+
text: String,
56+
chooseSourceSet: NamedDomainObjectContainer<KotlinSourceSet>.() -> NamedDomainObjectProvider<KotlinSourceSet>,
57+
) {
58+
val sourceSet = chooseSourceSet(sourceSets)
59+
val sourcesDir = File(project.layout.buildDirectory.asFile.get(), "generated-sources/kotlin/${sourceSet.name}")
60+
61+
val generatePluginVersionTask =
62+
tasks.register<GenerateSourceTask>("generateSources_$name", name, text, sourcesDir)
63+
64+
sourceSet.configure {
65+
kotlin.srcDir(generatePluginVersionTask.map { it.sourcesDir })
5866
}
5967
}

gradle-plugin/src/main/kotlin/kotlinx/rpc/Extensions.kt

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ internal fun Project.rpcExtensionOrNull(): RpcExtension? = extensions.findByType
2424
internal fun Project.rpcExtension(): RpcExtension = rpcExtensionOrNull()
2525
?: error("Rpc extension not found. Please apply the plugin to the project")
2626

27-
public open class RpcExtension @Inject constructor(objects: ObjectFactory, private val project: Project) {
27+
public open class RpcExtension @Inject constructor(objects: ObjectFactory, project: Project) {
2828
/**
2929
* Controls `@Rpc` [annotation type-safety](https://github.com/Kotlin/kotlinx-rpc/pull/240) compile-time checkers.
3030
*
@@ -48,25 +48,60 @@ public open class RpcExtension @Inject constructor(objects: ObjectFactory, priva
4848
configure.execute(strict)
4949
}
5050

51-
internal val protocApplied = AtomicBoolean(false)
5251

5352
/**
5453
* Protoc settings.
54+
*
55+
* Can't be called in a lazy context if not initialized.
5556
*/
56-
public val protoc: ProtocExtension by lazy {
57-
if (protocApplied.get()) {
58-
error("Illegal access to protoc extension during DefaultProtocExtension.init")
57+
public val protoc: Provider<ProtocExtension> = project.provider {
58+
if (!protocApplied.get()) {
59+
error("""
60+
Protoc extension was not initialized.
61+
Please, apply the plugin by using the following declaration:
62+
63+
rpc {
64+
protoc()
65+
}
66+
67+
If the error persists, check if you are using this property lazily,
68+
i.e. by calling 'protoc.map { }' and not 'protoc.get()',
69+
otherwise the order of initialization may be wrong.
70+
""".trimIndent())
5971
}
6072

61-
protocApplied.set(true)
62-
objects.newInstance<DefaultProtocExtension>()
73+
protocInternal
6374
}
6475

6576
/**
6677
* Protoc settings.
6778
*/
6879
public fun protoc(configure: Action<ProtocExtension> = Action {}) {
69-
configure.execute(protoc)
80+
configure.execute(protocInternal)
81+
}
82+
83+
internal val protocApplied = AtomicBoolean(false)
84+
85+
internal val protocInternal by lazy {
86+
if (protocApplied.get()) {
87+
error("Illegal access to protoc extension during DefaultProtocExtension.init")
88+
}
89+
90+
protocApplied.set(true)
91+
objects.newInstance<DefaultProtocExtension>().apply {
92+
callbacks.forEach { it.execute(this) }
93+
}
94+
}
95+
96+
private val callbacks = mutableListOf<Action<ProtocExtension>>()
97+
98+
internal fun whenProtocApplied(action: Action<ProtocExtension>) {
99+
if (protocApplied.get()) {
100+
action.execute(protoc.get())
101+
return
102+
}
103+
104+
callbacks.add(action)
70105
}
71106
}
72107

gradle-plugin/src/main/kotlin/kotlinx/rpc/buf/BufExtensions.kt

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import kotlin.time.Duration
2424
*
2525
* @see <a href="https://buf.build/docs/reference/cli/buf/">buf commands</a>
2626
*/
27-
public open class BufExtension @Inject constructor(objects: ObjectFactory) {
27+
public open class BufExtension @Inject internal constructor(objects: ObjectFactory) {
2828
/**
2929
* `--config` argument value.
3030
*
@@ -101,17 +101,17 @@ public open class BufExtension @Inject constructor(objects: ObjectFactory) {
101101
/**
102102
* Allows registering custom Buf tasks that can operate on the generated workspace.
103103
*/
104-
public open class BufTasksExtension @Inject constructor(internal val project: Project) {
104+
public open class BufTasksExtension @Inject internal constructor(internal val project: Project) {
105105

106106
/**
107107
* Registers a custom Buf task that operates on the generated workspace.
108108
*
109109
* Name conventions:
110110
* `lint` input for [name] will result in tasks
111111
* named 'bufLintMain' and 'bufLintTest' for Kotlin/JVM projects
112-
* and 'bufLintCommonMain' and 'bufLintCommonTest' for Kotlin/Multiplatform projects.
112+
* and 'bufLintCommonMain', 'bufLintCommonTest', 'bufLintNativeMain', etc., for Kotlin/Multiplatform projects.
113113
*
114-
* Note the by default 'test' task doesn't depend on 'main' task.
114+
* Note the by default 'test' task doesn't depend on the 'main' task.
115115
*/
116116
public fun <T : BufExecTask> registerWorkspaceTask(
117117
kClass: KClass<T>,
@@ -129,7 +129,6 @@ public open class BufTasksExtension @Inject constructor(internal val project: Pr
129129
return provider
130130
}
131131

132-
133132
/**
134133
* Registers a custom Buf task that operates on the generated workspace.
135134
*

gradle-plugin/src/main/kotlin/kotlinx/rpc/buf/tasks/BufExecTask.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ internal fun <T : BufExecTask> Project.registerBufExecTask(
117117
bufExecutable.set(executableConfiguration.singleFile)
118118
this.workingDir.set(workingDir)
119119

120-
val buf = provider { rpcExtension().protoc.buf }
120+
val buf = provider { rpcExtension().protoc.get().buf }
121121
configFile.set(buf.flatMap { it.configFile })
122122
logFormat.set(buf.flatMap { it.logFormat })
123123
bufTimeoutInWholeSeconds.set(buf.flatMap { it.timeout.map { duration -> duration.inWholeSeconds } })

gradle-plugin/src/main/kotlin/kotlinx/rpc/buf/tasks/BufGenerateTask.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ internal fun Project.registerBufGenerateTask(
131131
group = PROTO_GROUP
132132
description = "Generates code from .proto files using 'buf generate'"
133133

134-
val generate = provider { rpcExtension().protoc.buf.generate }
134+
val generate = provider { rpcExtension().protoc.get().buf.generate }
135135

136136
includeImports.set(generate.flatMap { it.includeImports })
137137
includeWkt.set(generate.flatMap { it.includeWkt })

gradle-plugin/src/main/kotlin/kotlinx/rpc/buf/tasks/GenerateBufGenYaml.kt

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -137,19 +137,13 @@ public abstract class GenerateBufGenYaml : DefaultTask() {
137137
internal fun Project.registerGenerateBufGenYamlTask(
138138
name: String,
139139
buildSourceSetsDir: File,
140-
protocPlugins: Provider<List<ProtocPlugin>>,
140+
protocPlugins: Provider<Set<ProtocPlugin>>,
141141
configure: GenerateBufGenYaml.() -> Unit = {},
142142
): TaskProvider<GenerateBufGenYaml> {
143143
val capitalizeName = name.replaceFirstChar { it.uppercase() }
144144
return project.tasks.register<GenerateBufGenYaml>("${GenerateBufGenYaml.NAME_PREFIX}$capitalizeName") {
145145
val pluginsProvider = project.provider {
146146
protocPlugins.get().map { plugin ->
147-
if (!plugin.artifact.isPresent) {
148-
throw GradleException(
149-
"Artifact is not specified for protoc plugin ${plugin.name}. " +
150-
"Use `local {}` or `remote {}` to specify it.")
151-
}
152-
153147
val artifact = plugin.artifact.get()
154148
val locator = when (artifact) {
155149
is ProtocPlugin.Artifact.Local -> artifact.executor.get()

gradle-plugin/src/main/kotlin/kotlinx/rpc/buf/tasks/GenerateBufYaml.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
package kotlinx.rpc.buf.tasks
66

77
import kotlinx.rpc.buf.BUF_YAML
8+
import kotlinx.rpc.protoc.DefaultProtoSourceSet
89
import kotlinx.rpc.protoc.PROTO_GROUP
910
import kotlinx.rpc.util.ensureRegularFileExists
1011
import org.gradle.api.DefaultTask
1112
import org.gradle.api.Project
1213
import org.gradle.api.provider.Property
14+
import org.gradle.api.provider.Provider
1315
import org.gradle.api.tasks.Input
1416
import org.gradle.api.tasks.OutputFile
1517
import org.gradle.api.tasks.TaskAction
@@ -88,7 +90,7 @@ internal fun Project.registerGenerateBufYamlTask(
8890
buildSourceSetsDir: File,
8991
buildSourceSetsProtoDir: File,
9092
buildSourceSetsImportDir: File,
91-
withImport: Boolean,
93+
withImport: Provider<Boolean>,
9294
configure: GenerateBufYaml.() -> Unit = {},
9395
): TaskProvider<GenerateBufYaml> {
9496
val capitalizeName = name.replaceFirstChar { it.uppercase() }

gradle-plugin/src/main/kotlin/kotlinx/rpc/internal/configureLocalProtocGenDevelopmentDependency.kt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ package kotlinx.rpc.internal
77
import kotlinx.rpc.buf.tasks.BufGenerateTask
88
import kotlinx.rpc.protoc.grpcKotlinMultiplatform
99
import kotlinx.rpc.protoc.kotlinMultiplatform
10-
import kotlinx.rpc.protoc.protoSourceSets
1110
import kotlinx.rpc.rpcExtension
1211
import org.gradle.api.Project
1312
import org.gradle.internal.extensions.core.extra
@@ -21,9 +20,7 @@ public fun Project.configureLocalProtocGenDevelopmentDependency(
2120
val globalRootDir: String by extra
2221

2322
// init
24-
rpcExtension().protoc()
25-
26-
protoSourceSets.all {
23+
rpcExtension().protoc {
2724
plugins {
2825
kotlinMultiplatform {
2926
local {

0 commit comments

Comments
 (0)