Many related questions have been asked regarding NDK linker errors, but I couldnt clearly found a solution to my situation.
I am trying to extend a sample NDK applicaiton, by adding 4 more local files of my own.
I am including them in the Android.mk file, and including the .h files appropriately.
Here is my Android.mk file.
include $(BUILD_SHARED_LIBRARY)
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libgl2jni
LOCAL_CFLAGS := -Werror
LOCAL_SRC_FILES := gl_code.cpp \
sglBandwidthBench.c \
sglBandwidth.c \
common.c \
timer.c
LOCAL_LDLIBS := -llog -lGLESv3 -lEGL
include $(BUILD_SHARED_LIBRARY)
and the .h files inclusion has been proper. but the compilation gives me undefined reference to function x.
I added the files sglBandwidthBench.c sglBandwidth.c common.c timer.c, none of them contain a main function, and the only link is through referecing one of those functions in gl_code.cpp.
how can I link these files together successfully? I couldnt think of any way of specifying it. Any help would be much appreciated.
As you may know, link errors on undefined references are due to one or more method's implemetation not being found by the build system inside the prebuit libraries you provided. So, bottom line, you are probably missing the shared library which contains the implementation for function x.
My advice would be to double-check if you actually have libGLESv3.so under any of your <ndk>\platforms\<android-api-level>\arch-arm\usr\lib directory. Alternatively, check <ndk>\docs\STABLE-APIS.html to see if all the libraries you're using are listed there. If one of them is not, you will either need to upgrade your NDK version or to manually add the missing library to your source code (for that, read section PREBUILT_SHARED_LIBRARY from <ndk>\docs\ANDROID-MK.html).
Hope that this helps!
EDIT: Hi Sai, from what I just learned from your comments, you are trying to call a method implemented in a .c file from inside a .cpp one. So you need to enclose the contents of your gl_code.cpp with the following piece of code:
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
Related
I am trying to include my prebuilt library on the existing Android Module art/runtime/. I have followed the official documentation, found here. In detail, these are the changes I 've made:
Added lines in art/Android.mk:
# This makes sure my library's .mk is found
include $(art_path)/mylib/Android.mk
Added lines in art/runtime/Android.mk:
# Added this, after the LOCAL_C_INCLUDES
LOCAL_STATIC_LIBRARIES := mylib-prebuilt
# Also, on the next mention of LOCAL_STATIC_LIBRARIES, I changed the
# assignment operator to '+=', so mylib won't overriden
Include in art/runtime.cc source mylib's header:
#include "mylib.h"
// then at some point use it
I have put mylib sources in art/mylib. I manually build, using a regular Makefile, the archive libmylib.a, which I want to be statically linked to libart.so.
In the Android.mk found at art/mylib I have added the following:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := mylib-prebuilt
LOCAL_SRC_FILES := $(LOCAL_PATH)/libmylib.a
LOCAL_EXPORT_C_INCLUDES := \
$(LOCAL_PATH)/mylib.h \
$(LOCAL_PATH)/another_header.h
include $(PREBUILT_STATIC_LIBRARY)
By exporting the C includes, the dependent modules should have automatically appended them to their local list. However, this is not the case, as I get the error:
fatal error: 'mylib.h' file not found
If I workaround this issue, with a stupid way that I really shouldn't, I stumble upon a link error, as my libmylib.a is never used during linking.
Other information:
I have placed mylib in art/mylib as it will be part of the art namespace and its methods will be calling/being called by art/runtime sources, e.g. runtime.cc. I have chosen to go with prebuilt-libraries, instead of directly including my sources, like Garbage Collector (found at art/runtime/gc`), as I want to pass particular compilation flags to individual source files.
I have already tried, and failed, solutions to other questions, found here and here.
Any thoughts?
EDIT:
When I try to make a full build, I get the following error:
make: *** No rule to make target
'out/host//obj/STATIC_LIBRARIES/mylib-prebuilt_intermediates/export_includes',
needed by
'out/host//obj/EXECUTABLES/dex2oat_intermediates/import_includes'.
Stop.
Thanks!
I finally managed to get this to work.
My library is now placed at art/runtime/mylib.
In art/runtime/Android.mk, I include the sources with:
LOCAL_C_INCLUDES += art/runtime/mylib
This makes mylib.h visible to the runtime source files.
The art/runtime/mylib/Android.mk has changed almost completely to:
LOCAL_MODULE := libmylib
LOCAL_SRC_FILES := libmylib.a
LOCAL_MODULE_SUFFIX := .a
LOCAL_MODULE_CLASS := STATIC_LIBRARIES
include $(BUILD_PREBUILT)
In my previous attempts, LOCAL_EXPORT_C_INCLUDES, in contrary to documentation, it didn't copy files to the dependent modules. Also PREBUILT_STATIC_LIBRARY didn't seem to be working.
Now, I can build my library in an archive of objects, using regular makefiles, and the build system copies it each time it gets changed to the appropriate locations, so at the link stage can be blended with libart.so.
I found similar questions on SO but none of them were with the same workflow.
I have a .so library (libcurl) in my project. The project builds but I need to get a hold of curl.h in my c code inside JNI.
Here's my Android.mk file:
LOCAL_PATH:= $(call my-dir)
LIBS_PATH := libs/$(TARGET_ARCH_ABI)
include $(CLEAR_VARS)
LOCAL_MODULE := libcurl
LOCAL_SRC_FILES := $(LIBS_PATH)/libcurl.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := testLib
LOCAL_SRC_FILES := lib.c
LOCAL_SHARED_LIBRARIES += libcurl
include $(BUILD_SHARED_LIBRARY)
Here's my c class:
#include "curl/curl.h"
#include "lib.h"
JNIEXPORT jint JNICALL Java_com_example_test_1libcurlandroidlib_Lib_getTestNumber
(JNIEnv *env , jclass clazz)
{
return 99;
}
The issue is with the "curl/curl.h" include command. I have also tried as but it does not find it either:
jni/lib.c:2:23: fatal error: curl/curl.h: No such file or directory
#include "curl/curl.h"
I have my libcurl.so file inside a lib folder inside the JNI folder, which at build time generates the same (I think) file into the libs folder at the root of the app:
Does anyone have any idea why I am not able to get a referece to curl.h, or what I have to do to get a hold of this library?
Thank you!
jni/lib.c:2:23: fatal error: curl/curl.h: No such file or directory
include "curl/curl.h"
To make use of this library, you need not only the compiled .so file, but also a set of function prototypes (and perhaps data type definitions) customarily provided by a header file.
With a well-defined library installation, these would be provided in a path adjacent to the binary - ie, you would have some "curlibrary/lib/libcurl.so" and next to it a "curlibrary/include/curl/curl.h"
To make that work, you would add the path of curl's include directory to your compiler command line, presumably by adding it to your Android.mk
LOCAL_C_INCLUDES := curlibrary/include
Or wherever you are keeping it.
To make use of the include path, your references to the library in code need to be enclosed in angle brackets, not double quotes, ie
#include <curl/curl.h> //this searches the include path
instead of
#include "curl/curl.h" //while this specifies a location relative to this source file
In a more fly-by-night context you may not really have a well-defined installation, but simply a .so file (hopefully compatible with your Android ABI) that you want to use, and a header file that you have either extracted or even re-created. In that case, you might more haphazardly toss "curl.h" somewhere in your project source, and include it via a specific quoted path as you were trying to do. Provided that path is correct, it will work - but it breaks the clean hierarchy of design, and could cause confusion if the api of curl ever changes in the future.
I added some new functionality in C and when I try to build it, it gives me the following error:
libnativehelper/include/nativehelper/JNIHelp.h:116: error: undefined reference to 'jniRegisterNativeMethods' error.
I have included jnihelp.h in my C files.
Is this a makefile related issue or am I missing something?
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := newfile
LOCAL_SRC_FILES := newfile.cpp
include $(BUILD_SHARED_LIBRARY)
EDIT 6/5/14: I finally fixed it. Just thought I'd put all the info here in case someone else needs it.
The manifest had to be modified to load certain libraries as mentioned in my comment below.This was to fix the undefined reference to 'jniRegisterNativeMethods' error
The cpp file that had the native implementation had to be inside an extern "C" block. This was causing the UnsatisfiedLinkError.
You need to go to parent folder where you have your build and dalvik binaries. Then from there you need to type:
build yourproj
(replace yourproj with folder you have your codes in it)
I found the issue was indeed in the makefile
I looked around for other JNI implementations and added this to the makefile
LOCAL_SHARED_LIBRARIES := \
libandroid_runtime \
libandroidfw \
libnativehelper \
libRS \
libcutils \
libskia \
libutils
I have no idea what a few of the libraries in there are for, but I left them there and it compiled.
Now I have a different issue. I get the 'Unsatified Link error' when I load the compiled library. Does anyone have an idea on this?
Edit: My compiled libraries are being transferred to the phone. I manually pushed them onto the /system/lib directory on the phone but I still get the 'UnsatisfiedLinkError'.
I'm trying out NDK for the first time, and I'm stuck with building this project. I'm attempting to use the libraries used in Android's screencap recording program to read data from my screen. I understand that I need to use LibGUI, which I've pulled from my phone. Whenever I compile, however, I get this as an error message:
C:/Users/Kevin/Desktop/ScreenCapture//jni/main.cpp:2:34: fatal error: gui/ISurfaceComposer.h: No such file or directory
Which is odd, considering that I have libgui.so included.
What my main file looks like:
#include <stdio.h>
#include <gui/ISurfaceComposer.h>
int main() {
printf("Started!");
return 0;
}
What my Android.mk looks like:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libgui-prebuilt
LOCAL_SRC_FILES := libgui.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := screencapture
LOCAL_SRC_FILES := main.cpp
LOCAL_SHARED_LIBRARIES := libgui-prebuilt
include $(BUILD_EXECUTABLE)
And I have both the main file and libgui.so in the same folder.
main.cpp:2:34: fatal error: gui/ISurfaceComposer.h: No such file or directory
Your error message indicates that the compiler is unable to find a header file, but your attempted solution is to provide a shared object (.so) library from the phone.
Libraries might help at link time, but before you can link you must successfully compile, and to do that you are going to have to obtain the missing header (perhaps from AOSP sources, as source code it will not be found on the phone) or else recreate it by deducing its contents from clues you collect. Unfortunately, it often isn't possible to take just one internal header out of AOSP, as it will likely depend on many others.
Linking against private system internals also introduces a risk of your program breaking if the private interface between internal components changes between Android versions.
(Normally I would also mention that you are unlikely to be able to record a screen with the NDK in it's normal usage of making a shared library to link into an application process, however your Android.mk seems to indicate you are building an executable - that might work if you can succesfully build it and you run it as a user with sufficient permission such as adb's shell userid or using a root hack)
Add one line for module screencapture:
LOCAL_C_INCLUDES := $(LOCAL_PATH)/
If you haven't folder gui, you need to copy&paste includes headers *.h into folder jni/gui. Always such a requirement about using like that for ndk...
Or second case - using other location of this source for ldlibs:
LOCAL_LDLIBS := -L/full_path_to_source_gui/gui/
I'm trying to create a shared library that links to another shared library.
Here is my main module Android.mk:
TOP_LOCAL_PATH := $(call my-dir)
include $(call all-subdir-makefiles)
LOCAL_PATH := $(TOP_LOCAL_PATH)
include $(CLEAR_VARS)
LOCAL_CPP_EXTENSION := cpp
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ $(LOCAL_PATH)/lib/include
LOCAL_MODULE := SightCore-jni
LOCAL_SRC_FILES := SightDemo.cpp SightCore-jni.cpp
LOCAL_SHARED_LIBRARIES := SightAPI
LOCAL_LDLIBS = -llog
include $(BUILD_SHARED_LIBRARY)
I also have the prebuilt shared library in ./lib directory with its own Android.mk file:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := SightAPI
LOCAL_SRC_FILES := libSightAPI.so
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
The SightCore-jni.cpp source file is the jni interface to the shared library and is loaded using the command
System.loadLibrary("SightCore-jni");
During the ndk-build process I get no compilation or linkage errors.
When I try to run the application and access one of the native methods I get the UnsatsfiedLinkError.
I noticed that if disable the references to the SightAPI in my jni code and put a typo to the LOCAL_STATIC_LIBRARIES := SightAPI line, The build is successful and there is no UnsatisfiedLinkError.
This mean that the jni code I have is good (I'm actually sure it is ok...)
So the observation is as follows:
If I compile the shared library with the prebuilt shared library I get a corrupted .so file.
If I compile the same ndk project without linking to the prebuilt shared library there is no problem loading the shared library from the java side.
Please help me out if you can.
Thanks in advance,
Ita
Found the issue.
Apparently the ndk build system doesn't automatically load referenced shared libraries, even if they are declared in your Android.mk.
I had to call on System.loadLibrary(SightAPI) & System.loadLibrary("SightCore-jni") in order to solve this issue. I would have expected that the only library to load would have been the main library SightCore-jni.
Well..I guess the moral is If you want something done, do it yourself :)
+1 to Roy Samuel for his effort and correct instincts.
I hope this helps anyone.
Cheers
Have you made sure that the cpp function name, that you'd like to use over JNI, is corresponding to the package name of the Java wrapper class where System.loadLibrary("SightCore-jni"); is present?
e.g. If you would like to use the C function, myFunction in the java layer, and suppose your JNI wrapper class is in the package com.my.package.sightcore,
then your C code function name should be like this :
JNIEXPORT JNICALL Java_com_my_package_sightcore_myFunction(JNIEnv * env, jobject thiz, ...)
If you are running your app on your device,
See if the API levels, and hence, the sdk release matches to your device's android version (API level).
Hope this helps. Let me know if you need more clarifications...
This happened to me, and the solution for me was to make sure I was including the proper file libgnustl_shared.so and not libc++_shared.so after I switched compilers. So, just making sure either one of these files is the correct one for your build, and making sure it's been updated with the latest, you shouldn't get this issue any longer.