Closed davido closed 6 years ago
Once Java 11 is supported (#5723) it will be possible to do this with the default toolchain, and won't require setting a custom --host_javabase
.
In the interim, you could do something like:
java_runtime(
name = "absolute_javabase",
java_home = "$(ABSOLUTE_JAVABASE)",
)
And then build with: --host_javabase=:absolute_javabase --define=ABSOLUTE_JAVABASE=/usr/lib64/jvm/java-11
. That keeps the non-portable JDK path out of your BUILD
files, at least.
Other options include vendoring a JDK into your repository, or fetching JDK 11 from a remote repository instead of using a locally installed version.
And then build with: --host_javabase=:absolute_javabase --define=ABSOLUTE_JAVABASE=/usr/lib64/jvm/java-11. That keeps the non-portal JDK path out of your BUILD files, at least.
Thanks for the workround. Another non intrusive way to support alternative JDKs would be to teach Bazel to induce the custom JDK from $JAVA_HOME (like other build tools are doing):
$ JAVA_HOME=/usr/lib64/jvm/java-11 bazel build --some-fancy-option-to-induce-custom-jdk-from-java-home :release
Other options include vendoring a JDK into your repository, [...]
Git is unsuitable for versioning binaries, and network bandwidth is very valuable resources, so that I rule out that option.
teach Bazel to induce the custom JDK from
$JAVA_HOME
(like other build tools are doing)
We're specifically not doing that by default so the non-VanillaJavaBuilder toolchain can rely on the embedded JDK instead of whatever the local JDK happens to be, to make sure it has a JDK 10. But it's fair to say there are some open questions about the best approach going forward.
To close the loop on this, @bazel_tools//tools/jdk:absolute_javabase
is now built-in: https://github.com/bazelbuild/bazel/blob/5f432e0cda5665334cc8db6192c5b3f14fb8aa8c/tools/jdk/BUILD#L27. I think that's the best we can do here.
That's nice, thanks.
Given that discussion on repo-discuss mailing list: [1] I'm looking for an option to build Gerrit on stable branches and older tags, where Dagger DI and auto-value still have outdated versions, that are not compatible with JDK9 javac because of removal of javax.annotation.Generated
class (what a mess?).
So my question is there an easy way to build gerrit say v2.15 tag with Bazel@HEAD using @bazel_tools//tools/jdk:absolute_javabase? Other options?
To reproduce the problem with Bazel@HEAD (a3ae3e2474bc5542161750fb8a358db5c5026908) checkout v2.15 tag and run:
$ b9 build gerrit-sshd:sshd
WARNING: The following rc files are no longer being read, please transfer their contents or import their path into one of the standard rc files:
/home/davido/projects/gerrit/tools/bazel.rc
Extracting Bazel installation...
Starting local Bazel server and connecting to it...
INFO: Analysed target //gerrit-sshd:sshd (120 packages loaded).
INFO: Found 1 target...
INFO: From Building gerrit-index/libindex.jar (34 source files) and running annotation processors (AutoAnnotationProcessor, AutoValueProcessor):
warning: An exception occurred while looking for AutoValue extensions. No extensions will function. This may be due to a corrupt jar file in the compiler's classpath. Exception: java.util.ServiceConfigurationError: com.google.auto.value.extension.AutoValueExtension: Provider com.google.auto.value.extension.memoized.MemoizeExtension could not be instantiated
INFO: From Building gerrit-server/libreceive.jar (15 source files) and running annotation processors (AutoAnnotationProcessor, AutoValueProcessor):
warning: An exception occurred while looking for AutoValue extensions. No extensions will function. This may be due to a corrupt jar file in the compiler's classpath. Exception: java.util.ServiceConfigurationError: com.google.auto.value.extension.AutoValueExtension: Provider com.google.auto.value.extension.memoized.MemoizeExtension could not be instantiated
ERROR: /home/davido/projects/gerrit/gerrit-sshd/BUILD:5:1: Building gerrit-sshd/libsshd.jar (97 source files) and running annotation processors (AutoAnnotationProcessor, AutoValueProcessor) failed (Exit 1)
java.lang.RuntimeException: java.lang.NoClassDefFoundError: javax/annotation/Generated
at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.handleExceptions(JavacTaskImpl.java:158)
at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:96)
at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:90)
at com.google.devtools.build.buildjar.javac.BlazeJavacMain.compile(BlazeJavacMain.java:111)
at com.google.devtools.build.buildjar.SimpleJavaLibraryBuilder$1.invokeJavac(SimpleJavaLibraryBuilder.java:106)
at com.google.devtools.build.buildjar.ReducedClasspathJavaLibraryBuilder.compileSources(ReducedClasspathJavaLibraryBuilder.java:54)
at com.google.devtools.build.buildjar.SimpleJavaLibraryBuilder.compileJavaLibrary(SimpleJavaLibraryBuilder.java:109)
at com.google.devtools.build.buildjar.SimpleJavaLibraryBuilder.run(SimpleJavaLibraryBuilder.java:117)
at com.google.devtools.build.buildjar.BazelJavaBuilder.processRequest(BazelJavaBuilder.java:105)
at com.google.devtools.build.buildjar.BazelJavaBuilder.runPersistentWorker(BazelJavaBuilder.java:67)
at com.google.devtools.build.buildjar.BazelJavaBuilder.main(BazelJavaBuilder.java:45)
Caused by: java.lang.NoClassDefFoundError: javax/annotation/Generated
at com.google.auto.value.processor.AutoAnnotationProcessor.getReferencedTypes(AutoAnnotationProcessor.java:443)
at com.google.auto.value.processor.AutoAnnotationProcessor.processMethod(AutoAnnotationProcessor.java:152)
at com.google.auto.value.processor.AutoAnnotationProcessor.process(AutoAnnotationProcessor.java:128)
at com.google.auto.value.processor.AutoAnnotationProcessor.process(AutoAnnotationProcessor.java:112)
at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:968)
at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:884)
at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.access$2200(JavacProcessingEnvironment.java:108)
at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1206)
at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1315)
at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1246)
at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:922)
at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.lambda$doCall$0(JavacTaskImpl.java:100)
at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.handleExceptions(JavacTaskImpl.java:142)
... 10 more
Caused by: java.lang.ClassNotFoundException: javax.annotation.Generated
at java.base/java.net.URLClassLoader.findClass(Unknown Source)
at java.base/java.lang.ClassLoader.loadClass(Unknown Source)
at java.base/java.lang.ClassLoader.loadClass(Unknown Source)
... 23 more
Target //gerrit-sshd:sshd failed to build
Use --verbose_failures to see the command lines of failed build steps.
INFO: Elapsed time: 53.027s, Critical Path: 42.66s
INFO: 98 processes: 78 linux-sandbox, 20 worker.
FAILED: Build did NOT complete successfully
It worth noting that there are other incompatible changes, like:
WARNING: The following rc files are no longer being read, please transfer their contents or import their path into one of the standard rc files:
/home/davido/projects/gerrit/tools/bazel.rc
So that building of release.war
would fail anyway, even if we would find a way to force Bazel to use JDK8 javac and Vanilla Java Builder.
It sounds like #5984 would help here a bit.
@lberki there's a higher-level question about the compatibility guarantees when using the latest Bazel to compile old release branches. It don't think there are any guarantees that will work (at least for pre-1.0 Bazel versions), given: https://groups.google.com/d/topic/bazel-discuss/wYocSoGTJOg/discussion.
The only thing I can think of that would definitely work is to use an old Bazel version corresponding to the version of the code you're using, or even to check the version of Bazel into your repository.
@cushon
It sounds like #5984 would help here a bit.
Yeah exactly! Just figured it out, that with this diff:
diff --git a/BUILD b/BUILD
index 722e240851..810cb296f5 100644
--- a/BUILD
+++ b/BUILD
@@ -3,6 +3,23 @@ package(default_visibility = ["//visibility:public"])
load("//tools/bzl:genrule2.bzl", "genrule2")
load("//tools/bzl:pkg_war.bzl", "pkg_war")
+load(
+ "@bazel_tools//tools/jdk:default_java_toolchain.bzl",
+ "default_java_toolchain",
+)
+
+filegroup(
+ name = "vanillajavabuilder",
+ srcs = ["@bazel_tools//tools/jdk:VanillaJavaBuilder_deploy.jar"],
+)
+
+default_java_toolchain(
+ name = "toolchain_vanilla",
+ forcibly_disable_header_compilation = True,
+ javabuilder = [":vanillajavabuilder"],
+ jvm_opts = [],
+)
+
genrule(
name = "gen_version",
outs = ["version.txt"],
That is actually the content of my pending PR (that was based on your suggestion actually) and voilá: Building gerrit v2.15 tag with Vanilla Java Builder and --javabase pointing to Java 8 just works:
$ b9 build --host_javabase=@bazel_tools//tools/jdk:absolute_javabase --define=ABSOLUTE_JAVABASE=/usr/lib64/jvm/java --host_java_toolchain=//:toolchain_vanilla --java_toolchain=//:toolchain_vanilla gerrit-sshd:sshd
WARNING: The following rc files are no longer being read, please transfer their contents or import their path into one of the standard rc files:
/home/davido/projects/gerrit/tools/bazel.rc
INFO: Build options have changed, discarding analysis cache.
INFO: Analysed target //gerrit-sshd:sshd (1 packages loaded).
INFO: Found 1 target...
Target //gerrit-sshd:sshd up-to-date:
bazel-bin/gerrit-sshd/libsshd.jar
INFO: Elapsed time: 18.279s, Critical Path: 17.79s
INFO: 43 processes: 22 linux-sandbox, 21 worker.
INFO: Build completed successfully, 44 total actions
Unfortunately I still have to patch BUILD
to artificially add toolchain_vanilla
. I think Bazel's backwards compatibility would benefit from adding toolchain_vanilla
as core Bazel feature.
The only thing I can think of that would definitely work is to use an old Bazel version corresponding to the version of the code you're using, or even to check the version of Bazel into your repository.
Another limitation: we cannot install multiple Bazel versions in the moment easily (or am I missing something?): after installing of bazel version foo
, bazel version bar
gone. We would need multiple docker images, or install different Bazel versions during the CI-build.
@cushon
Temporarily I added this to Gerrit in root BUILD file:
java_runtime(
name = "absolute_javabase",
java_home = "$(ABSOLUTE_JAVABASE)",
visibility = ["//visibility:public"],
)
this caused the CI: [1] to fail with:
Analyzing: 1562 targets (202 packages loaded)
ERROR: /home/jenkins/workspace/Gerrit-verifier-bazel/gerrit/BUILD:26:17: in java_home attribute of java_runtime rule //:absolute_javabase: $(ABSOLUTE_JAVABASE) not defined
ERROR: Analysis of target '//:absolute_javabase' failed; build aborted: Analysis of target '//:absolute_javabase' failed; build aborted
That's because we are building //... on the CI. In fact the CI still uses Java 8.
[1] https://gerrit-ci.gerritforge.com/job/Gerrit-verifier-bazel/54129/consoleText
If the issue is just avoiding building that target when you do build ...
, there are a couple of work-arounds:
tags=["manual"]
will exclude it from target patterns like ...
and :*
(https://docs.bazel.build/versions/master/user-manual.html#target-patterns)vardef("ABSOLUTE_JAVABASE", "")
will create a default value for the variableThank you! I will upload new CL with tags=["manual"]
added.
OK, that didn't work:
//:absolute_javabase: no such attribute 'tag' in 'java_runtime' rule
And vardef
doesn't seem to work:
BUILD:24:1: name 'vardef' is not defined
Sorry, vardef
doesn't exit, and I'd rather not add java_runtime.tags
just for this.
Once you can use the absolute_javabase
definition built in to Bazel this problem will go away.
In the interim, I have a hack that works around it by putting the variable reference behind a select
:
config_setting(
name = "use_absolute_javabase",
values = {"define": "USE_ABSOLUTE_JAVABASE=true"},
)
java_runtime(
name = "absolute_javabase",
java_home = select({
":use_absolute_javabase": "$(ABSOLUTE_JAVABASE)",
"//conditions:default": "",
}),
visibility = ["//visibility:public"],
)
bazel build --javabase=:absolute_javabase --define=ABSOLUTE_JAVABASE=<path to JDK> --define=USE_ABSOLUTE_JAVABASE=true ...
Thank you.
I would like to support custom JDK versions (e.g. JDK11) using
VanillaJavaBuilder
, usingdefault_java_toolchain
and leaving the source/target/bootclasspath unset.To make it work I have to pass custom jdk through a label to
--host_javabase
, e.g. on Linux:It could be simplified to set that up and I uploded this PR to expose
toolchain_vanilla
in core Bazel, but the main problem remains: I have to specify path to/usr/lib64/jvm/java-11
build file, making my toolchain non-portable:So that if on another system JDK11 is located under:
/usr/lib/jvm/java-11-oracle
the code above wouldn't work.Reproducer: https://gerrit-review.googlesource.com/c/gerrit/+/194040