Undefined reference error while compiling C files with android ndk - android

I have a bunch of C files with extensions .c and .h. I want to compile these files with Android NDK. When I tried with only one file, NDK worked perfectly, but when I tried including other files inside this main C files with includes, I get an error. What an I missing? This is my Android.mk file:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_LDLIBS := -llog
LOCAL_MODULE := ndksetupdemo
LOCAL_SRC_FILES := mymain_c_file.c
LOCAL_C_INCLUDES := includes
include $(BUILD_SHARED_LIBRARY)
Should I include anything more?

It appears that you only link against the log library (LOCAL_LDLIBS := -llog). If you are referencing functions that are not defined in any of the included headers and in your mymain_c_file.c, you will get the undefined reference error. You will need to find out what other libraries you need to link against and list them in LOCAL_LDLIBS.
If the functions are defined in the other .c files, you need to add them to the LOCAL_SRC_FILES variable.

Related

Use external static library in application (NDK)

I have recently started working with NDK and am stuck with a problem. I basically want to use an external static library (.so) into my application. Here's what I've tried till now.
Create a library
1) Add a method in the Java class with native keyword
public native static void FibNR ();
2) In the terminal navigate to the project folder and run the following command
mkdir jni
javah -jni -classpath bin/classes/ -d jni/ com.example.fibonaccinative.FibLib
3) Refresh project and add a C file corresponding to the generated H file.
4) Create a Android.mk file in the JNI folder and add the following code in it
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
OPENCV_LIB_TYPE :=STATIC
LOCAL_SRC_FILES := com_example_fibonaccinative_FibLib.c
LOCAL_MODULE := com_example_fibonaccinative_FibLib
include $(BUILD_SHARED_LIBRARY)
5) Build the code using the following command
/Developer/android-ndk-r9b/ndk-build all
The above steps execute successfully and I'm able to view the results of the c code also. Now I want to create a new application and use the generated .so file (com_example_fibonaccinative_FibLib.so) into it. For this I do the following
Use the library
follow steps 1, 2 and 3 from above for the new application
4) Create a Android.mk file in the JNI folder and add the following code in it
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
OPENCV_LIB_TYPE :=STATIC
LOCAL_SRC_FILES := com_example_usingstaticlibrary_LibraryTest.c
LOCAL_MODULE := com_example_usingstaticlibrary_LibraryTest
LOCAL_SHARED_LIBRARIES :=libcom_example_fibonaccinative_FibLib.so
LOCAL_LDLIBS := -L$(SYSROOT)/usr -llog
include $(BUILD_SHARED_LIBRARY)
5) Build the code using the following command
/Developer/android-ndk-r9b/ndk-build all
I'm not sure what to do next. What I think is I need to call the function of the library into com_example_usingstaticlibrary_LibraryTest.c. But doing so gives me an error saying
'com_example_fibonaccinative_FibLib' undeclared
EDIT 1:
1) In project 2 (where I want to use the Prebuilt Shared Library (.so)) I copied the library into the 'jni' folder
2) Changed the Android.mk file with the below text.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libcom_example_fibonaccinative_FibLib
LOCAL_SRC_FILES := libcom_example_fibonaccinative_FibLib.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := com_example_usingstaticlibrary_LibraryTest
LOCAL_SHARED_LIBRARIES := libcom_example_fibonaccinative_FibLib
LOCAL_SRC_FILES := com_example_usingstaticlibrary_LibraryTest.c
include $(BUILD_SHARED_LIBRARY)
3) Added the .h file from the old project (com_example_fibonaccinative_FibLib.h) into the 'jni' folder
4) Changed the source of com_example_usingstaticlibrary_LibraryTest.c to
#include "com_example_usingstaticlibrary_LibraryTest.h"
#include "com_example_fibonaccinative_FibLib.h"
JNIEXPORT jlong JNICALL Java_com_example_usingstaticlibrary_LibraryTest_callLibraryFunction
(JNIEnv *env, jclass class) {
Java_com_example_fibonaccinative_FibLib_fibNR(env, class, 500l);
return -500l;
}
Clean/Build results into the following error
undefined reference to 'Java_com_example_fibonaccinative_FibLib_fibNR'
Edit 2:
With reference to this I've edited the Android.mk as follows
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := com_example_fibonaccinative_FibLib
LOCAL_SRC_FILES := libcom_example_fibonaccinative_FibLib.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := com_example_usingstaticlibrary_LibraryTest
LOCAL_SRC_FILES := com_example_usingstaticlibrary_LibraryTest.c
LOCAL_SHARED_LIBRARIES := com_example_fibonaccinative_FibLib
include $(BUILD_SHARED_LIBRARY)
The NDK build command compiles the code without error. When trying to load the library it gives the following error
Exception Ljava/lang/UnsatisfiedLinkError; thrown while initializing Lcom/example/usingstaticlibrary/LibraryTest
When I remove LOCAL_SHARED_LIBRARIES := com_example_fibonaccinative_FibLib it works fine but I cannot use any function of the Prebuilt shared library.
Edit 3:
I tried a few more things including the suggestion by #jcm but nothing worked. I'm now attaching the source code. It has both the projects (Cleaned version to reduce size).
FibonacciNative: Contains the first project.
UsingStaticLibrary: Contains the second project. I intend to use the Prebuilt Shared Library of the first project into the second one.
You say you want to include a precompiled static library .a, but the file you reference is a shared library .so. If you still want to include a static library, here comes the solution and explanation:
LOCAL_SHARED_LIBRARIES :=libcom_example_fibonaccinative_FibLib.so
You're trying to include the static library as a shared one, looks like an accidental slip from using the previous shared library entry as reference :).
Upon that, Android makefiles still requires you to actually make a module for the external library.
include $(CLEAR_VARS)
LOCAL_MODULE := com_example_fibonaccinative_FibLib
LOCAL_SRC_FILES := com_example_fibonaccinative_FibLib.a
include $(PREBUILT_STATIC_LIBRARY)
Then you can simply add it as a dependency:
LOCAL_STATIC_LIBRARIES := com_example_fibonaccinative_FibLib
But if you're actually trying to include an external shared library. You would need to change the above to the following:
include $(CLEAR_VARS)
LOCAL_MODULE := com_example_fibonaccinative_FibLib
LOCAL_SRC_FILES := com_example_fibonaccinative_FibLib.so
include $(PREBUILT_SHARED_LIBRARY)
and include it as a shared library.
LOCAL_SHARED_LIBRARIES := com_example_fibonaccinative_FibLib
Hope I helped!
Disclaimer: I have not actually tried to compile an example, simply referencing my knowledge and quick research.
References:
Android NDK: Static library used is different than precompiled library specified
As you're including libcom_example_fibonaccinative_FibLib.so as LibraryTest's shared library, in your java static method, you should load it before loading LibraryTest:
System.loadlibrary(com_example_fibonaccinative_FibLib);
System.loadLibrary(LibraryTest);
Update:
After checking your code, LibraryTest.java should look like:
package com.kochartech.usingstaticlibrary;
public class LibraryTest {
public native static long callLibraryFunction();
static {
System.loadLibrary("com_kochartech_fibonaccinative_FibLib");
System.loadLibrary("com_kochartech_usingstaticlibrary_LibraryTest");
}
}

NDK: using user created .so when trying to build another .so

I'm trying to link some .so that I generated using the NDK to a new .so I'm trying to create,
as the old .so contains definitions of functions that I want to use in the new .so.
I've tried this Android.mk :
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := prog_test
LOCAL_SRC_FILES := main.c
LOCAL_MODULE_TAGS := optional
LOCAL_SHARED_LIBRARIES += mylib
include $(BUILD_SHARED_LIBRARY)
$(call import-module,<tag>) # with and without
I've also tried this method I found in stackoverflow NDK - How to use a generated .so library in another project but still no succes as I get always :
prebuilt/linux-x86/toolchain/arm-linux-androideabi-4.4.x/bin/../lib/gcc/arm-linux-androideabi/4.4.3/../../../../arm-linux-androideabi/bin/ld: error: cannot find -lmylib.so
I really appreciate any help to solve this issue.
B.R
you have to use include $(PREBUILD_SHARED_LIBRARY) instead of include $(BUILD_SHARED_LIBRARY)

Android NDK: Problems building library depending on a prebuilt one

I have a c library called B and it depends on other c library called A. I am sure I can successfully compile and use A through Android NDK.
Now I am trying to compile the B library using Android NDK. I have and Android project with a jni folder. My jni folder contains the A and B folders, they have the libraries c code. The jni folder also has a prebuilt folder, and it contains the a.so file (the prebuilt A library file).
My problem is that I can not build the B. I can compile it, but I cannot link it. Please, could anyone help me pointing what would be my mistake? A and B are generic names I am using to my projects, not the real ones I am using. I will list below the Android.mk files.
The Android.mk file used to build A (this file is not visible to the Android Project I described, although it has also the A code):
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libA
LOCAL_SRC_FILES := helloworld.c A/src/fileA.c
LOCAL_C_INCLUDES := $(LOCAL_PATH)/A/src
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/A/src
include $(BUILD_SHARED_LIBRARY)
The Android.mk file in the prebuilt folder:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libA
LOCAL_SRC_FILES := prebuilt/libA.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/A/src
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libB
LOCAL_SRC_FILES := B/src/fileB.c
LOCAL_SHARED_LIBRARIES := libA
include $(BUILD_SHARED_LIBRARY)
When I execute the ndk-build command I have the final output to be something like:
B/src/fileB.c:15: error: undefined reference to
'A_function' collect2: ld returned 1 exit status make: *
[obj/local/armeabi/libB.so] Error 1
Your B library files can actually access the A library, but they just don't know how. Add the required headers (.h files from the A library) to a subfolder of JNI and specify the following :
LOCAL_C_INCLUDES := $(LOCAL_PATH)/your/sub/folder
in your B project declaration.
I still had a problem, and had to declare the A library as PREBUILT_STATIC and then add to the B library
LOCAL_WHOLE_STATIC_LIBRARIES := libA

Loading shared libs using Android.mk

How can I specify shared libraries to load in the Android.mk when compiling with ndk-build ?
Edit: This is my Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := lib-crypto
LOCAL_SRC_FILES := libcrypto.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := tema1
LOCAL_SRC_FILES := tema1.c
LOCAL_SHARED_LIBRARIES := lib-crypto
LOCAL_C_INCLUDES := /home/aleksei/openSSL0.9.8/include
include $(BUILD_EXECUTABLE)
libcrypto.so is the library that I have built for android. I want to make a program using it. Now it gives me this error:
Install : libcrypto.so => libs/armeabi/libcrypto.so
Executable : tema1
./obj/local/armeabi/libcrypto.so: undefined reference to `dladdr'
collect2: ld returned 1 exit status
make: *** [obj/local/armeabi/tema1] Error 1
PREBUILT_SHARED_LIBRARY
Points to a build script used to specify a prebuilt shared library.
Unlike BUILD_SHARED_LIBRARY and BUILD_STATIC_LIBRARY, the value
of LOCAL_SRC_FILES must be a single path to a prebuilt shared
library (e.g. foo/libfoo.so), instead of a source file.
You can reference the prebuilt library in another module using
the LOCAL_PREBUILTS variable (see docs/PREBUILTS.html for more
information).
read more from http://source-android.frandroid.com/ndk/docs/ANDROID-MK.html
Show me what you have done till yet and where you facing problem.?
I had the same problem. To fix it, I did the following:
In the same directory as your Android.mk file, create a file named Application.mk
Add the following line of code into Application.mk:
"APP_PLATFORM := android-8"
If you already have an Application.mk file, just add the code in step 2 to the existing file. Now call ndk-build and see if it links. ndk-build may be compiling with an old version of libdl which does not have dladdr(). The code in step 2 will cause ndk-build to use an updated libdl which has dladdr().

Android NDK linking problems

I compiled Sox et al with NDK. So, I have all Android-friendly shared libs.
I made a simple test file which calls a sox function.
NDK build tells me:
undefined reference to `sox_open_read'
sox_open_read is defined in sox.h. I know it's finding sox.h because it gives me a warning about that file:
In file included from (...)/sox/sox.h:19
So maybe it wants to find sox_open_read in the actual libsox.so. Well, I've tried about a 100 different ways to tell it where the sox shared lib is e.g.
LOCAL_SHARED_LIBRARY := sox
LOCAL_LDLIBS := -L$(LOCAL_PATH_FULL)/jni/libs/libsox.so
However, It will work if I specify Sox as a static library:
#LOCAL_SHARED_LIBRARY := sox
LOCAL_STATIC_LIBRARIES := sox
LOCAL_LDLIBS := -L$(LOCAL_PATH_FULL)/jni/libs/libsox.so
It's my understanding that I don't want to staticly link to the sox lib - I want to dynamically link to it.
You should define libsox.so as a prebuilt library. Create a makefile as the following and put your prebuilt libsox.so in the same directory with this makefile. After that, you can use libsox same as you've rebuilt it. Don't forget to include this makefile into your build.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libsox
LOCAL_SRC_FILES := libsox.so
include $(PREBUILT_SHARED_LIBRARY)

Categories

Resources