Open dsyer opened 3 months ago
Hello @dsyer, please share more information on this issue, for example, what version of GraalVM are you using? which OS? what are the steps we need to take to reproduce this problem?
I'm on Linux (with Nix for the toolchain) I don't think it matters which version of Graal. I made some notes here (including a hacky workaround): https://github.com/scratches/graal-nix-test.
Are you sure zlib-devel
(or equivalent package for your Linux distro) is installed on your system?
https://www.graalvm.org/latest/reference-manual/native-image/#prerequisites
Yes. Otherwise neither the hacky solution nor the main.c
example from the notes would have worked.
Ok, maybe your shell sets some environment variables to configure gcc
. What happens if you set NATIVE_IMAGE_DEPRECATED_BUILDER_SANITATION=true
and build with native-image
?
Yes, that works. There's a deprecation warning though, so I wouldn't want to rely on it. Is there another way?
Warning: The NATIVE_IMAGE_DEPRECATED_BUILDER_SANITATION environment variable is deprecated and might be removed in a future release. Please refer to the GraalVM release notes.
Yes, you need to find out what env vars are set in your shell to configure gcc
, and then explicitly allow them in your build via the -E
option, for example -ELD_LIBRARY_PATH
or so.
I see. Isn't that a bug in native-image though? It is removing stuff from my environment that I don't even control, without asking, and which breaks its own build process.
This works for my case:
$ GRAAL_FLAGS=`env | grep ^NIX | sed -e 's/=.*//' | tr '\n' ' ' | sed -e 's/ *$//' | sed -e 's/ / -E/g' | sed -e 's/^NIX/-ENIX/'`
$ native-image $GRAAL_FLAGS Hello
but that's pretty complicated and onerous for what seems like a workaround.
That explains why you (currently) need to forward certain env vars explicitly.
Only very few, selected env vars are forwarded within a Native Image build by default. This protects from accidentally leaking values from env vars by freezing them into an image or including them in a Native Image bundle. With that in mind, I wouldn't recommend that you blindly forward all NIX*
env vars. Maybe something like NIX_LDFLAGS
is actually enough and if so, we can consider adding it to the selected list of env vars I mentioned.
With that in mind, I wouldn't recommend that you blindly forward all NIX* env vars.
That makes it look even more like a bug to me. How am I supposed to know which variables are needed or "safe"? It doesn't work with just NIX_LDFLAGS
by the way - it's the first ting I tried - which only goes to underline my point.
How am I supposed to know which variables are needed or "safe"?
I'm afraid it seems you have to if choose to use NIX. That's why there is comprehensive docs for C on NIX.
One could also argue that when you don't know how your C toolchain is correctly configured on your system, how is anyone going to support you in a reasonable way? By adding env vars explicitly with -E
, we know exactly what was used when trying to build with Native Image. Dumping the entire environment setup seems to lead to much bigger problems.
I don't even care about my C toolchain - I wouldn't even have one if native-image didn't require it. I just want a native image from my Java app. You are asking me to have quite detailed knowledge of stuff that has nothing to do with my goal.
I managed to narrow it down to only the env vars that start with NIX_C
or NIX_LD
. But there are 7 of them! If you are serious about adding them to the supported list in native-image I can try and verify for sure if they are all needed.
FWIW just these three seem to work for my trivial sample: -ENIX_CFLAGS_COMPILE -ENIX_LDFLAGS -ENIX_CC_WRAPPER_TARGET_HOST_x86_64_unknown_linux_gnu
. But I have no idea if that is always the case.
UPDATE: also works with just -ENIX_LDFLAGS -ENIX_CC_WRAPPER_TARGET_HOST_x86_64_unknown_linux_gnu
but both of those appear to be mandatory (and one of them is platform specific so you couldn't hard code it, but I suppose you could pattern match it).
I don't even care about my C toolchain
Things just work on most Linux distros. You chose to use NIX, and that uses a large amount of env vars to configure your C toolchain. They even tell you that their setup "is very different from other linux distributions". So since they have heavily customized the C toolchain and introduced lots of bash wrappers, it would only make sense they also make sure that Native Image works, or tell users what they need to do to make it work.
-ENIX_LDFLAGS -ENIX_CC_WRAPPER_TARGET_HOST_x86_64_unknown_linux_gnu
Good to see this works for you. It seems only a NIX specialist, someone familiar with how these Bash wrappers and env vars work, can tell us what this does and whether that's really all that's needed.
Just to be clear: we do want to make it as easy as possible to build with Native Image on NIX. We just don't want to change what is working fine for the majority of users just because things work differently on NIX. If we know how it's properly set up on NIX, we can document how or make adjustments if they are reasonable.
The NIX docs I linked specifically mention NIX_LDFLAGS
but also NIX_CFLAGS_COMPILE
. Does the build also work if you use -ENIX_CFLAGS_COMPILE -ENIX_LDFLAGS
(and not -ENIX_CC_WRAPPER_TARGET_HOST_x86_64_unknown_linux_gnu
)?
No, that doesn't work. Adding NIX_CFLAGS_COMPILE
(with or without the *TARGET_HOST*
doesn't change anything).
Perhaps other NixOS users/developers can give it a try and see whether it works for them or not (if they find this github issue here that is).
it would only make sense they also make sure that Native Image works, or tell users what they need to do to make it work.
That might be convenient from our perspective, but I don't think the maintainers of Nix care about GraalVM (nor should they have to). The best I came up with for anyone else finding this problematic was to add native-image.properties
to the project (at META-INF/native-image/<project-name>
) with
Args = -ENIX_LDFLAGS -ENIX_CC_WRAPPER_TARGET_HOST_x86_64_unknown_linux_gnu
Those args are basically ignored for anyone not using Nix IIUC.
What might help would be if GraalVM would look for an environment variable in addition to native-image.properties
for the additional args flags. I'm not sure but I don't think that's a feature right now. If we had that then you could set that variable in the initialization of the tooling for the project without modifying the source code.
I want to build a native image with Maven (or the native-image binary, I don't care, to start with). I have installed zlib, but the native image is trying to build without that on the library path somehow. How does native-image find it's library path?
Relevant sections of build log: