Avoid using shared module cache in cinterop
To improve compilation predictability
This commit is contained in:
committed by
SvyatoslavScherbina
parent
8a1d8a29b1
commit
de90535386
+31
-16
@@ -9,27 +9,42 @@ fun getModulesInfo(compilation: Compilation, modules: List<String>): ModulesInfo
|
||||
if (modules.isEmpty()) return ModulesInfo(emptyList(), emptySet())
|
||||
|
||||
withIndex { index ->
|
||||
|
||||
val ownHeaders = mutableSetOf<String>()
|
||||
val topLevelHeaders = linkedSetOf<String>()
|
||||
|
||||
getModulesASTFiles(index, compilation, modules).forEach {
|
||||
val moduleTranslationUnit = clang_createTranslationUnit(index, it)!!
|
||||
try {
|
||||
val modulesHeaders = getModulesHeaders(index, moduleTranslationUnit, modules.toSet(), topLevelHeaders)
|
||||
modulesHeaders.mapTo(ownHeaders) { it.canonicalPath }
|
||||
} finally {
|
||||
clang_disposeTranslationUnit(moduleTranslationUnit)
|
||||
}
|
||||
ModularCompilation(compilation).use {
|
||||
val modulesASTFiles = getModulesASTFiles(index, it, modules)
|
||||
return buildModulesInfo(index, modules, modulesASTFiles)
|
||||
}
|
||||
|
||||
return ModulesInfo(topLevelHeaders.toList(), ownHeaders)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getModulesASTFiles(index: CXIndex, compilation: Compilation, modules: List<String>): List<String> {
|
||||
private fun buildModulesInfo(index: CXIndex, modules: List<String>, modulesASTFiles: List<String>): ModulesInfo {
|
||||
val ownHeaders = mutableSetOf<String>()
|
||||
val topLevelHeaders = linkedSetOf<String>()
|
||||
modulesASTFiles.forEach {
|
||||
val moduleTranslationUnit = clang_createTranslationUnit(index, it)!!
|
||||
try {
|
||||
val modulesHeaders = getModulesHeaders(index, moduleTranslationUnit, modules.toSet(), topLevelHeaders)
|
||||
modulesHeaders.mapTo(ownHeaders) { it.canonicalPath }
|
||||
} finally {
|
||||
clang_disposeTranslationUnit(moduleTranslationUnit)
|
||||
}
|
||||
}
|
||||
|
||||
return ModulesInfo(topLevelHeaders.toList(), ownHeaders)
|
||||
}
|
||||
|
||||
internal open class ModularCompilation(compilation: Compilation): Compilation by compilation, Disposable {
|
||||
private val moduleCacheDirectory = createTempDir("ModuleCache")
|
||||
|
||||
override val compilerArgs = compilation.compilerArgs +
|
||||
listOf("-fmodules", "-fmodules-cache-path=${moduleCacheDirectory.absolutePath}")
|
||||
|
||||
override fun dispose() {
|
||||
moduleCacheDirectory.deleteRecursively()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getModulesASTFiles(index: CXIndex, compilation: ModularCompilation, modules: List<String>): List<String> {
|
||||
val compilationWithImports = object : Compilation by compilation {
|
||||
override val compilerArgs = compilation.compilerArgs + "-fmodules"
|
||||
override val additionalPreambleLines = modules.map { "@import $it;" } + compilation.additionalPreambleLines
|
||||
}
|
||||
|
||||
|
||||
+32
-20
@@ -428,34 +428,36 @@ internal class ModulesMap(
|
||||
val translationUnit: CXTranslationUnit
|
||||
) : Closeable {
|
||||
|
||||
private val modularCompilation: ModularCompilation
|
||||
private val index: CXIndex
|
||||
private val translationUnitWithModules: CXTranslationUnit
|
||||
|
||||
init {
|
||||
index = clang_createIndex(0, 0)!!
|
||||
try {
|
||||
translationUnitWithModules = object : Compilation by compilation {
|
||||
override val compilerArgs = compilation.compilerArgs + "-fmodules"
|
||||
}.parse(index)
|
||||
private val arena = Arena()
|
||||
|
||||
try {
|
||||
translationUnitWithModules.ensureNoCompileErrors()
|
||||
} catch (e: Throwable) {
|
||||
clang_disposeTranslationUnit(translationUnitWithModules)
|
||||
throw e
|
||||
}
|
||||
|
||||
} catch (e: Throwable) {
|
||||
clang_disposeIndex(index)
|
||||
throw e
|
||||
}
|
||||
private inline fun <T> T.toBeDisposedWith(crossinline block: (T) -> Unit): T = apply {
|
||||
arena.defer { block(this) }
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
arena.clear()
|
||||
}
|
||||
|
||||
init {
|
||||
try {
|
||||
clang_disposeTranslationUnit(translationUnitWithModules)
|
||||
} finally {
|
||||
clang_disposeIndex(index)
|
||||
modularCompilation = ModularCompilation(compilation)
|
||||
.toBeDisposedWith { it.dispose() }
|
||||
|
||||
index = clang_createIndex(0, 0)!!
|
||||
.toBeDisposedWith { clang_disposeIndex(it) }
|
||||
|
||||
translationUnitWithModules = modularCompilation.parse(index)
|
||||
.toBeDisposedWith { clang_disposeTranslationUnit(it) }
|
||||
|
||||
translationUnitWithModules.ensureNoCompileErrors()
|
||||
|
||||
} catch (e: Throwable) {
|
||||
this.close()
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
@@ -726,3 +728,13 @@ fun Type.canonicalIsPointerToChar(): Boolean {
|
||||
val unwrappedType = this.unwrapTypedefs()
|
||||
return unwrappedType is PointerType && unwrappedType.pointeeType.unwrapTypedefs() == CharType
|
||||
}
|
||||
|
||||
internal interface Disposable {
|
||||
fun dispose()
|
||||
}
|
||||
|
||||
internal inline fun <T : Disposable, R> T.use(block: (T) -> R): R = try {
|
||||
block(this)
|
||||
} finally {
|
||||
this.dispose()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user