-
Notifications
You must be signed in to change notification settings - Fork 579
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
How to use my own compiled library? #55
Comments
This is something that's been fixed a few days ago for a similar issue: bytedeco/javacpp-presets#127 Make sure your source code includes this commit: bytedeco/javacpp-presets@f594e8d |
Thanks, but firstly if I change the edition to 1.2-SNAPSHOT the gradle could not download the jar. compile 'org.bytedeco.javacpp-presets:gsl:1.2-SNAPSHOT' And secondly, I've noticed that one line of code was added in the cppbuild.sh before the ./configure->make->make install: patch -Np1 < ../../../gsl-$GSL_VERSION-android.patch And I read the android.patch file and runs it. But it's not totally correct. I've tried the gsl-1.6 and gsl-2.1 both. Something didn't match the patch file. For example, in the version gsl-2.1 the cblas/Makefile.in was like this: libgslcblas_la_LDFLAGS = $(GSLCBLAS_LDFLAGS) -version-info $(GSL_LT_CBLAS_VERSION) But the patch file is like this and so the patch won't work. -libgslcblas_la_LDFLAGS = -version-info $(GSL_LT_CBLAS_VERSION) So I do this manually. That is edit the cblas/Makefile.am, cblas/Makefile.in, Makefile.am and Makefile.in and replace the "-version-info $(GSL_LT_CBLAS_VERSION)" with "-avoid-version". Then ./configure and make and make install. This work fine too and no version information in the generated library files. For example, I got a libgsl.so.19 before but now it's libgsl.so. But my problem is when I'm using the compiled gsl library in my android studio, the app installs well but crash when running. Without any linking error or compile error. It just says the libgsl.so not found: 12-23 20:19:53.224 17215-17215/com.ict.hci.iwatcher E/dalvikvm: dlopen("/data/app-lib/com.ict.hci.iwatcher-1/libjniJavacppDemo.so") failed: Cannot load library: soinfo_link_image(linker.cpp:1635): could not load library "libgsl.so" needed by "libjniJavacppDemo.so"; caused by load_library(linker.cpp:745): library "libgsl.so" not found
12-23 20:19:53.227 17215-17215/com.ict.hci.iwatcher W/dalvikvm: Exception Ljava/lang/UnsatisfiedLinkError; thrown while initializing Lcom/ict/hci/iwatcher/service/JavacppDemo$NativeDemo;
12-23 20:19:53.227 17215-17215/com.ict.hci.iwatcher W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0x40d01930) And the libgsl.so is not packaged into the apk file. |
I've copid the libgsl.so and libgslcblas.so into a folder lib/armeabi and then zip the lib folder into lib.zip and then rename it to lib.jar. And finally copy the lib.jar to my android libs folder. In this way the libgsl.so and libgslcblas.so was successfully packaged into the apk file. But I got the .so file not found error too and if I remember correctly the error was exactly the same error I got when I'm using gsl of javacpp-presets directly. 12-23 21:01:01.609 18106-18106/com.ict.hci.iwatcher E/dalvikvm: dlopen("/data/app-lib/com.ict.hci.iwatcher-2/libgsl.so") failed: Cannot load library: soinfo_relocate(linker.cpp:975): cannot locate symbol "cblas_sdsdot" referenced by "libgsl.so"...
12-23 21:01:01.609 18106-18106/com.ict.hci.iwatcher E/dalvikvm: dlopen("/data/app-lib/com.ict.hci.iwatcher-2/libjniJavacppDemo.so") failed: Cannot load library: soinfo_link_image(linker.cpp:1635): could not load library "libgsl.so" needed by "libjniJavacppDemo.so"; caused by find_library(linker.cpp:889): "libgsl.so" failed to load previously
12-23 21:01:01.609 18106-18106/com.ict.hci.iwatcher W/dalvikvm: Exception Ljava/lang/UnsatisfiedLinkError; thrown while initializing Lcom/ict/hci/iwatcher/service/JavacppDemo$NativeDemo;
12-23 21:01:01.609 18106-18106/com.ict.hci.iwatcher W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0x40d01930) |
I didn't notice GSL 2.x was released. We'll have to update that! Anyway, for now, to get new binaries for 1.16, please try to follow the instructions here: |
I've found this link. It says something about APP_PLATFORM in the android.mk. But we have no android.mk file in javacpp project. So does this really matters? |
What error exactly do you get when running |
Sorry, but I didn't run this bash directly. But I run the code in cppbuild.sh manually. The cppbuild.sh runs something like downloading the gsl.tgz and unzip it and then running the patch and configure->make->make install. The patch file has some errors cause it does not match my gsl library source code. But I can fix it by manually edit every file described upside. Until now no errors. The error comes in the runtime. I'm sure the libgsl.so and libgslcblas.so and my own generated .so file was packaged and installed on my phone. But when I load the library with this: Loader.load();
//or
//System.loadLibrary("gslcblas");
//System.loadLibrary("gsl");
//System.loadLibrary("jniJavacppDemo"); The error come out when loading gsl. 12-24 10:01:20.034 30345-30345/com.ict.hci.iwatcher E/dalvikvm: dlopen("/data/app-lib/com.ict.hci.iwatcher-1/libgsl.so") failed: Cannot load library: soinfo_relocate(linker.cpp:975): cannot locate symbol "cblas_sdsdot" referenced by "libgsl.so"... |
By the way, which version of ndk did you used to compile the gsl-1.6? Some says r10 will lead to the "Cannot load library: soinfo_relocate" problem. |
As per the message above, I've updated the presets for GSL 2.1, so executing |
The patch file is OK now. But I've run the if [[ -z "$PLATFORM" ]]; then and then when it goes to pushd ..
bash cppbuild.sh "$@" gsl
popd the and what's more, the command download is not install on my ubuntu. And I can't install it with apt-get install. But anyway, the cppbuild.sh is not my problem. I've make it work manually. So you could think that I can run My problem is in the runtime. I've packaged the libgsl.so and libgslcblas.so into my apk file. But when I excute System.loadLibrary("gsl"); The error come out tells me that 12-24 23:42:25.820 21735-21735/com.ict.hci.iwatcher E/art: dlopen("/data/app/com.ict.hci.iwatcher-1/lib/arm/libgsl.so", RTLD_LAZY) failed: dlopen failed: cannot locate symbol "cblas_sdsdot" referenced by "libgsl.so"... |
Right, so try to use libraries built with the cppbuild.sh scripts. The error that you are getting indicates that the parent cppbuild.sh file is missing. So make sure that you haven't deleted it by mistake. |
Indeed, I missed the parent cppbuild.sh and now I've added it to the parent directory. But then the ANDROID_ROOT=/home/shekmun/android/android-ndk-r10e/platforms/android-14/arch-arm
ANDROID_BIN=/home/shekmun/android/android-ndk-r10e/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi Is this right? Now it runs and generates the library. |
Calling |
I'm doing this: Loader.load();
//or
//System.loadLibrary("gslcblas");
//System.loadLibrary("gsl");
//System.loadLibrary("jniJavacppDemo"); Then I got the error. So how can I use the library without loading it? This is my java code: @Name("Demo")
public static class NativeDemo extends Pointer {
static {
System.loadLibrary("gslcblas");
System.loadLibrary("gsl");
System.loadLibrary("jniJavacppDemo");
//Loader.load();
}
public NativeDemo() {
allocate();
}
private native void allocate();
private native int get();
} In the C++ code of get(), I used the gsl function. |
I checked the symbol link of libgsl.a and libgslcblas.a: shekmun@shekmun-desktop:~/android/libs/lib$ nm libgsl.a | grep cblas_sdsdot
U cblas_sdsdot
shekmun@shekmun-desktop:~/android/libs/lib$ nm libgslcblas.a | grep cblas_sdsdot
00000000 T cblas_sdsdot Note that I'm checking the .a file not .so. The .so gives nothing. Does this help? |
Why are you looking at the .a files? Anyway, make sure your app's target SDK version is not 23 or higher: bytedeco/javacv#245 |
The output of .so: shekmun@shekmun-desktop:~/android/libs/lib$ nm libgsl.so
nm: libgsl.so: no symbols Targeting 20 gives the same error. 12-28 10:39:22.120 726-726/com.ict.hci.iwatcher E/art: dlopen("/data/app/com.ict.hci.iwatcher-2/lib/arm/libgsl.so", RTLD_LAZY) failed: dlopen failed: cannot locate symbol "cblas_sdsdot" referenced by "libgsl.so"... |
It's weird. I run ......
U cblas_scnrm2
U cblas_scopy
U cblas_sdot
U cblas_sdsdot
U cblas_sgemm
U cblas_sgemv
U cblas_sger
...... And I've used the readelf command to check the .so file: shekmun@shekmun-desktop:~/android/libs/lib$ readelf -Ws libgsl.so | grep cblas_sdsdot
189: 00000000 0 NOTYPE GLOBAL DEFAULT UND cblas_sdsdot
shekmun@shekmun-desktop:~/android/libs/lib$ readelf -Ws libgslcblas.so | grep cblas_sdsdot
12: 0000298c 268 FUNC GLOBAL DEFAULT 8 cblas_sdsdot |
if I use readelf to check the undefined symbol link, the cblas_sdsdot is the first one of cblas library: shekmun@shekmun-desktop:~/android/libs/lib$ readelf -Ws libgsl.so | grep UND
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FUNC GLOBAL DEFAULT UND __cxa_finalize
2: 00000000 0 FUNC GLOBAL DEFAULT UND __cxa_atexit
6: 00000000 0 FUNC GLOBAL DEFAULT UND malloc
7: 00000000 0 FUNC GLOBAL DEFAULT UND free
10: 00000000 0 FUNC GLOBAL DEFAULT UND memset
52: 00000000 0 FUNC GLOBAL DEFAULT UND fread
54: 00000000 0 FUNC GLOBAL DEFAULT UND fwrite
62: 00000000 0 FUNC GLOBAL DEFAULT UND putc
63: 00000000 0 FUNC GLOBAL DEFAULT UND fprintf
65: 00000000 0 FUNC GLOBAL DEFAULT UND fscanf
189: 00000000 0 NOTYPE GLOBAL DEFAULT UND cblas_sdsdot
191: 00000000 0 NOTYPE GLOBAL DEFAULT UND cblas_dsdot
193: 00000000 0 NOTYPE GLOBAL DEFAULT UND cblas_sdot
195: 00000000 0 NOTYPE GLOBAL DEFAULT UND cblas_ddot So I think the error comes because of the system doesn't know where to find the symbol link. Maybe we should tell it to find it from "libgslcblas.so"? But how? |
On Android, the official way is to call System.loadLibrary("gslcblas"). If that doesn't work on your version of Android, you should report this issue upstream to Google so they can have it fixed. |
Ok, I will try as you said and do a bit more work on this. And if it works at last, I will post my solution here. Thanks all the same! |
Well, it looks like a bug in Android, but it would be nice to know the workaround, yes. I'll try out the new version myself next week, just to make sure that it still works :) |
Might be related to the issues explained here:
https://medium.com/keepsafe-engineering/the-perils-of-loading-native-libraries-on-android-befa49dce2db#.42pjsp4gi
|
Still no lucky for the ReLinker library. It's the same error. Thanks. I tried to load the library in c++ code: int ret = 0;
void *cblas = dlopen("/sdcard/Download/libgslcblas.so", RTLD_LAZY | RTLD_GLOBAL);
if (cblas == NULL) ret += 1;
else {
void (*sdsdot)() = (void (*)()) dlsym(cblas, "cblas_sdsdot");
ret += (sdsdot == NULL) ? 10 : 100;
}
void *gsl = dlopen("/sdcard/Download/libgsl.so", RTLD_LAZY | RTLD_GLOBAL);
if (gsl == NULL) ret += 1000;
return ret; And the ret's value always be 1100! It seems that the RTLD_LAZY and RTLD_GLOBAL do not make any differences. |
I've just tested here, and I'm getting the same exact problem, so it looks like a bug in Android. It should be reported upstream to the Android team, but if you're looking for a quick solution, I guess linking everything statically would work. |
Ok, I found a workaround. Check the latest commit I've made above, it works here. Basically, it looks like not only do we need to load manually all the libraries at runtime, but also we need to make sure that their names are linked in at build time as well. |
Great Job!!! Now it works, fantastic, it's long time since I was stuck on the problem. I'v added the Thanks again. I've almost given it up. Really nice job and I appreciate it very very much. It helps me a lot 👍 |
Work around included in version 1.2. Thanks for reporting and spending time debugging this! |
BTW, a build plugin for Gradle is now available here: |
I want use gsl library on my android phone. I've tried the gsl of javacpp-presets but it didn't work. The error said that some .so library did not found. So I want to compile the gsl library myself. I've download the gsl library and do as the gsl presets's cppbuild.sh. The main three line:
It works fine. And now I have a gsl library compiled with arm-linux-androideabi-gcc. Now I'm using this C++ code:
And the java code:
And I've added the header file path and library path of my newly compiled gsl library to the gradle file. So now I can completely rebuild the project and no errors come out. But when I run it, it says that "could not load library "libgsl.so.19"". I unzip the generated apk file and libgsl.so is not there(only my libjniJavacppDemo.so).
If I copy the libgsl.so to the armeabi folder, it won't package into the apk file automatically. So how to fix this? Please help me.
The text was updated successfully, but these errors were encountered: