bazelbuild / bazel

a fast, scalable, multi-language and extensible build system
https://bazel.build
Apache License 2.0
23.21k stars 4.06k forks source link

Add a flag to use Turbine only if we can use the GraalVM native image #21869

Open timothyg-stripe opened 7 months ago

timothyg-stripe commented 7 months ago

Description of the feature request:

In experimenting with --java_header_compilation, we have found that Turbine is only worth using if we can use the GraalVM native image added in #19361. If we cannot (such as if the java_library uses an annotation processor not supported by the native image), then we would rather fall back to Javac+JavaIjar, than using non–native image Turbine.

As such, we would like to have a flag in Bazel to only use Turbine if we will end up using the native image, tentatively called --[no]experimental_java_only_use_direct_header_compiler. We expect that this flag to be used in something like:

+def _would_use_header_compiler_direct(toolchain, plugin_info):
+    builtin_processors = {
+        proc: True
+        for proc in toolchain._header_compiler_builtin_processors.to_list()
+    }
+    return all([proc in builtin_processors for proc in plugin_info.plugins.processor_classes.to_list()])

-def _should_use_header_compilation(ctx, toolchain):
+def _should_use_header_compilation(ctx, toolchain, plugin_info):
     if not ctx.fragments.java.use_header_compilation():
         return False
     if toolchain._forcibly_disable_header_compilation:
         return False
     if not toolchain._header_compiler:
         fail(
             "header compilation was requested but it is not supported by the " +
             "current Java toolchain '" + str(toolchain.label) +
             "'; see the java_toolchain.header_compiler attribute",
         )
     if not toolchain._header_compiler_direct:
         fail(
             "header compilation was requested but it is not supported by the " +
             "current Java toolchain '" + str(toolchain.label) +
             "'; see the java_toolchain.header_compiler_direct attribute",
         )
+    if ctx.fragments.java.experimental_java_only_use_direct_header_compiler() and \
+       not _would_use_header_compiler_direct(toolchain, plkugin_info):
+        return False
     return True

(with equivalent change done to the Java version of the function)

Specifically, _would_use_header_compiler_direct is intended to mirror the logic in JavaHeaderCompilationAction.Builder.build.

cc @fmeum

Which category does this issue belong to?

Java Rules

What underlying problem are you trying to solve with this feature?

Making --java_header_compilation faster out of the box.

Which operating system are you running Bazel on?

macOS

What is the output of bazel info release?

7.1.1

If bazel info release returns development version or (@non-git), tell us how you built Bazel.

No response

What's the output of git remote get-url origin; git rev-parse HEAD ?

No response

Have you found anything relevant by searching the web?

No response

Any other information, logs, or outputs that you want to share?

No response

fmeum commented 7 months ago

Are you using --experimental_java_classpath=bazel? My understanding (and experience so far) is that Turbine isn't just beneficial when it's actually faster, but also because it provides the jdeps information needed for classpath pruning with this flag, which in turn reduces the amount of targets rebuilt during a typical incremental build. This information isn't available with ijar running after javac.

Cc @cushon

cushon commented 7 months ago

.jdeps are produced by both JavaBuilder and turbine, and if turbine is disabled the build should use the .jdeps output from JavaBuilder instead. There are some other things that could be get broken if turbine is only enabled for some actions in the build, including the 'direct classpath' stuff in JavaHeaderCompileAction which relies on information about transitive dependencies turbine repackages to allow compiling against direct dependencies only.