Interop: implement stub gen without .def

also add some default values to .def file format
This commit is contained in:
Svyatoslav Scherbina
2016-10-12 16:46:41 +03:00
parent fc5c7ac6df
commit 94f3c1d048
3 changed files with 70 additions and 29 deletions
@@ -11,8 +11,7 @@ fun main(args: Array<String>) {
val ktGenRoot = args[0] val ktGenRoot = args[0]
val nativeLibsDir = args[1] val nativeLibsDir = args[1]
val defFile = args[2] val otherArgs = args.drop(2)
val otherArgs = args.drop(3)
// TODO: remove OSX defaults. // TODO: remove OSX defaults.
val substitutions = mapOf( val substitutions = mapOf(
@@ -20,7 +19,7 @@ fun main(args: Array<String>) {
"os" to (System.getenv("TARGET_OS") ?: detectHost()) "os" to (System.getenv("TARGET_OS") ?: detectHost())
) )
processDefFile(File(defFile), ktGenRoot, nativeLibsDir, llvmInstallPath, substitutions, otherArgs) processLib(ktGenRoot, nativeLibsDir, llvmInstallPath, substitutions, otherArgs)
} }
private fun detectHost():String { private fun detectHost():String {
@@ -56,11 +55,21 @@ private fun substitute(properties: Properties, substitutions: Map<String, String
} }
} }
private fun String.removePrefixOrNull(prefix: String): String? { private fun getArgPrefix(arg: String): String? {
if (this.startsWith(prefix)) { val index = arg.indexOf(':')
return this.substring(prefix.length) if (index == -1) {
} else {
return null return null
} else {
return arg.substring(0, index)
}
}
private fun dropPrefix(arg: String): String? {
val index = arg.indexOf(':')
if (index == -1) {
return null
} else {
return arg.substring(index + 1)
} }
} }
@@ -73,30 +82,40 @@ private fun ProcessBuilder.runExpectingSuccess() {
} }
} }
private fun processDefFile(defFile: File, private fun Properties.getSpaceSeparated(name: String): List<String> {
ktGenRoot: String, return this.getProperty(name)?.split(' ') ?: emptyList()
nativeLibsDir: String, }
llvmInstallPath: String,
substitutions: Map<String, String>, private fun processLib(ktGenRoot: String,
additionalArgs: List<String>) { nativeLibsDir: String,
llvmInstallPath: String,
substitutions: Map<String, String>,
additionalArgs: List<String>) {
val args = additionalArgs.groupBy ({ getArgPrefix(it)!! }, { dropPrefix(it)!! }) // TODO
val defFile = args["-def"]?.single()?.let { File(it) }
val config = Properties() val config = Properties()
defFile.bufferedReader().use { reader -> defFile?.bufferedReader()?.use { reader ->
config.load(reader) config.load(reader)
} }
substitute(config, substitutions) substitute(config, substitutions)
val additionalCompilerOpts = additionalArgs.mapNotNull { it.removePrefixOrNull("-copt:") } val additionalHeaders = args["-h"].orEmpty()
val additionalLinkerOpts = additionalArgs.mapNotNull { it.removePrefixOrNull("-lopt:") } val additionalCompilerOpts = args["-copt"].orEmpty()
val additionalLinkerOpts = args["-lopt"].orEmpty()
val headerFiles = config.getProperty("headers").split(' ') val headerFiles = config.getSpaceSeparated("headers") + additionalHeaders
val compilerOpts = config.getProperty("compilerOpts").split(' ') + additionalCompilerOpts val compilerOpts = config.getSpaceSeparated("compilerOpts") + additionalCompilerOpts
val compiler = config.getProperty("compiler") val compiler = config.getProperty("compiler") ?: "clang"
val linkerOpts = config.getProperty("linkerOpts").split(' ').toTypedArray() + additionalLinkerOpts val linkerOpts = config.getSpaceSeparated("linkerOpts").toTypedArray() + additionalLinkerOpts
val linker = config.getProperty("linker") val linker = config.getProperty("linker") ?: "clang"
val excludedFunctions = config.getProperty("excludedFunctions")?.split(' ')?.toSet() ?: emptySet() val excludedFunctions = config.getSpaceSeparated("excludedFunctions").toSet()
val fqParts = defFile.name.split('.').reversed().drop(1) val fqParts = args["-pkg"]?.singleOrNull()?.let {
it.split('.')
} ?: defFile!!.name.split('.').reversed().drop(1)
val outKtFileName = fqParts.last() + ".kt" val outKtFileName = fqParts.last() + ".kt"
@@ -135,10 +154,10 @@ private fun processDefFile(defFile: File,
*compilerArgsForJniIncludes, *compilerArgsForJniIncludes,
"-c", outCFile.path, "-o", outOFile.path) "-c", outCFile.path, "-o", outOFile.path)
val defFileDir = defFile.parentFile val workDir = defFile?.parentFile ?: File(System.getProperty("java.io.tmpdir"))
ProcessBuilder(*compilerCmd) ProcessBuilder(*compilerCmd)
.directory(defFileDir) .directory(workDir)
.inheritIO() .inheritIO()
.runExpectingSuccess() .runExpectingSuccess()
@@ -150,7 +169,7 @@ private fun processDefFile(defFile: File,
"-Wl,-flat_namespace,-undefined,dynamic_lookup") "-Wl,-flat_namespace,-undefined,dynamic_lookup")
ProcessBuilder(*linkerCmd) ProcessBuilder(*linkerCmd)
.directory(defFileDir) .directory(workDir)
.inheritIO() .inheritIO()
.runExpectingSuccess() .runExpectingSuccess()
-2
View File
@@ -1,7 +1,5 @@
headers = llvm-c/Core.h llvm-c/ExecutionEngine.h llvm-c/Target.h llvm-c/Analysis.h llvm-c/BitWriter.h llvm-c/BitReader.h headers = llvm-c/Core.h llvm-c/ExecutionEngine.h llvm-c/Target.h llvm-c/Analysis.h llvm-c/BitWriter.h llvm-c/BitReader.h
compiler = clang
compilerOpts = -std=c99 -fPIC \ compilerOpts = -std=c99 -fPIC \
-Wall -W -Wno-unused-parameter -Wwrite-strings -Wmissing-field-initializers \ -Wall -W -Wno-unused-parameter -Wwrite-strings -Wmissing-field-initializers \
-pedantic -Wno-long-long -Wcovered-switch-default -Wdelete-non-virtual-dtor \ -pedantic -Wno-long-long -Wcovered-switch-default -Wdelete-non-virtual-dtor \
@@ -22,7 +22,10 @@ class NamedNativeInteropConfig extends AbstractFileCollection implements Named {
private String defFile private String defFile
private String pkg;
private List<String> compilerOpts = [] private List<String> compilerOpts = []
private FileCollection headers;
private List<String> linkerOpts = [] private List<String> linkerOpts = []
private FileCollection linkFiles; private FileCollection linkFiles;
private List<String> linkTasks = [] private List<String> linkTasks = []
@@ -32,10 +35,19 @@ class NamedNativeInteropConfig extends AbstractFileCollection implements Named {
genTask.inputs.file(project.file(defFile)) genTask.inputs.file(project.file(defFile))
} }
void pkg(String value) {
pkg = value
}
void compilerOpts(String... values) { void compilerOpts(String... values) {
compilerOpts.addAll(values) compilerOpts.addAll(values)
} }
void headers(FileCollection files) {
dependsOnFiles(files)
headers = headers + files
}
void linkerOpts(String... values) { void linkerOpts(String... values) {
linkerOpts.addAll(values) linkerOpts.addAll(values)
} }
@@ -95,6 +107,7 @@ class NamedNativeInteropConfig extends AbstractFileCollection implements Named {
this.name = name this.name = name
this.project = project this.project = project
this.headers = project.files()
this.linkFiles = project.files() this.linkFiles = project.files()
interopStubs = project.sourceSets.create(name + "InteropStubs") interopStubs = project.sourceSets.create(name + "InteropStubs")
@@ -139,10 +152,21 @@ class NamedNativeInteropConfig extends AbstractFileCollection implements Named {
linkerOpts += linkFiles.files linkerOpts += linkFiles.files
args = [generatedSrcDir, nativeLibsDir, project.file(defFile)] args = [generatedSrcDir, nativeLibsDir]
if (defFile != null) {
args "-def:" + project.file(defFile)
}
if (pkg != null) {
args "-pkg:" + pkg
}
args compilerOpts.collect { "-copt:$it" } args compilerOpts.collect { "-copt:$it" }
args linkerOpts.collect { "-lopt:$it" } args linkerOpts.collect { "-lopt:$it" }
headers.files.each {
args "-h:$it"
}
} }
} }
} }