rules_kotlin
rules_kotlin copied to clipboard
Lombok plugin with java + kotlin mixed sources not working
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
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.
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
It seems kapt is not using lombok at all and just analyzing kotlin files and then finishing
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?
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.
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 {
}
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?
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
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""",
]
)
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""",