graalvm

Ingy döt Net 2024-05-19T01:19:43.947379Z

Has anyone here written (or seen) a native-image compiled thing that loads a shared library?

✋ 1
Ingy döt Net 2024-05-20T17:01:36.499509Z

@smith.adriane from my mac

% otool -L rapidyaml/native/librapidyaml.dylib.0.6.0 
rapidyaml/native/librapidyaml.dylib.0.6.0:
	@rpath/librapidyaml.dylib (compatibility version 0.0.0, current version 0.0.0)
	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 1600.157.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1336.61.1)

phronmophobic 2024-05-20T17:06:41.457689Z

Are you loading that specific version?

phronmophobic 2024-05-20T17:07:10.451709Z

> I'm assuming you did (Native/loadLibrary "rapidyaml") or similar?

phronmophobic 2024-05-20T17:07:41.784959Z

when you load the library, are you just passing the name "rapidyaml" or a specific version of rapidyaml?

phronmophobic 2024-05-20T17:08:12.705589Z

what is otool -L rapidyaml/native/librapidyaml.dylib?

phronmophobic 2024-05-20T17:09:11.083199Z

My guess is you're loading library without specifying a version (which is typical) and librapidyaml.dylib references librapidyaml.dylib.0.6.0 which can't be found.

Ingy döt Net 2024-05-20T17:11:41.656449Z

note, this all works when using it as a JVM jar

Ingy döt Net 2024-05-20T17:12:25.018819Z

just not as a native-image file

phronmophobic 2024-05-20T17:15:17.443849Z

so you are loading a specific version

Ingy döt Net 2024-05-20T17:15:24.840879Z

% YS_PARSER=rapidyaml ./ys/bin/ys -pe 42
Error: java.lang.RuntimeException: Shared library file librapidyaml.dylib.0.6.0 not found
{:eval ["42"], :debug-stage {}, :print true, :mode "code"}

Ingy döt Net 2024-05-20T17:15:54.463789Z

that is the native-image (on the mac)

phronmophobic 2024-05-20T17:17:48.543219Z

You should be able to print out the paths it searched and figure out where it's currently looking and where it's not looking that you would expect it to look.

Ingy döt Net 2024-05-20T17:20:12.396949Z

This is pretty interesting... https://gist.github.com/ingydotnet/9389709e80d23588e9cf6ddeeee9855c

Ingy döt Net 2024-05-20T17:20:47.023649Z

2 failures with rapidyaml, but different when DYLD_LIBRARY_PATH set

Ingy döt Net 2024-05-20T17:20:52.187689Z

wasn't expecting that

Ingy döt Net 2024-05-20T17:21:43.180189Z

I'll try printing the path in the code you linked to

phronmophobic 2024-05-20T17:42:10.668219Z

So it looks like you’ve written your own code for finding and loading libraries, which also uses jna’s code for finding and loading libraries.

Ingy döt Net 2024-05-20T17:43:32.127749Z

I'm thinking we need to tell native-image about librapidyaml, like spire does here: https://github.com/epiccastle/spire/blob/3ff1a18a843f56a2a3b0aa646cc3dd8e6ca3891d/graal-configs/resource-config.json

phronmophobic 2024-05-20T17:46:22.348969Z

I'm not sure about windows, but I think linux and osx require shared libs to be actual files on the file system. JNA has its own thing for extracting libs to a temp folder. It relies on resources at specific paths.

phronmophobic 2024-05-20T17:46:59.013499Z

So you can probably include it as a resource, but you have to put it in the right subdirectory of the resource path.

Ingy döt Net 2024-05-20T17:47:14.302119Z

where is that resource path?

phronmophobic 2024-05-20T17:47:45.194799Z

I don't remember off the top of my head.

borkdude 2024-05-20T18:16:07.428779Z

> I'm not sure about windows, but I think linux and osx require shared libs to be actual files on the file system. spire packages the shared libs in the native-image but writes them out to disk on startup

Ingy döt Net 2024-05-20T19:37:57.833599Z

Interesting. Thanks for that.

Ingy döt Net 2024-05-21T04:18:47.877929Z

@smith.adriane this is a bit embarrassing but I've come full circle back to your original message in the thread. Google just led me to https://github.com/phronmophobic/jna-native-image 🙄 I'm out of tuits for the night but I think I can put that to good use in the morning. TBH, I don't think I would have understood enough about all this to try it when you first posted...

Ingy döt Net 2024-05-21T04:21:15.613509Z

I've studied and experimented enough to feel pretty comfortable with the Java and JNA. I was coming to the conclusion that native-image needed the right persuasions here and that led me back to you.

phronmophobic 2024-05-21T04:24:31.388349Z

that example expects that the library can be found through JNA natural library lookup. If you want to distribute a shared library, you'll have to either have it preinstalled where JNA expects or extract it somewhere that JNA can find it.

phronmophobic 2024-05-21T04:26:25.399339Z

There are a lot of cool native libraries. Once everything is setup, it's pretty easy to use them from clojure, but the setup itself is unfortunately very complicated given the various platforms and tools.

Ingy döt Net 2024-05-19T22:11:54.299619Z

https://github.com/epiccastle/spire/blob/3ff1a18a843f56a2a3b0aa646cc3dd8e6ca3891d/graal-configs/resource-config.json#L4 looks like what I need to solve:

Native library (home/ingy/src/yamlscript/rapidyaml/native/librapidyaml.so.0.6.0) not found in resource path ()

phronmophobic 2024-05-19T22:16:38.733509Z

Does that work?

Ingy döt Net 2024-05-19T22:17:34.734949Z

I'll let you know 🙂

Ingy döt Net 2024-05-19T22:17:56.300959Z

~/src/yamlscript rapidyaml $ LD_LIBRARY_PATH=$PWD/rapidyaml/native YS_PARSER=rapidyaml ./ys/bin/ys -e 'say: 42'
Exception in thread "main" java.lang.UnsatisfiedLinkError: Unable to load library '/home/ingy/src/yamlscript/rapidyaml/native/librapidyaml.so.0.6.0':
com.sun.jna.Native.open(Ljava/lang/String;I)J [symbol: Java_com_sun_jna_Native_open or Java_com_sun_jna_Native_open__Ljava_lang_String_2I]
com.sun.jna.Native.open(Ljava/lang/String;I)J [symbol: Java_com_sun_jna_Native_open or Java_com_sun_jna_Native_open__Ljava_lang_String_2I]
Native library (home/ingy/src/yamlscript/rapidyaml/native/librapidyaml.so.0.6.0) not found in resource path ()
        at com.sun.jna.NativeLibrary.loadLibrary(NativeLibrary.java:325)
is my current failure.

Ingy döt Net 2024-05-19T22:18:36.948409Z

./ys/bin/ys is native-image

phronmophobic 2024-05-19T22:20:30.396869Z

for building a native executable, it seems like you would want to build a static library and statically link it.

phronmophobic 2024-05-19T22:21:19.152369Z

probably.

Ingy döt Net 2024-05-19T22:22:07.585879Z

I'm not sure about that... If I can load stuff dynamically then it's possible to build libraries using Java classes that are not backed into bb or ys...

phronmophobic 2024-05-19T22:22:12.517299Z

does librapidyaml have other shared dependencies?

phronmophobic 2024-05-19T22:23:18.881439Z

you can go that route, where librapidyaml is required to be installed by the user

☝️ 1
Ingy döt Net 2024-05-19T22:23:23.385819Z

no. for librapidyaml doing it staticly is probably better. but exploring the dynamic option right now

Ingy döt Net 2024-05-19T22:24:23.115989Z

I can make it part of the various YS install methods

phronmophobic 2024-05-19T22:24:43.336559Z

in this particular case, it seems like librapidyaml is not "installed" correctly

Ingy döt Net 2024-05-19T22:25:38.879689Z

yeah but I think you need to tell native-image where that is exactly

phronmophobic 2024-05-19T22:26:06.721959Z

No, it just needs to be on the load path.

Ingy döt Net 2024-05-19T22:26:19.959079Z

you can see above that I set LD_LIBRARY_PATH

phronmophobic 2024-05-19T22:26:55.851969Z

right and it did load librapidyaml, which probably has a dependency on /home/ingy/src/yamlscript/rapidyaml/native/librapidyaml.so.0.6.0

phronmophobic 2024-05-19T22:27:18.105919Z

I can't remember the exact terminology, but it has something to with some combination of rpath and install name

Ingy döt Net 2024-05-19T22:29:06.174459Z

hmm, am I misunderstanding the error? not sure what you mean by > right and it did load librapidyaml, which probably has a dependency on /home/ingy/src/yamlscript/rapidyaml/native/librapidyaml.so.0.6.0

Ingy döt Net 2024-05-19T22:29:26.281069Z

@joaoppmagalhaes over here 🙂

phronmophobic 2024-05-19T22:29:39.831519Z

I'm assuming you did (Native/loadLibrary "rapidyaml") or similar?

phronmophobic 2024-05-19T22:29:59.492699Z

what does otool -L /home/ingy/src/yamlscript/rapidyaml/native/librapidyaml.dylib say?

Ingy döt Net 2024-05-19T22:30:38.799009Z

is that a mac thing?

phronmophobic 2024-05-19T22:31:25.617649Z

yea

phronmophobic 2024-05-19T22:31:43.593679Z

although, I think there's a similar thing on linux

phronmophobic 2024-05-19T22:31:58.160069Z

but with slightly different tools and names.

Ingy döt Net 2024-05-19T22:54:57.201829Z

last message got messed up.

Ingy döt Net 2024-05-19T22:56:16.479369Z

You should get the same result on a mac with:

git clone --branch=rapidyaml  && cd yamlscript && make -C ys build && LD_LIBRARY_PATH=$PWD/rapidyaml/native YS_PARSER=rapidyaml ./ys/bin/ys -e 'say: 42'
I'll ssh into my seattle mini and try

Ingy döt Net 2024-05-19T23:05:02.991179Z

rapidyaml not building on mac for me

Ingy döt Net 2024-05-19T23:05:18.890519Z

I need to meet people for dinner

Ingy döt Net 2024-05-19T23:05:25.239409Z

will try more after

jpmag 2024-05-20T00:29:39.731949Z

I was pushing for packaging the library in the jar archive. IIUC, that's the proper way to ship; eg https://stackoverflow.com/questions/2937406/how-to-bundle-a-native-library-and-a-jni-library-inside-a-jar?rq=1

phronmophobic 2024-05-20T00:56:57.482249Z

Are you distributing a jar or an executable built with native image?

Ingy döt Net 2024-05-20T01:13:31.145839Z

Both

Ingy döt Net 2024-05-20T01:14:51.212199Z

https://github.com/yaml/yamlscript/releases/tag/0.1.58

Ingy döt Net 2024-05-21T17:53:11.377189Z

https://github.com/phronmophobic/jna-native-image/pull/1

phronmophobic 2024-05-21T18:00:08.934529Z

oh, I guess cos isn't available in libc on linux. you can either use another libc function or change it to load libm instead.

Ingy döt Net 2024-05-21T18:02:08.741609Z

I'll add a check for mac and load the right lib

Ingy döt Net 2024-05-21T18:02:30.865909Z

if you like the PR

Ingy döt Net 2024-05-21T18:09:37.112849Z

+ ./target/jna
cosine of 42 is -0.39998531498835127
🙂

jpmag 2024-05-21T18:10:21.113589Z

yeah, cos is frequently on libm.so, and that would require explicit linking

phronmophobic 2024-05-21T18:12:52.370809Z

ideally, there would be a function in libc that is easy to test and is included on both mac and linux

Ingy döt Net 2024-05-21T18:16:17.208719Z

@smith.adriane do you think you can make that code work with Native/load instead of NativeLibrary/getInstance ? That's what I'm really trying to figure out...

Ingy döt Net 2024-05-21T18:16:48.215409Z

I like your very small example repo 🙂

phronmophobic 2024-05-21T18:16:50.538049Z

probably. why do you want that?

phronmophobic 2024-05-21T18:18:11.960429Z

If you've already loaded the library, you can just use NativeLibrary/getProcess instead of get instance.

phronmophobic 2024-05-21T18:18:15.782499Z

I think.

Ingy döt Net 2024-05-21T18:19:43.648389Z

Because that is what I have working fine with the JVM... I rewrote https://github.com/yaml/yamlscript/blob/rapidyaml/rapidyaml/src/main/java/org/rapidyaml/LibRapidyaml.java#L74-L96 to be much clearer and separate the code path for JVM (works) from native-image (does not work)

Ingy döt Net 2024-05-21T18:21:35.591549Z

> f you've already loaded the library, you can just use NativeLibrary/getProcess instead of get instance. Problem is I can't load the library yet with a native image: https://gist.github.com/ingydotnet/0363ad5c0647d35169b6cbd45dede8f6

Ingy döt Net 2024-05-21T19:06:32.920809Z

@smith.adriane We are at the point where we'd like to add print debugging near https://github.com/java-native-access/jna/blob/master/src/com/sun/jna/NativeLibrary.java#L325 Do you know how one would do that? I can't find that jar on my system 😞

Ingy döt Net 2024-05-21T19:07:00.670649Z

And if I did, wouldn't know how to edit a jar source...

Ingy döt Net 2024-05-21T19:07:16.704529Z

Any help would be greatly appreciated

phronmophobic 2024-05-21T19:12:30.871419Z

have you tried enabling jna's builtin logging? https://github.com/java-native-access/jna/blob/master/www/FrequentlyAskedQuestions.md#calling-nativeload-causes-an-unsatisfiedlinkerror

👀 1
Ingy döt Net 2024-05-21T19:13:02.928429Z

ha! we were just starting to look into logging (like 10 secs ago)

phronmophobic 2024-05-19T04:02:50.538529Z

See https://github.com/phronmophobic/jna-native-image for a JNA example.

phronmophobic 2024-05-19T04:53:11.262919Z

I can't seem to find the documentation for ffi calls that I used to use. Maybe it's been deprecated. Anyway, I'm pretty sure they support JNI and JNA. See https://www.graalvm.org/latest/reference-manual/native-image/native-code-interoperability/ more info.

phronmophobic 2024-05-19T05:04:31.732829Z

I've used https://cnuernber.github.io/dtype-next/tech.v3.datatype.ffi.graalvm.html with success previously.

borkdude 2024-05-19T06:06:45.322249Z

Spire is another example

👍 1