Kotlinc does not use Class-Path attribute in manifest files

Hello,
I am trying to use kotlinc compiler with target JVM and add a jar file to the classpath that references other jars in its manifest. Kotlinc seem to ignore this attribute.

Example:
I have a class

package testdataclass; 

data class TestDataClass(id: String)

in project A and I compile it into a jar file datalib.jar. Then I have another project B that uses this class:

import testdataclass.TestDataClass

fun main(args: Array<String>) {
  val d =  TestDataClass("id")
  println("Hello World $d")
}

I create another jar called refjar.jar with the following manifest:

Manifest-Version: 1.0
Ant-Version: Apache Ant 1.9.13
Created-By: 9+176 (Oracle Corporation)
Class-Path: datalib.jar

When I add datalib.jar directly to the compile classpath, it works:

kotlinc -cp datalib.jar src/* -d hello.jar

When I add the refjar.jar to the compile classpath, it does not:

kotlinc -cp refjar.jar src/* -d hello.jar
src/HelloKotlin.kt:1:8: error: unresolved reference: testdataclass
import testdataclass.TestDataClass
^
src/HelloKotlin.kt:4:12: error: unresolved reference: TestDataClass
val d = TestDataClass(“id”)

For comparison, the javac compiler does recognize the Class-Path attribute. Given this example class:

import testdataclass.TestDataClass;

public class Hello {

  public static void main(String[] args) {
    final TestDataClass tdc = new TestDataClass("id");
    System.out.println("Hello " + tdc);
  }
}

The following command succeeds:

javac -cp refjar.jar srcjava/Hello.java -d classesjava/

Am I missing something here? Or is Class-Path attribute not supported for Kotlinc classpath?

Why are we trying to do this? Our compile classpath is so huge, that we cannot launch kotlinc, because the underlying OS says “Argument list too long” and creating a so called manifest jar that contains references to all the needed jars is a way around that. We are using Apache Ant to compile, but the problem is reproducible with the cli compiler also.

Use Gradle.

Hi, thanks for the suggestion. We are actually using Apache Ant and it is not easy for us to migrate at this point. Will gradle start the compiler differently?

Well the Kotlin Plugin for Gradle take care of all the stuff for you. Plus you can write the scripts in Kotlin so it’s very easy. If you have a jar to add into you build just add in the dependency block:

plugins {
    // this line tells gradle that this is a kotlin jvm project
    kotlin("jvm") version "1.3.21"
    // this one tells gradle how to pack properly a jvm project
    application
}

application {
    // here you are saying to the `application` 
    // plugin which class to use as entrypoint
    mainClassName = "com.package.MainKt"
}

dependency {
    // this line adds the jars to your project
    implementation(files("/myFolder/jar1.jar", "./jar2.jar", 
            "$projectDir/libs/jar3.jar"))
}

Now you can generate a .zip or .tar file containing the script to start your app with our your dependencies on whatever OS with the commands gradle distZip or gradle distTar.
You can run gradle run to start the app as well.
Have a look at:

I highly recommend to use the Gradle wrapper which allows to install Gradle automatically on the machine you are using.

That is true, we can use gradle. I am just wondering, why Kotlin does not seem to support “Class-Path” attribute in a jar manifest file.

I don’t think there is any argument for not supporting it in the end. I guess this problem just hasn’t come up for the kotlin team.
Kotlin mostly focuses on gradle builds (and I guess a secondary system is IDEA). Maven, ant or other build systems are just not the primary focus.
I suspect that if you create a feature request for this at https://kotl.in/issue it will be added in the future. No idea how fast though.

I have done that now: https://youtrack.jetbrains.com/issue/KT-32244

1 Like