Chapter 1. Installing and Running Kotlin
The recipes in this chapter help you get up and running with the Kotlin compiler, both from the command line and using an integrated development environment (IDE).
1.1 Running Kotlin Without a Local Compiler
Solution
Use the Kotlin Playground, an online sandbox for exploring Kotlin.
Discussion
The Kotlin Playground provides an easy way to experiment with Kotlin, explore features you havenât used, or simply run Kotlin on systems that donât have an installed compiler. It gives you access to the latest version of the compiler, along with a web-based editor that allows you to add code without installing Kotlin locally.
Figure 1-1 is a snapshot of the browser page.
Just type in your own code and click the Play button to execute it. The Settings button (the gear icon) allows you to change Kotlin versions, decide which platform to run on (JVM, JS, Canvas, or JUnit), or add program arguments.
The Examples section contains an extensive set of sample programs, organized by topic, that can be executed using an embedded block in a browser. Figure 1-2 shows the âHello worldâ program page.
The playground also has a dedicated section for Kotlin Koans, which are a series of exercises to help you become more familiar with the language. While these are useful online, if you use IntelliJ IDEA or Android Studio, the Koans can be added using the EduTools plug-in.
1.2 Installing Kotlin Locally
Problem
You want to execute Kotlin from a command prompt on your local machine.
Solution
Perform a manual install from GitHub or use one of the available package managers for your operating system.
Discussion
The page at http://kotlinlang.org/docs/tutorials/command-line.html discusses the options for installing a command-line compiler. One option is to download a ZIP file containing an installer for your operating system. This page contains a link to the GitHub repository for Kotlin current releases. ZIP files are available for Linux, macOS, Windows, and the source distribution. Simply unzip the distribution and add its bin subdirectory to your path.
A manual install certainly works, but some developers prefer to use package managers. A package manager automates the installation process, and some of them allow you to maintain multiple versions of a particular compiler.
SDKMAN!, Scoop, and other package managers
One of the most popular installation programs is SDKMAN!. Originally designed for Unix-based shells, there are plans to make it available for other platforms as well.
Installing Kotlin with SDKMAN! begins with a curl
install:
> curl -s https://get.sdkman.io |
bash
Then, once itâs installed, you can use the sdk
command to install any one of a variety of products, including Kotlin:
> sdk install kotlin
By default, the latest version will be installed in the ~/.sdkman/candidates/kotlin directory, along with a link called current
that points to the selected version.
You can find out what versions are available by using the list
command:
> sdk list kotlin
The install
command by default selects the latest version, but the use
command will let you select any version, offering to install it if necessary:
> sdk use kotlin 1.3.50
That will install version 1.3.50 of Kotlin, if necessary, and use it in the current shell.
Note
IntelliJ IDEA or Android Studio can use the downloaded versions, or they can maintain their own versions separately.
Other package managers that support Kotlin include Homebrew, MacPorts, and Snapcraft.
On Windows, you can use Scoop. Scoop does for Windows what the other package managers do for non-Windows systems. Scoop requires PowerShell 5 or later and .NET Framework 4.5 or later. Simple installation instructions are found on the Scoop website.
Once Scoop is installed, the main bucket allows you to install the current version of Kotlin:
> scoop install kotlin
This will install the scripts kotlin.bat, kotlinc.bat, kotlin-js.bat, and kotlin-jvm.bat and add them all to your path.
That is sufficient, but if you want to try it, there is an experimental installer called kotlin-native
, which installs a native Windows compiler as well. This installs an LLVM backend for the Kotlin compiler, a runtime implementation, and a native code generation facility by using the LLVM toolchain.
Regardless of how you install Kotlin, you can verify that it works and is in your path by using the simple command kotlin -version
. A typical response to that command is shown here:
> kotlin -version Kotlin version 1.3.50-release-112 (JRE 13+33)
See Also
Recipe 1.3 discusses how to use Kotlin from the command line after it is installed.
1.3 Compiling and Running Kotlin from the Command Line
Solution
Use the kotlinc-jvm
and kotlin
commands, similar to Java.
Discussion
The Kotlin SDK for the JVM includes the Kotlin compiler command, kotlinc-jvm
, and the Kotlin execution command, kotlin
. They are used just like javac
and java
for Java files.
Note
The Kotlin installation includes a script called kotlinc-js for compiling to JavaScript. This book assumes you are planning to use the JVM version. The basic script kotlinc is an alias for kotlinc-jvm.
For example, consider a trivial âHello, Kotlin!â program, stored in a file called hello.kt, with the code shown in Example 1-1.
Example 1-1. hello.kt
fun
main
()
{
println
(
"Hello, Kotlin!"
)
}
The command kotlinc
compiles this file, and the command kotlin
is used to execute the resulting class file, as in Example 1-2.
Example 1-2. Compiling and executing a regular Kotlin file
>
kotlinc-jvm
hello.kt
>
ls
hello.kt
HelloKt.class
>
kotlin
HelloKt
Hello,
Kotlin!
The compiler produces the HelloKt.class file, which contains bytecodes that can be executed on the Java Virtual Machine. Kotlin does not generate Java source codeâitâs not a transpiler. It generates bytecodes that can be interpreted by the JVM.
The compiled class takes the name of the file, capitalizes the first letter, and appends Kt on the end. This can be controlled with annotations.
If you wish to produce a self-contained JAR file that can be executed by the Java command, add the -include-runtime
argument. That allows you to produce an executable JAR that can be run from the java
command, as in Example 1-3.
Example 1-3. Including the Kotlin runtime
> kotlinc-jvm hello.kt -include-runtime -d hello.jar
The resulting output file is called hello.jar, which can be executed using the java
command:
> java -jar hello.jar Hello, Kotlin!
Leaving out the -include-runtime
flag would produce a JAR file that needs the Kotlin runtime on the classpath in order to execute.
Warning
The kotlinc
command without any arguments starts the interactive Kotlin REPL, which is discussed in Example 1-4.
See Also
Example 1-4 shows how to use the Kotlin read-eval-print loop (REPL) for interactive coding. Recipe 1.5 discusses executing Kotlin scripts from the command line.
1.4 Using the Kotlin REPL
Discussion
Kotlin includes an interactive compiler session manager, known as a REPL (read-eval-print loop) that is triggered by the kotlinc
command with no arguments. Once inside the REPL, you can evaluate arbitrary Kotlin commands and see the results immediately.
Tip
The Kotlin REPL is also available inside Android Studio and IntelliJ IDEA as the Kotlin REPL entry under the Tools â Kotlin menu.
After running the kotlinc
command, you will receive an interactive prompt. An example session is shown in Example 1-4.
Example 1-4. Using the Kotlin REPL
ⶠkotlinc Welcome to Kotlin version 1.3.50(
JRE 11.0.4+11)
Type :helpfor
help
, :quitfor
quit >>> println(
"Hello, World!"
)
Hello, World! >>> varname
=
"Dolly"
>>> println(
"Hello,
$name
!"
)
Hello, Dolly! >>> :help Available commands: :help show thishelp
:quitexit
the interpreter :dump bytecode dump classes to terminal :load <file> load script from specified file >>> :quit
The REPL is a quick and easy way to evaluate Kotlin expressions without starting up a full IDE. Use it if you donât want to create an entire project or other IDE-based collection of files, or if you want to do a quick demo in order to help another developer, or if you donât have your preferred IDE available.
1.5 Executing a Kotlin Script
Solution
Enter your code in a file ending in .kts. Then use the kotlinc
command with the -script
option to execute it.
Discussion
The kotlinc
command supports several command-line options, one of which allows Kotlin to be used as a scripting language. A script is defined as a Kotlin source file with the file extension .kts that includes executable code.
As a simple example, the file southpole.kts in Example 1-5 shows the current time at the South Pole and prints whether it is currently on daylight saving time. The script uses the java.time package added to Java in version 8.
Example 1-5. southpole.kts
import
java.time.*
val
instant
=
Instant
.
now
()
val
southPole
=
instant
.
atZone
(
ZoneId
.
of
(
"Antarctica/South_Pole"
))
val
dst
=
southPole
.
zone
.
rules
.
isDaylightSavings
(
instant
)
println
(
"It is ${southPole.toLocalTime()} (UTC${southPole.offset})
at the South Pole"
)
println
(
"The South Pole ${if (dst) "
is
" else "
is
not
"} on Daylight Savings Time"
)
Execute this file with the kotlinc
command using the -script
option:
> kotlinc -script southpole.kts It is 10:42:56.056729 (UTC+13:00) at the South Pole The South Pole is on Daylight Savings Time
Scripts contain the code that would normally appear inside the standard main
method in a class. Kotlin can be used as a scripting language on the JVM.
1.6 Building a Standalone Application Using GraalVM
Solution
Use the GraalVM compiler and native-image
tool.
Discussion
GraalVM is a high-performance virtual machine that provides a cross-language runtime for running applications written in a variety of languages. You can write in a JVM-based language like Java or Kotlin, and integrate with JavaScript, Ruby, Python, R, and more.
One nice feature of GraalVM is that you can use it to create a native executable from your code. This recipe shows a simple example of how to use GraalVMâs native-image
tool to create a native binary from Kotlin source code.
You can install GraalVM from the downloads page. For the current recipe, the free Community Edition was installed using the SDKMAN! tool:
> sdk install java 19.2.0.1-grl > java -version openjdk version"1.8.0_222"
OpenJDK Runtime Environment(
build 1.8.0_222-20190711112007.graal.jdk8u-src... OpenJDK 64-Bit GraalVM CE 19.2.0.1(
build 25.222-b08-jvmci-19.2-b02, mixed mode)
> gu install native-image // installs native image component
Consider the Kotlin version of âHello, World!â from Figure 1-1, reproduced here:
fun
main
()
{
println
(
"Hello, World!"
)
}
As stated in Recipe 1.3, you can just compile this script by using kotlinc-jvm
, which generates HelloKt.class, and then run with kotlin
:
> kotlinc-jvm hello.kt // generates HelloKt.class > kotlin HelloKt Hello, World!
To generate a native image instead, first compile the script with the -include-runtime
option. That generates a file called hello.jar:
> kotlinc-jvm hello.kt -include-runtime -d hello.jar
The GraalVM system includes the native-image
tool, which you can use to generate the native executable, as in Example 1-6.
Example 1-6. Building a native executable using GraalVM
> native-image -jar hello.jar
Note
From the docs: âFor compilation, native-image depends on the local toolchain, so please make sure glibc-devel, zlib-devel (header files for the C library and zlib) and gcc are available on your system.â
The output will resemble the following:
> native-image -jar hello.jar Build on Server(pid: 61247, port: 49590)* [hello:61247] classlist: 1,497.63 ms [hello:61247] (cap): 2,225.47 ms [hello:61247] setup: 3,451.98 ms [hello:61247] (typeflow): 2,163.16 ms [hello:61247] (objects): 1,793.53 ms [hello:61247] (features): 215.90 ms [hello:61247] analysis: 4,247.68 ms [hello:61247] (clinit): 107.96 ms [hello:61247] universe: 399.58 ms [hello:61247] (parse): 329.84 ms [hello:61247] (inline): 753.12 ms [hello:61247] (compile): 3,426.14 ms [hello:61247] compile: 4,807.54 ms [hello:61247] image: 306.96 ms [hello:61247] write: 180.22 ms [hello:61247] [total]: 15,246.88 ms
The result will be a file called hello that you can invoke at the command line. On a Mac or other Unix-based system, youâll see the following:
> ./hello Hello, World!
There are now three ways to run the original script:
-
Compile with
kotlinc-jvm
and then execute withkotlin
. -
Compile including the runtime and then execute the resulting JAR with
java
. -
Compile with
kotlinc
, create a native image with GraalVM, and then execute from the command line.
The sizes of the resulting files are quite different. The compiled bytecode file HelloKt.class is only about 700 bytes. The hello.jar file with its included runtime is about 1.2 MB. The native image is still larger, at about 2.1 MB. The speed differences are dramatic however, even on a tiny script like this. Example 1-7 shows a simple comparison.
Example 1-7. Timing the hello script
> time kotlin HelloKt Hello, World! kotlin HelloKt 0.13s user 0.05s system 112% cpu 0.157 total ~/Documents/kotlin > time java -jar hello.jar Hello, World! java -jar hello.jar 0.08s user 0.02s system 99% cpu 0.106 total ~/Documents/kotlin > time ./hello Hello, World! ./hello 0.00s user 0.00s system 59% cpu 0.008 total
The relative values are telling. While the JAR file is somewhat quicker than running kotlin
directly, the native image is literally an order of magnitude faster. In this example, it takes only about 8 milliseconds to run.
Tip
If you are a Gradle user, you can use a GraalVM plug-in called gradle-graal
. It adds a native-image
task (among others) to your build. See the home page for the plug-in for details.
1.7 Adding the Kotlin Plug-in for Gradle (Groovy Syntax)
Solution
Add the Kotlin dependency and plug-in by using the Groovy DSL tags in a build file.
Discussion
Note
This recipe uses the Groovy DSL for Gradle. The next recipe shows how to use the Kotlin DSL for Gradle instead.
The Gradle build tool supports compiling Kotlin on the JVM by using a plug-in supplied by JetBrains. The kotlin-gradle-plugin, adding to Gradle build script
has been registered at the Gradle plug-ins repository, and can be added to a Gradle build script as in Example 1-8. The code shown is added to a file called build.gradle in the project root.
Example 1-8. Adding the Kotlin plug-in by using the plugins
block (Groovy DSL)
plugins
{
id
"org.jetbrains.kotlin.jvm"
version
"1.3.50"
}
The version
value represents both the plug-in version and the Kotlin version. Gradle still supports the older syntax for adding plug-ins, as shown in Example 1-9.
Example 1-9. Older syntax for the Kotlin plug-in (Groovy DSL)
buildscript
{
repositories
{
mavenCentral
()
}
dependencies
{
classpath
'org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.50'
}
}
plugins
{
id
"org.jetbrains.kotlin.jvm"
version
"1.3.50"
}
Both of these snippets use the Groovy DSL syntax for Gradle build files, which supports both single- and double-quoted strings. As with Kotlin, Groovy uses double-quoted strings when doing interpolation, but since none is required here, single-quoted strings also work.
The plugins
block does not require you to state where the plug-in is found, as in the repositories
block in the latter example. This is true for any Gradle plug-in registered at the Gradle plug-ins repository. Using the plugins
block also automatically âappliesâ the plug-in, so no apply
statement is required either.
The settings.gradle file is recommended but not required. It is processed during the initialization phase of Gradle processing, which occurs when Gradle determines which project build files need to be analyzed. In a multiproject build, the settings file shows which subdirectories of the root are themselves Gradle projects as well. Gradle can share settings and dependencies among subprojects, can make one subproject depend on another, or can even process subproject builds in parallel. For details, see the multiproject build sections of the Gradle User Manual.
Kotlin sources can be mixed with Java sources in the same folder, or you can create separate src/main/java and src/main/kotlin folders for them individually.
Android projects
The Kotlin plug-in for Android is handled slightly differently. Android projects are multiproject builds in Gradle, meaning they normally have two build.gradle files: one in the root directory, and one in a subdirectory called app by default. Example 1-10 shows a typical top-level build.gradle file containing only the Kotlin plug-in information.
Example 1-10. Using Kotlin in Android projects (Groovy DSL)
buildscript
{
ext
.
kotlin_version
=
'1.3.50'
repositories
{
()
jcenter
()
}
dependencies
{
classpath
'com.android.tools.build:gradle:3.5.0'
classpath
"org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
// ... more tasks, unrelated to the plug-in ...
In Gradle parlance, the plug-in is then applied, as in the typical app directory build.gradle file shown in Example 1-11.
Example 1-11. Applying the Kotlin plug-in
apply
plugin:
'com.android.application'
apply
plugin:
'kotlin-android'
apply
plugin:
'kotlin-android-extensions'
android
{
// ... android information ...
}
dependencies
{
implementation
"org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
// ... other unrelated dependencies ...
}
The Kotlin plug-in for Android is declared in the buildscript
section and then applied in this file. The plug-in knows how to compile Kotlin code inside your Android application. The downloaded plug-in also includes the Android extensions, which makes it easy to access Android widgets by their ID values.
The Kotlin plug-in can generate bytecodes for either JDK 7 or JDK 8. Change the jdk
value in the listed dependency to select whichever you prefer.
Note
At the time of this writing, there is no option to select the Kotlin DSL when creating Android projects. You can create your own build files that use the Kotlin DSL, but that is unusual. The Kotlin DSL will be available in version 4.0 of Android Studio, which will also include full support for KTS files and Kotlin live templates.
See Also
The same process using the Kotlin DSL is shown in Recipe 1.8, other than for the Android section.
1.8 Adding the Kotlin Plug-in for Gradle (Kotlin Syntax)
Solution
Add the Kotlin dependency and plug-in, using the Kotlin DSL tags in a build file.
Discussion
Note
This recipe uses the Kotlin DSL for Gradle. The previous recipe shows how to use the Groovy DSL for Gradle instead.
Gradle (version 5.0 and above) includes the new Kotlin DSL for configuring the build file. It also makes available kotlin-gradle-plugin
, registered at the Gradle plug-in repository, which can be added to a Gradle build script shown in Example 1-12. Alternatively, you can use the older buildscript
syntax in Example 1-13. The code shown is added to a file called build.gradle.kts in the project root.
Example 1-12. Adding the Kotlin plug-in by using the plugins
block (Kotlin DSL)
plugins
{
kotlin
(
"jvm"
)
version
"1.3.50"
}
Example 1-13. Older syntax for the Kotlin plug-in (Kotlin DSL)
buildscript
{
repositories
{
mavenCentral
()
}
dependencies
{
classpath
(
kotlin
(
"gradle-plugin"
,
version
=
"1.3.50"
))
}
}
plugins
{
kotlin
(
"jvm"
)
}
The plugins
block does not require you to state where the plug-in is found, as in the repositories
block in the latter example. This is true for any Gradle plug-in registered at the Gradle plug-ins tepository. Using the plugins
block also automatically âappliesâ the plug-in, so no apply
statement is required either.
Tip
The default build filenames for the Kotlin DSL in Gradle are settings.gradle.kts and build.gradle.kts.
As you can see, the biggest differences from the Groovy DSL syntax are as follows:
-
Double quotes are required on any strings.
-
The parentheses are required in the Kotlin DSL.
-
Kotlin uses an equals sign (
=
) to assign values, rather than a colon (:
).
The settings.gradle.kts file is recommended but not required. It is processed during the initialization phase of Gradle processing, which occurs when Gradle determines which project build files need to be analyzed. In a multiproject build, the settings file shows which subdirectories of the root are themselves Gradle projects as well. Gradle can share settings and dependencies among subprojects, can make one subproject depend on another, or can even process subproject builds in parallel. For details, see the multiproject build sections of the Gradle User Manual.
Kotlin and Java source code can be mixed together in src/main/java or src/main/kotlin, or you can add your own source files by using the sourceSets
property of Gradle. See the Gradle documentation for details.
See Also
The same process using the Groovy DSL in Gradle is shown in Recipe 1.7. Additional details for Android projects can be found in that recipe as well, as the Kotlin DSL is not currently an option when generating Android projects.
1.9 Using Gradle to Build Kotlin Projects
Discussion
The examples in Recipes 1.7 and 1.8 showed how to add the Kotlin plug-in for Gradle. This recipe adds features to the build file to process any Kotlin code in your project.
To compile the Kotlin code in Gradle, you need to add an entry to the dependencies
block in your Gradle build file, as shown in Example 1-14.
Example 1-14. Kotlin DSL for simple Kotlin project (build.gradle.kts)
plugins { `java-library` kotlin("jvm") version "1.3.50" } repositories { jcenter() } dependencies { implementation(kotlin("stdlib")) }
The java-library
plug-in defines tasks for a basic JVM-based project, like build
, compileJava
, compileTestJava
, javadoc
, jar
, and more.
Note
The plugins
section must come first, but the other top-level blocks (repositories
, dependencies
, etc.) can be in any order.
The dependencies
block indicates that the Kotlin standard library is added at compile time (older versions of Gradle still use the compile
configuration instead of implementation
, but the effect is the same). The repositories
block indicates that the Kotlin dependency will be downloaded from jcenter
, which is the public Artifactory Bintray repository.
If you run the gradle build --dry-run
task at the command line, you can see the tasks that would be executed by Gradle without actually running them. The result is as follows:
> gradle build -m :compileKotlin SKIPPED :compileJava SKIPPED :processResources SKIPPED :classes SKIPPED :inspectClassesForKotlinIC SKIPPED :jar SKIPPED :assemble SKIPPED :compileTestKotlin SKIPPED :compileTestJava SKIPPED :processTestResources SKIPPED :testClasses SKIPPED :test SKIPPED :check SKIPPED :build SKIPPED BUILD SUCCESSFUL in 0s
The Kotlin plug-in adds the compileKotlin
, inspectClassesForKotlinIC
, and compileTestKotlin
tasks.
The project can be built by using the same command without the -m
flag, which is the abbreviation for --dry-run
.
1.10 Using Maven with Kotlin
Discussion
The basic details for using Maven can be found on the documentation web page.
This documentation recommends that first you specify the Kotlin version you want to use as a property in a Maven pom.xml file that looks like this:
<properties>
<kotlin.version>
1.3.50</kotlin.version>
</properties>
Then, add the Kotlin standard library as a dependency, as in Example 1-15.
Example 1-15. Adding the Kotlin standard library dependency
<dependencies>
<dependency>
<groupId>
org.jetbrains.kotlin</groupId>
<artifactId>
kotlin-stdlib</artifactId>
<version>
${kotlin.version}</version>
</dependency>
</dependencies>
Note
As with Gradle, you can specify kotlin-stdlib-jdk7
or kotlin-stdlib-jdk8
to use extension functions for Java 1.7 or 1.8.
Additional available artifact IDs include kotlin-reflect
for reflection, and kotlin-test
and kotlin-test-junit
for testing.
To compile Kotlin source code, tell Maven in which directories it is located, as in Example 1-16.
Example 1-16. Specifying Kotlin source directories
<build>
<sourceDirectory>
${project.basedir}/src/main/kotlin</sourceDirectory>
<testSourceDirectory>
${project.basedir}/src/test/kotlin</testSourceDirectory>
</build>
Then tell the Kotlin plug-in to compile the sources and tests (Example 1-17).
Example 1-17. Referencing the Kotlin plug-in
<build>
<plugins>
<plugin>
<artifactId>
kotlin-maven-plugin</artifactId>
<groupId>
org.jetbrains.kotlin</groupId>
<version>
${kotlin.version}</version>
<executions>
<execution>
<id>
compile</id>
<goals><goal>
compile</goal></goals>
</execution>
<execution>
<id>
test-compile</id>
<goals><goal>
test-compile</goal></goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
When your project contains both Kotlin code and Java code, the Kotlin compiler should be invoked first. That means kotlin-maven-plugin
should be run before maven-compiler-plugin
. The documentation page provided previously shows how to ensure that via configuration options in your pom.xml file.
Get Kotlin Cookbook now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.