how to add dependency to Kotlin compiler without using Gradle? - kotlin

I want to add kotlinx.coroutines to the command line compiler of the Kotlin so that i can import it without using gradle. For example I have a file Main.kt and no gradle tool for Kotlin. just look at mywindow. I tried search on YouTube, StackOverflow, reddit, Google and Github but it didn't solved my problem please help me out.

You will need to use the Kotlin compiler directly:
https://kotlinlang.org/docs/command-line.html
In addition, to use kotlinx.coroutines, you will need to have these JARs locally and add them to the classpath to the Kotlin compiler:
https://kotlinlang.org/docs/compiler-reference.html#classpath-path-cp-path

Related

How to import a Kotlin Library in IntelliJ

So i want to use the Serialization Library in my kotlin project, and from what i can gather from this page, i must use this: "org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2", to do so, now i use "IntelliJ" as my build system, so i went to the project structure, and in libraries, clicked the + sign, clicked on "From Maven" and put this as the link to the library, and it downloaded it and i set it as a dependency of my project, it even shows as a external library, like this:
But when i try to import the lib, it gives error:
Apparently you can indeed use IntelliJ IDEA as a build system without maven or gradle, but I don't think this is a supported way to use kotlinx-serialization.
I'd advise to pick either maven or gradle as your build system for your project (this can be done through IntelliJ, just create a new project and pick either one).
Then you can just follow the relevant paragraph at https://github.com/Kotlin/kotlinx.serialization#setup for either maven or gradle.

How do I apply a plugin in a .kts (Kotlin script) file?

Kotlin script (.main.kts) files have the idea of providing executable Kotlin code in ONE single standalone file, which is immensely convenient for scripting or when sharing code snippets on StackOverflow for example. In contrast to that, currently almost all Java/Kotlin uses a build system (e.g. gradle) with cryptic build files and a deep folder structure.
While I like the Kotlin script idea a lot, it seems to be barely used, with only 22 questions on StackOverflow and extremely sparse documentation and precious few Google results. I am able to pull in dependencies using #file:DependsOn inside of the actual script rather than the traditional build file:
build.gradle:
dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.0'
}
foo.main.kts:
#file:DependsOn("org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.0")
However, I can't find a way to use "apply plugin" in my .main.kts file. It's not used in any of the code snippets I found online.
build.gradle:
apply plugin: 'kotlinx-serialization'
foo.main.kts:
???
For reference, I attached an MWE below. The error message says the class Node is not serializable, but as pointed out in this question that message is misleading and the actual issue that apply plugin is missing, which I do not know how to use outside of a build.gradle file:
#file:DependsOn("org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.0")
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
#Serializable
data class Node (val numbers: List<Int>)
val h = Json.decodeFromString<Node>(""" {"numbers": [1, 2, 3]} """)
Run it on Ubuntu:
snap install kotlin
kotlin foo.main.kts
kotlinx-serialization is a Gradle plugin, which adds to pipeline same-named compiler plugin - it generates the serializer() method for classes annotated with #Serializable.
When you compile Kotlin code with kotlinc compiler, you can attach the plugin by providing the path to its JAR file (it's bundled with the compiler) using the -Xplugin=/snap/kotlin/current/lib/kotlinx-serialization-compiler-plugin.jar compiler option.
For .kts files, there is a #file:CompilerOptions annotation, but currently (in Kotlin 1.5.10) this particular key is not supported (warning: the following compiler arguments are ignored on script compilation: -Xplugin)
Command line
On the command line you may use
kotlinc -script -Xplugin="/snap/kotlin/current/lib/kotlinx-serialization-compiler-plugin.jar" foo.main.kts
Script header
As a workaround you may use this shebang:
#!/usr/bin/env -S kotlinc -script -Xplugin="/snap/kotlin/current/lib/kotlinx-serialization-compiler-plugin.jar"
To run your script you need to turn it into an executable:
chmod u+x foo.main.kts
Now it could be run with:
./foo.main.kts

how to compile kotlinx.serialization libraries on the command line?

This is very close to what I'm trying to accomplish. How to compile and run kotlin program in command line with external java library
I really want to learn how to compile and run simple code that includes libraries but am getting a bit lost when it comes to including classpaths.
I’m currently trying to compile and run
import kotlinx.serialization.*
import kotlinx.serialization.json.*
#Serializable
data class Project(val name: String, val language: String)
fun main() {
// Serializing objects
val data = Project("kotlinx.serialization", "Kotlin")
val string = Json.encodeToString(data)
println(string) // {"name":"kotlinx.serialization","language":"Kotlin"}
// Deserializing back into objects
val obj = Json.decodeFromString<Project>(string)
println(obj) // Project(name=kotlinx.serialization, language=Kotlin)
}
using
kotlinc -cp "C:\PROGRA~1\Kotlin\lib\kotlinx-serialization-runtime-1.0-M1-1.4.0-rc.jar" main.kt
to compile with this compiler
https://blog.jetbrains.com/kotlin/2020/07/kotlin-1-4-rc-released/
allowed lib at bottom of the article
that's where kotlinx-serialization-runtime-1.0-M1-1.4.0-rc.jar is coming from. I chose this runtime jar because when I use the new kotlin 4.0.21 compiler it requires the kotlin-serialization-runtime-1.0.1.jar which you need to build yourself but when I download the source and run gradle build it doesn't seem to get generated (separate problem but would love to know how to build the runtime jar myself)
when I try and run I get
Exception in thread "main" java.lang.NoClassDefFoundError: kotlinx/serialization/json/Json
at MainKt.main(main.kt:12)
at MainKt.main(main.kt)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at org.jetbrains.kotlin.runner.AbstractRunner.run(runners.kt:64)
at org.jetbrains.kotlin.runner.Main.run(Main.kt:149)
at org.jetbrains.kotlin.runner.Main.main(Main.kt:159)
Caused by: java.lang.ClassNotFoundException: kotlinx.serialization.json.Json
at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:435)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:589)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
... 9 more
I know I need to include a classpath when I run
kotlin MainKt
but have tried everything with no success
I've tried many different combinations of things including
compiling with and without
-Xplugin="C:\PROGRA~1\Kotlin\lib\kotlinx-serialization-compiler-plugin.jar doesn't seem to make a difference so I left it off.
I have tried compiling to both a java .jar as well as a kotlin .class file both seem to need classpath information at runtime. I would rather compile to a kotlin .class and keep java out of this until I really need it. This way I can learn what java is really doing in my application.
I guess what I really want to know is how one can determine what is required at runtime for an executable to run. I found this site which helps show dependencies but is for older versions of kotlin https://kotlin.binarydoc.org/org.jetbrains.kotlin/kotlin-compiler-dist/1.3.71/package?package=kotlinx.serialization
I’ve also been peaking into the .class files using https://github.com/google/android-classyshark
and
https://github.com/borisf/classyshark-bytecode-viewer
but still when people tell others, on StackOverflow, what classpath they need to use to solve their problem it seems like magic. Can someone out there teach me how to fish without gradle?
p.s. If anyone has any good resources on learning the internals of how gradle is building the project. I've looked here a bit https://docs.gradle.org/current/userguide/userguide.pdf but didn’t seem to help. maybe I missed something. Also, this page https://kotlinlang.org/docs/reference/serialization.html#example-json-serialization seems to have what I need but can't seem to transfer that to what the command line needs.
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.1")
}
what does this mean? I think this is referring to this https://github.com/Kotlin/kotlinx.serialization
but then how can I build what I need from this repo and use it to allow my application to know where its runtime dependencies are? ugh. I really wanted to figure all this out myself, but I must kneel to the internet gods for this one. Sorry, my post is a mess. I love to learn.
It took some time but I was able to build and run the serialization sample found at https://github.com/Kotlin/kotlinx.serialization on the command line using the current kotlinc compiler and the kotlinx.serializtion.1.0.1 library.
Here are the direct links to the compilers and libs
kotlinc and kotlinc-native v1.4.20
https://github.com/JetBrains/kotlin/releases/tag/v1.4.20
Kotlinx.serialization v1.0.1
https://github.com/Kotlin/kotlinx.serialization/releases/tag/v1.0.1
These both can also be found in the 1.4.20 releases blog post under the section titled How To Update:
https://blog.jetbrains.com/kotlin/2020/11/kotlin-1-4-20-released/
Setting Up Katlin’s .jar Libraries
After updating my path to point to the new compilers I still needed to build the serialization libs. This was as simple as running gradle build in the root directory of the unzipped kotlinx-serialization-1.0.1 folder. Make sure to set your JAVA-HOME system variable before you do this or it won’t work.
Once it's built you need to grab both the kotlinx-serialization-json-jvm-SNAPSHOT-1.0.1.jar and the kotlinx-serialization-core-jvm-SNAPSHOT-1.0.1.jar files and move them into the project directory. This definitely confused me because I had found a runtime lib for kotlinx serialization on the MVN repository site that was one jar file, but I wasn't seeing it after building the 1.0.1 libraries. Once I extracted the 1.0.1 runtime jar I found online, by renaming the .jar to .zip, it became apparent that it consisted of both the contents of the core and json jars. Don’t use the kotlinx-serialization-1.0.1-SNAPSHOT.jar. This jar only contains a blank MANIFEST.ms file. You can find the kotlinx-serialization-core-jvm-1.0.1-SNAPSHOT.jar in the kotlinx.serialization-1.0.1\core\build\libs folder and the kotlinx-serialization-json-jvm-1.0.1-SNAPSHOT.jar in the kotlinx.serialization-1.0.1\formats\json\build\libs folder. anyways.
Compiling Your .jar Library
once you have the jars in your project folder you can build your project
I included my cleanbuildandrun.sh shell script down below for easy reference.
My first attempt 1) was to try and build the project without compiling it to a .jar library file. This was a complete failure. I got it to compile but running the project proved much harder. I was unable to tell kotlin where the libraries were at runtime. I tried so many different things Including trying to point it to a manifest file I created but nothing seemed to work. It seems you need to build an executable jar in order to make this work. which brings me to my second try 2). This is where I found more success.
Attempt 2)
First you need to include the kotlinx-serialization-compiler-plugin.jar using the "-Xplugin" compiler flag. My understanding is that plugins are used to define annotations to the compiler like #Serializable. You can find this jar file in the lib folder inside the compiler you just downloaded. I copied this into my projects /lib folder next to the other jar files to make things self-contained and portable.
Next you need to tell the compiler where to find the library classes you want to access using the "-classpath" or "-cp" compiler flag.
Make sure to include kotlin runtime libraries using the "-include-runtime" compiler flag. This will bundle the kotlin standard class libraries within your jar so you don’t need to point at them during runtime.
Last direct the compiler to build a jar file by providing the -d compiler flag with the name and extension of your soon to be .jar file. That’s it, your off compiling.
Example Shell Script:
#!/bin/bash
sh clean.sh
case $1 in
1) # Comming Soon
kotlinc -verbose -Xplugin="lib\kotlinx-serialization-compiler-plugin.jar" \
-cp "lib\kotlinx-serialization-json-jvm-1.0.1.jar;lib\kotlinx-serialization-core-jvm-1.0.1.jar" \
main.kt
;;
2) # Working
kotlinc main.kt -Xplugin="lib\kotlinx-serialization-compiler-plugin.jar" \
-cp "lib\kotlinx-serialization-json-jvm-1.0.1.jar;lib\kotlinx-serialization-core-jvm-1.0.1.jar" \
-include-runtime -d main.jar
jar ufm Main.jar ManifestAdditions.txt lib
kotlin main.jar
;;
3) # Comming Soon
kotlinc-native main.kt -verbose -Xplugin="lib\kotlinx-serialization-compiler-plugin.jar" \
-cp "lib\kotlinx-serialization-json-jvm-1.0.1.jar;lib\kotlinx-serialization-core-jvm-1.0.1.jar" \
-manifest ManifestAddition.txt -o main
;;
esac
Running your .jar Library
By default, when you compiled the jar it created a MANIFEST.ms file that it uses to tell your jar library where the entry point is. which would be enough if we weren’t using additional libraries in our application. So next we need to add those libraries to the jar file we compiled while at the same time updating its MANIFEST.ms file to tell it where those libraries are within that jar file. We can use the cli tool jar to accomplish this. With the command:
jar ufm Main.jar ManifestAdditions.txt lib
we are able to update the current jar file.
u - tells jar we want to update an existing jar file
f - indicates that we are providing the jar file we want to update on the cmd line
m - indicates that we will be providing the manifest file
The Manifest .txt file should look like this:
Main-Class: MainKt
Class-Path: lib\kotlinx-serialization-core-jvm-1.0.1.jar lib\kotlinx-serialization-json-jvm-1.0.1.jar
Make sure to add a new line at the end of the file or it won’t parse the Class-Path.
That’s it. Now we have an executable jar file that we can use to run our serialization code on the command line:
kotlin main.jar
should output:
{"name":"kotlinx.serialization","language":"Kotlin"}
Project(name=kotlinx.serialization, language=Kotlin)
Post Mark
I would really like to turn this answer into a blog post that explains how to use the kotlin compiler, with libraries, on the command line. The information is out there but it seems to be scattered. I would like to include how to compile and run without using jar files, if that’s even possible, as well as how to compile and run using the native compiler. If anyone can help fill in these gaps it would be much appreciated. I think this information could help others learn how to set up simple test environments so they can better understand the functionality of these libs without having to set up a build script. This will be my first attempt at creating a tutorial type blog post so any information would really help.

(Kotlin) Any workaround for annotation processing in Intellij IDEA

I've created a gradle modules main that contains main program logic and codegen that contains annotation definitions with processors. I found that:
Please note that kapt is still not supported for IntelliJ IDEA’s own build system. Launch the build from the “Maven Projects” toolbar whenever you want to re-run the annotation processing.
on kapt page (https://kotlinlang.org/docs/reference/kapt.html) but I really need it. May be there is some (may be ugly) workaround for that? Terminal background worker or prebuild tasks or something else?
P.S.
This can appear as duplicate question but I really didn't found working solution at the moment
At the current project we have this problem as well; we use gradle and the work around is to run gradle classes testClasses from the commandline - either in an external terminal program or in IJ's terminal (alt-F12 on macOS). This triggers kapt as well, and when this is done I do a Build/Rebuild project from IJ's menu as well.
This is enough if the code that is processed by kapt does not change too often (we just use mapstruct and querydsl).
If you are using maven a mvn compile test-compile should work as well.
Finally I found that repository that does work in Intellij IDEA without any workarounds (https://github.com/miquelbeltran/kotlin-code-gen-sample). Taken from https://medium.com/#Miqubel/hello-world-of-annotation-processing-in-kotlin-3ec0290c1fdd

How to use square dagger-compiler for "compile-only" using gradle?

Currently I have my dagger dependencies declared like this:
compile 'com.squareup.dagger:dagger:1.2.1'
compile 'com.squareup.dagger:dagger-compiler:1.2.1'
I don't want dagger-compiler to be included to my Android apk since it also adds Guava dependency, which is big and break Android 65K limit for our app.
I saw that in maven projects dagger-compiler is added as "provided", but I failed to find anything similar for gradle android build.
There exists a provided keyword:
compile 'com.squareup.dagger:dagger:1.2.1'
provided 'com.squareup.dagger:dagger-compiler:1.2.1'
Heres a sample build.gradle: volley-examples
The provided scope is supported in Android-Gradle/Android Studio. You can get at it through the UI in Project Structure > Dependencies, or you can use the provided keyword instead of compile in your build files if you want to edit them by hand.