boot-clj / boot

Build tooling for Clojure.
https://boot-clj.github.io/
Eclipse Public License 1.0
1.75k stars 181 forks source link

invalid java.library.path #185

Open mbuczko opened 9 years ago

mbuczko commented 9 years ago

recently I tried to boot-ize a project mostly based on opencv lib and I observed a problem with loading a native java extensions. it seems that whole the problems boils down to the wrong java.library.path which is different with boot and lein (which loads extension perfectly):

boot:

boot.user=>  (System/getProperty "java.library.path")
"/Users/mbuczko/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:."

lein:

user=> (System/getProperty "java.library.path")
"/Users/mbuczko/workspace/clojure/my-project/target/native/macosx/x86_64"

# boot --version
BOOT_CLOJURE_VERSION=1.6.0
BOOT_VERSION=2.0.0-rc13
micha commented 9 years ago

Ok, I'm ready to work on this. Can you please provide a minimal setup I can use to reproduce the issue?

mbuczko commented 9 years ago

sure. I've started with this page to create opencv & opencv-native jars:

http://docs.opencv.org/doc/tutorials/introduction/clojure_dev_intro/clojure_dev_intro.html

as it takes a bit time to compile all this stuff, I've dumped to my repo already compiled jars for macosx x64_64 architecture here, just in case you have a mac:

https://github.com/mbuczko/opencv-2.4.10

having these 2 jars in local repo (opencv-2.4.10 & opencv-native-2.4.10), just add dependecies to build.boot file:

[opencv/opencv "2.4.10"]
[opencv/opencv-native "2.4.10"]

and that's actually all. in case of correctly set java.library.path, you should be able to call:

(clojure.lang.RT/loadLibrary org.opencv.core.Core/NATIVE_LIBRARY_NAME)

lein return nil, boot complains about missing native extension in a path. as descried before, it's due to different java.library.paths set by both tools under repl.

esp1 commented 8 years ago

I'm encountering this issue as well (also trying to get OpenCV to work). I was able to get it to work by setting java.library.path in BOOT_JVM_OPTIONS like so:

BOOT_JVM_OPTIONS="$BOOT_JVM_OPTIONS -Djava.library.path=native/macosx/x86_64" boot -d opencv/opencv -d opencv/opencv-native repl

in repl:

boot.user=> (clojure.lang.RT/loadLibrary org.opencv.core.Core/NATIVE_LIBRARY_NAME)
nil

I also noticed that there was an alter-java-library-path! function in the old tailrecursion version of boot: https://github.com/tailrecursion/boot/blob/master/src/tailrecursion/boot/classlojure/core.clj#L40. Porting this function into my repl allowed me to do:

boot -d opencv/opencv -d opencv/opencv-native repl

in repl after loading alter-java-library-path! fn:

boot.user=> (alter-java-library-path! conj "native/macosx/x86_64")
"/Users/esp/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:."
boot.user=> (clojure.lang.RT/loadLibrary org.opencv.core.Core/NATIVE_LIBRARY_NAME)
nil

The functionality in alter-java-library-path! should be easy to package up as a third party boot task. I may do this myself if this isn't something that makes more sense to add as a default option in boot core.

esp1 commented 8 years ago

Actually, scratch that. The alter-java-library-path! thing isn't working for me after all. The only way I can reliably get this to work is to set BOOT_JVM_OPTIONS before calling boot. Notably, setting this property in boot.properties does not work either.

esp1 commented 8 years ago

I finally realized I was getting all confused because I was (sometimes) working against a directory where the native jar was already unpacked, which was why things seemed to be working in some cases and not others. Both BOOT_JVM_OPTIONS and alter-java-library-path! mechanisms work, but the trick is taking native deps that are packed up and distributed as maven artifacts and exploding them into a directory that java.library.path can be pointed to. There may also be other caveats, e.g. I don't know if this kind of modification of the system environment can be isolated into pods.

micha commented 8 years ago

For reference: http://stackoverflow.com/a/15409446/3096353