Kotlin/Library Package Maintainer Guide

This page contains useful information for any maintainers of the Kotlin library packages' ebuilds.

Eclasses
The following eclasses are provided to facilitate creation of ebuilds for Kotlin libraries:


 * 
 * The eclass designed for building general Kotlin library packages, with support for compiling additional Java sources, JAR generation, source archive creation, JUnit 4 tests, installing pre-built binary JAR, and checks based on and.


 * 
 * An eclass based on for building modules under the directory in the upstream project's source tree.  The directory consists of reflection.jvm, which is the major part of kotlin-reflect, and various other modules which are both required by reflection.jvm during build time and parts of kotlin-reflect.  The modules correspond to the   subprojects in the main Gradle project.  This is a specialized eclass which is not intended to be used by a general Kotlin library package's ebuild.

Kotlin compiler classes and wrappers
The standalone version of the Kotlin compiler packaged and distributed by the upstream contains the following components for the compiler proper:


 * , the main compiler module
 * Various compiler wrapper executables
 * Other libraries used by the compiler

A compiler wrapper may set the KOTLIN_COMPILER environment variable to the name of the compiler class to be used, and the environment variable will be read by , the main Kotlin compiler wrapper.

Here is a list of classes in that are used when Gradle builds the Kotlin libraries:


 * org.jetbrains.kotlin.cli.jvm.K2JVMCompiler: Takes Kotlin sources as input, and produces Java class files as output. This is the default compiler class if KOTLIN_COMPILER is unset, and it is also the compiler class used in building all the JVM libraries.
 * org.jetbrains.kotlin.cli.js.K2JSCompiler: Takes Kotlin sources as input, and produces JavaScript files as output. This is the compiler class for.
 * org.jetbrains.kotlin.cli.js.internal.JSStdlibLinker: Processes JavaScript sources. Only used in building kotlin-stdlib-js.
 * org.jetbrains.kotlin.serialization.builtins.RunKt: The built-in serializer, which takes Kotlin sources as input and produces files as output.  Only used in building.

Obtaining compiler arguments for a library package
The compiler options for a Kotlin library package can be obtained using the same method as for third-party Kotlin packages with some minor variations.

Prepare the project's source tree
The Kotlin programming language project's source tree can either be downloaded as a Zip archive or a tarball storing it or be cloned using. If Git is used, the following cloning options are recommended to minimize the download size by pulling objects for only one commit for a single tag ( in this example):

Before any command is run, a few extra steps are needed to fix some potential issues. Enter the project's source root and perform the following steps.

First, the project needs to be configured to skip probing JDK 6 and 7. Otherwise, the following error might be raised:

FAILURE: Build failed with an exception. * Where: Build file '/home/leo/Projects/forks/kotlin/libraries/stdlib/jvm/build.gradle' line: 88 * What went wrong: A problem occurred evaluating project ':kotlin-stdlib'. > Could not resolve all dependencies for configuration ':kotlin-stdlib:commonSources'. > Failed to calculate the value of task ':kotlin-stdlib:compileJava' property 'javaCompiler'. > No compatible toolchains found for request filter: {languageVersion=6, vendor=any, implementation=vendor-specific} (auto-detect true, auto-download true) * Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights. * Get more help at https://help.gradle.org Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0. Use '--warning-mode all' to show the individual deprecation warnings. See https://docs.gradle.org/6.9/userguide/command_line_interface.html#sec:command_line_warnings BUILD FAILED in 10s

To avoid this error, add  to  :

Next, it is recommended that Gradle build cache is disabled, although this is not a requirement. The build cache's purpose is to avoid compiling the same source file twice even if has been run, but this behavior is undesired if the compiler arguments to build a set of source files need to be collected after the files have been compiled at least once because it will prevent the compiler arguments from being included in the Gradle debug logs.

To disable Gradle build cache, add  to :

Find out the Gradle compilation tasks for Kotlin library packages
The list of tasks for building all Kotlin compiler and library modules can be found from the output of, just like for third-party Kotlin packages. However, many Kotlin library packages consist of both Kotlin and Java source files, and they are covered by different compilation tasks.

Both the Kotlin source files and the Java source files need to be compiled. These are covered by a single  task, which can be run with  to get compiler options for both set of source files.

Search compiler arguments in Gradle debug logs
In addition to Kotlin compiler arguments, Gradle also prints the arguments it uses for. These arguments can be found by searching for occurrences of string, like:

For a few modules, Gradle may also call a command to start an external process directly. For example, it calls the command directly to build the   subproject. Such commands can be captured by searching for string  in the debug log:

Compiler class used in kotlin-libs.eclass
does not have a variable for setting KOTLIN_COMPILER before is invoked, so the default compiler class for, which is org.jetbrains.kotlin.cli.jvm.K2JVMCompiler, will be used. However, ebuilds using can still specify a different compiler class by directly setting the KOTLIN_COMPILER environment variable before the eclass's   is called. For example, the following code changes the Kotlin compiler class used by to org.jetbrains.kotlin.cli.js.K2JSCompiler:

This method only works for compiler classes that comply with the common Kotlin compiler options because the  function of  sets some of the options in the arguments to. Some compiler classes listed above are known to be incompatible with those options, and this method does not work on them:


 * org.jetbrains.kotlin.cli.js.internal.JSStdlibLinker
 * org.jetbrains.kotlin.serialization.builtins.RunKt

When Gradle uses one of these compiler classes, it would run these classes directly with like. More details can be found in the following sections.

To see if a compiler class complies with the common Kotlin compiler options, try to set KOTLIN_COMPILER to that class and run, then see what options the compiler class accepts. If no common compiler option is shown at all in the help message or an exception is even thrown, then the compiler class is likely to not comply with the common compiler options.

{{Cmd|KOTLIN_COMPILER{{=}}org.jetbrains.kotlin.cli.js.K2JSCompiler kotlinc -help|collapse-output=true|output= Usage: kotlinc-js,   and   phase functions work similarly as {{Path|java-pkg-simple.eclass}} too. also has some additional variables for controlling how Kotlin sources are compiled, tested and installed.

Allow pre-built binary JAR to be used
The upstream hosts pre-built binary JAR artifacts for many libraries on Maven Central. To allow the pre-built JAR to be installed for an ebuild, specify the URI to the JAR in KOTLIN_LIBS_BINJAR_SRC_URI before inheriting kotlin-libs, and set JAVA_BINJAR_FILENAME to the base name of the JAR anywhere in the ebuild.

Specifying a non-empty value for KOTLIN_LIBS_BINJAR_SRC_URI has the following effects:


 * A  USE flag will be automatically added for the ebuild.  When this USE flag is enabled, the package will not be compiled and installed from source; the pre-built JAR pointed by KOTLIN_LIBS_BINJAR_SRC_URI will be installed instead.


 * If the  USE flag is disabled, then during , the JAR created by the ebuild will be compared with the pre-built JAR pointed by KOTLIN_LIBS_BINJAR_SRC_URI for non-trivial difference in JAR contents and incompatibility in API.  This is equivalent to specifying   for.


 * Another variable, KOTLIN_LIBS_SRCJAR_SRC_URI, will be recognized by . If KOTLIN_LIBS_SRCJAR_SRC_URI has a non-empty value that is set before kotlin-libs is inherited, then the   USE flag can be set when the   USE flag is enabled.  With  , the ebuild will pull the file pointed by KOTLIN_LIBS_SRCJAR_SRC_URI and install it as the source archive for the package at.
 * If KOTLIN_LIBS_SRCJAR_SRC_URI has a non-empty value, then another variable, KOTLIN_LIBS_SRCJAR_FILENAME, must be set to the base name of the file pointed by KOTLIN_LIBS_SRCJAR_SRC_URI.

Dependencies
A Kotlin package can have both build dependencies and runtime dependencies on other Java or Kotlin packages. Build dependencies are to be added to DEPEND. Runtime dependencies that should present in the classpath when the package is being used should go into both RDEPEND and CP_DEPEND. CP_DEPEND is used by to generate a runtime classpath for the package accordingly.

Checking build dependencies
The list of build dependencies for a Kotlin package can be extracted from the value for the  option in the Kotlin compiler arguments Gradle uses to build the package, which can be obtained by using instructions in the  section.

For example, the following JARs are in the classpath when kotlin-test-junit 1.5.20 is built by Gradle:



Not all JARs in the classpath are really required to build the package: the package can still compile without them. In general, JARs meeting any of the following criteria are not required:


 * JARs that contain only files and no  files.  Generally, all  files have this property.
 * JARs which are a dependency of another JAR in the classpath but are not directly used by the Kotlin package. For instance,  is a dependency of, but it is not used by the package itself, nor is its presence in the classpath required for  to work.

After applying these criteria, the list of JARs from the classpath can be filtered so only the ones that are really necessary are left:



Now, the value of DEPEND in the ebuild can be derived from this list:

If the ebuild supports the  USE flag, then the build dependencies from the classpath are unnecessary when that USE flag is enabled. For such kind of ebuilds, the build dependencies can be pulled conditionally:

Compilation
provides variables that can be used to control the command-line arguments to and. For the simplest case where a package can be compiled with just one normal invocation of (and possibly one additional invocation of, it is possible to write an ebuild for the package which does not define   at all, by inheriting kotlin-libs and setting the relevant eclass variables.

KOTLIN_LIBS_RUNTIME_COMPONENT
This variable manipulates the content of file in the produced JAR. Whether or not this variable should be set and the proper value for it can be determined by inspecting in the JAR pre-built by the upstream. If it contains a Kotlin-Runtime-Component entry, then this eclass variable should be set to the value for that entry (which should be either  or  ); this will cause an equivalent  to be created and copied into the JAR generated by the ebuild. If there is no such entry, or does not exist in the pre-built JAR, or there is even not a pre-built JAR for the package, then this variable needs not be set.