rumbleD5
rumbleD5

Reputation: 67

How to define a local Java Toolchain in Bazel

I want to use a specific Azul Zulu JDK for my Java builds. Therefore I have stored it in my repository locally e.g. under tools/zulu19.30.11-ca-jdk19.0.1-macosx_x64. Now I want to configure a java toolchain target such that I can pass it via --java_toolchain=//tools:my_custom_java_toolchain. I don't want to depend on some remote repositories.

What are the required steps to achieve this?

I have found this repository: https://github.com/salesforce/bazel-jdt-java-toolchain/blob/main/jdt/defs.bzl which defines a target of type default_java_toolchain but I can not derive something useful for my use case. I don't know e.g. what the field header_compiler means. My naive assumption is that I just have to pass some paths to the required tools (such as bin/javac) for java compilation.

My current approach uses the rules java_toolchain and java_runtime. My BUILD file looks like this:

java_runtime(
  name = "zulu19.30.11-ca-jdk19.0.1-macosx_x64",
  srcs = glob(["zulu19.30.11-ca-jdk19.0.1-macosx_x64/**"]),
  java_home = "zulu19.30.11-ca-jdk19.0.1-macosx_x64",
)

java_toolchain(
  name = "zulu-19",
  source_version = "19",
  target_version = "19",
  java_runtime = ":zulu19.30.11-ca-jdk19.0.1-macosx_x64",
  javabuilder = "",
  ijar = "",
  singlejar = "",
  genclass = "",
)

I am trying to execute the command: bazel build --extra_toolchains="//tools:zulu-19" //:ProjectRunner and it complains about the missing mandatory attributes javabuilder, ijar, singlejar and genclass but I have no idea which are the correct paths or values.

I'm just wondering how bazel knows how to compile the java code with these few information. Why I don't have to specify javac for example?

Upvotes: 2

Views: 1733

Answers (1)

rumbleD5
rumbleD5

Reputation: 67

Basically I came up with the following solution which seems to solve my problem and is inspired by the rule default_java_toolchain. I used the existing targets for javabuilder, ijar, singlejar and genclass which are defined in @bazel_tools//tools/jdk. Note that I had to use BASE_JDK9_JVM_OPTS for a successful build.

load("@bazel_tools//tools/jdk:default_java_toolchain.bzl", "BASE_JDK9_JVM_OPTS")

java_runtime(
  name = "zulu19.30.11-ca-jdk19.0.1-macosx_x64",
  srcs = glob(["zulu19.30.11-ca-jdk19.0.1-macosx_x64/**"]),
  java_home = "zulu19.30.11-ca-jdk19.0.1-macosx_x64",
)

config_setting(
  name = "zulu-19-runtime_version_setting",
  values = {"java_runtime_version": "19"},
  visibility = ["//visibility:private"],
)

toolchain(
  name = "zulu-19_runtime_toolchain_definition",
  target_settings = ["zulu-19-runtime_version_setting"],
  toolchain_type = "@bazel_tools//tools/jdk:runtime_toolchain_type",
  toolchain = "zulu19.30.11-ca-jdk19.0.1-macosx_x64",
)

java_toolchain(
  name = "zulu-19",
  source_version = "19",
  target_version = "19",
  java_runtime = ":zulu19.30.11-ca-jdk19.0.1-macosx_x64",
  jvm_opts = BASE_JDK9_JVM_OPTS,
  javabuilder = ["@bazel_tools//tools/jdk:javabuilder"],
  ijar = ["@bazel_tools//tools/jdk:ijar"],
  singlejar = ["@bazel_tools//tools/jdk:singlejar"],
  genclass = ["@bazel_tools//tools/jdk:genclass"],
)

config_setting(
  name = "zulu-19_version_setting",
  values = {"java_language_version": "19"},
  visibility = ["//visibility:private"],
)

toolchain(
  name = "zulu-19_toolchain_definition",
  toolchain_type = "@bazel_tools//tools/jdk:toolchain_type",
  target_settings = ["zulu-19_version_setting"],
  toolchain = "zulu-19",
)

The following command now successfully runs without any errors. System.out.println(Runtime.version()); also prints the correct version.

bazel run --extra_toolchains="//tools:zulu-19_toolchain_definition,//tools:zulu-19_runtime_toolchain_definition" --java_language_version="19" --java_runtime_version="19" //:ProjectRunner

But I still have a couple of questions, e.g. why javabuilder, ijar, singlejar and genclass are needed and what is the purpose of those targets? How does the toolchain target know about my javac binary for compiling the java code? Why do I have to use BASE_JDK9_JVM_OPTS for a successful build and can I omit some settings?

Upvotes: 1

Related Questions