Skip to content

Make variable substituion for javacopts #345

@protocol7

Description

@protocol7

The documentation for java_library and java_binary states that the javacopts attribute supports make variable substitution, e.g.

"javacopts": attr.string_list(
. However, this does not seem to be the case. Here's a small test case:

  MODULE.bazel
  module(name = "make_var_bug_repro")

  bazel_dep(name = "rules_java", version = "8.6.3")

  java = use_extension("@rules_java//java:extensions.bzl", "java")
  java.toolchain(version = "21")

  make_var_provider.bzl
  "A simple rule that provides a make variable via TemplateVariableInfo."

  def _make_var_provider_impl(ctx):
      return [
          platform_common.TemplateVariableInfo({
              ctx.attr.var_name: ctx.attr.var_value,
          }),
      ]

  make_var_provider = rule(
      implementation = _make_var_provider_impl,
      attrs = {
          "var_name": attr.string(mandatory = True),
          "var_value": attr.string(mandatory = True),
      },
  )

  BUILD.bazel
  load("@rules_java//java:defs.bzl", "java_library")
  load(":make_var_provider.bzl", "make_var_provider")

  make_var_provider(
      name = "my_make_var",
      var_name = "MY_CUSTOM_OPT",
      var_value = "-Xlint:none",
  )

  # According to docs, javacopts supports "Make variable" substitution
  # but this fails with: error: invalid flag: $(MY_CUSTOM_OPT)
  java_library(
      name = "hello",
      srcs = ["Hello.java"],
      javacopts = ["$(MY_CUSTOM_OPT)"],
      toolchains = [":my_make_var"],
  )

  Hello.java
  public class Hello {
      public static void main(String[] args) {
          System.out.println("Hello, World!");
      }
  }

  Run with: bazel build //:hello --java_runtime_version=remotejdk_21

This fails with:

$ bazel build //:hello --java_runtime_version=remotejdk_21
INFO: Analyzed target //:hello (0 packages loaded, 0 targets configured).
ERROR: /private/tmp/claude/rules_java_make_var_bug/BUILD.bazel:14:13: Building libhello.jar (1 source file) failed: (Exit 1): java failed: error executing Javac command (from java_library rule target //:hello) external/rules_java++toolchains+remotejdk25_macos_aarch64/bin/java '--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED' '--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED' ... (remaining 19 arguments skipped)
java.lang.IllegalArgumentException: error: invalid flag: $(MY_CUSTOM_OPT)
	at jdk.compiler/com.sun.tools.javac.main.Arguments.reportDiag(Arguments.java:914)
	at jdk.compiler/com.sun.tools.javac.main.Arguments.doProcessArgs(Arguments.java:409)
	at jdk.compiler/com.sun.tools.javac.main.Arguments.processArgs(Arguments.java:361)
	at jdk.compiler/com.sun.tools.javac.main.Arguments.init(Arguments.java:260)
	at jdk.compiler/com.sun.tools.javac.api.JavacTool.getTask(JavacTool.java:191)
	at com.google.devtools.build.buildjar.javac.BlazeJavacMain.compile(BlazeJavacMain.java:137)
	at com.google.devtools.build.buildjar.ReducedClasspathJavaLibraryBuilder.compileSources(ReducedClasspathJavaLibraryBuilder.java:57)
	at com.google.devtools.build.buildjar.SimpleJavaLibraryBuilder.compileJavaLibrary(SimpleJavaLibraryBuilder.java:110)
	at com.google.devtools.build.buildjar.SimpleJavaLibraryBuilder.run(SimpleJavaLibraryBuilder.java:118)
	at com.google.devtools.build.buildjar.BazelJavaBuilder.build(BazelJavaBuilder.java:111)
	at com.google.devtools.build.buildjar.BazelJavaBuilder.parseAndBuild(BazelJavaBuilder.java:91)
	at com.google.devtools.build.buildjar.BazelJavaBuilder.lambda$main$0(BazelJavaBuilder.java:52)
	at com.google.devtools.build.lib.worker.WorkRequestHandler$WorkRequestCallback.apply(WorkRequestHandler.java:252)
	at com.google.devtools.build.lib.worker.WorkRequestHandler.respondToRequest(WorkRequestHandler.java:480)
	at com.google.devtools.build.lib.worker.WorkRequestHandler.lambda$startResponseThread$0(WorkRequestHandler.java:433)
	at java.base/java.lang.Thread.run(Thread.java:1474)

This shows that the make variable has not been substitued before javac is invoked. Is this expected, and the docs should be updated, or should support for substitution be added?

Metadata

Metadata

Assignees

Labels

P1I'll work on this now. (Assignee required)bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions