Bootclasspath for kotlinc


#1

Hi,

I’m trying to integrate kotlin with our platform that doesn’t support the full Java runtime library. I’m using the <withKotlin> Ant task inside a <javac> ant task to do the compilation. We run into issues later down the line in our toolchain when it is determined that some of the classes or methods that kotlinc has compiled into the bytecode doen’t exist in our runtime.

I’d like to force compliance at compile-time. With javac we can do this by setting the bootclasspath to use our libs. <withKotlin> doesn’t seem to respect this though… it allows use of apis that aren’t on the bootclasspath.

Is there any equivalent way to achieve this type of compile-time checking with kotlin?

Thanks for any pointers.


#2

You can use -jdk-home command line option:

-jdk-home: Path to JDK home directory to include into classpath, if differs from default JAVA_HOME

An example of specifying custom options when using withKotlin:

<withKotlin>
            <compilerarg line="-jvm-target 1.6"/>
            <compilerarg value="-jdk-home"/>
            <compilerarg value="${env.JDK_16}"/>
</withKotlin>

#3

Thanks. That’s very helpful. In my case our classlib is just in a single .jar file. The -jdk-home directive looks like it expects a path to a full JDK. I’m not sure exactly what would be involved in making a “mock” jdk that has my alternative class library.


#4

I think you could then specify -no-jdk option and provide the path to that classlib just in the classpath.


#5

Thanks. I had been using that but it didn’t seem to be working. I did some more digging and found that it was sort of working. This will correctly fail if the code references classes that are missing from my JRE, but it won’t fail if there are only methods missing.

E.g. If my JRE is missing the entire java.io.File class, and I try to use that class, then the compilation will fail (correctly). However if my JRE is missing the String.isEmpty() method, then the compilation will still succeed even if I use that method.

This is similar behaviour to if I run javap -v /path/to/My/java/lang/String.class. This will output the bytecode for the system String class and not the String.class file I provided. But if I do javap -v -bootclasspath /path/to/my/rt.jar /path/to/My/java/lang/String.class then it will show me the one from my rt.jar


#6

I have posted an issue in the issue tracker about this here
https://youtrack.jetbrains.com/issue/KT-22483


#7

String.isEmpty(), in particular, is defined in Kotlin standard library (in Strings.kt) as an extension of CharSequence , so it does not matter wether it exists in your JRE or not. If you plan to remove some core methods like those, then you have to also create your own (reduced) version of the Kotlin standard library.


#8

Thanks! I guess I was just using the wrong litmus test. Tried it with Math.pow() which is also missing from out lib, and it failed correctly.


#9

Note that the standard library itself uses some API from JDK which may be missing in your rt.jar.


#10

Thanks. I’m handling that separately. I’ve scanned the runtime for all of the problematic references and we’ve implemented some glue for those. That portion is at least tractable since it’s a small finite set. Covering all possible APIs that a user might use from the JDK would be harder though so relying on kotlinc to catch these is essential.