文字内容
1. Kotlin/Native. Final step on the way to multiplatform projects on Kotlin Elena Lepilkina, JetBrains
2. 2 Kotlin ▸ Cross-platform, statically typed, general-purpose programming language with type inference. Kotlin started as a language to target the JVM.
3. 3 World of modern Kotlin
4. 3 World of modern Kotlin Kotlin/JVM • • • Servers Android …
5. 3 World of modern Kotlin Kotlin/JVM • • • Servers Android … Kotlin/JS • • Browser (client-side JS) Server (NodeJS)
6. 3 World of modern Kotlin Kotlin/JVM • • • Kotlin/JS Servers Android … • • Kotlin/Native • • • • iOS MacOS/Linux/Windows WebAssembly … Browser (client-side JS) Server (NodeJS)
7. “ Programmers working with high-level languages achieve better productivity and quality than those working with lower-level languages. Good code is its own best documentation. ― Steve McConnell “Code Complete”
8. 5 Multiplatform concept
9. 6 Best practices of programming are easy on Kotlin Effective reusing code Abstractions Clear abstractions in right places Common part of project + Kotlin libraries + interoperability with other languages Managing complexity Separating on subsystems by main responsibility Central control points Iterative developing In common code Adding targets one by one + interoperability High-level and low-level programming Access to targets API straight way
10. 7 Interoperability Kotlin/JVM Kotlin/Native Kotlin/JS
11. 8 Kotlin/Native Compiler X86 ARM Frontend Common optimizations Native specific optimizations LLVM … Common part for all flavors MIPS Native runtime clang LLVM Backends
12. 9 How to make JVM and Native worlds become friends Kotlin platform libraries ▸ ▸ ▸ ▸ ▸ platfrom.posix platform.linux platform.windows platform.osx etc. Kotlin stdlib ▸ kotlin.collections ▸ kotlin.math ▸ etc. Kotlin MPP libraries ▸ kotlinx.serialization ▸ kotlinx.coroutines ▸ kotlinx-io
13. 10 How to make JVM and Native worlds become friends C world ▸ pointer ▸ struct ▸ lvalue ▸ rvalue ▸ macros ▸ etc. JVM world
14. 11 Kotlin/Native approach Equality of similar features ▸ C enum = Kotlin enum int ▸ C struct = Kotlin class ▸ C typedef = Kotlin typealias Extensions for strings ▸ kotlinString.cstr ▸ CPointer<ByteVar>.toK String() Abstractions for absent definitions ▸ ▸ ▸ ▸ ▸ ▸ CPointer<T> CVariable CValues CValuesRef StableRef staticCFunction
15. 12 Automatic memory management ▸ Kotlin/Native has GC reference-counter based algorithm in runtime ▸ It works with Objective C ARC ▸ Cycle collector based on the trial deletion
16. 13 Manual memory management ▸ ▸ ▸ ▸ fun <reified T : CVariable> alloc(): T usePinned nativeHeap (needs free!) memScoped val fileSize = memScoped { val statBuf = alloc<stat>() val error = stat("/", statBuf.ptr) statBuf.st_size }
17. 14 Objective C/Swift Interoperability Kotlin Swift Objective-C class class @interface Extension Extension Category member companion member <- Class method or property Class method or property MutableList NSMutableArray NSMutableArray ... ... ... Function type Function type Block pointer type https://github.com/JetBrains/kotlin-native/blob/master/OBJC_INTEROP.md
18. 15 Usage of cinterop def file for C interop def file for Objective C interop headers = curl/curl.h headerFilter = curl/* linkerOpts.osx = -L/opt/local/lib -L/usr/local/opt/curl/lib -lcurl linkerOpts.linux = -L/usr/lib64 -L/usr/lib/x86_64-linux-gnu -lcurl linkerOpts.mingw = -lcurl package = org.jetbrains.complexNumbers language = Objective-C --/* C code */
19. 16 Multiplatform projects. Expect/actual expect class Logger { fun log(message: String) } import platform.Foundation.* import android.util.Log actual class Logger() { fun log(message: String) { NSLog(message) } } actual class Logger { fun log(message: String) { Log.i("Tag", message) } }
20. 17 Multiplatform project. Example. Common part. Common code Common code Target specific code Def files for Kotlin/Native interop
21. 18 Multiplatform project. Example. Common part. // Implemented common part. class FieldChange<T>(val field: String, val previous: T, val current: T) { ... } // Declaring target specific things. expect fun Double.format(decimalNumber: Int = 4): String expect fun writeToFile(fileName: String, text: String) expect fun readFile(fileName: String): String expect class ComplexNumber
22. 19 Multiplatform project. Example. JVM target. actual fun readFile(fileName: String): String { val inputStream = File(fileName).inputStream() val inputString = inputStream.bufferedReader().use { it.readText() } return inputString } actual fun Double.format(decimalNumber: Int): String = "%.${decimalNumber}f".format(this) actual fun writeToFile(fileName: String, text: String) { File(fileName).printWriter().use { out -> out.println(text) } } actual class ComplexNumber { ...}
23. 20 Multiplatform project. Example. Native target. actual typealias ComplexNumber = Complex // Complex - struct from C library actual fun readFile(fileName: String): String {...} actual fun Double.format(decimalNumber: Int): String { ... } actual fun writeToFile(fileName: String, text: String) { val file = fopen(fileName, "wt") ?: error("Cannot write file '$fileName'") try { if (fputs(text, file) == EOF) throw Error("File write error") } finally { fclose(file) } }
24. 21 Multiplatform project. Example. JS target. actual typealias ComplexNumber = math.complex // from math.js actual fun readFile(fileName: String): String { error("Reading from local file for JS isn't supported") } actual fun Double.format(decimalNumber: Int): String = this.asDynamic().toFixed(decimalNumber) actual fun writeToFile(fileName: String, text: String) { if (fileName != "html") error("Writing to local file for JS isn't supported") val bodyPart = text.substringAfter("<body>").substringBefore("</body>") document.body?.innerHTML = bodyPart }
25. 22 Multiplatform project. Example. JS specific. // API for interop with JS library Chartist. external object Chartist { class Svg(form: String, parameters: dynamic, chartArea: String) val plugins: ChartistPlugins val Interpolation: dynamic fun Line(query: String, data: dynamic, options: dynamic): dynamic } val chart = Chartist.Line("#chart", getChartData(labels, time.values), getChartOptions(samples.keys.toTypedArray(), "Time"))
26. 23 Multiplatform project. Example. JS specific. js("$('#inputGroupBuild')").change({ val newValue = js("$(this).val()") if (newValue != parameters["type"]) { window.location.href = "http://some-link.com" } })
27. 24 Multiplatform project. Example. Build script. apply plugin: 'kotlin-multiplatform' kotlin { sourceSets { commonMain { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-common" } kotlin.srcDir 'src/main/kotlin' } nativeMain { dependsOn commonMain kotlin.srcDir 'src/main/kotlin-native' }
28. 25 Multiplatform project. Example. Build script. ... jvmMain { dependencies {implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" } kotlin.srcDir 'src/main/kotlin-jvm' } jsMain { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-js" } kotlin.srcDir 'src/main/kotlin-js' } linuxMain { dependsOn nativeMain } windowsMain { dependsOn nativeMain } macosMain {dependsOn nativeMain } }
29. 26 Multiplatform project. Example. Build script. jvm() { compilations.all { tasks[compileKotlinTaskName].kotlinOptions.suppressWarnings = true } } targetFromPreset(presets.mingwX64, 'windows') { compilations.main.cinterops { libcurl { includeDirs.headerFilterOnly "${getMingwPath()}/include" } } }
30. 27 Multiplatform project. Example. Build script. targetFromPreset(presets.linuxX64, 'linux') { compilations.main.cinterops { libcurl { includeDirs.headerFilterOnly '/usr/include', '/usr/include/x86_64-linux-gnu' } } } targetFromPreset(presets.macosX64, 'macos') { ... } js()
31. 28 Multiplatform project. Example. Build script. configure([windows, linux, macos]) { binaries.all { linkTask.enabled = isCurrentHost } binaries { executable('myExecutable', [RELEASE]) } } }te decks and from Chrome with Google Slides deck
32. 29 Current status ▸ Kotlin/Native is in beta phase. ▸ MPP plugin is changing. It should become better! ▸ You can influence technology development providing use cases where it can work better.
33. 30 THANKS! Any questions? https://kotlinlang.slack.com/ https://github.com/JetBrains/kotlin-native