as a Kotlin beginner, I am not sure what I can use when I want to create a JVM independent library.
I try to use only the “Common part” of the documentation, as for my purposes this seems feasable avoiding implementing platform-dependent expect/actual code myself.
But its hard to find out if I am doing this correctly.
For example, I need Regex.
There seems to be a JVM Regex implementation, and there is also kotlin.text.Regex.
And Regex is described in the Kotlin documentation.
So what does this mean?
Has Kotlin now an independent implementation of Regex? Or is it always using the JVM, and on other platforms there is no Regex? Or does it use the platform-specific implementations if available? But then that is not Java style?
What is the case here?
And how I can find out myself the next time I have such a question?
Just to clarify, when you say this, you mean create a library using purely Kotlin code, which can then be compiled down to the JVM, but also be compiled down to native machine code, or compiled for iOS, or JavaScript, or whatever?
I would say in that case, use Kotlin libraries, NOT whatever is in the Java standard library. Also do NOT use any Kotlin libraries that have jvm in the name. My rough understanding is that there are various Kotlin libraries that have a base version, and then specific platform versions, like JVM, or native, or whatever. For example, the kotlinx-coroutines-core has a -jvm version, and the various KTOR libraries also have -jvm versions. You would use these versions if you knew your app/library should only be compiled down to Java bytecode. But in your case, since you want a library that can be used anywhere, you would NOT use the -jvm specific versions of the libraries.
Just to clarify, when you say this, you mean create a library using purely Kotlin code, which can then be compiled down to the JVM, but also be compiled down to native machine code, or compiled for iOS, or JavaScript, or whatever?
Yes, this is exactly what I am aiming for.
Currently, I use Android Studio and I started my library project with:
since I did not plan to use anything platform specific, only Common Kotlin code.
There are some Java references in gradlew.bat (which I do not use) and some more that are seemingly required only for running the tests. But I am not completely sure.
Maybe it would be better to restructure my project based on:
Since all the files and dependencies that might be needed are present and hopefully there are no unwanted and hidden dependencies exist.
I am just not sure whether this is necessary, or at least useful, for a lib that will not contain any platform-specific code. Do you have some advice for me regarding this?
As of the Regex part, it seems to me that it is available on any platform, but I am not sure yet. As I will need it only in one place, and with a fairly simple pattern, I have been even thinking of parsing that pattern “manually”, wholly avoiding the platform calls. Or is this unnecessary?
The simplest thing you can do is make a multiplatform library and stay strictly within commonMain. All code in commonMain is guaranteed to be available for all the platforms you support.
See also youtrack.jetbrains.com/projects/KT/issues/KT-52666
@redflitzi , regular expressions (kotlin.text.Regex) are available on all supported platforms indeed. While their API remains the same across all platforms, supported syntax and features of regular expressions themselves differ. Each platform has its own underlying implementation, on JVM that’s a java.util.regex.Pattern-based one (meaning that Kotlin’s Regex is backed by the Java Pattern). On other platforms, the underlying implementation will be different.
If you’re writing code that aimed to run on multiple platform, you’re most likely interested in the “Common” section of the API reference. Documentation for specific platforms usually provide details specific to a particular platform. For example, kotlin.text.Regex documentation for JVM and JS targets provide information about regular expressions syntax supported there.
A concrete, immediate step to take to easily make sure your lib is multi-platform is to use it in a multi-platform build. The most obvious thing to do is to compile your unit tests with a non-JVM target. This will immediately tell you, for sure, whether all your dependencies are supported for that target.
It is possible, in principle at least, that a given dependency exists in some environments but not all (e.g. JVM and native but not JS). The only real defense against this would eventually be to compile and run your tests on all targets that you hope to support ; if this is a professional project you likely will have to do this anyway.
Strictly speaking, this does not show “platform independence”, it only shows support for all platforms you compile for. This will be good enough for almost all cases. If you want to show strict independence, you’d have to stick to commonMain as was explained before. It is probably possible to write tools that make sure you don’t use kotlin tools out of there, but it’s very likely overkill for almost any use case.
Another advantage would be that running these tests on these other platforms will also let you gain confidence that your API work as expected on said target. There are occasional bugs where an API behaves differently on different platforms (for example in the case of Regex, I found this issue a few years ago when targetting Kotlin/JS) ; it’s rare, but not unheard of. Running tests on all targets may help detecting issues that affect your lib.