Improved Gradle plugin. Fixed samples according to these changes. (#594)

This commit is contained in:
Alexander Podkhalyuzin
2017-05-26 15:43:16 +03:00
committed by Nikolay Igotti
parent 7d901dc610
commit 8b18c7c8cb
81 changed files with 803 additions and 748 deletions
+15
View File
@@ -0,0 +1,15 @@
# Concurrent
This example shows how to implement concurrent programming in Kotlin/Native.
In this example we start multiple threads running concurrently and exchange messages with them.
To build cpp use `./buildCpp.sh`.
To build kotlin use `../gradlew build`.
To run use `../gradlew run`
Alternatively you can run artifact directly
./build/konan/bin/MessageChannel/MessageChannel.kexe
It will print all passed messages.
+14
View File
@@ -0,0 +1,14 @@
apply plugin: 'konan'
konanInterop {
MessageChannel {
includeDirs "${project.projectDir}/src/cpp"
}
}
konanArtifacts {
MessageChannel {
useInterop "MessageChannel"
nativeLibrary "${project.buildDir.canonicalPath}/clang/MessageChannel.bc"
}
}
Executable → Regular
+16 -11
View File
@@ -1,8 +1,8 @@
#!/usr/bin/env bash
DIR=.
DIR=$(dirname "$0")
PATH=../../dist/bin:../../bin:$PATH
DEPS=$(dirname `type -p konanc`)/../dependencies
if [ x$TARGET == x ]; then
case "$OSTYPE" in
@@ -12,19 +12,24 @@ case "$OSTYPE" in
esac
fi
CLANG_linux=$DEPS/clang-llvm-3.9.0-linux-x86-64/bin/clang++
CLANG_macbook=$DEPS/clang-llvm-3.9.0-darwin-macos/bin/clang++
var=CFLAGS_${TARGET}
CFLAGS=${!var}
var=LINKER_ARGS_${TARGET}
LINKER_ARGS=${!var}
var=COMPILER_ARGS_${TARGET}
COMPILER_ARGS=${!var} # add -opt for an optimized build.
var=CLANG_${TARGET}
CLANG=${!var}
$CLANG -std=c++11 -c $DIR/MessageChannel.cpp -o $DIR/MessageChannel.bc -emit-llvm || exit 1
cinterop -def $DIR/MessageChannel.def -copt "-I$DIR" -target $TARGET -o $DIR/MessageChannel.kt.bc || exit 1
konanc $DIR/Concurrent.kt -library $DIR/MessageChannel.kt.bc \
-nativelibrary $DIR/MessageChannel.bc -o Concurrent.kexe || exit 1
rm -rf $DIR/build/
mkdir $DIR/build/
mkdir $DIR/build/c_interop/
mkdir $DIR/build/bin/
./buildCpp.sh
cinterop -def $DIR/src/c_interop/MessageChannel.def -copt "-I$DIR/src/cpp" -target $TARGET \
-o $DIR/build/c_interop/MessageChannel.kt.bc || exit 1
konanc $DIR/src/kotlin-native/Concurrent.kt -library $DIR/build/c_interop/MessageChannel.kt.bc \
-nativelibrary $DIR/build/clang/MessageChannel.bc -o $DIR/build/bin/Concurrent.kexe || exit 1
echo "Artifact path is ./build/bin/Concurrent.kexe"
+24
View File
@@ -0,0 +1,24 @@
#!/usr/bin/env bash
DIR=$(dirname "$0")
PATH=../../dist/bin:../../bin:$PATH
DEPS=$(dirname `type -p konanc`)/../dependencies
if [ x$TARGET == x ]; then
case "$OSTYPE" in
darwin*) TARGET=macbook ;;
linux*) TARGET=linux ;;
*) echo "unknown: $OSTYPE" && exit 1;;
esac
fi
CLANG_linux=$DEPS/clang-llvm-3.9.0-linux-x86-64/bin/clang++
CLANG_macbook=$DEPS/clang-llvm-3.9.0-darwin-macos/bin/clang++
var=CLANG_${TARGET}
CLANG=${!var}
mkdir $DIR/build/
mkdir $DIR/build/clang/
$CLANG -std=c++11 -c $DIR/src/cpp/MessageChannel.cpp -o $DIR/build/clang/MessageChannel.bc -emit-llvm || exit 1
+8 -4
View File
@@ -4,12 +4,16 @@
A sample data [European Mammals Red List for 2009](https://data.europa.eu/euodp/en/data/dataset?res_format=CSV)
from EU is being used.
To build use `./build.sh` script without arguments (or specify `TARGET` variable if cross-compiling).
You also may use Gradle to build this sample: `../gradlew build`.
To build use `../gradlew build`.
To run use
To run use `../gradlew run`
./CsvParser.kexe ./European_Mammals_Red_List_Nov_2009.csv 4 100
To change run arguments, change property runArgs in gradle.propeties file
or pass `-PrunArgs="./European_Mammals_Red_List_Nov_2009.csv 4 100"` to gradle run.
Alternatively you can run artifact directly
./build/konan/bin/CsvParser/CsvParser.kexe ./European_Mammals_Red_List_Nov_2009.csv 4 100
It will print number of all unique entries in fifth column
(Family, zero-based index) in first 100 rows of the CSV file.
+1 -62
View File
@@ -1,72 +1,11 @@
apply plugin: 'konan'
konanInterop {
stdio {
defFile 'stdio.def'
}
stdio { }
}
konanArtifacts {
CsvParser {
inputFiles project.file('CsvParser.kt')
useInterop 'stdio'
}
}
build {
project.ext { outputFile = "${projectDir.canonicalPath}/${file(compileKonanCsvParser.artifactPath).name}" }
doLast {
copy {
from compileKonanCsvParser.artifactPath
into projectDir.canonicalPath
}
}
}
void dumpCompilationTask(Task task) {
println()
println("Compilation task: ${task.name}")
println("outputDir : ${task.outputDir}")
println("artifactPath : ${task.artifactPath}")
println("inputFiles : ${task.inputFiles.files}")
println("libraries : ${task.libraries}")
println("nativeLibraries : ${task.nativeLibraries}")
println("linkerOpts : ${task.linkerOpts}")
println("noStdLib : ${task.noStdLib}")
println("noLink : ${task.noLink}")
println("noMain : ${task.noMain}")
println("enableOptimization : ${task.enableOptimization}")
println("enableAssertions : ${task.enableAssertions}")
println("target : ${task.target}")
println("languageVersion : ${task.languageVersion}")
println("apiVersion : ${task.apiVersion}")
}
void dumpInteropTask(Task task) {
println()
println("Stub generation task: ${task.name}")
println("stubsDir : ${task.stubsDir}")
println("libsDir : ${task.libsDir}")
println("defFile : ${task.defFile}")
println("target : ${task.target}")
println("pkg : ${task.pkg}")
println("linker : ${task.linker}")
println("compilerOpts : ${task.compilerOpts}")
println("linkerOpts : ${task.linkerOpts}")
println("headers : ${task.headers.files}")
println("linkFiles : ${task.linkFiles}")
}
task dumpParameters(type: DefaultTask) {
doLast {
dumpCompilationTask(konanArtifacts['CsvParser'].compilationTask)
dumpInteropTask(konanInterop['stdio'].generateStubsTask)
dumpCompilationTask(konanInterop['stdio'].compileStubsTask)
}
}
clean {
doLast {
delete outputFile
}
}
Executable → Regular
+12 -3
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
DIR=.
DIR=$(dirname "$0")
PATH=../../dist/bin:../../bin:$PATH
if [ x$TARGET == x ]; then
@@ -18,5 +18,14 @@ LINKER_ARGS=${!var}
var=COMPILER_ARGS_${TARGET}
COMPILER_ARGS=${!var} # add -opt for an optimized build.
cinterop -def $DIR/stdio.def -copt "$CFLAGS" -target $TARGET -o stdio.kt.bc || exit 1
konanc $COMPILER_ARGS -target $TARGET $DIR/CsvParser.kt -library stdio.kt.bc -o CsvParser.kexe || exit 1
rm -rf $DIR/build/
mkdir $DIR/build/
mkdir $DIR/build/c_interop/
mkdir $DIR/build/bin/
cinterop -def $DIR/src/c_interop/stdio.def -copt "$CFLAGS" -target $TARGET -o $DIR/build/c_interop/stdio.kt.bc || exit 1
konanc $COMPILER_ARGS -target $TARGET $DIR/src/kotlin-native/CsvParser.kt -library $DIR/build/c_interop/stdio.kt.bc \
-o $DIR/build/bin/CsvParser.kexe || exit 1
echo "Artifact path is ./build/bin/CsvParser.kexe"
+1
View File
@@ -0,0 +1 @@
runArgs=./European_Mammals_Red_List_Nov_2009.csv 4 100
+9 -5
View File
@@ -1,13 +1,17 @@
# GIT frequency analyzer
This example shows how one could perform statistics on Git repository.
This example shows how one could perform statistics on Git repository.
libgit2 is required for this to work (`apt-get install libgit2-dev`).
To build use `./build.sh` script without arguments (or specify `TARGET` variable if cross-compiling).
You also may use Gradle to build this sample: `../gradlew build`.
To build use `../gradlew build`.
To run use
To run use `../gradlew run`.
./GitChurn.kexe <path-to-some-git-repo>
To change run arguments, change property runArgs in gradle.propeties file
or pass `-PrunArgs="../../"` to gradle run.
Alternatively you can run artifact directly
./build/konan/bin/GitChurn/GitChurn.kexe ../../
It will print most frequently modified (by number of commits) files in repository.
-62
View File
@@ -1,76 +1,14 @@
apply plugin: 'konan'
konanInterop {
libgit2 {
defFile 'libgit2.def'
includeDirs '/opt/local/include', '/usr/include', '/usr/local/include'
}
}
konanArtifacts {
GitChurn {
inputFiles project.fileTree('src')
useInterop 'libgit2'
linkerOpts "-L/opt/local/lib -L/usr/lib/x86_64-linux-gnu -L/usr/local/lib -lgit2"
}
}
build {
project.ext { outputFile = "${projectDir.canonicalPath}/${file(compileKonanGitChurn.artifactPath).name}" }
doLast {
copy {
from compileKonanGitChurn.artifactPath
into projectDir.canonicalPath
}
}
}
void dumpCompilationTask(Task task) {
println()
println("Compilation task: ${task.name}")
println("outputDir : ${task.outputDir}")
println("artifactPath : ${task.artifactPath}")
println("inputFiles : ${task.inputFiles.files}")
println("libraries : ${task.libraries}")
println("nativeLibraries : ${task.nativeLibraries}")
println("linkerOpts : ${task.linkerOpts}")
println("noStdLib : ${task.noStdLib}")
println("noLink : ${task.noLink}")
println("noMain : ${task.noMain}")
println("enableOptimization : ${task.enableOptimization}")
println("enableAssertions : ${task.enableAssertions}")
println("target : ${task.target}")
println("languageVersion : ${task.languageVersion}")
println("apiVersion : ${task.apiVersion}")
}
void dumpInteropTask(Task task) {
println()
println("Stub generation task: ${task.name}")
println("stubsDir : ${task.stubsDir}")
println("libsDir : ${task.libsDir}")
println("defFile : ${task.defFile}")
println("target : ${task.target}")
println("pkg : ${task.pkg}")
println("linker : ${task.linker}")
println("compilerOpts : ${task.compilerOpts}")
println("linkerOpts : ${task.linkerOpts}")
println("headers : ${task.headers.files}")
println("linkFiles : ${task.linkFiles}")
}
task dumpParameters(type: DefaultTask) {
doLast {
dumpCompilationTask(konanArtifacts['GitChurn'].compilationTask)
dumpInteropTask(konanInterop['libgit2'].generateStubsTask)
dumpCompilationTask(konanInterop['libgit2'].compileStubsTask)
}
}
clean {
doLast {
delete outputFile
}
}
Executable → Regular
+15 -8
View File
@@ -1,14 +1,11 @@
#!/usr/bin/env bash
DIR=$(dirname "$0")
PATH=../../dist/bin:../../bin:$PATH
DIR=.
# Uncomment flags if your paths differ from these ones.
CFLAGS_macbook=-I/opt/local/include
#CFLAGS_macbook=-I/usr/local/include
CFLAGS_macbook="-I/opt/local/include -copt -I/usr/local/include"
CFLAGS_linux=-I/usr/include
LINKER_ARGS_macbook="-L/opt/local/lib -lgit2"
#LINKER_ARGS_macbook="-L/usr/local/lib -lgit2"
LINKER_ARGS_macbook="-L/usr/local/lib -L/opt/local/lib -lgit2"
LINKER_ARGS_linux="-L/usr/lib/x86_64-linux-gnu -lgit2"
if [ x$TARGET == x ]; then
@@ -26,5 +23,15 @@ LINKER_ARGS=${!var}
var=COMPILER_ARGS_${TARGET}
COMPILER_ARGS=${!var} # add -opt for an optimized build.
cinterop -copt $CFLAGS -def $DIR/libgit2.def -target $TARGET -o libgit2.kt.bc || exit 1
konanc -target $TARGET src -library libgit2.kt.bc -linkerArgs "$LINKER_ARGS" -o GitChurn.kexe || exit 1
rm -rf $DIR/build/
mkdir $DIR/build/
mkdir $DIR/build/c_interop/
mkdir $DIR/build/bin/
cinterop -copt $CFLAGS -def $DIR/src/c_interop/libgit2.def -target $TARGET \
-o $DIR/build/c_interop/libgit2.kt.bc || exit 1
konanc -target $TARGET $DIR/src/kotlin-native -library $DIR/build/c_interop/libgit2.kt.bc -linkerArgs "$LINKER_ARGS" \
-o $DIR/build/bin/GitChurn.kexe || exit 1
echo "Artifact path is ./build/bin/GitChurn.kexe"
+1
View File
@@ -0,0 +1 @@
runArgs=../../
@@ -1,3 +1,3 @@
headers = git2.h time.h
linkerOpts = -lgit2
headerFilter = git2/** time.h
headerFilter = git2/** time.h
+6 -3
View File
@@ -3,15 +3,18 @@
This example shows how one may use _Kotlin/Native_ to build GUI
applications with the GTK toolkit.
To build use `./build.sh` script without arguments (or specify `TARGET` variable if cross-compiling).
You also may use gradle to build the sample: `../gradlew build`.
To build use `../gradlew build`.
Do not forget to install GTK3.
On Mac use `port install gtk3`, on Debian flavours of Linux - `apt-get install libgtk-3-dev`.
To run on Mac also install XQuartz X server (https://www.xquartz.org/), and then
./Gtk3Demo.kexe
../gradlew run
Alternatively you can run artifact directly
./build/konan/bin/Gtk3Demo/Gtk3Demo.kexe
Dialog box with the button will be shown, and application will print message
and terminate on button click.
-18
View File
@@ -7,30 +7,12 @@ konanInterop {
includeDirs "$it/atk-1.0", "$it/gdk-pixbuf-2.0", "$it/cairo", "$it/pango-1.0", "$it/gtk-3.0", "$it/glib-2.0"
}
includeDirs '/opt/local/lib/glib-2.0/include', '/usr/lib/x86_64-linux-gnu/glib-2.0/include', '/usr/local/lib/glib-2.0/include'
defFile 'gtk3.def'
}
}
konanArtifacts {
Gtk3Demo {
inputFiles project.fileTree('src')
useInterop 'gtk3'
linkerOpts "-L/opt/local/lib -L/usr/local/lib -L/usr/lib/x86_64-linux-gnu -lglib-2.0 -lgdk-3.0 -lgtk-3 -lgio-2.0 -lgobject-2.0"
}
}
build {
project.ext { outputFile = "${projectDir.canonicalPath}/${file(compileKonanGtk3Demo.artifactPath).name}" }
doLast {
copy {
from compileKonanGtk3Demo.artifactPath
into projectDir.canonicalPath
}
}
}
clean {
doLast {
delete outputFile
}
}
Executable → Regular
+15 -10
View File
@@ -1,12 +1,12 @@
#!/usr/bin/env bash
DIR=$(dirname "$0")
PATH=../../dist/bin:../../bin:$PATH
DIR=.
IPREFIX_macbook=-I/opt/local/include
#IPREFIX_macbook=-I/usr/local/include
IPREFIX_linux=-I/usr/include
LINKER_ARGS_macbook="-L/opt/local/lib -lglib-2.0 -lgdk-3.0 -lgtk-3 -lgio-2.0 -lgobject-2.0"
LINKER_ARGS_macbook="-L/opt/local/lib -L/usr/local/lib -lglib-2.0 -lgdk-3.0 -lgtk-3 -lgio-2.0 -lgobject-2.0"
LINKER_ARGS_linux="-L/usr/lib/x86_64-linux-gnu -lglib-2.0 -lgdk-3 -lgtk-3 -lgio-2.0 -lgobject-2.0"
if [ x$TARGET == x ]; then
@@ -24,13 +24,18 @@ LINKER_ARGS=${!var}
var=COMPILER_ARGS_${TARGET}
COMPILER_ARGS=${!var} # add -opt for an optimized build.
if [ ! -f $DIR/gtk3.bc ]; then
echo "Generating GTK stubs (once), may take few mins depending on the hardware..."
cinterop -J-Xmx8g -copt $IPREFIX/atk-1.0 -copt $IPREFIX/gdk-pixbuf-2.0 -copt $IPREFIX/cairo -copt $IPREFIX/pango-1.0 \
-copt -I/opt/local/lib/glib-2.0/include -copt -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -copt -I/usr/local/lib/glib-2.0/include \
-copt $IPREFIX/gtk-3.0 -copt $IPREFIX/glib-2.0 -def $DIR/gtk3.def \
-target $TARGET -o $DIR/gtk3.bc || exit 1
fi
konanc -target $TARGET $DIR/src -library $DIR/gtk3.bc -linkerArgs "$LINKER_ARGS" -o $DIR/Gtk3Demo.kexe || exit 1
rm -rf $DIR/build/
mkdir $DIR/build/
mkdir $DIR/build/c_interop/
mkdir $DIR/build/bin/
echo "Generating GTK stubs, may take few mins depending on the hardware..."
cinterop -J-Xmx8g -copt $IPREFIX/atk-1.0 -copt $IPREFIX/gdk-pixbuf-2.0 -copt $IPREFIX/cairo -copt $IPREFIX/pango-1.0 \
-copt -I/opt/local/lib/glib-2.0/include -copt -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -copt -I/usr/local/lib/glib-2.0/include \
-copt $IPREFIX/gtk-3.0 -copt $IPREFIX/glib-2.0 -def $DIR/src/c_interop/gtk3.def \
-target $TARGET -o $DIR/build/c_interop/gtk3.bc || exit 1
konanc -target $TARGET $DIR/src/kotlin-native -library $DIR/build/c_interop/gtk3.bc -linkerArgs "$LINKER_ARGS" \
-o $DIR/build/bin/Gtk3Demo.kexe || exit 1
echo "Artifact path is ./build/bin/Gtk3Demo.kexe"
+9 -4
View File
@@ -2,11 +2,16 @@
This example shows how to communicate with libcurl, HTTP/HTTPS/FTP/etc client library.
Debian-like distros may need to `apt-get install libcurl4-openssl-dev`.
To build use `./build.sh` script without arguments (or specify `TARGET` variable if cross-compiling).
You also may use Gradle to build this sample: `../gradlew build`.
To run use
To build use `../gradlew build`.
./Curl.kexe https://www.jetbrains.com
To run use `../gradlew run`
To change run arguments, change property runArgs in gradle.propeties file
or pass `-PrunArgs="https://www.jetbrains.com"` to gradle run.
Alternatively you can run artifact directly
./build/konan/bin/Curl/Curl.kexe https://www.jetbrains.com
It will perform HTTP get and print out the data obtained.
-18
View File
@@ -2,31 +2,13 @@ apply plugin: 'konan'
konanInterop {
libcurl {
defFile 'libcurl.def'
includeDirs '/usr/include', '/opt/local/include', '/usr/local/opt/curl/include', '.'
}
}
konanArtifacts {
Curl {
inputFiles project.fileTree('src')
useInterop 'libcurl'
linkerOpts "-L/opt/local/lib -L/usr/lib/x86_64-linux-gnu -L/usr/local/opt/curl/lib -lcurl"
}
}
build {
project.ext { outputFile = "${projectDir.canonicalPath}/${file(compileKonanCurl.artifactPath).name}" }
doLast {
copy {
from compileKonanCurl.artifactPath
into projectDir.canonicalPath
}
}
}
clean {
doLast {
delete outputFile
}
}
+13 -3
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
DIR=$(dirname "$0")
PATH=../../dist/bin:../../bin:$PATH
DIR=.
CFLAGS_macbook=-I/opt/local/include
CFLAGS_linux=-I/usr/include/x86_64-linux-gnu
@@ -23,5 +23,15 @@ LINKER_ARGS=${!var}
var=COMPILER_ARGS_${TARGET}
COMPILER_ARGS=${!var} # add -opt for an optimized build.
cinterop -copt "$CFLAGS" -copt -I. -copt -I/usr/include -def $DIR/libcurl.def -target $TARGET -o libcurl.bc || exit 1
konanc -target $TARGET src -library libcurl.bc -linkerArgs "$LINKER_ARGS" -o Curl.kexe || exit 1
rm -rf $DIR/build/
mkdir $DIR/build/
mkdir $DIR/build/c_interop/
mkdir $DIR/build/bin/
cinterop -copt "$CFLAGS" -copt -I$DIR -copt -I/usr/include -def $DIR/src/c_interop/libcurl.def -target $TARGET \
-o $DIR/build/c_interop/libcurl.bc || exit 1
konanc -target $TARGET $DIR/src/kotlin-native -library $DIR/build/c_interop/libcurl.bc -linkerArgs "$LINKER_ARGS" \
-o $DIR/build/bin/Curl.kexe || exit 1
echo "Artifact path is ./build/bin/Curl.kexe"
+1
View File
@@ -0,0 +1 @@
runArgs=https://www.jetbrains.com
+9 -6
View File
@@ -7,17 +7,20 @@ are being suspended and resumed whenever relevant.
Thus, while server can process multiple connections concurrently,
each individual connection handler is written in simple linear manner.
Compile the echo server (in EAP only supported on Mac host):
./build.sh
You also may use Gradle to build the server:
To build use:
../gradlew build
Run the server:
./EchoServer.kexe 3000 &
../gradlew run
To change run arguments, change property runArgs in gradle.propeties file
or pass `-PrunArgs="3000"` to gradle run.
Alternatively you can run artifact directly
./build/konan/bin/EchoServer/EchoServer.kexe 3000 &
Test the server by connecting to it, for example with telnet:
+1 -20
View File
@@ -1,30 +1,11 @@
apply plugin: 'konan'
konanInterop {
sockets {
defFile "sockets.def"
}
sockets { }
}
konanArtifacts {
EchoServer {
inputFiles project.file("EchoServer.kt")
useInterop "sockets"
}
}
build {
project.ext { outputFile = "${projectDir.canonicalPath}/${file(compileKonanEchoServer.artifactPath).name}" }
doLast {
copy {
from compileKonanEchoServer.artifactPath
into projectDir.canonicalPath
}
}
}
clean {
doLast {
delete outputFile
}
}
+13 -3
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
DIR=$(dirname "$0")
PATH=../../dist/bin:../../bin:$PATH
DIR=.
if [ x$TARGET == x ]; then
case "$OSTYPE" in
@@ -18,5 +18,15 @@ LINKER_ARGS=${!var}
var=COMPILER_ARGS_${TARGET}
COMPILER_ARGS=${!var} # add -opt for an optimized build.
cinterop -def $DIR/sockets.def -copt "$CFLAGS" -target $TARGET -o sockets.kt.bc || exit 1
konanc $COMPILER_ARGS -target $TARGET $DIR/EchoServer.kt -library sockets.kt.bc -o EchoServer.kexe || exit 1
rm -rf $DIR/build/
mkdir $DIR/build/
mkdir $DIR/build/c_interop/
mkdir $DIR/build/bin/
cinterop -def $DIR/src/c_interop/sockets.def -copt "$CFLAGS" -target $TARGET \
-o $DIR/build/c_interop/sockets.kt.bc || exit 1
konanc $COMPILER_ARGS -target $TARGET $DIR/src/kotlin-native/EchoServer.kt \
-library $DIR/build/c_interop/sockets.kt.bc -o build/bin/EchoServer.kexe || exit 1
echo "Artifact path is ./build/bin/EchoServer.kexe"
@@ -0,0 +1 @@
runArgs=3000
+5 -4
View File
@@ -3,12 +3,13 @@
This example shows interaction with OpenGL library, to render classical 3D test model. Linux build requires `apt-get install freeglut3-dev` or similar,
MacOS shall work as is.
To build use `./build.sh` script without arguments (or specify `TARGET` variable if cross-compiling).
You also may use Gradle to build this sample: `../gradlew build`.
To build use `../gradlew build`.
To run use
To run use `../gradlew run`
./OpenGlTeapot.kexe
Alternatively you can run artifact directly
./build/konan/bin/OpenGlTeapot${target}/OpenGlTeapot${target}.kexe
It will render 3D model of teapot. Feel free to experiment with it, the whole power of OpenGL
is at your hands.
+8 -27
View File
@@ -1,39 +1,20 @@
apply plugin: 'konan'
konanInterop {
opengl {
defFile 'opengl.def'
}
opengl { }
}
konanArtifacts {
OpenGlTeapot {
inputFiles project.file("OpenGlTeapot.kt")
OpenGlTeapotMacbook {
useInterop 'opengl'
def osName = System.getProperty("os.name")
if (osName.equals("Mac OS X")) {
linkerOpts "-framework OpenGL -framework GLUT"
}
if (osName.equals("Linux")) {
linkerOpts "-L/usr/lib/x86_64-linux-gnu -lglut -lGL -lGLU"
}
linkerOpts "-framework OpenGL -framework GLUT"
target "macbook"
}
}
build {
project.ext { outputFile = "${projectDir.canonicalPath}/${file(compileKonanOpenGlTeapot.artifactPath).name}" }
doLast {
copy {
from compileKonanOpenGlTeapot.artifactPath
into projectDir.canonicalPath
}
}
}
clean {
doLast {
delete outputFile
OpenGlTeapotLinux {
useInterop 'opengl'
linkerOpts "-L/usr/lib/x86_64-linux-gnu -lglut -lGL -lGLU"
target "linux"
}
}
Executable → Regular
+13 -3
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
DIR=$(dirname "$0")
PATH=../../dist/bin:../../bin:$PATH
DIR=.
LINKER_ARGS_macbook="-framework OpenGL -framework GLUT"
LINKER_ARGS_linux="-L/usr/lib/x86_64-linux-gnu -lglut -lGL -lGLU"
@@ -21,5 +21,15 @@ LINKER_ARGS=${!var}
var=COMPILER_ARGS_${TARGET}
COMPILER_ARGS=${!var} # add -opt for an optimized build.
cinterop -def $DIR/opengl.def -target $TARGET -o opengl.kt.bc || exit 1
konanc -target $TARGET $DIR/OpenGlTeapot.kt -library opengl.kt.bc -linkerArgs "$LINKER_ARGS" -o OpenGlTeapot.kexe || exit 1
rm -rf $DIR/build/
mkdir $DIR/build/
mkdir $DIR/build/c_interop/
mkdir $DIR/build/bin/
cinterop -def $DIR/src/c_interop/opengl.def -target $TARGET \
-o $DIR/build/c_interop/opengl.kt.bc || exit 1
konanc -target $TARGET $DIR/src/kotlin-native/OpenGlTeapot.kt -library $DIR/build/c_interop/opengl.kt.bc \
-linkerArgs "$LINKER_ARGS" -o $DIR/build/bin/OpenGlTeapot.kexe || exit 1
echo "Artifact path is ./build/bin/OpenGlTeapot.kexe"
+2
View File
@@ -6,3 +6,5 @@ include ':nonBlockingEchoServer'
include ':opengl'
include ':socket'
include ':tetris'
include ':tensorflow'
include ':concurrent'
+9 -8
View File
@@ -1,16 +1,17 @@
# Sockets demo
Compile the echo server (in EAP only supported on Mac host):
./build.sh
You also may use Gradle to build the server:
../gradlew build
To build use `../gradlew build`.
Run the server:
./EchoServer.kexe 3000 &
../gradlew run
To change run arguments, change property runArgs in gradle.propeties file
or pass `-PrunArgs="3000"` to gradle run.
Alternatively you can run artifact directly
./build/konan/bin/EchoServer/EchoServer.kexe 3000 &
Test the server by conecting to it, for example with telnet:
+1 -20
View File
@@ -1,30 +1,11 @@
apply plugin: 'konan'
konanInterop {
sockets {
defFile "sockets.def"
}
sockets { }
}
konanArtifacts {
EchoServer {
inputFiles project.file("EchoServer.kt")
useInterop "sockets"
}
}
build {
project.ext { outputFile = "${projectDir.canonicalPath}/${file(compileKonanEchoServer.artifactPath).name}" }
doLast {
copy {
from compileKonanEchoServer.artifactPath
into projectDir.canonicalPath
}
}
}
clean {
doLast {
delete outputFile
}
}
Executable → Regular
+14 -3
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
DIR=$(dirname "$0")
PATH=../../dist/bin:../../bin:$PATH
DIR=.
if [ x$TARGET == x ]; then
case "$OSTYPE" in
@@ -18,5 +18,16 @@ LINKER_ARGS=${!var}
var=COMPILER_ARGS_${TARGET}
COMPILER_ARGS=${!var} # add -opt for an optimized build.
cinterop -def $DIR/sockets.def -copt "$CFLAGS" -target $TARGET -o sockets.kt.bc || exit 1
konanc $COMPILER_ARGS -target $TARGET $DIR/EchoServer.kt -library sockets.kt.bc -o EchoServer.kexe || exit 1
rm -rf $DIR/build/
mkdir $DIR/build/
mkdir $DIR/build/c_interop/
mkdir $DIR/build/bin/
cinterop -def $DIR/src/c_interop/sockets.def -copt "$CFLAGS" -target $TARGET \
-o $DIR/build/c_interop/sockets.kt.bc || exit 1
konanc $COMPILER_ARGS -target $TARGET $DIR/src/kotlin-native/EchoServer.kt \
-library $DIR/build/c_interop/sockets.kt.bc \
-o $DIR/build/bin/EchoServer.kexe || exit 1
echo "Artifact path is ./build/bin/EchoServer.kexe"
+1
View File
@@ -0,0 +1 @@
runArgs=3000
+12 -4
View File
@@ -10,14 +10,22 @@ showing how a TensorFlow client in Kotlin/Native could look like.
## Installation
./build.sh
./downloadTensorflow.sh
will install [TensorFlow for C](https://www.tensorflow.org/versions/r1.1/install/install_c) into
`$HOME/.konan/third-party/tensorflow` (if not yet done) and build the example.
`$HOME/.konan/third-party/tensorflow` (if not yet done).
./HelloTensorflow.kexe
To build use
will then run the example.
../gradlew build
Then run
../gradlew run
Alternatively you can run artifact directly
./build/konan/bin/Tensorflow/Tensorflow.kexe
You may need to specify `LD_LIBRARY_PATH` or `DYLD_LIBRARY_PATH` to `$HOME/.konan/third-party/tensorflow/lib`
if the TensorFlow dynamic library cannot be found.
+14
View File
@@ -0,0 +1,14 @@
apply plugin: 'konan'
konanInterop {
tensorflow {
includeDirs "${System.getProperty("user.home")}/.konan/third-party/tensorflow/include"
}
}
konanArtifacts {
Tensorflow {
useInterop "tensorflow"
linkerOpts "-L${System.getProperty("user.home")}/.konan/third-party/tensorflow/lib -ltensorflow"
}
}
Executable → Regular
+20 -14
View File
@@ -1,13 +1,13 @@
#!/usr/bin/env bash
./downloadTensorflow.sh
DIR=$(dirname "$0")
PATH=../../dist/bin:../../bin:$PATH
DIR=.
TF_TARGET_DIRECTORY="$HOME/.konan/third-party/tensorflow"
TF_TYPE="cpu" # Change to "gpu" for GPU support
CFLAGS_macbook="-I${TF_TARGET_DIRECTORY}/include"
CFLAGS_linux="-I${TF_TARGET_DIRECTORY}/include"
if [ x$TARGET == x ]; then
case "$OSTYPE" in
darwin*) TARGET=macbook; TF_TARGET=darwin ;;
@@ -16,6 +16,9 @@ case "$OSTYPE" in
esac
fi
CFLAGS_macbook="-I${TF_TARGET_DIRECTORY}/include"
CFLAGS_linux="-I${TF_TARGET_DIRECTORY}/include"
var=CFLAGS_${TARGET}
CFLAGS=${!var}
var=LINKER_ARGS_${TARGET}
@@ -23,16 +26,19 @@ LINKER_ARGS=${!var}
var=COMPILER_ARGS_${TARGET}
COMPILER_ARGS=${!var} # add -opt for an optimized build.
if [ ! -d $TF_TARGET_DIRECTORY/include/tensorflow ]; then
echo "Installing TensorFlow into $TF_TARGET_DIRECTORY ..."
mkdir -p $TF_TARGET_DIRECTORY
curl -s -L \
"https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-${TF_TYPE}-${TF_TARGET}-x86_64-1.1.0.tar.gz" |
tar -C $TF_TARGET_DIRECTORY -xz
fi
rm -rf $DIR/build/
mkdir $DIR/build/
mkdir $DIR/build/c_interop/
mkdir $DIR/build/bin/
cinterop -def $DIR/tensorflow.def -copt "$CFLAGS" -target $TARGET -o tensorflow.kt.bc || exit 1
konanc $COMPILER_ARGS -target $TARGET $DIR/HelloTensorflow.kt -library tensorflow.kt.bc -o HelloTensorflow.kexe \
-linkerArgs "-L$TF_TARGET_DIRECTORY/lib -ltensorflow" || exit 1
cinterop -def $DIR/src/c_interop/tensorflow.def -copt "$CFLAGS" -target $TARGET \
-o $DIR/build/c_interop/tensorflow.kt.bc || exit 1
konanc $COMPILER_ARGS -target $TARGET $DIR/src/kotlin-native/HelloTensorflow.kt \
-library $DIR/build/c_interop/tensorflow.kt.bc \
-o $DIR/build/bin/HelloTensorflow.kexe \
-linkerArgs "-L$TF_TARGET_DIRECTORY/lib -ltensorflow" || exit 1
echo "Note: You may need to specify LD_LIBRARY_PATH or DYLD_LIBRARY_PATH env variables to $TF_TARGET_DIRECTORY/lib if the TensorFlow dynamic library cannot be found."
echo "Artifact path is ./build/bin/HelloTensorflow.kexe"
+23
View File
@@ -0,0 +1,23 @@
#!/usr/bin/env bash
DIR=$(dirname "$0")
PATH=../../dist/bin:../../bin:$PATH
TF_TARGET_DIRECTORY="$HOME/.konan/third-party/tensorflow"
TF_TYPE="cpu" # Change to "gpu" for GPU support
if [ x$TARGET == x ]; then
case "$OSTYPE" in
darwin*) TARGET=macbook; TF_TARGET=darwin ;;
linux*) TARGET=linux; TF_TARGET=linux ;;
*) echo "unknown: $OSTYPE" && exit 1;;
esac
fi
if [ ! -d $TF_TARGET_DIRECTORY/include/tensorflow ]; then
echo "Installing TensorFlow into $TF_TARGET_DIRECTORY ..."
mkdir -p $TF_TARGET_DIRECTORY
curl -s -L \
"https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-${TF_TYPE}-${TF_TARGET}-x86_64-1.1.0.tar.gz" |
tar -C $TF_TARGET_DIRECTORY -xz
fi
+12 -7
View File
@@ -13,18 +13,23 @@ use `apt-get install libsdl2-dev`.
To build Tetris application for your host platform use
./build.sh
You also may use gradle to build this sample: `../gradlew build`. This task builds the sample for all platforms
supported by the host. Note that SDL2 must be installed on the host.
`../gradlew build`
This task builds the sample for your host platform. Note that SDL2 must be installed on the host.
For cross-compilation to iOS (on Mac host) use
To run it on the host use `../gradlew run`
TARGET=iphone ./build.sh
Alternatively you can run artifact directly
./build/konan/bin/Tetris${target}/Tetris${target}.kexe
For cross-compilation to iOS (on Mac host) use gradle property
konan.build.targets=all
For cross-compilation to Raspberry Pi (on Linux host) use
TARGET=raspberrypi ./build.sh
konan.build.targets=all
During build process compilation script creates interoperability bindings to SDL2, using SDL C headers,
and then compiles an application with the produced bindings.
+11 -25
View File
@@ -2,7 +2,8 @@ apply plugin: 'konan'
konanInterop {
sdlMacbook {
defFile 'sdl.def'
defFile 'src/c_interop/sdl.def'
pkg 'sdl'
includeDirs '/Library/Frameworks/SDL2.framework/Headers',
"${System.getProperty("user.home")}/Library/Frameworks/SDL2.framework/Headers",
'/opt/local/include/SDL2',
@@ -12,19 +13,22 @@ konanInterop {
}
sdlLinux {
defFile 'sdl.def'
defFile 'src/c_interop/sdl.def'
pkg 'sdl'
includeDirs '/usr/include/SDL2'
target 'linux'
}
sdlIphone {
defFile 'sdl.def'
defFile 'src/c_interop/sdl.def'
pkg 'sdl'
includeDirs "${project.property("konan.home")}/dependencies/target-sysroot-2-darwin-ios/System/Library/Frameworks/SDL2.framework/Headers"
target 'iphone'
}
sdlRaspberry {
defFile 'sdl.def'
defFile 'src/c_interop/sdl.def'
pkg 'sdl'
includeDirs "${project.property("konan.home")}/dependencies/target-sysroot-1-raspberrypi/usr/include/SDL2"
target 'raspberrypi'
}
@@ -32,7 +36,6 @@ konanInterop {
konanArtifacts {
TetrisMacbook {
inputFiles project.file('Tetris.kt')
useInterop 'sdlMacbook'
linkerOpts "-F ${System.getProperty("user.home")}/Library/Frameworks -F /Library/Frameworks -framework SDL2"
// Use this line instead of the previous one if you've got a 'No SDL-framework' error.
@@ -41,18 +44,13 @@ konanArtifacts {
}
TetrisLinux {
inputFiles project.file('Tetris.kt')
useInterop 'sdlLinux'
linkerOpts '-L/usr/lib/x86_64-linux-gnu -lSDL2'
target 'linux'
}
TetrisIphone {
inputFiles project.file('Tetris.kt')
useInterop 'sdlIphone'
linkerOpts '-framework SDL2 -framework AVFoundation -framework CoreGraphics -framework CoreMotion ' +
'-framework Foundation -framework GameController -framework AudioToolbox -framework OpenGLES ' +
'-framework QuartzCore -framework UIKit'
@@ -61,34 +59,22 @@ konanArtifacts {
}
TetrisRaspberry {
inputFiles project.file('Tetris.kt')
useInterop 'sdlRaspberry'
linkerOpts '-lSDL2'
target 'raspberrypi'
}
}
build {
project.ext {
buildTasks = getTaskDependencies().getDependencies().findAll { task -> task.name.startsWith("compileKonan") }
outputFiles = buildTasks.collect { task -> "${projectDir.canonicalPath}/${file(task.artifactPath).name}" }
}
doLast {
buildTasks.forEach() { task ->
copy {
from task.artifactPath
into projectDir.canonicalPath
from 'src/resources'
into file(task.artifactPath).parentFile
}
}
}
}
clean {
doLast {
outputFiles.forEach {
delete it
}
}
}
}
Executable → Regular
+15 -4
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
DIR=$(dirname "$0")
PATH=../../dist/bin:../../bin:$PATH
DIR=.
DEPS=$(dirname `type -p konanc`)/../dependencies
CFLAGS_macbook=-I$HOME/Library/Frameworks/SDL2.framework/Headers
@@ -42,6 +42,17 @@ LINKER_ARGS=${!var}
var=COMPILER_ARGS_${TARGET}
COMPILER_ARGS=${!var} # add -opt for an optimized build.
cinterop -def $DIR/sdl.def -copt "$CFLAGS" -target $TARGET -o sdl.kt.bc || exit 1
konanc $COMPILER_ARGS -target $TARGET $DIR/Tetris.kt -library sdl.kt.bc -linkerArgs "$LINKER_ARGS" -o Tetris.kexe || exit 1
#strip Tetris.kexe
rm -rf $DIR/build/
mkdir $DIR/build/
mkdir $DIR/build/c_interop/
mkdir $DIR/build/bin/
cinterop -def $DIR/src/c_interop/sdl.def -copt "$CFLAGS" -target $TARGET -o $DIR/build/c_interop/sdl.kt.bc || exit 1
konanc $COMPILER_ARGS -target $TARGET $DIR/src/kotlin-native/Tetris.kt \
-library $DIR/build/c_interop/sdl.kt.bc -linkerArgs "$LINKER_ARGS" \
-o $DIR/build/bin/Tetris.kexe || exit 1
cp -R $DIR/src/resources $DIR/build/bin
echo "Artifact path is ./build/bin/Tetris.kexe"

Before

Width:  |  Height:  |  Size: 110 KiB

After

Width:  |  Height:  |  Size: 110 KiB

@@ -1,125 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.gradle.plugin
import org.gradle.api.DefaultTask
import org.gradle.api.file.FileCollection
import org.gradle.api.tasks.*
import java.io.File
// TODO: form groups for tasks
// TODO: Make the task class nested for config with properties accessible for outer users.
open class KonanCompileTask: DefaultTask() {
companion object {
const val COMPILER_MAIN = "org.jetbrains.kotlin.cli.bc.K2NativeKt"
}
val COMPILER_JVM_ARGS: List<String>
get() = listOf("-Dkonan.home=${project.konanHome}", "-Djava.library.path=${project.konanHome}/konan/nativelib")
val COMPILER_CLASSPATH: String
get() = "${project.konanHome}/konan/lib/"
// Output artifact --------------------------------------------------------
lateinit var artifactName: String
@OutputDirectory
lateinit var outputDir: File
internal set
internal fun initialize(artifactName: String) {
dependsOn(project.konanCompilerDownloadTask)
this.artifactName = artifactName
outputDir = project.file("${project.konanCompilerOutputDir}/$artifactName")
}
val artifactPath: String
get() = "${outputDir.absolutePath}/$artifactName.${ if (noLink) "bc" else "kexe" }"
// Other compilation parameters -------------------------------------------
@InputFiles val inputFiles = mutableSetOf<FileCollection>()
@InputFiles val libraries = mutableSetOf<FileCollection>()
@InputFiles val nativeLibraries = mutableSetOf<FileCollection>()
@Input var linkerOpts = mutableListOf<String>()
internal set
@Input var noStdLib = false
internal set
@Input var noLink = false
internal set
@Input var noMain = false
internal set
@Input var enableOptimization = false
internal set
@Input var enableAssertions = false
internal set
@Optional @Input var target : String? = null
internal set
@Optional @Input var languageVersion : String? = null
internal set
@Optional @Input var apiVersion : String? = null
internal set
// TODO: Is there a better way to rerun tasks when the compiler version changes?
@Input val konanVersion = project.konanVersion
// Task action ------------------------------------------------------------
protected fun buildArgs() = mutableListOf<String>().apply {
addArg("-output", artifactPath)
addFileArgs("-library", libraries)
addFileArgs("-nativelibrary", nativeLibraries)
addListArg("-linkerArgs", linkerOpts)
addArgIfNotNull("-target", target)
addArgIfNotNull("-language-version", languageVersion)
addArgIfNotNull("-api-version", apiVersion)
addKey("-nostdlib", noStdLib)
addKey("-nolink", noLink)
addKey("-nomain", noMain)
addKey("-opt", enableOptimization)
addKey("-ea", enableAssertions)
inputFiles.forEach {
it.files.filter { it.name.endsWith(".kt") }.mapTo(this) { it.canonicalPath }
}
}
@TaskAction
fun compile() {
project.file(outputDir).mkdirs()
// TODO: Use compiler service.
project.javaexec {
with(it) {
main = COMPILER_MAIN
classpath = project.fileTree(COMPILER_CLASSPATH).apply { include("*.jar") }
jvmArgs(COMPILER_JVM_ARGS)
args(buildArgs().apply { logger.info("Compiler args: ${this.joinToString(separator = " ")}") })
}
}
}
}
@@ -1,116 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.gradle.plugin
import org.gradle.api.Named
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.file.FileCollection
import org.gradle.api.internal.project.ProjectInternal
/**
* What we can:
*
* konanInterop {
* foo {
* defFile <def-file>
* pkg <package with stubs>
* target <target: linux/macbook/iphone/iphone_sim>
* compilerOpts <Options for native stubs compilation>
* linkerOpts <Options for native stubs >
* headers <headers to process>
* includeDirs <directories where headers are located>
* linkFiles <files which will be linked with native stubs>
* }
*
* // TODO: add configuration for konan compiler
* }
*/
open class KonanInteropConfig(
val configName: String,
val project: ProjectInternal
): Named {
override fun getName() = configName
// Child tasks ------------------------------------------------------------
// Task to process the library and generate stubs
val generateStubsTask: KonanInteropTask = project.tasks.create(
"gen${name.capitalize()}InteropStubs",
KonanInteropTask::class.java
)
// Config and task to compile *.kt stubs in a *.bc library
internal val compileStubsConfig = KonanCompilerConfig("${name}InteropStubs", project, "compile").apply {
compilationTask.dependsOn(generateStubsTask)
outputDir("${project.konanInteropCompiledStubsDir}/$name")
noLink()
inputFiles(project.fileTree(generateStubsTask.stubsDir).apply { builtBy(generateStubsTask) })
}
val compileStubsTask = compileStubsConfig.compilationTask
// DSL methods ------------------------------------------------------------
fun defFile(file: Any) = with(generateStubsTask) {
defFile = project.file(file)
}
fun pkg(value: String) = with(generateStubsTask) {
pkg = value
}
fun target(value: String) = with(generateStubsTask) {
generateStubsTask.target = value
compileStubsTask.target = value
}
fun compilerOpts(vararg values: String) = with(generateStubsTask) {
compilerOpts.addAll(values)
}
fun header(file: Any) = headers(file)
fun headers(vararg files: Any) = with(generateStubsTask) {
headers.add(project.files(files))
}
fun headers(files: FileCollection) = with(generateStubsTask) {
headers.add(files)
}
fun includeDirs(vararg values: String) = with(generateStubsTask) {
compilerOpts.addAll(values.map { "-I$it" })
}
fun linker(value: String) = with(generateStubsTask) {
linker = value
}
fun linkerOpts(vararg values: String) = linkerOpts(values.toList())
fun linkerOpts(values: List<String>) = with(generateStubsTask) {
linkerOpts.addAll(values)
}
fun link(vararg files: Any) = with(generateStubsTask) {
linkFiles.add(project.files(files))
}
fun link(files: FileCollection) = with(generateStubsTask) {
linkFiles.add(files)
}
}
@@ -1,113 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.gradle.plugin
import org.gradle.api.DefaultTask
import org.gradle.api.Task
import org.gradle.api.file.FileCollection
import org.gradle.api.tasks.*
import java.io.File
open class KonanInteropTask: DefaultTask() {
internal companion object {
const val INTEROP_MAIN = "org.jetbrains.kotlin.native.interop.gen.jvm.MainKt"
}
init {
dependsOn(project.konanCompilerDownloadTask)
}
internal val INTEROP_JVM_ARGS: List<String>
get() = listOf("-Dkonan.home=${project.konanHome}", "-Djava.library.path=${project.konanHome}/konan/nativelib")
internal val INTEROP_CLASSPATH: String
get() = "${project.konanHome}/konan/lib/"
// Output directories -----------------------------------------------------
/** Directory with autogenerated interop stubs (*.kt) */
@OutputDirectory
val stubsDir = project.file("${project.konanInteropStubsOutputDir}/$name")
/** Directory with library bitcodes (*.bc) */
@OutputDirectory
val libsDir = project.file("${project.konanInteropLibsOutputDir}/$name")
// Interop stub generator parameters -------------------------------------
@Optional @InputFile var defFile: File? = null
internal set
@Optional @Input var target: String? = null
internal set
@Optional @Input var pkg: String? = null
internal set
@Optional @Input var linker: String? = null
internal set
@Input val compilerOpts = mutableListOf<String>()
@Input val linkerOpts = mutableListOf<String>()
// TODO: Check if we can use only one FileCollection instead of set.
@InputFiles val headers = mutableSetOf<FileCollection>()
@InputFiles val linkFiles = mutableSetOf<FileCollection>()
@Input val konanVersion = project.konanVersion
@TaskAction
fun exec() {
project.javaexec {
with(it) {
main = INTEROP_MAIN
classpath = project.fileTree(INTEROP_CLASSPATH).apply { include("*.jar") }
jvmArgs(INTEROP_JVM_ARGS)
environment("LIBCLANG_DISABLE_CRASH_RECOVERY", "1")
args(buildArgs().apply { logger.info("Interop args: ${this.joinToString(separator = " ")}") })
}
}
}
protected fun buildArgs() = mutableListOf<String>().apply {
addArg("-properties", "${project.konanHome}/konan/konan.properties")
addArg("-flavor", "native")
addArg("-generated", stubsDir.canonicalPath)
addArg("-natives", libsDir.canonicalPath)
addArgIfNotNull("-target", target)
addArgIfNotNull("-def", defFile?.canonicalPath)
addArgIfNotNull("-pkg", pkg)
addArgIfNotNull("-linker", linker)
addFileArgs("-h", headers)
compilerOpts.forEach {
addArg("-copt", it)
}
val linkerOpts = mutableListOf<String>().apply { addAll(linkerOpts) }
linkFiles.forEach {
linkerOpts.addAll(it.files.map { it.canonicalPath })
}
linkerOpts.forEach {
addArg("-lopt", it)
}
}
}
@@ -16,9 +16,11 @@
package org.jetbrains.kotlin.gradle.plugin
import org.gradle.api.DefaultTask
import org.gradle.api.Named
import org.gradle.api.file.FileCollection
import org.gradle.api.internal.project.ProjectInternal
import org.gradle.api.tasks.*
import java.io.File
/**
@@ -61,9 +63,119 @@ import java.io.File
* }
*/
// TODO: form groups for tasks
// TODO: Make the task class nested for config with properties accessible for outer users.
open class KonanCompileTask: DefaultTask() {
companion object {
const val COMPILER_MAIN = "org.jetbrains.kotlin.cli.bc.K2NativeKt"
}
val COMPILER_JVM_ARGS: List<String>
get() = listOf("-Dkonan.home=${project.konanHome}", "-Djava.library.path=${project.konanHome}/konan/nativelib")
val COMPILER_CLASSPATH: String
get() = "${project.konanHome}/konan/lib/"
// Output artifact --------------------------------------------------------
protected lateinit var artifactName: String
@OutputDirectory
lateinit var outputDir: File
internal set
internal fun init(artifactName: String) {
dependsOn(project.konanCompilerDownloadTask)
this.artifactName = artifactName
outputDir = project.file("${project.konanCompilerOutputDir}/$artifactName")
}
val artifactPath: String
get() = "${outputDir.absolutePath}/$artifactName.${ if (noLink) "bc" else "kexe" }"
// Other compilation parameters -------------------------------------------
@InputFiles val inputFiles = mutableSetOf<FileCollection>()
@InputFiles val libraries = mutableSetOf<FileCollection>()
@InputFiles val nativeLibraries = mutableSetOf<FileCollection>()
@Input var linkerOpts = mutableListOf<String>()
internal set
@Input var noStdLib = false
internal set
@Input var noLink = false
internal set
@Input var noMain = false
internal set
@Input var enableOptimization = false
internal set
@Input var enableAssertions = false
internal set
@Optional @Input var target : String? = null
internal set
@Optional @Input var languageVersion : String? = null
internal set
@Optional @Input var apiVersion : String? = null
internal set
@Input var dumpParameters: Boolean = false
// TODO: Is there a better way to rerun tasks when the compiler version changes?
@Input val konanVersion = project.konanVersion
// Task action ------------------------------------------------------------
protected fun buildArgs() = mutableListOf<String>().apply {
addArg("-output", artifactPath)
addFileArgs("-library", libraries)
addFileArgs("-nativelibrary", nativeLibraries)
addListArg("-linkerArgs", linkerOpts)
addArgIfNotNull("-target", target)
addArgIfNotNull("-language-version", languageVersion)
addArgIfNotNull("-api-version", apiVersion)
addKey("-nostdlib", noStdLib)
addKey("-nolink", noLink)
addKey("-nomain", noMain)
addKey("-opt", enableOptimization)
addKey("-ea", enableAssertions)
(if (inputFiles.isEmpty()) {
project.fileTree("${project.projectDir.canonicalPath}/src/kotlin-native")
} else {
inputFiles.flatMap { it.files }
}).filter { it.name.endsWith(".kt") }.mapTo(this) { it.canonicalPath }
}
@TaskAction
fun compile() {
project.file(outputDir).mkdirs()
if (dumpParameters) dumpProperties(this@KonanCompileTask)
// TODO: Use compiler service.
project.javaexec {
with(it) {
main = COMPILER_MAIN
classpath = project.fileTree(COMPILER_CLASSPATH).apply { include("*.jar") }
jvmArgs(COMPILER_JVM_ARGS)
args(buildArgs().apply { logger.info("Compiler args: ${this.joinToString(separator = " ")}") })
}
}
}
}
// TODO: check debug outputs
// TODO: Use +=/-= syntax for libraries and inputFiles
open class KonanCompilerConfig(
open class KonanCompileConfig(
val configName: String,
val project: ProjectInternal,
taskNamePrefix: String = "compileKonan"): Named {
@@ -73,14 +185,14 @@ open class KonanCompilerConfig(
val compilationTask: KonanCompileTask = project.tasks.create(
"$taskNamePrefix${configName.capitalize()}",
KonanCompileTask::class.java
) { it.initialize(this@KonanCompilerConfig.name) }
) { it.init(this@KonanCompileConfig.name) }
protected fun String.toAbsolutePath() = project.file(this).canonicalPath
// DSL methods --------------------------------------------------
// TODO: Check if we copied all data or not
fun extendsFrom(anotherConfig: KonanCompilerConfig) = with(compilationTask) {
fun extendsFrom(anotherConfig: KonanCompileConfig) = with(compilationTask) {
val anotherTask = anotherConfig.compilationTask
outputDir(anotherTask.outputDir.absolutePath)
@@ -98,7 +210,7 @@ open class KonanCompilerConfig(
if (anotherTask.enableAssertions) enableAssertions()
}
fun useInterop(interopConfig: KonanInteropConfig) {
private fun useInteropFromConfig(interopConfig: KonanInteropConfig) {
val generateStubsTask = interopConfig.generateStubsTask
val compileStubsTask = interopConfig.compileStubsTask
@@ -115,7 +227,14 @@ open class KonanCompilerConfig(
include("**/*.bc")
})
}
fun useInterop(interop: String) = useInterop(project.konanInteropContainer.getByName(interop))
fun useInterops(interops: ArrayList<String>) {
interops.forEach { useInteropFromConfig(project.konanInteropContainer.getByName(it)) }
}
fun useInterop(interop: String) {
useInteropFromConfig(project.konanInteropContainer.getByName(interop))
}
// DSL. Input/output files
@@ -189,4 +308,8 @@ open class KonanCompilerConfig(
fun enableAssertions() = with(compilationTask) {
enableAssertions = true
}
}
fun dumpParameters(value: Boolean) = with(compilationTask) {
dumpParameters = value
}
}
@@ -22,12 +22,12 @@ import org.gradle.api.tasks.TaskAction
import org.jetbrains.kotlin.konan.DependencyDownloader
import java.io.File
open class CompilerDownloadTask: DefaultTask() {
open class KonanCompilerDownloadTask : DefaultTask() {
internal companion object {
internal const val DOWNLOAD_URL = "http://download.jetbrains.com/kotlin/native"
private val KONAN_PARENT_DIR = "${System.getProperty("user.home")}/.konan"
internal val KONAN_PARENT_DIR = "${System.getProperty("user.home")}/.konan"
internal fun simpleOsName(): String {
val osName = System.getProperty("os.name")
@@ -47,10 +47,9 @@ open class CompilerDownloadTask: DefaultTask() {
return
}
try {
val konanCompiler = "kotlin-native-${simpleOsName()}-${project.konanVersion}"
val konanCompiler = project.konanCompilerName()
logger.info("Downloading Kotlin Native compiler from $DOWNLOAD_URL/$konanCompiler into $KONAN_PARENT_DIR")
DependencyDownloader(File(KONAN_PARENT_DIR), DOWNLOAD_URL, listOf(konanCompiler)).run()
project.extensions.extraProperties.set(KonanPlugin.KONAN_HOME_PROPERTY_NAME, "$KONAN_PARENT_DIR/$konanCompiler")
} catch (e: RuntimeException) {
throw GradleScriptException("Cannot download Kotlin Native compiler", e)
}
@@ -0,0 +1,221 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.gradle.plugin
import org.gradle.api.DefaultTask
import org.gradle.api.Named
import org.gradle.api.file.FileCollection
import org.gradle.api.internal.project.ProjectInternal
import org.gradle.api.tasks.*
import java.io.File
/**
* What we can:
*
* konanInterop {
* pkgName {
* defFile <def-file>
* pkg <package with stubs>
* target <target: linux/macbook/iphone/iphone_sim>
* compilerOpts <Options for native stubs compilation>
* linkerOpts <Options for native stubs >
* headers <headers to process>
* includeDirs <directories where headers are located>
* linkFiles <files which will be linked with native stubs>
* dumpParameters <Option to print parameters of task before execution>
* }
*
* // TODO: add configuration for konan compiler
* }
*/
open class KonanInteropTask: DefaultTask() {
internal companion object {
const val INTEROP_MAIN = "org.jetbrains.kotlin.native.interop.gen.jvm.MainKt"
}
internal fun init(libName: String) {
dependsOn(project.konanCompilerDownloadTask)
this.libName = libName
}
internal val INTEROP_JVM_ARGS: List<String>
get() = listOf("-Dkonan.home=${project.konanHome}", "-Djava.library.path=${project.konanHome}/konan/nativelib")
internal val INTEROP_CLASSPATH: String
get() = "${project.konanHome}/konan/lib/"
internal val C_INTEROP_DIR_PATH: String
get() = "${project.projectDir}/src/c_interop"
// Output directories -----------------------------------------------------
/** Directory with autogenerated interop stubs (*.kt) */
@OutputDirectory
val stubsDir = project.file("${project.konanInteropStubsOutputDir}/$name")
/** Directory with library bitcodes (*.bc) */
@OutputDirectory
val libsDir = project.file("${project.konanInteropLibsOutputDir}/$name")
// Interop stub generator parameters -------------------------------------
@Optional @InputFile var defFile: File? = null
internal set
@Optional @Input var target: String? = null
internal set
@Optional @Input var pkg: String? = null
internal set
@Input lateinit var libName: String
@Optional @Input var linker: String? = null
internal set
@Input var dumpParameters: Boolean = false
@Input val compilerOpts = mutableListOf<String>()
@Input val linkerOpts = mutableListOf<String>()
// TODO: Check if we can use only one FileCollection instead of set.
@InputFiles val headers = mutableSetOf<FileCollection>()
@InputFiles val linkFiles = mutableSetOf<FileCollection>()
@Input val konanVersion = project.konanVersion
@TaskAction
fun exec() {
if (dumpParameters) dumpProperties(this@KonanInteropTask)
project.javaexec {
with(it) {
main = INTEROP_MAIN
classpath = project.fileTree(INTEROP_CLASSPATH).apply { include("*.jar") }
jvmArgs(INTEROP_JVM_ARGS)
environment("LIBCLANG_DISABLE_CRASH_RECOVERY", "1")
args(buildArgs().apply { logger.info("Interop args: ${this.joinToString(separator = " ")}") })
}
}
}
protected fun buildArgs() = mutableListOf<String>().apply {
addArg("-properties", "${project.konanHome}/konan/konan.properties")
addArg("-flavor", "native")
addArg("-generated", stubsDir.canonicalPath)
addArg("-natives", libsDir.canonicalPath)
addArgIfNotNull("-target", target)
val defFilePath = defFile?.canonicalPath ?:
project.file("$C_INTEROP_DIR_PATH/$libName.def").takeIf { it.exists() }?.canonicalPath
addArgIfNotNull("-def", defFilePath)
addArg("-pkg", pkg ?: libName)
addArgIfNotNull("-linker", linker)
addFileArgs("-h", headers)
compilerOpts.forEach {
addArg("-copt", it)
}
val linkerOpts = mutableListOf<String>().apply { addAll(linkerOpts) }
linkFiles.forEach {
linkerOpts.addAll(it.files.map { it.canonicalPath })
}
linkerOpts.forEach {
addArg("-lopt", it)
}
}
}
open class KonanInteropConfig(
val configName: String,
val project: ProjectInternal
): Named {
override fun getName() = configName
// Child tasks ------------------------------------------------------------
// Task to process the library and generate stubs
val generateStubsTask: KonanInteropTask = project.tasks.create(
"gen${name.capitalize()}InteropStubs",
KonanInteropTask::class.java
) { it.init(name) }
// Config and task to compile *.kt stubs in a *.bc library
internal val compileStubsConfig = KonanCompileConfig("${name}InteropStubs", project, "compile").apply {
compilationTask.dependsOn(generateStubsTask)
outputDir("${project.konanInteropCompiledStubsDir}/$name")
noLink()
inputFiles(project.fileTree(generateStubsTask.stubsDir).apply { builtBy(generateStubsTask) })
}
val compileStubsTask = compileStubsConfig.compilationTask
// DSL methods ------------------------------------------------------------
fun defFile(file: Any) = with(generateStubsTask) {
defFile = project.file(file)
}
fun pkg(value: String) = with(generateStubsTask) {
pkg = value
}
fun target(value: String) = with(generateStubsTask) {
generateStubsTask.target = value
compileStubsTask.target = value
}
fun compilerOpts(vararg values: String) = with(generateStubsTask) {
compilerOpts.addAll(values)
}
fun header(file: Any) = headers(file)
fun headers(vararg files: Any) = with(generateStubsTask) {
headers.add(project.files(files))
}
fun headers(files: FileCollection) = with(generateStubsTask) {
headers.add(files)
}
fun includeDirs(vararg values: String) = with(generateStubsTask) {
compilerOpts.addAll(values.map { "-I$it" })
}
fun linker(value: String) = with(generateStubsTask) {
linker = value
}
fun linkerOpts(vararg values: String) = linkerOpts(values.toList())
fun linkerOpts(values: List<String>) = with(generateStubsTask) {
linkerOpts.addAll(values)
}
fun link(vararg files: Any) = with(generateStubsTask) {
linkFiles.add(project.files(files))
}
fun link(files: FileCollection) = with(generateStubsTask) {
linkFiles.add(files)
}
fun dumpParameters(value: Boolean) = with(generateStubsTask) {
dumpParameters = value
}
}
@@ -58,26 +58,25 @@ internal val Project.konanVersion
get() = findProperty(KonanPlugin.KONAN_VERSION_PROPERTY_NAME) as String? ?: KonanPlugin.DEFAULT_KONAN_VERSION
internal val Project.supportedCompileTasks: TaskCollection<KonanCompileTask>
get() = project.tasks.withType(KonanCompileTask::class.java).matching { it.target?.isSupported() ?: true }
get() {
return project.tasks.withType(KonanCompileTask::class.java).matching { it.target?.isSupported() ?: true }
}
internal val Project.supportedInteropTasks: TaskCollection<KonanInteropTask>
get() = project.tasks.withType(KonanInteropTask::class.java).matching { it.target?.isSupported() ?: true }
private fun String.isSupported(): Boolean {
val os = CompilerDownloadTask.simpleOsName()
return when (os) {
"macos" -> this == "macbook" || this == "iphone"
"linux" -> this == "linux" || this == "raspberrypi"
else -> false
}
}
internal fun Project.konanCompilerName(): String =
"kotlin-native-${KonanCompilerDownloadTask.simpleOsName()}-${this.konanVersion}"
class KonanArtifactsContainer(val project: ProjectInternal): AbstractNamedDomainObjectContainer<KonanCompilerConfig>(
KonanCompilerConfig::class.java,
internal fun Project.konanCompilerDownloadDir(): String =
KonanCompilerDownloadTask.KONAN_PARENT_DIR + "/" + project.konanCompilerName()
class KonanArtifactsContainer(val project: ProjectInternal): AbstractNamedDomainObjectContainer<KonanCompileConfig>(
KonanCompileConfig::class.java,
project.gradle.services.get(Instantiator::class.java)) {
override fun doCreate(name: String): KonanCompilerConfig =
KonanCompilerConfig(name, project)
override fun doCreate(name: String): KonanCompileConfig =
KonanCompileConfig(name, project)
}
class KonanInteropContainer(val project: ProjectInternal): AbstractNamedDomainObjectContainer<KonanInteropConfig>(
@@ -125,6 +124,58 @@ internal fun MutableList<String>.addListArg(parameter: String, values: List<Stri
}
}
internal fun dumpProperties(task: Task) {
when (task) {
is KonanCompileTask -> {
println()
println("Compilation task: ${task.name}")
println("outputDir : ${task.outputDir}")
println("artifactPath : ${task.artifactPath}")
println("inputFiles : ${task.inputFiles.joinToString(prefix = "[", separator = ", ", postfix = "]")}")
println("libraries : ${task.libraries}")
println("nativeLibraries : ${task.nativeLibraries}")
println("linkerOpts : ${task.linkerOpts}")
println("noStdLib : ${task.noStdLib}")
println("noLink : ${task.noLink}")
println("noMain : ${task.noMain}")
println("enableOptimization : ${task.enableOptimization}")
println("enableAssertions : ${task.enableAssertions}")
println("target : ${task.target}")
println("languageVersion : ${task.languageVersion}")
println("apiVersion : ${task.apiVersion}")
println()
}
is KonanInteropTask -> {
println()
println("Stub generation task: ${task.name}")
println("stubsDir : ${task.stubsDir}")
println("libsDir : ${task.libsDir}")
println("defFile : ${task.defFile}")
println("target : ${task.target}")
println("pkg : ${task.pkg}")
println("linker : ${task.linker}")
println("compilerOpts : ${task.compilerOpts}")
println("linkerOpts : ${task.linkerOpts}")
println("headers : ${task.headers.joinToString(prefix = "[", separator = ", ", postfix = "]")}")
println("linkFiles : ${task.linkFiles}")
println()
}
else -> {
println("Unsupported task.")
}
}
}
private fun String.isSupported(): Boolean {
val os = KonanCompilerDownloadTask.simpleOsName()
return when (os) {
"macos" -> this == "macbook" || this == "iphone"
"linux" -> this == "linux" || this == "raspberrypi"
else -> false
}
}
class KonanPlugin @Inject constructor(private val registry: ToolingModelBuilderRegistry)
: Plugin<ProjectInternal> {
@@ -135,6 +186,7 @@ class KonanPlugin @Inject constructor(private val registry: ToolingModelBuilderR
internal const val KONAN_HOME_PROPERTY_NAME = "konan.home"
internal const val KONAN_VERSION_PROPERTY_NAME = "konan.version"
internal const val KONAN_BUILD_TARGETS = "konan.build.targets"
internal const val DEFAULT_KONAN_VERSION = "0.2"
}
@@ -153,28 +205,57 @@ class KonanPlugin @Inject constructor(private val registry: ToolingModelBuilderR
}
}
private fun String.isSupported(): Boolean {
val os = CompilerDownloadTask.simpleOsName()
return when (os) {
"macos" -> this == "macbook" || this == "iphone"
"linux" -> this == "linux" || this == "raspberrypi"
else -> false
}
}
// TODO: Create default config? what about test sources?
override fun apply(project: ProjectInternal?) {
if (project == null) { return }
registry.register(KonanToolingModelBuilder)
project.tasks.create(KONAN_DOWNLOAD_TASK_NAME, CompilerDownloadTask::class.java)
project.tasks.create(KONAN_DOWNLOAD_TASK_NAME, KonanCompilerDownloadTask::class.java)
project.extensions.add(COMPILER_EXTENSION_NAME, KonanArtifactsContainer(project))
project.extensions.add(INTEROP_EXTENSION_NAME, KonanInteropContainer(project))
if (!project.extensions.extraProperties.has(KonanPlugin.KONAN_HOME_PROPERTY_NAME)) {
project.extensions.extraProperties.set(KonanPlugin.KONAN_HOME_PROPERTY_NAME, project.konanCompilerDownloadDir())
}
val hostTarget = when (KonanCompilerDownloadTask.simpleOsName()) {
"macos" -> "macbook"
"linux" -> "linux"
else -> throw IllegalStateException("Unsupported platform")
}
if (!project.extensions.extraProperties.has(KonanPlugin.KONAN_BUILD_TARGETS)) {
project.extensions.extraProperties.set(KonanPlugin.KONAN_BUILD_TARGETS, hostTarget)
}
getTask(project, "clean").doLast {
project.delete(project.konanBuildRoot)
}
val targets = project.extensions.extraProperties.get(KonanPlugin.KONAN_BUILD_TARGETS).toString().trim().split(' ')
val predicate: (KonanCompileTask) -> Boolean = { task ->
if (targets.contains("all")) {
task.target?.isSupported() ?: true
} else {
val target = task.target
target == null || targets.contains(target)
}
}
val matchingTasks = project.tasks.withType(KonanCompileTask::class.java).matching(predicate)
getTask(project, "build").apply {
dependsOn(project.supportedCompileTasks)
dependsOn(project.supportedInteropTasks)
}
getTask(project, "run").apply {
dependsOn(getTask(project, "build"))
doLast {
for (task in project.tasks.withType(KonanCompileTask::class.java).matching { it.target?.equals(hostTarget) ?: true}) {
if (task.artifactPath.endsWith("kexe")) {
project.exec {
with(it) {
commandLine(task.artifactPath)
if (project.extensions.extraProperties.has("runArgs")) {
args(project.extensions.extraProperties.get("runArgs").toString().split(' '))
}
}
}
}
}
}
}
}