jnr / jnr-ffi

Java Abstracted Foreign Function Layer
Other
1.25k stars 156 forks source link

LibraryLoader.search() path not taken into consideration unless also in LD_LIBRARY_PATH #303

Open ja2142 opened 2 years ago

ja2142 commented 2 years ago

On linux, when loading library outside of normal library paths, the LD_LIBRARY_PATH has to be set - if it isn't, library fails to load.

Example:

Let's say there's a lib at ~/mylib/libmylib.so. Trying to load it with:

MyLib lib = LibraryLoader.create(MyLib.class).failImmediately()
    .search("~/mylib")
    .load("libmylib.so");

Fails with java.lang.UnsatisfiedLinkError: libmylib.so: cannot open shared object file: No such file or directory.

When the path in which library resides is added to LD_LIBRARY_PATH (by export LD_LIBRARY_PATH=~/mylib), code above loads the library without any problems.

Expected behaviour:

I'd expect LibraryLoader.search(path) to work, without me having to deal with environment variables. Maybe a fix would be as easy as just prepending path from LibraryLoader.search() to LD_LIBRARY_PATH?

Why:

I'm trying to get a project with native libs packaged in a .jar to work. It works by unpacking these native libs into some directory in users home, and then loading them with jnr-ffi. Again I'd hope that LibraryLoader.search(path).load(lib) would just work, without having to fiddle with env variables.

May be related to #129 (paths added via search() seem to have priority, as long as they are in LD_LIBRARY_PATH - otherwise they don't seem to be taken into consideration at all)

basshelal commented 2 years ago

I'm fairly sure this is an issue because of ~ which wouldn't be interpreted as you expect in Java.

I believe ~ expanding to the current user's home directory is a bashism or at least a shell behavior that isn't expected to be found everywhere including Java.

Solutions

Hope this helps

ja2142 commented 2 years ago

Sorry for the confusion, but I used ~ as a placeholder for my home directory, in code and in commands I used absolute paths (/home/user/...) everywhere. Although now that I tested it, it works exactly the same when I do use ~ (both in code and export LD_LIBRARY_PATH=...).

I guess the problem might be with some dlopen, or whatever underlying mechanism is being used that only looks in predefined library paths, and LD_LIBRARY_PATH?

ja2142 commented 2 years ago

Alright, I've dug a little deeper, and I've discovered couple of things:

It's not possible to use full name of library, when not providing a path, because in such case LibraryLoader assumes that short name is being used (i.e. load("mylib") and load("mylib/libmylib.so") are ok, but load("libmylib.so"), or load("libmylib.so.3") isn't). The solution to my original problem is just to use short name.

For now I guess there are two workarounds that more or less work for me: