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

Leverage java_home command to help FindJava and FindJNI modules on Mac #80

Closed
wants to merge 1 commit into from

Conversation

dakcarto
Copy link

@dakcarto dakcarto commented Jan 9, 2014

@bradking
Copy link
Member

bradking commented Jan 9, 2014

I applied the issue 14508 patch as 519084c. Please rebase on that.

Also please revise this patch to use the execute_process OUTPUT_STRIP_TRAILING_WHITESPACE option instead of separate string processing.

@dakcarto
Copy link
Author

dakcarto commented Jan 9, 2014

Here's what I did:

  1. Removed the issue #14508 edit, committed and locally squashed down.
  2. Rewrote commit message to somewhat match others in history
  3. Tested that the new local branch merges into local branch of next
  4. Force-pushed PR topic branch (still against CMake's master, not next)

This avoided the rebase in of next commits. When reviewing the CMake git workflow, I notice 'Do not merge from next!'. I'm quite familiar with a linear rebase-based git workflow, but am unsure how best to rebase in changes (in this instance the newer commits, including 519084c) from the next branch. Do I just cherry-pick those?

For future reference, should I have merged my topic branch into next, pushed next to my github repo, then created a PR from the next branch against CMake's next, instead of creating a PR of my topic branch against master?

@bradking
Copy link
Member

bradking commented Jan 9, 2014

A topic -> master pull request as you did is correct.

@dakcarto
Copy link
Author

dakcarto commented Jan 9, 2014

Fixed logical error when reverting back CMAKE_FIND_FRAMEWORK in FindJNI (added AND NOT EXISTS "${_JAVA_HOME}/bundle" to expression). All local tests now work fine on Mac OS X 10.9 with non-Apple Java install (via /usr/libexec/java_home) and forcing Apple's older JavaVM.framework via JAVA_HOME environment variable.

Mac has a utility, /usr/libexec/java_home, which returns the currently defined home for the system, similar to setting JAVA_HOME environment variable. Most users have always used the JavaVM.framework provided by Apple, but with Mac OS X 10.9 Apple no longer readily provides one (though a user may have a previous install lingering), but instead prompts users to download and install the latest from Oracle.

To get FindJava and FindJNI modules to work on Mac, you usually have to set JAVA_HOME in the environment first, if you want to use a non-Apple Java install, e.g. Oracle's, even though /usr/libexec/java_home now correctly points to the non-Apple install. Also, if a user installs the Oracle Java, but still has a lingering previous Apple install, FindJNI returns mixed results unless CMAKE_FIND_FRAMEWORK = LAST (FIRST by default).

It is not difficult to determine an Apple Java.framework install, when returned by /usr/libexec/java_home, since they all have a 'bundle' symlink in their root directory, while non-Apple installs do not.

To choose any Java install (including an older Apple install) other than that returned by /usr/libexec/java_home, set the JAVA_HOME environment variable. Available versions can be listed with /usr/libexec/java_home -V.
@dakcarto
Copy link
Author

dakcarto commented Jan 9, 2014

Included suggested changes.

CMAKE_FIND_FRAMEWORK is supposed to be a local setting for the user to choose whether to prefer frameworks or traditional libraries. What if I want to find the Apple framework?

I added the following to the end of the commit message:

To choose any Java install (including an older Apple install) other than that returned by /usr/libexec/java_home, set the JAVA_HOME environment variable. Available versions can be listed with /usr/libexec/java_home -V.

Since Apple has dropped Java support, things are a bit of a mess. Seems /usr/libexec/java_home mostly returns the 'latest' version installed, while setting JAVA_HOME is the general override for its results. There doesn't seem to be a way to influence /usr/libexec/java_home results other than uninstalling a newer versions.

Since Apple's older JavaVM.framework is the only likely framework installed, temporarily setting CMAKE_FIND_FRAMEWORK=LAST seems to be the most reasonable workaround, since all other installs are likely to be lib-based. I think it unlikely that a newer framework version of JAVA will come along from a third-party for some time. Not sure of a better approach than temporarily setting CMAKE_FIND_FRAMEWORK=LAST. Any ideas?

Here are the results when no JAVA_HOME is set, and a newer Oracle install, and older Apple install coexist:

$ echo '' > CMakeCache.txt && cmake .
-- JAVA_HOME= 
-- CMAKE_FIND_FRAMEWORK(Original)= FIRST
-- 
-- Found JNI: /Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home/jre/lib/libjawt.dylib  
-- _JAVA_HOME= /Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home
-- 
-- JNI_INCLUDE_DIRS= /Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home/include;/System/Library/Frameworks/JavaVM.framework/Headers;/Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home/include
-- JNI_LIBRARIES= /Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home/jre/lib/libjawt.dylib;/Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home/jre/lib/server/libjvm.dylib
-- JAVA_AWT_LIBRARY= /Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home/jre/lib/libjawt.dylib
-- JAVA_JVM_LIBRARY= /Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home/jre/lib/server/libjvm.dylib
-- JAVA_INCLUDE_PATH= /Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home/include
-- JAVA_INCLUDE_PATH2= /System/Library/Frameworks/JavaVM.framework/Headers
-- JAVA_AWT_INCLUDE_PATH= /Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home/include
-- 
-- CMAKE_FIND_FRAMEWORK(Reverted)= FIRST
-- 
-- Found Java: /Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home/bin/java (found version "1.7.0.45") 
-- _JAVA_HOME= /Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home
-- 
-- Java_JAVA_EXECUTABLE= /Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home/bin/java
-- Java_JAVAC_EXECUTABLE= /Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home/bin/javac
-- Java_JAVAH_EXECUTABLE= /Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home/bin/javah
-- Java_JAVADOC_EXECUTABLE= /Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home/bin/javadoc
-- Java_JAR_EXECUTABLE= /Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home/bin/jar
-- Java_VERSION_STRING= 1.7.0_45
-- Java_VERSION_MAJOR= 1
-- Java_VERSION_MINOR= 7
-- Java_VERSION_PATCH= 0
-- Java_VERSION_TWEAK= 45
-- Java_VERSION= 1.7.0.45

Then defining JAVA_HOME to the older Apple install:

$ export JAVA_HOME=/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home

$ echo '' > CMakeCache.txt && cmake .
-- JAVA_HOME= /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home
-- CMAKE_FIND_FRAMEWORK(Original)= FIRST
-- 
-- Found JNI: -framework JavaVM  
-- _JAVA_HOME= /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home
-- 
-- JNI_INCLUDE_DIRS= /System/Library/Frameworks/JavaVM.framework/Headers;/System/Library/Frameworks/JavaVM.framework/Headers;/System/Library/Frameworks/JavaVM.framework/Headers
-- JNI_LIBRARIES= -framework JavaVM;-framework JavaVM
-- JAVA_AWT_LIBRARY= -framework JavaVM
-- JAVA_JVM_LIBRARY= -framework JavaVM
-- JAVA_INCLUDE_PATH= /System/Library/Frameworks/JavaVM.framework/Headers
-- JAVA_INCLUDE_PATH2= /System/Library/Frameworks/JavaVM.framework/Headers
-- JAVA_AWT_INCLUDE_PATH= /System/Library/Frameworks/JavaVM.framework/Headers
-- 
-- CMAKE_FIND_FRAMEWORK(Reverted)= FIRST
-- 
-- Found Java: /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/bin/java (found version "1.6.0.65") 
-- _JAVA_HOME= /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home
-- 
-- Java_JAVA_EXECUTABLE= /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/bin/java
-- Java_JAVAC_EXECUTABLE= /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/bin/javac
-- Java_JAVAH_EXECUTABLE= /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/bin/javah
-- Java_JAVADOC_EXECUTABLE= /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/bin/javadoc
-- Java_JAR_EXECUTABLE= /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/bin/jar
-- Java_VERSION_STRING= 1.6.0_65
-- Java_VERSION_MAJOR= 1
-- Java_VERSION_MINOR= 6
-- Java_VERSION_PATCH= 0
-- Java_VERSION_TWEAK= 65
-- Java_VERSION= 1.6.0.65

@dakcarto
Copy link
Author

dakcarto commented Jan 9, 2014

There is another scenario I have not yet tested. On Mac OS X 10.9, there exists no Java at all by default. Users are then prompted to install the Oracle JRE (not JDK, as tested above), which is now only distributed as a system-wide internet plugin (/Library/Internet\ Plug-Ins/JavaAppletPlugin.plugin). I need to test whether using FindJava will correctly locate the new Java Home at:

/Library/Internet\ Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/

If /usr/libexec/java_home correctly locates this, then all is good. If not, FindJava (and maybe FindJNI) will need updated to search that path.

@bradking
Copy link
Member

bradking commented Jan 9, 2014

We must honor the user's choice for CMAKE_FIND_FRAMEWORKS. If it is set to ONLY then we should not find a non-framework or override it at all. If it is set to FIRST then we should search first for a framework and then for plain libraries. Etc. One approach to all this is to find the framework and the java_home result and choose whichever matches the user preference. More logic reorganization of the original code may be needed.

@bradking
Copy link
Member

I've refactored FindJNI on APPLE to honor CMAKE_FIND_FRAMEWORK while allowing JAVA_HOME to override it when set explicitly. See commit 4b3614b, commit fcd66a7, and commit 70560ee. Finally, commit dd72b19 introduces use of /usr/libexec/java_home as you suggest.

With this you can add -DCMAKE_FIND_FRAMEWORKS=LAST and CMake will find the Java returned by /usr/libexec/java_home.

@dakcarto
Copy link
Author

@bradking Thank you for the work on this. Apologies for not getting back to this sooner. I will test this on Mac OS X 10.7 and 10.9, both with Apple frameworks and with Oracle installed/activated.

@bradking
Copy link
Member

Okay. Please subscribe and post to the cmake-developers mailing list for follow-up discussion if there are problems:

http://www.cmake.org/mailman/listinfo/cmake-developers

That will have wider visibility.

@bradking bradking closed this Jan 29, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants