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.
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
Feature
s depend on classes within the SVM API. Such dependencies are embedded within GraalVM in addition to being made available via Maven. Whennative-image
is invoked, these classes are present automatically, but before that step, when Bazel is building the regular java withjavac
, it won't be able to find those symbols.The user's first impulse is probably to add
@maven//:org_graalvm_nativeimage_svm
to theirdeps
, but this yields a nasty warning from thenative-image
compiler (and rightfully so, since these dependencies must always align perfectly if they are provided on the classpath or modulepath):The user may sensibly try
neverlink
next, but, because of this issue, the following surfaces:Now Bazel can find the dependency and build it with
javac
, but Bazel considersnative-image
a run-phase task (I think?), and so omits the entire dependency from the classpath.