Skip to content

Commit b9e6693

Browse files
committed
[cinterop] Use clang modules instead of headers for cinterop. Cleanup arguments for swift build. Some logging.
1 parent 014aac4 commit b9e6693

File tree

2 files changed

+71
-41
lines changed

2 files changed

+71
-41
lines changed

plugin/src/main/kotlin/io/github/ttypic/swiftklib/gradle/task/CompileSwiftTask.kt

Lines changed: 67 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ open class CompileSwiftTask @Inject constructor(
3333
@get:Internal
3434
internal val targetDir: File
3535
get() {
36-
return project.buildDir.resolve("${EXTENSION_NAME}/$cinteropName/$compileTarget")
36+
return project.layout.buildDirectory.file("${EXTENSION_NAME}/$cinteropName/$compileTarget").get().asFile
3737
}
3838

3939
@get:OutputDirectory
@@ -96,15 +96,21 @@ open class CompileSwiftTask @Inject constructor(
9696
val sourceFilePathReplacements = mapOf(
9797
buildDir().absolutePath to pathProperty.get().absolutePath
9898
)
99+
val extraArgs = if (xcodeVersion >= 15 && compileTarget in SDKLESS_TARGETS) {
100+
additionalSysrootArgs()
101+
} else {
102+
emptyList()
103+
}
104+
val args = generateBuildArgs() + extraArgs
105+
106+
logger.info("-- Running swift build --")
107+
logger.info("Working directory: $swiftBuildDir")
108+
logger.info("xcrun ${args.joinToString(" ")}")
109+
99110
project.exec {
100111
it.executable = "xcrun"
101112
it.workingDir = swiftBuildDir
102-
val extraArgs = if (xcodeVersion >= 15 && compileTarget in SDKLESS_TARGETS) {
103-
additionalSysrootArgs()
104-
} else {
105-
emptyList()
106-
}
107-
it.args = generateBuildArgs() + extraArgs
113+
it.args = args
108114
it.standardOutput = StringReplacingOutputStream(
109115
delegate = System.out,
110116
replacements = sourceFilePathReplacements
@@ -115,42 +121,43 @@ open class CompileSwiftTask @Inject constructor(
115121
)
116122
}
117123

124+
val releaseBuildPath = File(swiftBuildDir, ".build/${compileTarget.arch()}-apple-macosx/release")
125+
118126
return SwiftBuildResult(
119-
libPath = File(
120-
swiftBuildDir,
121-
".build/${compileTarget.arch()}-apple-macosx/release/lib${cinteropName}.a"
122-
),
123-
headerPath = File(
124-
swiftBuildDir,
125-
".build/${compileTarget.arch()}-apple-macosx/release/$cinteropName.build/$cinteropName-Swift.h"
126-
)
127+
libPath = File(releaseBuildPath, "lib${cinteropName}.a"),
128+
headerPath = File(releaseBuildPath, "$cinteropName.build/$cinteropName-Swift.h")
127129
)
128130
}
129131

130-
private fun generateBuildArgs(): List<String> = listOf(
131-
"swift",
132-
"build",
133-
"--arch",
134-
compileTarget.arch(),
135-
"-c",
136-
"release",
137-
"-Xswiftc",
138-
"-sdk",
139-
"-Xswiftc",
140-
readSdkPath(),
141-
"-Xswiftc",
142-
"-target",
143-
"-Xswiftc",
144-
"${compileTarget.archPrefix()}-apple-${operatingSystem(compileTarget)}.0${compileTarget.simulatorSuffix()}",
145-
)
132+
private fun generateBuildArgs(): List<String> {
133+
val sdkPath = readSdkPath()
134+
val baseArgs = "swift build --arch ${compileTarget.arch()} -c release".split(" ")
135+
136+
val xcrunArgs = listOf(
137+
"-sdk",
138+
sdkPath,
139+
"-target",
140+
compileTarget.asSwiftcTarget(compileTarget.operatingSystem()),
141+
).asSwiftcArgs()
142+
143+
return baseArgs + xcrunArgs
144+
}
146145

147146
/** Workaround for bug in toolchain where the sdk path (via `swiftc -sdk` flag) is not propagated to clang. */
148-
private fun additionalSysrootArgs(): List<String> = listOf(
149-
"-Xcc",
150-
"-isysroot",
151-
"-Xcc",
152-
readSdkPath(),
153-
)
147+
private fun additionalSysrootArgs(): List<String> =
148+
listOf(
149+
"-isysroot",
150+
readSdkPath(),
151+
).asCcArgs()
152+
153+
private fun List<String>.asSwiftcArgs() = asBuildToolArgs("swiftc")
154+
private fun List<String>.asCcArgs() = asBuildToolArgs("cc")
155+
156+
private fun List<String>.asBuildToolArgs(tool: String): List<String> {
157+
return this.flatMap {
158+
listOf("-X$tool", it)
159+
}
160+
}
154161

155162
private fun readSdkPath(): String {
156163
val stdout = ByteArrayOutputStream()
@@ -209,22 +216,41 @@ open class CompileSwiftTask @Inject constructor(
209216
if (xcodeVersion >= 15) compileTarget.linkerPlatformVersionName()
210217
else compileTarget.linkerMinOsVersionName()
211218

219+
val modulePath = headerPath.parentFile.absolutePath
220+
221+
val basicLinkerOpts = listOf(
222+
"-L/usr/lib/swift",
223+
"-$linkerPlatformVersion",
224+
"${minOs(compileTarget)}.0",
225+
"${minOs(compileTarget)}.0",
226+
"-L${xcodePath}/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/${compileTarget.os()}"
227+
)
228+
229+
val linkerOpts = basicLinkerOpts.joinToString(" ")
230+
212231
val content = """
213232
package = $packageName
214233
language = Objective-C
215-
headers = ${headerPath.absolutePath}
234+
modules = $cinteropName
216235
217236
# md5 ${libPath.md5()}
218237
staticLibraries = ${libPath.name}
219238
libraryPaths = ${libPath.parentFile.absolutePath}
220239
221-
linkerOpts = -L/usr/lib/swift -$linkerPlatformVersion ${minOs(compileTarget)}.0 ${minOs(compileTarget)}.0 -L${xcodePath}/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/${compileTarget.os()}
240+
compilerOpts = -fmodules -I$modulePath
241+
linkerOpts = $linkerOpts
222242
""".trimIndent()
243+
244+
logger.info("--- Generated cinterop def file for $cinteropName ---")
245+
logger.info("--- cinterop def ---")
246+
logger.info(content)
247+
logger.info("---/ cinterop def /---")
248+
223249
defFile.create(content)
224250
}
225251

226-
private fun operatingSystem(compileTarget: CompileTarget): String =
227-
when (compileTarget) {
252+
private fun CompileTarget.operatingSystem(): String =
253+
when (this) {
228254
CompileTarget.iosX64, CompileTarget.iosArm64, CompileTarget.iosSimulatorArm64 -> "ios$minIos"
229255
CompileTarget.watchosX64, CompileTarget.watchosArm64, CompileTarget.watchosSimulatorArm64 -> "watchos$minWatchos"
230256
CompileTarget.tvosX64, CompileTarget.tvosArm64, CompileTarget.tvosSimulatorArm64 -> "tvos$minTvos"

plugin/src/main/kotlin/io/github/ttypic/swiftklib/gradle/task/CompileTargetExt.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,7 @@ internal fun CompileTarget.linkerMinOsVersionName() = when(this) {
7272
CompileTarget.macosX64 -> "macosx_version_min"
7373
CompileTarget.macosArm64 -> "macosx_version_min"
7474
}
75+
76+
internal fun CompileTarget.asSwiftcTarget(operatingSystem: String): String {
77+
return "${archPrefix()}-apple-${operatingSystem}.0${simulatorSuffix()}"
78+
}

0 commit comments

Comments
 (0)