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 more generic Mac Framework support #123

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/com/sun/jna/NativeLibrary.java
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,12 @@ private static NativeLibrary loadLibrary(String libraryName, Map options) {
}
catch(UnsatisfiedLinkError e) {
// Add the system paths back for all fallback searching
if (Platform.isMac() && libraryName.contains(".framework/")) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why the trailing slash?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seemed more consistent with other tests in the file, since they could all be tested with beginsWith() and endsWith(). Using a leading dot and trailing slash bounded the test on both ends. And it fits the definition of a Mac Framework: a bundle directory structure with a .framework for the directory name. Thus the test includes that the libraryName acknowledges it as a directory.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm just thinking that I'd say "JavaVM.framework" to indicate the library I want, I wouldn't explicitly add a trailing slash.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps a use case to indicate how you'd actually use this (a test case could reasonably "install" something in ~/LibraryFrameworks and subsequently attempt to load it)?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was taking a minimal change approach to modifying the code to support loading general frameworks. There are three ways a framework can be specified — MyKit.framework/MyKit, MyKit.framework/Versions/Current/MyKit, or MyKit.framework/Versions/YYY/MyKit. This was the smallest change I could come up with that could address all three cases and leave the user in control.

The changes I submitted are enough to enable generic loading of a framework from /Library/Frameworks or from ~/Library/Frameworks, where before an absolute path to the framework binary was required to bypass all the checks — So the change is an strict improvement, but there is certainly room for more.

The macholib of Python approaches this problem by returning a list of alternatives from the parallel to mapLibraryName() so that many different options can be used, and the loadLibrary could remain "MyKit" instead of "MyKit.framework".

Another option could be:

if (libName.contains(".framework")) {
    if (libName.endsWith(".framework")) {
       // get <name> before ".framework", and construct a result like "<name>.framework/Versions/Current/<name>"
    } else return libName;
}

This is quite literally the first Java code I've ever written, so complex string work in Java is a bit beyond my skills of mimicry.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you could change the code circa line 152 to loop over the extra frameworks paths (instead of trying a single one), and expand the extra paths to include potential name variations, e.g.
suffix = name.indexOf(".framework") == -1 ? name + ".framework/" + name : name;
for each:
"~/Library/Frameworks/" + name,
"/Library/Frameworks/" + name,
"/System/Library/Frameworks/" + name;
try library lookup and break when found

This allows specification by framework name, or explicit framework path to a particular version.

// Add standard dyld fallback paths
searchPath.add(System.getProperty("user.home")+"/Library/Frameworks/");
searchPath.add("/Library/Frameworks/");
searchPath.add("/System/Library/Frameworks/");
}
searchPath.addAll(librarySearchPath);
}
try {
Expand Down Expand Up @@ -498,6 +504,10 @@ private static String findLibraryPath(String libName, List searchPath) {
private static String mapLibraryName(String libName) {

if (Platform.isMac()) {
if (libName.contains(".framework/")) {
// Leave name unchanged if specified as a framework
return libName;
}
if (libName.startsWith("lib")
&& (libName.endsWith(".dylib")
|| libName.endsWith(".jnilib"))) {
Expand Down