rules_kotlin icon indicating copy to clipboard operation
rules_kotlin copied to clipboard

Lombok plugin with java + kotlin mixed sources not working

Open jeffzoch opened this issue 4 years ago • 10 comments
trafficstars

I have a mixed Java + Kotlin project where the java code uses some lombok annotations. None of the kotlin code depends on these lombok annotations, so with maven and gradle things compile fine (kotlin compiler runs first and then java compiler processes these annotations afaict). This doesn't seem to work with bazel. I don't have a way to say "kotlin compile all sources you need only and nothing else because im going to then call another compile afterwards w/ lombok". Here is sort of what i was hoping would work:

java_plugin(
    name = "lombok-java",
    processor_class = "lombok.launch.AnnotationProcessorHider$AnnotationProcessor",
    generates_api = True,
    deps = ["@org_projectlombok_lombok//jar",],
)


kt_jvm_library(
    name = "test",
    srcs = ["src/main/java/Test.java", "src/main/java/com/Other.kt"],
    resources = [],
    plugins = [
    ],
    deps = deps + [":lombok-java"],
    tags = ["trace", "timings"],
    runtime_deps = runtime_deps
)
)

Or even better just a single call to kt_jvm_library. However, with the former approach the kotlin code cant compile because the java code that doesnt use lombok isnt compiled at all for it to reference and in the latter example lombok doesn't seem to run in time and we get compilation errors where the lomboked code doesnt exist

If I remove the Other.kt from srcs it compiles fine. But the presence of the kotlin file (even if it depends on nothing and does nothing) causes

Test.java:13: error: cannot find symbol
       int res = new Test().getFoo();
                           ^
 symbol:   method getFoo()
 location: class Test
Target //projects/services:test failed to build

jeffzoch avatar Dec 02 '20 17:12 jeffzoch

I'm wondering if this doesn't work because you reference :lombok-java in the deps of test? Try moving it to plugins...

How this should work is that KAPT runs first and picks up your Lombok annotation processor, runs it over any Java + Kotlin source and generates some source code (Java I assume?). Then Kotlinc and Javac run in parallel over your module source and including the generated lombok java source code.

In the existing flow, I'm not sure if deps are scanned for annotation processors but I know plugins are. Also, for Java compilation annotation processing is disabled because in a Kotlin project this is always handled by KAPT.

The new flow with use_experimental_abi_jars works in a similar way but compiles Java source code using Bazels Java Starlark APIs.

You can check what command was sent to the actions by running bazel build --subcommands //foo/bar:test - you should see an innovation with a param file something like foo/bar/lib-test.jar-params or something, this is a text file with the command line options sent to the builder where the flags --processors and --processorpath list the processor class and jar path respectively.

jongerrish avatar Dec 03 '20 00:12 jongerrish

I tried including lombok-java in plugins[] and that didnt work either - as matter of fact, i tried that with every combination of use_experimental_abi_jars. Despite lombok showing up as an annotationprocessor in the command line it didnt seem to be running if kotlin code was included

jeffzoch avatar Dec 03 '20 00:12 jeffzoch

It seems kapt is not using lombok at all and just analyzing kotlin files and then finishing

jeffzoch avatar Dec 03 '20 00:12 jeffzoch

Also, for Java compilation annotation processing is disabled because in a Kotlin project this is always handled by KAPT.

@jongerrish i wonder if maybe kapt doesnt work with lombok? Does use_experimental_abi_jars use java compilation annotation processing?

jeffzoch avatar Dec 03 '20 02:12 jeffzoch

Annotation processing always happens (w/ + w/o use_experimental_abi_jars) using KAPT ahead of Kotlin and Java compilation. Can you provide snippets of the relevant .params files for building your "test" lib, or validate that the processor class and processor jars are passed to the builder in the params file and the jars exist.

jongerrish avatar Dec 03 '20 06:12 jongerrish

params1.txt

Here is the params file

Edit: accidentally included big app params.txt. changed to minimal reproduction

For posterity here is exactly how it was run:

BUILD

java_plugin(
    name = "lombok-java",
    processor_class = "lombok.launch.AnnotationProcessorHider$AnnotationProcessor",
    generates_api = True,
    deps = ["@org_projectlombok_lombok//jar",],
)

kt_jvm_library(
    name = "tst",
    srcs = glob(["src/main/java/com/salesforce/dataprotection/Other.kt", "src/main/java/com/salesforce/dataprotection/Test.java"]),
    resources = glob(["src/main/resources/**/*"]),
    plugins = [
        ":lombok-java",
    ],
    deps = ["@maven//:org_projectlombok_lombok"],
    tags = ["trace", "timings"],

)

and Test.java

package com.salesforce.dataprotection;


import lombok.Data;

@Data
public class Test {
    int foo = 1;
}

class Bar {
    void test() {
        int res = new Test().getFoo();
        System.out.println(res);
    }
}

and Other.kt:

package com.salesforce.dataprotection

class Other {
}

jeffzoch avatar Dec 03 '20 21:12 jeffzoch

processors + processor_path is passed to the builders so that looks correct.

Can you confirm that bazel-out/host/bin/external/maven/v1/https/nexus-proxy-prd.soma.salesforce.com/nexus/content/groups/public/org/projectlombok/lombok/1.18.8/lombok-1.18.8.jar exists?

Also, are there no other dependent jars for lombok or is this a fat jar?

jongerrish avatar Dec 03 '20 22:12 jongerrish

I can confirm it exists. As far as I know there are no other jars - its runnable directly from the command line or as an annotation processor for java using the exact same setup

java_library(
    name = "compile_java",
    srcs = glob(["src/main/java/**/*.java"]),
    resources = glob(["src/main/resources/**/*"]),
    deps = deps + [":lombok-java"],
    runtime_deps = runtime_deps
)

this compiles w/ lombok processing just fine for example

jeffzoch avatar Dec 04 '20 00:12 jeffzoch

droping "-proc:none" javac opts in compile.bzl can make lombok compiles in mixed mode.

rules_kotlin_version = "1.7.1"
rules_kotlin_sha = "fd92a98bd8a8f0e1cdcb490b93f5acef1f1727ed992571232d33de42395ca9b3"
http_archive(
    name = "io_bazel_rules_kotlin",
    urls = [
        "http://search-cicd.oss-cn-hangzhou-zmf.aliyuncs.com/third_party_archives/v%s/rules_kotlin_release.tgz" % rules_kotlin_version,
        "https://github.com/bazelbuild/rules_kotlin/releases/download/v%s/rules_kotlin_release.tgz" % rules_kotlin_version
    ],
    sha256 = rules_kotlin_sha,
    patch_cmds = [
        """sed -i 's/javac_opts.append("-proc:none")/pass/g' kotlin/internal/jvm/compile.bzl""",
    ]
)

zpzjzj avatar Apr 04 '23 09:04 zpzjzj

That works perfectly for us, as of rules_kotlin version 1.9.0.

For those who code on macOS and build on Linux, I'd suggest perl over sed:

"""perl -pi -e 's/javac_opts.append("-proc:none")/pass/g' kotlin/internal/jvm/compile.bzl""",

benjamin-bader avatar Apr 10 '24 17:04 benjamin-bader