diff --git a/HACKING.md b/HACKING.md index dd04b25d9f8..20b7de4ceec 100644 --- a/HACKING.md +++ b/HACKING.md @@ -1,9 +1,10 @@ + ## Compiler Gradle options There are several gradle flags one can use for Konan build. * **-Pkonanc_flags** passes flags to the compiler used to build stdlib - ./gradlew -Pkonanc_flags="-disable lower_inline -print_ir" stdlib + ./gradlew -Pkonanc_flags="--disable lower_inline --print_ir" stdlib * **-Pshims** compiles LLVM interface with tracing "shims". Allowing one to trace the LLVM calls from the compiler. @@ -15,6 +16,19 @@ There are several gradle flags one can use for Konan build. ./gradlew -Pfilter=overflowLong.kt run_external -* **-Pperfix** allows one to choose external test directories to run. Only tests from directories with given prefix will be executed. +* **-Pprefix** allows one to choose external test directories to run. Only tests from directories with given prefix will be executed. - ./gradlew -Pfilter=external_codegen_box_cast run_external \ No newline at end of file + ./gradlew -Pprefix=external_codegen_box_cast run_external + + + ## Testing + +To run blackbox compiler tests from JVM Kotlin use (takes time): + + ./gradlew run_external + +To update the blackbox compiler tests set TeamCity build number in `gradle.properties`: + + testDataVersion=:id + +and run `./gradlew update_external_tests` \ No newline at end of file diff --git a/INTEROP.md b/INTEROP.md index a9bdd4d7e5d..81bf4669584 100644 --- a/INTEROP.md +++ b/INTEROP.md @@ -19,20 +19,25 @@ imported into an IDE for purposes of code completion and navigation. ## Simple example ## -Build the dependencies and the compiler (see README.md). +Build the dependencies and the compiler (see `README.md`). Prepare stubs for the system sockets library: - ./dist/bin/interop -def:backend.native/tests/interop/basics/sockets.def + cd samples/socket + ../../dist/bin/interop -def:sockets.def Compile the echo server: - ./dist/bin/kotlinc backend.native/tests/interop/basics/echo_server.kt \ - sockets -nativelibrary socketsstubs.bc + ../../dist/bin/kotlinc EchoServer.kt sockets -nativelibrary socketsstubs.bc \ + -o EchoServer.kexe + +This whole process is automated in `build.sh` script, which also support cross-compilation +to supported cross-targets with `TARGET=raspberrypi ./build.sh` (`cross_dist` target must +be executed first). Run the server: - ./program.kexe 3000 & + ./EchoServer.kexe 3000 & Test the server by conecting to it, for example with telnet: @@ -51,12 +56,11 @@ Structurally it's a simple property file, looking like this: header = zlib.h compilerOpts = -std=c99 - linkerOpts = -lz Then run interop tool with something like (note that for host libraries not included in sysroot search paths for headers may be needed): - ./dist/bin/interop -def:zlib.def -copt:-I/opt/local/include + interop -def:zlib.def -copt:-I/opt/local/include This command will produce directory named `zlib` containing file `zlib.kt` and file `zlibstubs.bc` containing implementation specific glue bitcode. @@ -72,8 +76,7 @@ After generation of bindings they could be used by IDE as proxy view of the native library. For typical Unix library with config script `compilerOpts` will likely contain -output of config script with `--cflags` flag (maybe without exact paths) and -`linkerOpts` - output of config script with `--libs`. +output of config script with `--cflags` flag (maybe without exact paths). -Also all those values could be passed directly as values for `-copt` and -`linkedArgs` respectively. +Output of config script with `--libs` shall be passed as `-linkedArgs` `kotlinc` +flag value (quoted) when compiling. diff --git a/README.md b/README.md index eea062e4976..e9858e40445 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,45 @@ -# Kotlin-native backend # +# Kotlin N # -Download dependencies: +Kotlin Native backend, codenamed _Kotlin N_, is a LLVM backend for the Kotlin +compiler, runtime implementation and native code generation facility +using LLVM toolchain. + + _Kotlin N_ is primarily designed to allow compilation for platforms where +virtual machines are not desirable or possible (such as iOS, embedded targets), +or where developer is willing to produce reasonably-sized self-contained program +without need to ship an additional execution runtime. + +To compile from sources use following steps. + +First download dependencies: ./gradlew dependencies:update -Then build the compiler: +Then build the compiler and standard library: ./gradlew dist +To build standard library for cross-targets (currently, iOS on Mac OSX and Raspberry Pi on +Linux hosts) use: + + ./gradlew cross_dist + After that you should be able to compile your programs like that: - ./dist/bin/kotlinc hello.kt -o hello + export PATH=./dist/bin:$PATH + kotlinc hello.kt -o hello For an optimized compilation use -opt: - ./dist/bin/kotlinc hello.kt -o hello -opt + kotlinc hello.kt -o hello -opt For some tests, use: ./gradlew backend.native:tests:run -To run blackbox compiler tests from JVM Kotlin use (takes time): +To generate interoperability stubs create library definition file +(take a look on `samples/tetris/tetris.sdl`) and run `interop` tool like this: - ./gradlew run_external + interop -def:lib.def -To update the blackbox compiler tests set TeamCity build number in `gradle.properties`: - - testDataVersion=:id - -and run `./gradlew update_external_tests` \ No newline at end of file +See provided samples and `INTEROP.md` for more details. \ No newline at end of file diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 4f01c5b35c2..62eaa377128 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -23,8 +23,8 @@ the following platforms: * Mac OS X 10.10 and later (x86-64) * x86-64 Ubuntu Linux (14.04, 16.04 and later), other Linux flavours may work as well - * Apple iOS (arm64 and simulator on x86-64), cross-compiled on MacOS X host - * Raspberry Pi, cross-compiled on Linux host + * Apple iOS (arm64), cross-compiled on MacOS X host (`-target iphone`) + * Raspberry Pi, cross-compiled on Linux host (`-target raspberrypi`) Adding support for other target platforms shalln't be too hard, if LLVM support diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LinkStage.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LinkStage.kt index 0ab503bece7..880d958c361 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LinkStage.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LinkStage.kt @@ -276,7 +276,7 @@ internal class LinkStage(val context: Context) { } } phaser.phase(KonanPhase.LINKER) { - val executable = link(objectFiles) + link(objectFiles) } } } diff --git a/cmd/interop b/cmd/interop index f564eee1922..91c23982eec 100644 --- a/cmd/interop +++ b/cmd/interop @@ -59,6 +59,6 @@ LD_LIBRARY_PATH=${NATIVE_LIB} \ $JAVACMD $JAVA_OPTS ${java_args[@]} \ -cp $INTEROP_CLASSPATH \ $INTEROP_TOOL \ - $FLAVOR_ARG ${interop_args[@]} \ + $FLAVOR_ARG "${interop_args[@]}" \ diff --git a/samples/csv_parser/CsvParser.kt b/samples/csvparser/CsvParser.kt similarity index 100% rename from samples/csv_parser/CsvParser.kt rename to samples/csvparser/CsvParser.kt diff --git a/samples/csv_parser/European_Mammals_Red_List_Nov_2009.csv b/samples/csvparser/European_Mammals_Red_List_Nov_2009.csv similarity index 100% rename from samples/csv_parser/European_Mammals_Red_List_Nov_2009.csv rename to samples/csvparser/European_Mammals_Red_List_Nov_2009.csv diff --git a/samples/csv_parser/README.md b/samples/csvparser/README.md similarity index 67% rename from samples/csv_parser/README.md rename to samples/csvparser/README.md index 40a58d67954..8c1bc97bbdb 100644 --- a/samples/csv_parser/README.md +++ b/samples/csvparser/README.md @@ -4,11 +4,11 @@ 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` script without arguments (or specify `TARGET` variable if cross-compiling). +To build use `./build.sh` script without arguments (or specify `TARGET` variable if cross-compiling). To run use - ./csvparser.kexe ./European_Mammals_Red_List_Nov_2009.csv 4 100 + ./CsvParser.kexe ./European_Mammals_Red_List_Nov_2009.csv 4 100 Which will print fifth column (Family, zero-based index) in first 100 rows of the CSV file. \ No newline at end of file diff --git a/samples/csvparser/build.sh b/samples/csvparser/build.sh new file mode 100755 index 00000000000..0a3a19af578 --- /dev/null +++ b/samples/csvparser/build.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +DIR=. +PATH=../../dist/bin:../../bin:$PATH + +if [ x$TARGET == x ]; then +case "$OSTYPE" in + darwin*) TARGET=macbook ;; + linux*) TARGET=linux ;; + *) echo "unknown: $OSTYPE" && exit 1;; +esac +fi + +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. + +interop -def:$DIR/stdio.def -copt:"$CFLAGS" -target:$TARGET || exit 1 +konanc $COMPILER_ARGS -target $TARGET $DIR/CsvParser.kt stdio -nativelibrary stdiostubs.bc -o CsvParser.kexe || exit 1 diff --git a/samples/csv_parser/stdio.def b/samples/csvparser/stdio.def similarity index 87% rename from samples/csv_parser/stdio.def rename to samples/csvparser/stdio.def index 7a227fa393c..dff176612d1 100644 --- a/samples/csv_parser/stdio.def +++ b/samples/csvparser/stdio.def @@ -1,4 +1,3 @@ headers = stdio.h stdlib.h string.h compilerOpts = -D_POSIX_SOURCE -linkerOpts = excludedFunctions = diff --git a/samples/opengl/OpenGlTeapot.kt b/samples/opengl/OpenGlTeapot.kt new file mode 100644 index 00000000000..56abd7b2e7a --- /dev/null +++ b/samples/opengl/OpenGlTeapot.kt @@ -0,0 +1,109 @@ +import kotlinx.cinterop.* +import opengl.* + +// Ported from http://openglsamples.sourceforge.net/projects/index.php/blog/index/ + +private var rotation: GLfloat = 0.0f +private val rotationSpeed: GLfloat = 0.2f + +private val windowWidth = 640 +private val windowHeight = 480 + +fun display() { + // Clear Screen and Depth Buffer + glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT) + glLoadIdentity() + + // Define a viewing transformation + gluLookAt(4.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) + + // Push and pop the current matrix stack. + // This causes that translations and rotations on this matrix wont influence others. + + glPushMatrix() + glColor3f(1.0f, 0.0f, 0.0f) + glTranslatef(0.0f, 0.0f, 0.0f) + glRotatef(rotation, 0.0f, 1.0f, 0.0f) + glRotatef(90.0f, 0.0f, 1.0f, 0.0f) + + // Draw the teapot + glutSolidTeapot(1.0) + glPopMatrix() + + + rotation += rotationSpeed + glutSwapBuffers() +} + + +fun initialize() { + // select projection matrix + glMatrixMode(GL_PROJECTION) + + // set the viewport + glViewport(0, 0, windowWidth, windowHeight) + + // set matrix mode + glMatrixMode(GL_PROJECTION) + + // reset projection matrix + glLoadIdentity() + val aspect = windowWidth.toDouble() / windowHeight + + // set up a perspective projection matrix + gluPerspective(45.0, aspect, 1.0, 500.0) + + // specify which matrix is the current matrix + glMatrixMode(GL_MODELVIEW) + glShadeModel(GL_SMOOTH) + + // specify the clear value for the depth buffer + glClearDepth(1.0) + glEnable(GL_DEPTH_TEST) + glDepthFunc(GL_LEQUAL) + + // specify implementation-specific hints + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST) + + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, cValuesOf(0.1f, 0.1f, 0.1f, 1.0f)) + glLightfv(GL_LIGHT0, GL_DIFFUSE, cValuesOf(0.6f, 0.6f, 0.6f, 1.0f)) + glLightfv(GL_LIGHT0, GL_SPECULAR, cValuesOf(0.7f, 0.7f, 0.3f, 1.0f)) + + glEnable(GL_LIGHT0) + glEnable(GL_COLOR_MATERIAL) + glShadeModel(GL_SMOOTH) + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE) + glDepthFunc(GL_LEQUAL) + glEnable(GL_DEPTH_TEST) + glEnable(GL_LIGHTING) + glEnable(GL_LIGHT0) + glClearColor(0.0f, 0.0f, 0.0f, 1.0f) +} + +fun main(args: Array) { + // initialize and run program + memScoped { + val argc = alloc().apply { value = 0 } + glutInit(argc.ptr, null) // TODO: pass real args + } + + // Display Mode + glutInitDisplayMode(GLUT_RGB or GLUT_DOUBLE or GLUT_DEPTH) + + // Set window size + glutInitWindowSize(windowWidth, windowHeight) + + // create Window + glutCreateWindow("The GLUT Teapot") + + // register Display Function + glutDisplayFunc(staticCFunction(::display)) + + // register Idle Function + glutIdleFunc(staticCFunction(::display)) + + initialize() + + // run GLUT mainloop + glutMainLoop() +} \ No newline at end of file diff --git a/samples/opengl/build.sh b/samples/opengl/build.sh new file mode 100755 index 00000000000..8148f9676e0 --- /dev/null +++ b/samples/opengl/build.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +PATH=../../dist/bin:../../bin:$PATH +DIR=. + +LINKER_ARGS_macbook="-framework OpenGL -framework GLUT" +LINKER_ARGS_linux="-L/usr/lib/x86_64-linux-gnu -lSDL2" + +if [ x$TARGET == x ]; then +case "$OSTYPE" in + darwin*) TARGET=macbook ;; + linux*) TARGET=linux ;; + *) echo "unknown: $OSTYPE" && exit 1;; +esac +fi + +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. + +interop -def:$DIR/opengl.def -target:$TARGET || exit 1 +konanc -target $TARGET opengl $DIR/OpenGlTeapot.kt -nativelibrary openglstubs.bc -linkerArgs "$LINKER_ARGS" -o OpenGlTeapot.kexe || exit 1 diff --git a/samples/opengl/opengl.def b/samples/opengl/opengl.def new file mode 100644 index 00000000000..0ace79a6c88 --- /dev/null +++ b/samples/opengl/opengl.def @@ -0,0 +1,2 @@ +headers = GLUT/glut.h +compilerOpts = -framework OpenGL -framework GLUT diff --git a/samples/socket/build.sh b/samples/socket/build.sh new file mode 100755 index 00000000000..e550368146a --- /dev/null +++ b/samples/socket/build.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +PATH=../../dist/bin:../../bin:$PATH +DIR=. + +if [ x$TARGET == x ]; then +case "$OSTYPE" in + darwin*) TARGET=macbook ;; + linux*) TARGET=linux ;; + *) echo "unknown: $OSTYPE" && exit 1;; +esac +fi + +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. + +interop -def:$DIR/sockets.def -copt:"$CFLAGS" -target:$TARGET || exit 1 +konanc $COMPILER_ARGS -target $TARGET $DIR/EchoServer.kt sockets -nativelibrary socketsstubs.bc -o EchoServer.kexe || exit 1 diff --git a/samples/tetris/README.md b/samples/tetris/README.md index 375e353d996..f870f2f764a 100644 --- a/samples/tetris/README.md +++ b/samples/tetris/README.md @@ -6,12 +6,12 @@ of cross-platform game and multimedia applications. Start with building compiler by using `dist` and `cross_dist` for cross-targets. To build Tetris application for your host platform use - ./build + ./build.sh note that SDL2 must be installed on the host. For cross-compilation to iOS (on Mac host) use - TARGET=iphone ./build + TARGET=iphone ./build.sh For cross-compilation to Raspberry Pi (on Linux host) use - TARGET=raspberrypi ./build + TARGET=raspberrypi ./build.sh During build process compilation script creates interoperability bindings to SDL2, using SDL C headers, and then compiles an application with the produced bindings. @@ -19,5 +19,5 @@ and then compiles an application with the produced bindings. To deploy executable to iPhone device take Info.plist, then use XCode and your own private signing identity. To run on Raspberry Pi one need to install SDL package with `apt-get install libsdl2-2.0.0` on the Pi. -Also GLES2 renderer is recommended (use `SDL_RENDER_DRIVER=opengles2 ./tetris.kexe`). +Also GLES2 renderer is recommended (use `SDL_RENDER_DRIVER=opengles2 ./Tetris.kexe`). diff --git a/samples/tetris/tetris.kt b/samples/tetris/Tetris.kt similarity index 100% rename from samples/tetris/tetris.kt rename to samples/tetris/Tetris.kt diff --git a/samples/tetris/build b/samples/tetris/build.sh similarity index 73% rename from samples/tetris/build rename to samples/tetris/build.sh index be059efdc0f..77430862c18 100755 --- a/samples/tetris/build +++ b/samples/tetris/build.sh @@ -1,14 +1,14 @@ #!/usr/bin/env bash +PATH=../../dist/bin:../../bin:$PATH DIR=. -DIST=../../dist -DEPS=../../dependencies/all +DEPS=$(dirname `type -p konanc`)/../dependencies CFLAGS_macbook=-I/Library/Frameworks/SDL2.framework/Headers LINKER_ARGS_macbook="-F /Library/Frameworks -framework SDL2" COMPILER_ARGS_macbook= -#CFLAGS_macbook=-I/opt/local/include/SDL2 -#LINKER_ARGS_macbook="-L/opt/local/lib -lSDL2" +CFLAGS_macbook=-I/opt/local/include/SDL2 +LINKER_ARGS_macbook="-L/opt/local/lib -lSDL2" CFLAGS_linux=-I/usr/include/SDL2 LINKER_ARGS_linux="-L/usr/lib/x86_64-linux-gnu -lSDL2" COMPILER_ARGS_linux= @@ -35,6 +35,6 @@ LINKER_ARGS=${!var} var=COMPILER_ARGS_${TARGET} COMPILER_ARGS=${!var} # add -opt for an optimized build. -$DIST/bin/interop -def:$DIR/sdl.def -copt:"$CFLAGS" -target:$TARGET || exit 1 -$DIST/bin/konanc $COMPILER_ARGS -target $TARGET sdl $DIR/tetris.kt -nativelibrary sdlstubs.bc -linkerArgs "$LINKER_ARGS" -o tetris.kexe || exit 1 -#strip tetris.kexe +interop -def:$DIR/sdl.def -copt:"$CFLAGS" -target:$TARGET || exit 1 +konanc $COMPILER_ARGS -target $TARGET sdl $DIR/Tetris.kt -nativelibrary sdlstubs.bc -linkerArgs "$LINKER_ARGS" -o Tetris.kexe || exit 1 +#strip Tetris.kexe diff --git a/samples/tetris/sdl.def b/samples/tetris/sdl.def index d33e373d2c6..a050448b1f4 100644 --- a/samples/tetris/sdl.def +++ b/samples/tetris/sdl.def @@ -10,5 +10,3 @@ compilerOpts = -D_POSIX_SOURCE compilerOpts.osx = compilerOpts.linux = -D_REENTRANT compilerOpts.ios = - -linkerOpts.linux = -lm