Interop: handle all main.kotlin.srcDirs in Gradle plugin

also fix minor bug with default package
This commit is contained in:
Svyatoslav Scherbina
2016-09-29 11:52:53 +07:00
parent d053fd9ed0
commit a6f7500126
2 changed files with 100 additions and 89 deletions
@@ -9,96 +9,101 @@ import kotlin.system.exitProcess
fun main(args: Array<String>) {
val llvmInstallPath = System.getProperty("llvmInstallPath")!!
val ktSrcRoot = args[0]
val ktGenRoot = args[1]
val nativeLibsDir = args[2]
val ktGenRoot = args[0]
val nativeLibsDir = args[1]
val ktSrcRoots = args.drop(2)
val defFiles = File(ktSrcRoot).walk().filter { it.name.endsWith(".def") }
ktSrcRoots.forEach { ktSrcRoot ->
val defFiles = File(ktSrcRoot).walk().filter { it.name.endsWith(".def") }
defFiles.forEach { defFile ->
val config = Properties()
defFile.bufferedReader().use { reader ->
config.load(reader)
defFiles.forEach { defFile ->
processDefFile(ktSrcRoot, defFile, ktGenRoot, nativeLibsDir, llvmInstallPath)
}
val headerFiles = config.getProperty("headers").split(' ')
val compilerOpts = config.getProperty("compilerOpts").split(' ')
val compiler = config.getProperty("compiler")
val libName = config.getProperty("libName")
val linkerOpts = config.getProperty("linkerOpts").split(' ').toTypedArray()
val linker = config.getProperty("linker")
val excludedFunctions = config.getProperty("excludedFunctions")?.split(' ')?.toSet() ?: emptySet()
val defFileRelative = defFile.relativeTo(File(ktSrcRoot))
val outKtFile = File(ktGenRoot, defFileRelative.toString().substringBeforeLast(".def") + ".kt")
val outKtPkg = defFileRelative.parentFile.path.replace(File.separatorChar, '.')
val nativeIndex = buildNativeIndex(headerFiles, compilerOpts)
val gen = StubGenerator(nativeIndex, outKtPkg, libName, excludedFunctions)
outKtFile.parentFile.mkdirs()
outKtFile.bufferedWriter().use { out ->
gen.withOutput({ out.appendln(it) }) {
gen.generateKotlinFile()
}
}
val outCFile = createTempFile(suffix = ".c")
outCFile.bufferedWriter().use { out ->
gen.withOutput({ out.appendln(it) }) {
gen.generateCFile(headerFiles)
}
}
val outOFile = createTempFile(suffix = ".o")
val javaHome = System.getProperty("java.home")
val compilerArgsForJniIncludes = listOf("", "linux", "darwin").map { "-I$javaHome/../include/$it" }.toTypedArray()
val compilerCmd = arrayOf("$llvmInstallPath/bin/$compiler", *compilerOpts.toTypedArray(),
*compilerArgsForJniIncludes,
"-c", outCFile.path, "-o", outOFile.path)
println(compilerCmd.joinToString(" "))
val compilerRes = ProcessBuilder(*compilerCmd)
.inheritIO()
.start()
.waitFor()
if (compilerRes != 0) {
exitProcess(compilerRes)
}
File(nativeLibsDir).mkdirs()
val outLib = nativeLibsDir + "/" + System.mapLibraryName(libName)
val linkerCmd = arrayOf("$llvmInstallPath/bin/$linker", *linkerOpts, outOFile.path, "-shared", "-o", outLib,
"-Wl,-flat_namespace,-undefined,dynamic_lookup")
println(linkerCmd.joinToString(" "))
val linkerRes = ProcessBuilder(*linkerCmd)
.inheritIO()
.start()
.waitFor()
if (linkerRes != 0) {
exitProcess(linkerRes)
}
outCFile.delete()
outOFile.delete()
}
}
private fun processDefFile(ktSrcRoot: String, defFile: File, ktGenRoot: String, nativeLibsDir: String, llvmInstallPath: String) {
val config = Properties()
defFile.bufferedReader().use { reader ->
config.load(reader)
}
val headerFiles = config.getProperty("headers").split(' ')
val compilerOpts = config.getProperty("compilerOpts").split(' ')
val compiler = config.getProperty("compiler")
val libName = config.getProperty("libName")
val linkerOpts = config.getProperty("linkerOpts").split(' ').toTypedArray()
val linker = config.getProperty("linker")
val excludedFunctions = config.getProperty("excludedFunctions")?.split(' ')?.toSet() ?: emptySet()
val defFileRelative = defFile.relativeTo(File(ktSrcRoot))
val outKtFile = File(ktGenRoot, defFileRelative.toString().substringBeforeLast(".def") + ".kt")
val outKtPkg = defFileRelative.parentFile?.path?.replace(File.separatorChar, '.') ?: ""
val nativeIndex = buildNativeIndex(headerFiles, compilerOpts)
val gen = StubGenerator(nativeIndex, outKtPkg, libName, excludedFunctions)
outKtFile.parentFile.mkdirs()
outKtFile.bufferedWriter().use { out ->
gen.withOutput({ out.appendln(it) }) {
gen.generateKotlinFile()
}
}
val outCFile = createTempFile(suffix = ".c")
outCFile.bufferedWriter().use { out ->
gen.withOutput({ out.appendln(it) }) {
gen.generateCFile(headerFiles)
}
}
val outOFile = createTempFile(suffix = ".o")
val javaHome = System.getProperty("java.home")
val compilerArgsForJniIncludes = listOf("", "linux", "darwin").map { "-I$javaHome/../include/$it" }.toTypedArray()
val compilerCmd = arrayOf("$llvmInstallPath/bin/$compiler", *compilerOpts.toTypedArray(),
*compilerArgsForJniIncludes,
"-c", outCFile.path, "-o", outOFile.path)
println(compilerCmd.joinToString(" "))
val compilerRes = ProcessBuilder(*compilerCmd)
.inheritIO()
.start()
.waitFor()
if (compilerRes != 0) {
exitProcess(compilerRes)
}
File(nativeLibsDir).mkdirs()
val outLib = nativeLibsDir + "/" + System.mapLibraryName(libName)
val linkerCmd = arrayOf("$llvmInstallPath/bin/$linker", *linkerOpts, outOFile.path, "-shared", "-o", outLib,
"-Wl,-flat_namespace,-undefined,dynamic_lookup")
println(linkerCmd.joinToString(" "))
val linkerRes = ProcessBuilder(*linkerCmd)
.inheritIO()
.start()
.waitFor()
if (linkerRes != 0) {
exitProcess(linkerRes)
}
outCFile.delete()
outOFile.delete()
}
private fun buildNativeIndex(headerFiles: List<String>, compilerOpts: List<String>): NativeIndex {
val tempHeaderFile = createTempFile(suffix = ".h")
tempHeaderFile.deleteOnExit()
@@ -8,8 +8,6 @@ class NativeInteropPlugin implements Plugin<Project> {
@Override
void apply(Project prj) {
// TODO: handle other source sets
def srcDir = prj.file("src/main/kotlin")
def generatedSrcDir = new File(prj.buildDir, "nativeInteropStubs/kotlin")
def nativeLibsDir = new File(prj.buildDir, "nativelibs")
@@ -27,18 +25,26 @@ class NativeInteropPlugin implements Plugin<Project> {
prj.task(genStubsTaskName, type: JavaExec) {
classpath = prj.configurations.interopStubGenerator
main = "org.jetbrains.kotlin.native.interop.gen.jvm.MainKt"
args = [srcDir, generatedSrcDir, nativeLibsDir]
args = [generatedSrcDir, nativeLibsDir]
systemProperties "java.library.path" : new File(prj.findProject(":Interop:Indexer").buildDir, "nativelibs")
systemProperties "llvmInstallPath" : prj.llvmInstallPath
environment "LIBCLANG_DISABLE_CRASH_RECOVERY": "1"
environment "DYLD_LIBRARY_PATH": "${prj.llvmInstallPath}/lib"
inputs.files prj.fileTree(srcDir.path).include('**/*.def')
outputs.dir generatedSrcDir
outputs.dir nativeLibsDir
}
prj.afterEvaluate {
prj.tasks.getByName(genStubsTaskName) {
// TODO: handle other source sets
prj.sourceSets.main.kotlin.srcDirs.each { srcDir ->
inputs.files prj.fileTree(srcDir.path).include('**/*.def')
args srcDir
}
}
}
prj.sourceSets {
main {
kotlin {