Skip to content

Commit 16c76c3

Browse files
committed
grpc-native: Add gradle configuration for cInterop and grpcpp_c library
Signed-off-by: Johannes Zottele <[email protected]>
1 parent 4d8bc92 commit 16c76c3

File tree

4 files changed

+142
-0
lines changed

4 files changed

+142
-0
lines changed
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
* Copyright 2023-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package util
6+
7+
8+
import org.gradle.kotlin.dsl.assign
9+
import org.gradle.kotlin.dsl.getValue
10+
import org.gradle.kotlin.dsl.provideDelegate
11+
import org.gradle.kotlin.dsl.withType
12+
import org.jetbrains.dokka.gradle.tasks.DokkaGeneratePublicationTask
13+
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
14+
import org.jetbrains.kotlin.gradle.plugin.mpp.DefaultCInteropSettings
15+
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
16+
import org.jetbrains.kotlin.gradle.tasks.KotlinNativeCompile
17+
18+
19+
/**
20+
* Creates a CInterop configuration for all Native targets using the given [sourceSet]
21+
* in a Kotlin Multiplatform project.
22+
*
23+
* The [name] defines the CInterop configuration name. Definition file is expected to be located
24+
* at `[sourceSet]/interop/[name].def` by default, but can be customized via [definitionFilePath].
25+
* Additional configuration can be provided through [configure] block.
26+
*
27+
* Simple usage:
28+
* ```
29+
* kotlin {
30+
* createCInterop("ssl", "posix")
31+
* }
32+
* ```
33+
*
34+
* Advanced usage with a separate definition for each target and additional configuration:
35+
* ```
36+
* kotlin {
37+
* createCInterop(
38+
* name = "ssl",
39+
* sourceSet = "posix",
40+
* definitionFilePath = { target -> "$target/interop/ssl.def" },
41+
* configure = { target ->
42+
* includeDirs("$target/interop/include")
43+
* compilerOpts("-DUSE_SSL")
44+
* }
45+
* )
46+
* }
47+
* ```
48+
*/
49+
@Suppress("UnstableApiUsage")
50+
fun KotlinMultiplatformExtension.createCInterop(
51+
name: String,
52+
sourceSet: String,
53+
definitionFilePath: (String) -> String = { "$sourceSet/interop/$name.def" },
54+
configure: DefaultCInteropSettings.(String) -> Unit = {}
55+
) {
56+
57+
val cinteropTargets = grpcNativeTargets().map { it.name }
58+
val projectDirectory = project.isolated.projectDirectory
59+
60+
targets.named { it in cinteropTargets }
61+
.all {
62+
check(this is KotlinNativeTarget) { "Can't create cinterop for non-native target $targetName" }
63+
64+
val main by compilations
65+
main.cinterops.create(name) {
66+
definitionFile = projectDirectory.file(definitionFilePath(targetName))
67+
configure(targetName)
68+
}
69+
}
70+
71+
// Disable configuration cache for compile[target]MainKotlinMetadata tasks
72+
project.tasks.withType<KotlinNativeCompile>()
73+
.named { it.endsWith("MainKotlinMetadata") }
74+
.configureEach { notCompatibleWithConfigurationCache("Workaround for KT-76147") }
75+
76+
// The problem with compile*MainKotlinMetadata tasks also affects Dokka tasks
77+
project.tasks.withType<DokkaGeneratePublicationTask>()
78+
.named { it == "dokkaGeneratePublicationHtml" }
79+
.configureEach { notCompatibleWithConfigurationCache("Workaround for KT-76147") }
80+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/*
2+
* Copyright 2023-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package util
6+
7+
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
8+
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
9+
10+
11+
fun KotlinMultiplatformExtension.grpcNativeTargets(): Set<KotlinNativeTarget> = setOf(macosArm64())

grpc/grpc-core/build.gradle.kts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
* Copyright 2023-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
33
*/
44

5+
import org.gradle.internal.extensions.stdlib.capitalized
6+
import util.createCInterop
7+
58
plugins {
69
alias(libs.plugins.conventions.kmp)
710
alias(libs.plugins.kotlinx.rpc)
@@ -28,4 +31,45 @@ kotlin {
2831
}
2932
}
3033
}
34+
35+
val grpcppCLib = projectDir.resolve("../grpcpp-c")
36+
37+
fun findProgram(name: String) = org.gradle.internal.os.OperatingSystem.current().findInPath(name)
38+
val checkBazel by tasks.registering {
39+
doLast {
40+
val bazelPath = findProgram("bazel")
41+
if (bazelPath != null) {
42+
println("bazel: $bazelPath")
43+
} else {
44+
throw GradleException("'bazel' not found on PATH. Please install Bazel (https://bazel.build/).")
45+
}
46+
}
47+
}
48+
49+
val buildGrpcppCLib = tasks.register<Exec>("buildGrpcppCLib") {
50+
group = "build"
51+
workingDir = grpcppCLib
52+
commandLine("bash", "-c", "bazel build :grpcpp_c_static --config=release")
53+
inputs.files(fileTree(grpcppCLib) { exclude("bazel-*/**") })
54+
outputs.dir(grpcppCLib.resolve("bazel-bin"))
55+
56+
dependsOn(checkBazel)
57+
}
58+
59+
createCInterop("libgrpcpp_c", sourceSet = "src/nativeMain") { target ->
60+
includeDirs(grpcppCLib.resolve("include"))
61+
extraOpts(
62+
"-libraryPath", "${grpcppCLib.resolve("bazel-out/darwin_arm64-opt/bin")}"
63+
)
64+
includeDirs(
65+
grpcppCLib.resolve("include"),
66+
grpcppCLib.resolve("bazel-grpcpp-c/external/grpc+/include")
67+
)
68+
69+
tasks.named("cinteropLibgrpcpp_c${target.capitalized()}") {
70+
dependsOn(buildGrpcppCLib)
71+
}
72+
73+
}
74+
3175
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
headers = grpcpp_c.h
2+
headerFilter= grpcpp_c.h grpc/slice.h grpc/byte_buffer.h
3+
4+
noStringConversion = grpc_slice_from_copied_buffer my_grpc_slice_from_copied_buffer
5+
6+
linkerOpts.osx = -lgrpcpp_c_static
7+
#staticLibraries = libgrpcpp_c_static.a

0 commit comments

Comments
 (0)