Implement -headerFilterAdditionalSearchPrefix option in cinterop

This commit is contained in:
SvyatoslavScherbina
2017-10-30 13:35:41 +03:00
committed by GitHub
parent 9bc9003cdd
commit 78873c5f4d
2 changed files with 108 additions and 1 deletions
@@ -20,6 +20,8 @@ import clang.*
import kotlinx.cinterop.*
import java.io.Closeable
import java.io.File
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.security.DigestInputStream
import java.security.MessageDigest
@@ -542,3 +544,58 @@ internal fun CValue<CXSourceLocation>.getContainingFile(): CXFile? = memScoped {
clang_getFileLocation(this@getContainingFile, fileVar.ptr, null, null, null)
fileVar.value
}
private fun createVfsOverlayFileContents(virtualPathToReal: Map<Path, Path>): ByteArray {
val overlay = clang_VirtualFileOverlay_create(0)
try {
fun addFileMapping(realPath: Path, virtualPath: Path) {
clang_VirtualFileOverlay_addFileMapping(
overlay,
virtualPath = virtualPath.toAbsolutePath().toString(),
realPath = realPath.toAbsolutePath().toString()
)
}
virtualPathToReal.forEach { virtualPath, realPath ->
if (Files.isDirectory(realPath)) {
realPath.toFile().walkTopDown().forEach {
if (!it.isDirectory) {
addFileMapping(
realPath = it.toPath(),
virtualPath = virtualPath.resolve(realPath.relativize(it.toPath()))
)
}
}
} else {
addFileMapping(realPath = realPath, virtualPath = virtualPath)
}
}
memScoped {
val bufferVar = alloc<CPointerVar<ByteVar>>().apply { value = null }
val bufferSizeVar = alloc<IntVar>()
val res = clang_VirtualFileOverlay_writeToBuffer(overlay, 0, bufferVar.ptr, bufferSizeVar.ptr)
if (res != CXErrorCode.CXError_Success) {
// TODO: shall we free the buffer in this case?
error(res)
}
return bufferVar.value!!.readBytes(bufferSizeVar.value)
}
} finally {
clang_VirtualFileOverlay_dispose(overlay)
}
}
fun createVfsOverlayFile(virtualPathToReal: Map<Path, Path>): Path {
val bytes = createVfsOverlayFileContents(virtualPathToReal)
return createTempFile(prefix = "konan", suffix = ".vfsoverlay").apply {
bufferedWriter().use {
writeBytes(bytes)
}
deleteOnExit()
}.toPath()
}
@@ -23,8 +23,8 @@ import org.jetbrains.kotlin.native.interop.gen.ImportsImpl
import org.jetbrains.kotlin.native.interop.indexer.*
import java.io.File
import java.lang.IllegalArgumentException
import java.nio.file.*
import java.util.*
import kotlin.reflect.KFunction
fun main(args: Array<String>) = interop(args, null)
@@ -211,6 +211,55 @@ private fun parseImports(args: Map<String, List<String>>): ImportsImpl {
return ImportsImpl(headerIdToPackage)
}
fun getCompilerFlagsForVfsOverlay(args: Map<String, List<String>>, def: DefFile): List<String> {
val relativeToRoot = mutableMapOf<Path, Path>() // TODO: handle clashes
val HEADER_FILTER_ADDITIONAL_SEARCH_PREFIX = "-headerFilterAdditionalSearchPrefix"
val filteredIncludeDirs = args[HEADER_FILTER_ADDITIONAL_SEARCH_PREFIX]?.map { Paths.get(it) }
if (filteredIncludeDirs != null) {
val headerFilterGlobs = def.config.headerFilter
if (headerFilterGlobs.isEmpty()) {
error("'$HEADER_FILTER_ADDITIONAL_SEARCH_PREFIX' option requires " +
"'headerFilter' to be specified in .def file")
}
relativeToRoot += findFilesByGlobs(roots = filteredIncludeDirs, globs = headerFilterGlobs)
}
if (relativeToRoot.isEmpty()) {
return emptyList()
}
val virtualRoot = Paths.get(System.getProperty("java.io.tmpdir")).resolve("konanSystemInclude")
val virtualPathToReal = relativeToRoot.map { (relativePath, realRoot) ->
virtualRoot.resolve(relativePath) to realRoot.resolve(relativePath)
}.toMap()
val vfsOverlayFile = createVfsOverlayFile(virtualPathToReal)
return listOf("-I${virtualRoot.toAbsolutePath()}", "-ivfsoverlay", vfsOverlayFile.toAbsolutePath().toString())
}
private fun findFilesByGlobs(roots: List<Path>, globs: List<String>): Map<Path, Path> {
val relativeToRoot = mutableMapOf<Path, Path>()
val pathMatchers = globs.map { FileSystems.getDefault().getPathMatcher("glob:$it") }
roots.reversed().forEach { root ->
// TODO: don't scan the entire tree, skip subdirectories according to globs.
Files.walk(root, FileVisitOption.FOLLOW_LINKS).forEach { path ->
val relativePath = root.relativize(path)
if (!Files.isDirectory(path) && pathMatchers.any { it.matches(relativePath) }) {
relativeToRoot[relativePath] = root
}
}
}
return relativeToRoot
}
private fun processLib(args: Map<String, List<String>>,
argsToCompiler: MutableList<String>?) {
@@ -250,6 +299,7 @@ private fun processLib(args: Map<String, List<String>>,
addAll(def.config.compilerOpts)
addAll(tool.defaultCompilerOpts)
addAll(additionalCompilerOpts)
addAll(getCompilerFlagsForVfsOverlay(args, def))
addAll(when (language) {
Language.C -> emptyList()
Language.OBJECTIVE_C -> {