Skip to content

Commit

Permalink
Fix Swift incremental compilation.
Browse files Browse the repository at this point in the history
  • Loading branch information
FilipDolnik committed Nov 2, 2023
1 parent c3c1df6 commit f6ba496
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -89,18 +89,38 @@ class SkieBuildDirectory(

val objectFiles: ObjectFiles = ObjectFiles(this)

val module: Module = Module(this)

fun moduleHeader(moduleName: String): ModuleHeader = ModuleHeader(this, moduleName)

val fakeObjCFrameworks: FakeObjCFrameworks = FakeObjCFrameworks(this)

val apiNotes: ApiNotes = ApiNotes(this)

val config: Config = Config(this)

class ObjectFiles(parent: Directory) : PermanentDirectory(parent, "object-files") {

val all: List<File>
get() = directory.walkTopDown()
.filter { it.extension == "o" }
.toList()
val allFiles: List<File>
get() = directory.walkTopDown().toList()

val allObjectFiles: List<File>
get() = allFiles.filter { it.extension == "o" }

fun objectFile(sourceFileName: String): File = directory.resolve("$sourceFileName.o")

fun swiftDependencies(sourceFileName: String): File = directory.resolve("$sourceFileName.swiftdeps")

fun dependencies(sourceFileName: String): File = directory.resolve("$sourceFileName.d")

fun partialSwiftModule(sourceFileName: String): File = directory.resolve("$sourceFileName~partial.swiftmodule")
}

class Module(parent: Directory) : PermanentDirectory(parent, "module") {

fun swiftDependencies(moduleName: String): File = directory.resolve("$moduleName.swiftdeps")

fun dependencies(moduleName: String): File = directory.resolve("$moduleName.d")
}

class ModuleHeader(parent: Directory, moduleName: String) : PermanentDirectory(parent, "headers") {
Expand Down Expand Up @@ -142,6 +162,13 @@ class SkieBuildDirectory(

fun apiNotes(moduleName: String): File = directory.resolve("$moduleName.apinotes")
}

class Config(parent: Directory) : PermanentDirectory(parent, "config") {

val outputFileMap: File = directory.resolve("OutputFileMap.json")

fun swiftFileList(moduleName: String): File = directory.resolve("$moduleName.SwiftFileList")
}
}

class Temp(parent: Directory) : PermanentDirectory(parent, "temp") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ class CompileSwiftPhase(
private val skieBuildDirectory = context.skieBuildDirectory
private val targetTriple = context.configurables.targetTriple
private val swiftFrameworkHeader = context.skieBuildDirectory.swiftCompiler.moduleHeader(framework.moduleName)
private val swiftFileList = context.skieBuildDirectory.swiftCompiler.config.swiftFileList(framework.moduleName)
private val outputFileMap = context.skieBuildDirectory.swiftCompiler.config.outputFileMap
private val objectFiles = skieBuildDirectory.swiftCompiler.objectFiles
private val moduleDirectory = skieBuildDirectory.swiftCompiler.module

private val isDebug = konanConfig.debug

context(SirPhase.Context)
override fun execute() {
Expand All @@ -30,7 +36,11 @@ class CompileSwiftPhase(
return
}

callSwiftCompiler(sourceFiles)
createSwiftFileList(sourceFiles)

createOutputFileMap(sourceFiles)

callSwiftCompiler()

deleteOldObjectFiles(sourceFiles)

Expand All @@ -41,7 +51,43 @@ class CompileSwiftPhase(
addSwiftSpecificLinkerArgs()
}

private fun callSwiftCompiler(sourceFiles: List<File>) {
private fun createSwiftFileList(sourceFiles: List<File>) {
val content = sourceFiles.joinToString("\n") { it.absolutePath }

swiftFileList.writeText(content)
}

private fun createOutputFileMap(sourceFiles: List<File>) {
if (!isDebug) {
return
}

val root = """
"": {
"emit-module-dependencies": "${moduleDirectory.dependencies(framework.moduleName).absolutePath}",
"swift-dependencies": "${moduleDirectory.swiftDependencies(framework.moduleName).absolutePath}"
},
""".trimIndent()

val body = sourceFiles.joinToString(",\n") { sourceFile ->
val sourceFileName = sourceFile.nameWithoutExtension

"""
"${sourceFile.absolutePath}": {
"object": "${objectFiles.objectFile(sourceFileName).absolutePath}",
"dependencies": "${objectFiles.dependencies(sourceFileName).absolutePath}",
"swift-dependencies": "${objectFiles.swiftDependencies(sourceFileName).absolutePath}",
"swiftmodule": "${objectFiles.partialSwiftModule(sourceFileName).absolutePath}"
}
""".trimIndent()
}

val content = "{\n$root\n$body\n}"

outputFileMap.writeText(content)
}

private fun callSwiftCompiler() {
Command("${configurables.absoluteTargetToolchain}/usr/bin/swiftc").apply {
+listOf("-module-name", framework.moduleName)
+"-import-underlying-module"
Expand All @@ -62,10 +108,18 @@ class CompileSwiftPhase(
+"-emit-objc-header-path"
+swiftFrameworkHeader.swiftHeader
getSwiftcBitcodeArg()?.let { +it }
+getSwiftcBuildTypeArgs()
+"-emit-object"
+"-parse-as-library"
+"-enable-batch-mode"
if (isDebug) {
+"-Onone"
+"-incremental"
+"-output-file-map"
+outputFileMap.absolutePath
} else {
+"-O"
+"-whole-module-optimization"
}
+"-g"
+"-module-cache-path"
+skieBuildDirectory.cache.swiftModules.directory.absolutePath
Expand All @@ -76,28 +130,28 @@ class CompileSwiftPhase(
+configurables.absoluteTargetSysRoot
+"-target"
+configurables.targetTriple.withOSVersion(configurables.osVersionMin).toString()
+sourceFiles.map { it.absolutePath }
+"@${swiftFileList.absolutePath}"

workingDirectory = skieBuildDirectory.swiftCompiler.objectFiles.directory
workingDirectory = objectFiles.directory

execute(logFile = skieBuildDirectory.debug.logs.swiftc)
}
}

private fun deleteOldObjectFiles(sourceFiles: List<File>) {
if (konanConfig.debug) {
if (isDebug) {
val sourceFilesNames = sourceFiles.map { it.nameWithoutExtension }.toSet()

skieBuildDirectory.swiftCompiler.objectFiles.all
objectFiles.allFiles
.filterNot { it.nameWithoutExtension in sourceFilesNames }
.forEach { objectFile ->
objectFile.delete()
.forEach {
it.delete()
}
} else {
skieBuildDirectory.swiftCompiler.objectFiles.all
objectFiles.allFiles
.filter { it.nameWithoutExtension != framework.moduleName }
.forEach { objectFile ->
objectFile.delete()
.forEach {
it.delete()
}
}
}
Expand All @@ -109,13 +163,6 @@ class CompileSwiftPhase(
BitcodeEmbedding.Mode.MARKER -> "-embed-bitcode-marker"
}

private fun getSwiftcBuildTypeArgs() =
if (konanConfig.debug) {
emptyList()
} else {
listOf("-O", "-whole-module-optimization")
}

private fun copySwiftModuleFiles() {
val copyFiles = mapOf(
swiftFrameworkHeader.swiftModule to framework.swiftModule(targetTriple),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ package co.touchlab.skie.util
import co.touchlab.skie.util.directory.SkieDirectories

val SkieDirectories.objectFilePaths: List<String>
get() = buildDirectory.swiftCompiler.objectFiles.all.map { it.absolutePath }
get() = buildDirectory.swiftCompiler.objectFiles.allObjectFiles.map { it.absolutePath }

0 comments on commit f6ba496

Please sign in to comment.