Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added feature: Check if library exists without loading it #229

Merged
merged 6 commits into from
May 19, 2021

Conversation

basshelal
Copy link
Contributor

This gives callers a way to determine if the system will find the library with the passed in name in the system library default locations in addition to the optional passed in additional paths, without having to try to the load the library, so that callers are aware of missing libraries early.

This fixes #228

This gives callers a way to determine if the system will find the library with the passed in name in the system library default locations in addition to the optional passed in additional paths, without having to try to the load the library, so that callers are aware of missing libraries early.

This fixes jnr#228
@basshelal basshelal marked this pull request as draft April 3, 2021 00:24
@basshelal
Copy link
Contributor Author

Hmm, something's not right on Darwin.

I tested the new code on a macOS Big Sur 11.2.3 x86_64 and it's not as I expected, namely my assumption, system property java.library.path will contain default dylib locations, was false.

I installed JACK which then created /usr/local/lib/libjack.dylib but running canFindLibrary("jack", null) returned false because java.library.path returned the following:

/Users/user/Library/Java/Extensions
/Library/Java/Extensions
/Network/Library/Java/Extensions
/System/Library/Java/Extensions
/usr/lib/java
.

But here's the funny thing...

If I add /usr/local/lib to LibraryLoader.StaticDataHolder.USER_LIBRARY_PATH and try to load a minimal library using this Jack interface

Jack jack = LibraryLoader.loadLibrary(Jack.class, new HashMap<>(), "jack");

public interface Jack {
    int jack_activate(PointerByReference client);
}

It works!

This mostly makes sense to me but indicates that LibraryLoader.StaticDataHolder.USER_LIBRARY_PATH is missing functionality regarding default library locations for non Linux or BSD based systems or at least systems that don't use a .conf file to list their lib locations.

Apple's own documentation labels some expected default locations for dylibs similar to most Unixes I believe, see this for some kind of Unix documentation regarding locations, though generally they are as I put in (my discussion](#225) previously:

  • /usr/local/lib/
  • /usr/lib/
  • /lib/

I still haven't even touched Windows.

Anyway, this is all to say, things are a little more complicated than I thought and I still have more to check and test before I'd call this "Cross-platform ready", but at least GNU/Linux (the most important OS) is done I think.

…ader.DefaultLibPaths.PATHS and added more functionality to the class so that it adds expected Unix lib paths.

Also added Platform.libraryLocations which will most likely replace Platform.canFindLibrary because Platform.libraryLocations is much more useful.

Still need to look into using Windows and write some better tests
@basshelal basshelal changed the title Added Platform.canFindLibrary() Added feature: Check if library exists without loading it Apr 3, 2021
and slightly modified behavior of LibraryLoader.DefaultLibPaths.PATHS such that it will not contain duplicate paths AND will also add all paths from ld.so.conf even if they don't exist because they could later exist and validation is done elsewhere anyway.
@basshelal
Copy link
Contributor Author

After further exploration, it really was just a matter of slightly tweaking and improving LibraryLoader.StaticDataHolder to get what I wanted.

The class is now called LibraryLoader.DefaultLibPaths and its essentially just that, a holder with the paths to the default library paths.

The static block puts all the default paths into the PATHS list which will not include duplicates but may include non-existent directories because they may exist at a later time at runtime and more importantly, path validation is done later elsewhere anyway.

Anyway that's probably the final commit to add this functionality to the API, officially this is the addition of Platform.libraryLocations().

I also added tests to verify expected behavior.

Hope this helps, cheers 😊

@basshelal basshelal marked this pull request as ready for review April 4, 2021 18:00
@headius
Copy link
Member

headius commented May 19, 2021

I will review this for inclusion in 2.2.3 today!

@headius headius added this to the 2.2.3 milestone May 19, 2021
@headius
Copy link
Member

headius commented May 19, 2021

I like this. It does not change the existing logic substantially but clarifies the search order and provides a way to query where the library was found. Ship it!

@headius headius merged commit a05f6a3 into jnr:master May 19, 2021
@basshelal
Copy link
Contributor Author

@headius cheers man!
Really appreciate your kind words and I'm grateful to have contributed to this project 😊

@headius
Copy link
Member

headius commented May 19, 2021

@basshelal The 2.2.3 release and all other downstream JNR library releases should be live shortly! Thanks again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Feature Request: Check if library exists without loading it
2 participants