sgammon / rules_graalvm

Build GraalVM native binaries with Bazel
Apache License 2.0
46 stars 13 forks source link

Compatibility with `neverlink` #243

Open sgammon opened 10 months ago

sgammon commented 10 months ago

In rare cases, a native-image target needs various JARs available at native compile time only, so classes can be referenced for compile-time directive mechanisms like GraalVM Features.

Most of the time these dependencies are inert on the compile or runtime classpath; because they export no usable functionality, directive classes are typically compiled out early and do not end up in the final binary. Keeping them on the classpath, then, is normally fine.

The problem arises when directive classes such as Features depend on classes within the SVM API. Such dependencies are embedded within GraalVM in addition to being made available via Maven. When native-image is invoked, these classes are present automatically, but before that step, when Bazel is building the regular java with javac, it won't be able to find those symbols.

The user's first impulse is probably to add @maven//:org_graalvm_nativeimage_svm to their deps, but this yields a nasty warning from the native-image compiler (and rightfully so, since these dependencies must always align perfectly if they are provided on the classpath or modulepath):

Error: Class-path entry file:///.../processed_objectfile-23.1.1.jar contains class com.oracle.objectfile.pecoff.cv.CVUtil. This class is part of the image builder itself (in file:///.../objectfile.jar) and must not be passed via -cp. This can be caused by a fat-jar that illegally includes svm.jar (or graal-sdk.jar) due to its build-time dependency on it. As a workaround, -H:+AllowDeprecatedBuilderClassesOnImageClasspath allows turning this error into a warning. Note that this option is deprecated and will be removed in a future version.

The user may sensibly try neverlink next, but, because of this issue, the following surfaces:

Error: Feature <feature> class not found on the classpath. Ensure that the name is correct and that the class is on the classpath.
com.oracle.svm.core.util.UserError$UserException: Feature gvm.workerd.feature.WorkerDFeature class not found on the classpath. Ensure that the name is correct and that the class is on the classpath.

Now Bazel can find the dependency and build it with javac, but Bazel considers native-image a run-phase task (I think?), and so omits the entire dependency from the classpath.

sgammon commented 10 months ago

This probably involves switching to transitive_compile_time_jars or combining it with our current use of transitive_runtime_jars.