trouble building under java8 on arm64
strophy opened this issue · 5 comments
Hello, I am trying to native build ScalaPB so it can be included in the rvolosatovs/docker-protobuf plugin collection, but I am having difficulty building for ARM architecture. I followed the example in the CI from this repo, which uses jabba
under the hood to install graalvm@21.1.0
. This resolves to graalvm-ce-java8-linux-amd64-21.1.0.tar.gz
. However, under ARM only the following two packages are available in jabba
:
$ uname -m
aarch64
$ jabba ls-remote | grep graalvm
graalvm-ce-java11@21.1.0
graalvm-ce-java16@21.1.0
It turns out GraalVM 21 does not support Java 8 on ARM: https://github.com/graalvm/graalvm-ce-builds/releases/tag/vm-21.1.0
The same problem means using the sbtscala/scala-sbt
Docker images is also not possible.
Unfortunately attempting to build with any other version of Java fails as follows (e.g. Java 11 on x86):
#0 178.7 Downloading: Component catalog from www.graalvm.org
#0 179.4 Processing Component: Native Image
#0 179.4 Downloading: Component native-image: Native Image from github.com
#0 181.0 Installing new component: Native Image (org.graalvm.native-image, version 20.2.0)
#0 185.6 [info] /root/.cache/coursier/jvm/graalvm-java11@20.2.0/bin/native-image -cp /scala-protobuf/protoc-gen-scala-native-image/target/native-image-internal/manifest.jar -H:ReflectionConfigurationFiles=/scala-protobuf/protoc-gen-scala-native-image/native-image-config/reflect-config.json -H:Name=protoc-gen-scala --static --no-fallback scalapb.ScalaPbCodeGenerator /scala-protobuf/target/protoc-gen-scala
#0 189.4 [/scala-protobuf/target/protoc-gen-scala:498] classlist: 3,350.61 ms, 0.96 GB
#0 190.4 [/scala-protobuf/target/protoc-gen-scala:498] (cap): 598.99 ms, 0.96 GB
#0 190.5 [/scala-protobuf/target/protoc-gen-scala:498] setup: 1,137.79 ms, 0.96 GB
#0 190.5 Error: Error parsing reflection configuration in /scala-protobuf/protoc-gen-scala-native-image/native-image-config/reflect-config.json:
#0 190.5 Unknown attribute 'queriedMethods' (supported attributes: allDeclaredConstructors, allPublicConstructors, allDeclaredMethods, allPublicMethods, allDeclaredFields, allPublicFields, methods, fields) in defintion of class com.google.protobuf.DescriptorProtos$DescriptorProto
#0 190.5 Verify that the configuration matches the schema described in the -H:PrintFlags=+ output for option ReflectionConfigurationFiles.
#0 190.5 Error: Use -H:+ReportExceptionStackTraces to print stacktrace of underlying exception
#0 190.6 Error: Image build request failed with exit status 1
#0 190.6 [error] native-image command failed with exit code '1'
#0 190.6 [error] (protocGenScalaNativeImage / nativeImage) native-image command failed with exit code '1'
#0 190.6 [error] Total time: 181 s (03:01), completed Jan 2, 2023, 4:48:25 AM
------
Dockerfile:335
--------------------
333 | RUN gu install native-image
334 | RUN ./make_reflect_config.sh
335 | >>> RUN sbt protocGenScalaNativeImage/nativeImage
336 | RUN install -D /scala-protobuf/target/protoc-gen-scala /out/usr/bin/protoc-gen-scala
337 |
--------------------
I don't know anything about Java or Scala toolchains, can anyone help me out here? Do I have to use GraalVM, or is some other Java base image like Zulu possible? Otherwise, if the build only runs on Java 8 and Java 8 does not support ARM, how can I run a build?
Hi @strophy
ScalaPB works on all JVMs>=8, so using a JDK that supports Java 11 should be fine. Can you confirm that the make_reflect.config.sh
step generates a new reflect-config.json
? Does it have a queriedMethods
key in it? If so, why graalvm doesn't recognize it? This sounds more like a question for the GraalVM team.
Yes, running make_reflect.config.sh
generates protoc-gen-scala-nativ-image/native-image-config/reflect-config.json
, is this the file you are expecting to see? The contents of the relevant section appear as follows:
{
"name": "com.google.protobuf.DescriptorProtos$DescriptorProto",
"methods": [
{
"name": "newBuilder",
"parameterTypes": []
}
],
"queriedMethods": [
{
"name": "getEnumType",
"parameterTypes": [
"int"
]
},
{
"name": "getEnumTypeCount",
"parameterTypes": []
},
{
"name": "getEnumTypeList",
"parameterTypes": []
},
{
"name": "getExtension",
"parameterTypes": [
"int"
]
},
{
"name": "getExtensionCount",
"parameterTypes": []
},
{
"name": "getExtensionList",
"parameterTypes": []
},
{
"name": "getExtensionRange",
"parameterTypes": [
"int"
]
},
{
"name": "getExtensionRangeCount",
"parameterTypes": []
},
{
"name": "getExtensionRangeList",
"parameterTypes": []
},
{
"name": "getField",
"parameterTypes": [
"int"
]
},
{
"name": "getFieldCount",
"parameterTypes": []
},
{
"name": "getFieldList",
"parameterTypes": []
},
{
"name": "getName",
"parameterTypes": []
},
{
"name": "getNameBytes",
"parameterTypes": []
},
{
"name": "getNestedType",
"parameterTypes": [
"int"
]
},
{
"name": "getNestedTypeCount",
"parameterTypes": []
},
{
"name": "getNestedTypeList",
"parameterTypes": []
},
{
"name": "getOneofDecl",
"parameterTypes": [
"int"
]
},
{
"name": "getOneofDeclCount",
"parameterTypes": []
},
{
"name": "getOneofDeclList",
"parameterTypes": []
},
{
"name": "getOptions",
"parameterTypes": []
},
{
"name": "getReservedName",
"parameterTypes": [
"int"
]
},
{
"name": "getReservedNameCount",
"parameterTypes": []
},
{
"name": "getReservedNameList",
"parameterTypes": []
},
{
"name": "getReservedRange",
"parameterTypes": [
"int"
]
},
{
"name": "getReservedRangeCount",
"parameterTypes": []
},
{
"name": "getReservedRangeList",
"parameterTypes": []
},
{
"name": "hasName",
"parameterTypes": []
},
{
"name": "hasOptions",
"parameterTypes": []
}
]
},
This can be reproduced quite easily using the following short Dockerfile:
FROM sbtscala/scala-sbt:${SCALA_SBT_VERSION} as protoc_gen_scala
RUN mkdir -p /scala-protobuf
RUN curl -sSL https://api.github.com/repos/scalapb/ScalaPB/tarball/v0.11.12 | tar xz --strip 1 -C /scala-protobuf
WORKDIR /scala-protobuf
RUN gu install native-image
RUN ./make_reflect_config.sh
RUN sbt protocGenScalaNativeImage/nativeImage
RUN install -D /scala-protobuf/target/protoc-gen-scala /out/usr/bin/protoc-gen-scala
Running this file with different vars for SCALA_SBT_VERSION
produces the following results, just under x86_64 for now to try and get native build working under Java >8:
SCALA_SBT_VERSION=graalvm-ce-21.2.0-java8_1.8.0_2.12.17 //works
SCALA_SBT_VERSION=graalvm-ce-21.3.0-java11_1.8.0_2.12.17 //fails
SCALA_SBT_VERSION=graalvm-ce-21.3.0-java17_1.8.0_2.12.17 //fails
SCALA_SBT_VERSION=graalvm-ce-21.3.0-java17_1.8.0_3.2.1 //fails
Can you reproduce this on x86? Or should I ask GraalVM for help?
When running the Dockerfile you provided I noticed that the sbt protocGenScalaNativeImage/nativeImage
step ends up downloading an older version of native-image
(20.2.0), while make_reflect_config
is using a more recent version. Since we install native-image manually using gu install
, we need to disable the auto-download feature of sbt's native image plugin. The following dockerfile worked for me on x86 (the fix is the in ENV
line):
FROM sbtscala/scala-sbt:graalvm-ce-21.3.0-java11_1.8.0_2.12.17
RUN mkdir -p /scala-protobuf
RUN curl -sSL https://api.github.com/repos/scalapb/ScalaPB/tarball/v0.11.12 | tar xz --strip 1 -C /scala-protobuf
WORKDIR /scala-protobuf
RUN gu install native-image
RUN ./make_reflect_config.sh
ENV NATIVE_IMAGE_INSTALLED=true
RUN sbt protocGenScalaNativeImage/nativeImage
RUN install -D /scala-protobuf/target/protoc-gen-scala /out/usr/bin/protoc-gen-scala
Thanks, this works perfectly now, including under ARM. You can track inclusion of the Scala plugin in rvolosatovs/protoc
here: rvolosatovs/docker-protobuf#121