2015-10-29

XGBoost の Java wrapper を OS X でビルドするときに気をつけるべきたった二つのこと

Posted on 2015-10-29, 2:22 in

追記: 2016-09-27 最新のビルド手順は こちら に記載しています。


なんで Java から XGBoost を扱いたいのかはさておき、概ね XGBoostをJavaのwrapperを使用して実行する - TASK NOTES こちらのサイトの解説どおりではあるのですが、OS X で素直に java/create_wrap.sh を叩いてビルドしようとすると

$ ./create_wrap.sh
build java wrapper
clang-omp++ -Wall -O3 -msse2  -Wno-unknown-pragmas -funroll-loops -fopenmp -fPIC -fPIC -shared -o java/libxgboostjavawrapper.so java/xgboost4j_wrapper.cpp wrapper/xgboost_wrapper.cpp updater.o gbm.o io.o subtree/rabit/lib/librabit.a dmlc_simple.o -pthread -lm  -I/Library/Java/JavaVirtualMachines/jdk1.8.0_66.jdk/Contents/Home/include -I/Library/Java/JavaVirtualMachines/jdk1.8.0_66.jdk/Contents/Home/include/linux -I./java
In file included from java/xgboost4j_wrapper.cpp:15:
/Library/Java/JavaVirtualMachines/jdk1.8.0_66.jdk/Contents/Home/include/jni.h:45:10: fatal error: 'jni_md.h' file not found
#include "jni_md.h"
         ^

みたいなエラーが出てしまうはずです。

この問題の対処法は実に簡単で、xgboost リポジトリのトップディレクトリ配下にある Makefile の 8行目を

before: export JAVAINCFLAGS = -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux -I./java
after : export JAVAINCFLAGS = -I${JAVA_HOME}/include -I${JAVA_HOME}/include/darwin -I./java

と書き換えるだけ、です。

続いて、java/xgboost4j ディレクトリ配下で mvn package コマンドを実行して jar ファイルを生成しようとしてみると、今度は

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running org.dmlc.xgboost4j.BoosterTest
Oct 29, 2015 2:51:55 AM org.dmlc.xgboost4j.DMatrix <clinit>
SEVERE: load native library failed.
Oct 29, 2015 2:51:55 AM org.dmlc.xgboost4j.DMatrix <clinit>
SEVERE: java.io.FileNotFoundException: File /lib/libxgboostjavawrapper.dylib was not found inside JAR.
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.121 sec <<< FAILURE!
testBoosterBasic(org.dmlc.xgboost4j.BoosterTest)  Time elapsed: 0.063 sec  <<< ERROR!
java.lang.UnsatisfiedLinkError: org.dmlc.xgboost4j.wrapper.XgboostJNI.XGDMatrixCreateFromFile(Ljava/lang/String;I[J)I
        at org.dmlc.xgboost4j.wrapper.XgboostJNI.XGDMatrixCreateFromFile(Native Method)
        at org.dmlc.xgboost4j.DMatrix.<init>(DMatrix.java:62)
        at org.dmlc.xgboost4j.BoosterTest.testBoosterBasic(BoosterTest.java:75)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        ...

と、test フェーズでこけてしまうかと思います。これは native ライブラリの拡張子が .so となってしまっているのが原因なので、これは create_wrap.sh の 12 行目 の移動先ファイル名を明示的に libxgboostjavawrapper.dylib と指定するか、もしくはすでに移動先にある native ライブラリの拡張子を .so から .dylib に書き換えてやれば OK です。

0 コメント:

コメントを投稿