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())
|
if (modules.isEmpty()) return ModulesInfo(emptyList(), emptySet())
|
||||||
|
|
||||||
withIndex { index ->
|
withIndex { index ->
|
||||||
|
ModularCompilation(compilation).use {
|
||||||
val ownHeaders = mutableSetOf<String>()
|
val modulesASTFiles = getModulesASTFiles(index, it, modules)
|
||||||
val topLevelHeaders = linkedSetOf<String>()
|
return buildModulesInfo(index, modules, modulesASTFiles)
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
val compilationWithImports = object : Compilation by compilation {
|
||||||
override val compilerArgs = compilation.compilerArgs + "-fmodules"
|
|
||||||
override val additionalPreambleLines = modules.map { "@import $it;" } + compilation.additionalPreambleLines
|
override val additionalPreambleLines = modules.map { "@import $it;" } + compilation.additionalPreambleLines
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+32
-20
@@ -428,34 +428,36 @@ internal class ModulesMap(
|
|||||||
val translationUnit: CXTranslationUnit
|
val translationUnit: CXTranslationUnit
|
||||||
) : Closeable {
|
) : Closeable {
|
||||||
|
|
||||||
|
private val modularCompilation: ModularCompilation
|
||||||
private val index: CXIndex
|
private val index: CXIndex
|
||||||
private val translationUnitWithModules: CXTranslationUnit
|
private val translationUnitWithModules: CXTranslationUnit
|
||||||
|
|
||||||
init {
|
private val arena = Arena()
|
||||||
index = clang_createIndex(0, 0)!!
|
|
||||||
try {
|
|
||||||
translationUnitWithModules = object : Compilation by compilation {
|
|
||||||
override val compilerArgs = compilation.compilerArgs + "-fmodules"
|
|
||||||
}.parse(index)
|
|
||||||
|
|
||||||
try {
|
private inline fun <T> T.toBeDisposedWith(crossinline block: (T) -> Unit): T = apply {
|
||||||
translationUnitWithModules.ensureNoCompileErrors()
|
arena.defer { block(this) }
|
||||||
} catch (e: Throwable) {
|
|
||||||
clang_disposeTranslationUnit(translationUnitWithModules)
|
|
||||||
throw e
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (e: Throwable) {
|
|
||||||
clang_disposeIndex(index)
|
|
||||||
throw e
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun close() {
|
override fun close() {
|
||||||
|
arena.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
try {
|
try {
|
||||||
clang_disposeTranslationUnit(translationUnitWithModules)
|
modularCompilation = ModularCompilation(compilation)
|
||||||
} finally {
|
.toBeDisposedWith { it.dispose() }
|
||||||
clang_disposeIndex(index)
|
|
||||||
|
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()
|
val unwrappedType = this.unwrapTypedefs()
|
||||||
return unwrappedType is PointerType && unwrappedType.pointeeType.unwrapTypedefs() == CharType
|
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