From d800e193e850b6f07c3f8572a652975c90ccf9f4 Mon Sep 17 00:00:00 2001 From: Svyatoslav Scherbina Date: Thu, 13 Oct 2016 16:46:27 +0300 Subject: [PATCH 1/6] runtime/build.gradle: extract bitcode compilation to custom task class --- .../jetbrains/kotlin/CompileToBitcode.groovy | 93 +++++++++++++++++++ runtime/build.gradle | 39 ++------ 2 files changed, 99 insertions(+), 33 deletions(-) create mode 100644 buildSrc/src/main/groovy/org/jetbrains/kotlin/CompileToBitcode.groovy diff --git a/buildSrc/src/main/groovy/org/jetbrains/kotlin/CompileToBitcode.groovy b/buildSrc/src/main/groovy/org/jetbrains/kotlin/CompileToBitcode.groovy new file mode 100644 index 00000000000..2cc4f2ab0c7 --- /dev/null +++ b/buildSrc/src/main/groovy/org/jetbrains/kotlin/CompileToBitcode.groovy @@ -0,0 +1,93 @@ +package org.jetbrains.kotlin + +import org.gradle.api.DefaultTask +import org.gradle.api.tasks.InputDirectory +import org.gradle.api.tasks.OutputFile +import org.gradle.api.tasks.TaskAction + +class CompileCppToBitcode extends DefaultTask { + private String name = "main" + private File srcRoot; + + private List compilerArgs = [] + private List linkerArgs = [] + + @InputDirectory + File getSrcRoot() { + return srcRoot ?: project.file("src/$name") + } + + @OutputFile + File getOutFile() { + return new File(project.buildDir, "${name}.bc") + } + + private File getSrcDir() { + return new File(this.getSrcRoot(), "cpp") + } + + private File getHeadersDir() { + return new File(this.getSrcRoot(), "headers") + } + + private File getObjDir() { + return new File(project.buildDir, name) + } + + void name(String value) { + name = value + } + + void srcRoot(File value) { + srcRoot = value + } + + private List getCompilerArgs() { + return compilerArgs + } + + private List getLinkerArgs() { + return linkerArgs + } + + void compilerArgs(String... args) { + compilerArgs.addAll(args) + } + + void linkerArgs(String... args) { + linkerArgs.addAll(args) + } + + @TaskAction + void compile() { + // the strange code below seems to be required due to some Gradle (Groovy?) behaviour + File headersDir = this.getHeadersDir() + File srcDir = this.getSrcDir() + List compilerArgs = this.getCompilerArgs() + List linkerArgs = this.getLinkerArgs() + File objDir = this.getObjDir() + objDir.mkdirs() + + project.exec { + workingDir objDir + executable "$project.llvmInstallPath/bin/clang++" + args '-std=c++11' + + args compilerArgs + + args "-I$headersDir" + + args '-c', '-emit-llvm' + args project.fileTree(srcDir).include('**/*.cpp') + } + + project.exec { + executable "$project.llvmInstallPath/bin/llvm-link" + args project.fileTree(objDir).include('**/*.bc') + + args linkerArgs + + args '-o', outFile + } + } +} diff --git a/runtime/build.gradle b/runtime/build.gradle index 9ec91384345..2923fa46d46 100644 --- a/runtime/build.gradle +++ b/runtime/build.gradle @@ -1,39 +1,12 @@ +import org.jetbrains.kotlin.CompileCppToBitcode + // TODO: consider using some Gradle plugins to build and test -def srcDir = 'src/main/cpp' -def objDir = "$buildDir/bitcode" -def outFile = "$buildDir/runtime.bc" -task compile(type: Exec) { - doFirst { - new File(objDir).mkdirs() - } +task build(type: CompileCppToBitcode) { + name 'runtime' + srcRoot file('src/main') - inputs.dir srcDir - outputs.dir objDir - - workingDir objDir - - executable "$llvmInstallPath/bin/clang" - args '-std=c++11' - - args '-c', '-emit-llvm' - - args fileTree(srcDir).include('**/*.cpp') -} - -task build(type: Exec) { - dependsOn compile - - inputs.dir objDir - outputs.file outFile - - executable "$llvmInstallPath/bin/llvm-link" - args '-o', outFile - - doFirst { - args fileTree(objDir).include('**/*.bc') - } } task test { @@ -44,7 +17,7 @@ task test { commandLine "$llvmInstallPath/bin/clang", 'src/test/c/main.c', '-c', '-emit-llvm', '-o', "$buildDir/main.bc" } exec { - commandLine "$llvmInstallPath/bin/clang++", outFile, "$buildDir/main.bc", '-o', "$buildDir/main" + commandLine "$llvmInstallPath/bin/clang++", build.outFile, "$buildDir/main.bc", '-o', "$buildDir/main" } exec { workingDir buildDir From d00d3daf863ef72c155b61457dbf4154b329912f Mon Sep 17 00:00:00 2001 From: Svyatoslav Scherbina Date: Thu, 13 Oct 2016 16:47:32 +0300 Subject: [PATCH 2/6] Interop: support passing linker as arg to stub generator --- .../org/jetbrains/kotlin/native/interop/gen/jvm/main.kt | 2 +- .../org/jetbrains/kotlin/NativeInteropPlugin.groovy | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/main.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/main.kt index 280be77d483..c4625721558 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/main.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/main.kt @@ -110,7 +110,7 @@ private fun processLib(ktGenRoot: String, val compilerOpts = config.getSpaceSeparated("compilerOpts") + additionalCompilerOpts val compiler = config.getProperty("compiler") ?: "clang" val linkerOpts = config.getSpaceSeparated("linkerOpts").toTypedArray() + additionalLinkerOpts - val linker = config.getProperty("linker") ?: "clang" + val linker = args["-linker"]?.singleOrNull() ?: config.getProperty("linker") ?: "clang" val excludedFunctions = config.getSpaceSeparated("excludedFunctions").toSet() val fqParts = args["-pkg"]?.singleOrNull()?.let { diff --git a/buildSrc/src/main/groovy/org/jetbrains/kotlin/NativeInteropPlugin.groovy b/buildSrc/src/main/groovy/org/jetbrains/kotlin/NativeInteropPlugin.groovy index 1465a7964e7..07fc7507828 100644 --- a/buildSrc/src/main/groovy/org/jetbrains/kotlin/NativeInteropPlugin.groovy +++ b/buildSrc/src/main/groovy/org/jetbrains/kotlin/NativeInteropPlugin.groovy @@ -26,6 +26,7 @@ class NamedNativeInteropConfig extends AbstractFileCollection implements Named { private List compilerOpts = [] private FileCollection headers; + private String linker private List linkerOpts = [] private FileCollection linkFiles; private List linkTasks = [] @@ -48,6 +49,10 @@ class NamedNativeInteropConfig extends AbstractFileCollection implements Named { headers = headers + files } + void linker(String value) { + linker = value + } + void linkerOpts(String... values) { linkerOpts.addAll(values) } @@ -161,6 +166,10 @@ class NamedNativeInteropConfig extends AbstractFileCollection implements Named { args "-pkg:" + pkg } + if (linker != null) { + args "-linker:" + linker + } + args compilerOpts.collect { "-copt:$it" } args linkerOpts.collect { "-lopt:$it" } From 2f004edff76fad8f4d2f238210cf6c07757e443b Mon Sep 17 00:00:00 2001 From: Svyatoslav Scherbina Date: Thu, 13 Oct 2016 16:48:48 +0300 Subject: [PATCH 3/6] Interop: fix minor bug in Indexer handle empty compiler args --- .../org/jetbrains/kotlin/native/interop/indexer/Indexer.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/Indexer.kt b/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/Indexer.kt index a974f1b5c11..ab0ac552182 100644 --- a/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/Indexer.kt +++ b/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/Indexer.kt @@ -279,8 +279,10 @@ fun buildNativeIndexImpl(headerFile: File, args: List): NativeIndex { indexEntityReference.setStatic(null) } + val commandLineArgs = if (args1.size != 0) mallocNativeArrayOf(Int8Box.Companion, *args1)[0] else null + clang_indexSourceFile(indexAction, clientData, callbacks, IndexerCallbacks.size, 0, headerFile.path, - mallocNativeArrayOf(Int8Box.Companion, *args1)[0], args1.size, null, 0, null, 0) + commandLineArgs, args1.size, null, 0, null, 0) return res From f30c840d1c7cd83e47a2c46d56f5681fb2a9c8b8 Mon Sep 17 00:00:00 2001 From: Svyatoslav Scherbina Date: Thu, 13 Oct 2016 17:19:19 +0300 Subject: [PATCH 4/6] runtime: move hash functions to newly created subproject to reuse in compiler --- common/build.gradle | 16 ++++++++++++++++ .../src/main => common/src/hash}/cpp/City.cpp | 0 .../src/main => common/src/hash}/cpp/Sha1.cpp | 0 .../main/cpp => common/src/hash/headers}/City.h | 0 .../main/cpp => common/src/hash/headers}/Sha1.h | 0 runtime/build.gradle | 3 +++ settings.gradle | 1 + 7 files changed, 20 insertions(+) create mode 100644 common/build.gradle rename {runtime/src/main => common/src/hash}/cpp/City.cpp (100%) rename {runtime/src/main => common/src/hash}/cpp/Sha1.cpp (100%) rename {runtime/src/main/cpp => common/src/hash/headers}/City.h (100%) rename {runtime/src/main/cpp => common/src/hash/headers}/Sha1.h (100%) diff --git a/common/build.gradle b/common/build.gradle new file mode 100644 index 00000000000..09d78a6f1c1 --- /dev/null +++ b/common/build.gradle @@ -0,0 +1,16 @@ +import org.jetbrains.kotlin.CompileCppToBitcode + +// TODO: consider using some Gradle plugins to build and test + + +task compileHash(type: CompileCppToBitcode) { + name 'hash' +} + +task build { + dependsOn compileHash +} + +task clean << { + delete buildDir +} diff --git a/runtime/src/main/cpp/City.cpp b/common/src/hash/cpp/City.cpp similarity index 100% rename from runtime/src/main/cpp/City.cpp rename to common/src/hash/cpp/City.cpp diff --git a/runtime/src/main/cpp/Sha1.cpp b/common/src/hash/cpp/Sha1.cpp similarity index 100% rename from runtime/src/main/cpp/Sha1.cpp rename to common/src/hash/cpp/Sha1.cpp diff --git a/runtime/src/main/cpp/City.h b/common/src/hash/headers/City.h similarity index 100% rename from runtime/src/main/cpp/City.h rename to common/src/hash/headers/City.h diff --git a/runtime/src/main/cpp/Sha1.h b/common/src/hash/headers/Sha1.h similarity index 100% rename from runtime/src/main/cpp/Sha1.h rename to common/src/hash/headers/Sha1.h diff --git a/runtime/build.gradle b/runtime/build.gradle index 2923fa46d46..1cb729defdc 100644 --- a/runtime/build.gradle +++ b/runtime/build.gradle @@ -7,6 +7,9 @@ task build(type: CompileCppToBitcode) { name 'runtime' srcRoot file('src/main') + dependsOn ':common:compileHash' + compilerArgs '-I' + project.file('../common/src/hash/headers') // TODO: copy-pasted from 'common' + linkerArgs project.file('../common/build/hash.bc').path } task test { diff --git a/settings.gradle b/settings.gradle index fbd1ea6cbcd..04fc18c90ee 100644 --- a/settings.gradle +++ b/settings.gradle @@ -4,3 +4,4 @@ include ':Interop:Runtime' include ':InteropExample' include ':backend.native' include ':runtime' +include ':common' From edc88c67daed3d2db440255a91680d6cd6a1d127 Mon Sep 17 00:00:00 2001 From: Svyatoslav Scherbina Date: Thu, 13 Oct 2016 17:20:36 +0300 Subject: [PATCH 5/6] backend.native: include interop with :common:hash --- backend.native/build.gradle | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/backend.native/build.gradle b/backend.native/build.gradle index 211e0fba13b..dd9f6a901a6 100644 --- a/backend.native/build.gradle +++ b/backend.native/build.gradle @@ -39,11 +39,24 @@ kotlinNativeInterop { compilerOpts "-I$llvmInstallPath/include" linkerOpts "-L$llvmInstallPath/lib" } + + hash { // TODO: copy-pasted from ':common:compileHash' + linker 'clang++' + linkOutputs ':common:compileHash' + + headers fileTree('../common/src/hash/headers') { + include '**/*.h' + include '**/*.hpp' + } + + pkg 'org.jetbrains.kotlin.backend.native.hash' + } } dependencies { compilerCompile deps compilerCompile kotlinNativeInterop['llvm'] + compilerCompile kotlinNativeInterop['hash'] cli_bcCompile deps cli_bcCompile sourceSets.compiler.output From 8c4f5c3cef396e0ad4f0b59c04879685cec08e90 Mon Sep 17 00:00:00 2001 From: Svyatoslav Scherbina Date: Thu, 13 Oct 2016 18:12:21 +0300 Subject: [PATCH 6/6] backend.native: add -fPIC for interop with :common:hash to fix build on Linux --- backend.native/build.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend.native/build.gradle b/backend.native/build.gradle index dd9f6a901a6..85fd514dfb9 100644 --- a/backend.native/build.gradle +++ b/backend.native/build.gradle @@ -41,6 +41,8 @@ kotlinNativeInterop { } hash { // TODO: copy-pasted from ':common:compileHash' + compilerOpts '-fPIC' + linkerOpts '-fPIC' linker 'clang++' linkOutputs ':common:compileHash'