pubref / rules_kotlin

Bazel rules for Kotlin
Other
159 stars 20 forks source link

Importing Kotlin jars #40

Closed jmmk closed 7 years ago

jmmk commented 7 years ago

I'm getting build errors trying to access some functions from third-party jars. I'm not sure if this is directly related to rules_kotlin or a more general problem with how bazel handles Kotlin code in jars. I haven't tried importing Kotlin code into Java (with bazel).

I've made a small example gist: https://gist.github.com/jmmk/2aa367c00548dd34e0a8637462493bd2. I tried all 3 of java_deps, jars, and deps as I'm not 100% clear on the difference between these. Using java_deps gets the farthest in the build, but still fails. Note that I'm using rules_maven for the dependencies, but experienced the same issue with bazel-deps.

Example build output of bazel build main_deploy.jar:

ERROR: /Users/jmmk/Desktop/bazel-kotlin/BUILD:3:1: Compiling 1 Kotlin source files to main_kt.jar failed (Exit 1).
/private/var/tmp/_bazel_jmmk/b4a1d5dca7a3dfe59337df9230eb1872/bazel-sandbox/5737601483947724481/execroot/__main__/App.kt:4:18: error: unresolved reference: launch
import tornadofx.launch
                 ^
/private/var/tmp/_bazel_jmmk/b4a1d5dca7a3dfe59337df9230eb1872/bazel-sandbox/5737601483947724481/execroot/__main__/App.kt:11:33: error: unresolved reference: launch
fun main(args: Array<String>) = launch<MyApp>(args)
                                ^
Target //:main_deploy.jar failed to build

Another library I've had fail is https://github.com/FasterXML/jackson-module-kotlin/blob/master/src/main/kotlin/com/fasterxml/jackson/module/kotlin/Extensions.kt#L15, where I got unresolved reference: jacksonObjectMapper().

pcj commented 7 years ago

Here's the difference between the dependency types:

  1. deps: names other kotlin_library rules (you only have the one :main, so this does not apply here). It goes through the provider and adds in generated jar files to the compilation classpath.

  2. java_deps: names other java_library or java_import rules. The kotlin_compile rule goes through these and picks out the jar files that are present / generated and adds these to the compilation classpath. Internally, bazel converts "full" jars to their "ijar" equvalent (representing only the public API, meaning that if the public api does not change, no need to recompile later java deps, since only runtime is affected).

  3. jars: names other jar files directly and adds these to the classpath (not seen by ijar).

Anyway, I do see the tornadofx jar in the compile classpath, so I'm a little confused why the import errors are occuring. Still looking...

pcj commented 7 years ago

Got a little farther.

kotlin_binary(
    name = "main",
    main_class = "AppKt",
    srcs = ["App.kt"],
    verbose = 1,
    args = [
        "-jvm-target", "1.8",
    ],
    jars = [
        "@no_tornado_tornadofx//jar:file", 
    ],
)

yields:

ERROR: /home/pcj/github/pubref/rules_kotlin/tests/tornadofx/BUILD:3:1: Compiling 1 Kotlin source files to main_kt.jar failed (Exit 1)
error: supertypes of the following classes cannot be resolved. Please make sure you have the required dependencies in the classpath:
    class tornadofx.UIComponent, unresolved supertypes: javafx.event.EventTarget
    class tornadofx.App, unresolved supertypes: javafx.application.Application

/home/pcj/.cache/bazel/_bazel_pcj/348236377e7dabb3cd37e4fd75ac5343/bazel-sandbox/9038050504771389730/execroot/__main__/App.kt:6:15: error: cannot access class 'javafx.scene.Node'. Check your module classpath for missing or conflicting dependencies
class MyView: View() {
              ^
/home/pcj/.cache/bazel/_bazel_pcj/348236377e7dabb3cd37e4fd75ac5343/bazel-sandbox/9038050504771389730/execroot/__main__/App.kt:7:22: error: type of 'root' is not a subtype of the overridden property 'public abstract val root: Parent defined in tornadofx.View'
        override val root = vbox()
                     ^
/home/pcj/.cache/bazel/_bazel_pcj/348236377e7dabb3cd37e4fd75ac5343/bazel-sandbox/9038050504771389730/execroot/__main__/App.kt:7:29: error: cannot access class 'javafx.scene.layout.VBox'. Check your module classpath for missing or conflicting dependencies
        override val root = vbox()
                            ^
/home/pcj/.cache/bazel/_bazel_pcj/348236377e7dabb3cd37e4fd75ac5343/bazel-sandbox/9038050504771389730/execroot/__main__/App.kt:7:29: error: cannot access class 'javafx.event.EventTarget'. Check your module classpath for missing or conflicting dependencies
        override val root = vbox()
                            ^
/home/pcj/.cache/bazel/_bazel_pcj/348236377e7dabb3cd37e4fd75ac5343/bazel-sandbox/9038050504771389730/execroot/__main__/App.kt:7:29: error: cannot access class 'javafx.geometry.Pos'. Check your module classpath for missing or conflicting dependencies
        override val root = vbox()
                            ^
Target //:main failed to build

So there does seem to be a difference between providing the original jar and the ijar for kotlin. Also, need to add a new argument for the jvm-target.

Now the issue is the missing javafx.* classes. I have not used javafx, are these supposed to be in the java standard library or do they exist in a different set of jar files?

jmmk commented 7 years ago

@pcj javafx classes will only be in Oracle's JDK 8 I think

As for the ijar vs jar, I wonder if this is related: https://github.com/facebook/buck/issues/1386 (ijar might not work 100% for Kotlin)

jmmk commented 7 years ago

@pcj maybe also related: https://github.com/bazelbuild/bazel/issues/3528 (has to do with ijars and bazel's scala_rules)

pcj commented 7 years ago

OK, I was able to get this working with the oracle jdk and have seen the app window popup :smile: . Trying to use the JavaInfo provider per your last comment...