I covert a ADT project to Android Studio. however, i kept getting the error when building this project:
Error:(687) Android NDK: Module MediaEncoder depends on undefined modules: cutils gnustl dl
This is what is in the Android.mk. I am new to NTK, anybody can advise the issue here?
# building application library
#
include $(CLEAR_VARS)
LOCAL_MODULE := libMediaEncoder
LOCAL_CPP_EXTENSION := .cc .cpp
LOCAL_CPPFLAGS := -O2 -Werror -Wall
LOCAL_C_INCLUDES := $(MY_LOCAL_PATH)
LOCAL_SRC_FILES := main_jni.cpp \
h264encoder.cpp \
g72x/g726_32.c \
g72x/g711.c \
g72x/g72x.c
LOCAL_LDLIBS += -llog -lz
LOCAL_SHARED_LIBRARIES := libcutils\
libgnustl\
libdl
I believe that you use a project that was configured to be built in the context of AOSP build, not by NDK. But it could still work with a very old version of NDK.
The current version, r14 which is integrated into Android Studio 2.3, requires some changes to Android.mk.
include $(CLEAR_VARS)
LOCAL_MODULE := libMediaEncoder
LOCAL_CPPFLAGS := -O2 -Werror -Wall
LOCAL_C_INCLUDES := $(MY_LOCAL_PATH)
LOCAL_SRC_FILES := main_jni.cpp \
h264encoder.cpp \
g72x/g726_32.c \
g72x/g711.c \
g72x/g72x.c
LOCAL_LDLIBS += -llog -lz -ldl
LOCAL_SHARED_LIBRARIES := libcutils_prebuilt
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libcutils_prebuilt
LOCAL_SRC_FILES := {full-path-to}/libcutils.so
include $(PREBUILT_SHARED_LIBRARY)
To resolve the dependency on gnustl, run ndk-build APP_STL=gnustl_static, or define APP_STL in your Application.mk file.
Note that your project uses non-public system library libcutils.so. This library was once included in NDK (see https://stackoverflow.com/a/22017733/192373), but for the last 3 years Google has been struggling to discourage linking to it.
You can build libcutils.so yourself as part of AOSP, or you can adb pull it from your device or even from a compatible emulator. You can also find this binary somewhere on the Web (e.g. GitHub).
The final blow comes with the announced changes to system linking for Android 7.0 Nougat. TL;NR: any app that depends on this library will not work on future Android versions.
You need to install an older version of ndk Android NDK, Revision 10e (May 2015) worked for me and then use that ndk-build
Related
This question already has an answer here:
Android NDK: how to link multiple 3rd party libraries
(1 answer)
Closed 5 years ago.
We are working on a project where we need to create a shared library from the static libraries. The issues we are facing is the static libraries contains a circular dependency. Following is the sample of my makefile:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := Mylib1
LOCAL_SRC_FILES := lib/libMylib1.a
include $(PREBUILT_STATIC_LIBRARY)
....
....
....
LOCAL_MODULE := DisplayDriver
LOCAL_SRC_FILES := \
file1.c \
file2.c \
file3.c
LOCAL_STATIC_LIBRARIES := -Wl,--start-group \
Mylib1 \
Mylib2 \
Mylib3 \
Mylib4 \
-Wl,--end-group
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/include \
$(LOCAL_PATH)/examples \
LOCAL_CFLAGS := -x c -DHAVE_STDINT -DHAVE_SETENV -DNDEBUG -c
LOCAL_LDLIBS += -llog
APP_ABI := armeabi-v7a
include $(BUILD_SHARED_LIBRARY)
When I give the ndk-build V=1 I can see in the output that clearly -Wl,--start-group and -Wl,--end-group is removed from the compilation when it is going to create the shared library. So is there any other flags which is obvious and I am missing the same?
I am using NDK R9 on windows 7 64 bit.
It appears that -Wl,--start-group specified in LOCAL_STATIC_LIBRARIES is ignored.
There use to be LOCAL_GROUP_STATIC_LIBRARIES which would group static libraries with -Wl,--start-group and -Wl,--end-group when linking.
Now (ndk-10c) the only relevant variable is LOCAL_WHOLE_STATIC_LIBRARIES which uses the linker flag --whole-archive.
This is generally useful when there are circular dependencies between several static libraries. Note that when used to build a shared library, this will force all object files from your whole static libraries to be added to the final binary. This is not true when generating executables though.
Not exactly the same thing but may solve the dependency problem.
In my project, I've created a dedicated cpp file which explicitly references the problematic symbols.
auto i_reference_you =
{
(void *)MyClass::some_symbol,
(void *)some_other_symbol
};
This works for me because there are only a few symbols. It's nothing elegant but saves me from fighting the build system.
I'm struggling to get a native Android application correctly link against a custom shared object built in the same AOSP tree.
I have a shared object built with
LOCAL_SRC_FILES += \
src/libscanengine.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include/
LOCAL_C_INCLUDES += kernel/include/
#every module depending on us will
#automagically have this included
LOCAL_EXPORT_C_INCLUDES := \
$(LOCAL_PATH)/include
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := libscanengine
LOCAL_PRELINK_MODULE := false
include $(BUILD_SHARED_LIBRARY)
It gets built and installed as the mm command invocation
build/core/dynamic_binary.mk:141: warning: overriding commands for target `.so'
build/core/dynamic_binary.mk:118: warning: ignoring old commands for target `.so'
build/core/shared_library.mk:54: warning: overriding commands for target `.so'
build/core/dynamic_binary.mk:141: warning: ignoring old commands for target `.so'
No private recovery resources for TARGET_DEVICE X
No recovery.fstab for TARGET_DEVICE X
make: Circular .so <- .so dependency dropped.
make: Circular .so <- out/target/product/X/symbols/system/lib/libscanengine dependency dropped.
make: Circular .so <- .so dependency dropped.
target Non-prelinked: libscanengine (out/target/product/X/symbols/system/lib/libscanengine)
target Strip: libscanengine (out/target/product/X/obj/lib/libscanengine)
Install: out/target/product/X/system/lib/libscanengine.so
Once I try to buil a native application linked against the newly created .so with the following Android.mk
LOCAL_SRC_FILES := \
src/mores.c
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/include/
#not working: commented out
#LOCAL_LDLIBS += \
-lscanengine
#LOCAL_C_FLAGS += \
-L../../out/target/product/X/system/lib/
LOCAL_SHARED_LIBRARIES := \
libscanengine
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := mores
include $(BUILD_EXECUTABLE)
I get:
make: *** No rule to make target `out/target/product/X/obj/lib/libscanengine.so', needed by `out/target/product/X/obj/EXECUTABLES/mores_intermediates/LINKED/mores'. Stop.
I noticed two things: the shared library is installed under X/out/lib as libscanengine and not libscanenegine.so as it is required by the native application.
I have to manually copy the .so everytime, which is stupid since all of this should be handled in some way by the Android build system.
Furthermore, the LOCAL_EXPORT_C_INCLUDES directive does not work. Does it work only with PREBUILT_SHARED_OBJECTS?
Android version is 2.3, there is no Java involved, everything is built under AOSP.
Thank you
j
LOCAL_C_FLAGS += \
-L../../out/target/product/X/system/lib/
does not work because it should read
LOCAL_LDFLAGS += \
-Lout/target/product/X/system/lib
or
LOCAL_LDFLAGS += \
-L$(LOCAL_PATH)/out/target/product/X/system/lib
But this does not explain why LOCAL_SHARED_LIBRARIES is not working. What commands do you use to build?
Whilst not a good solution, if the libscanengine target can't be found implicitly via AOSP, then you can always include it manually, like so.
include $(AOSP_ROOT)/PATH/TO/libscanengine/Android.mk
Regarding why the shared object won't build correctly, a hacky solution is providing a static object directly after the shared one which references it, in the Android.mk. For instance, this I adapted from an existing jpeg port. What I wanted was a shared library I could work with in a separate compilation step, but it wouldn't be built unless it was required by something.
$(call my-dir)
include $(CLEAR_VARS)
LOCAL_ARM_MODE := arm
LOCAL_SRC_FILES := \
jcapimin.c jcapistd.c jccoefct.c jccolor.c jcdctmgr.c jchuff.c \
jcinit.c jcmainct.c jcmarker.c jcmaster.c jcomapi.c jcparam.c \
jcphuff.c jcprepct.c jcsample.c jctrans.c jdapimin.c jdapistd.c \
jdatadst.c jdatasrc.c jdcoefct.c jdcolor.c jddctmgr.c jdhuff.c \
jdinput.c jdmainct.c jdmarker.c jdmaster.c jdmerge.c jdphuff.c \
jdpostct.c jdsample.c jdtrans.c jerror.c jfdctflt.c jfdctfst.c \
jfdctint.c jidctflt.c jidctred.c jquant1.c \
jquant2.c jutils.c jmemmgr.c \
jmem-android.c
# the assembler is only for the ARM version, don't break the Linux sim
ifneq ($(TARGET_ARCH),arm)
ANDROID_JPEG_NO_ASSEMBLER := true
endif
# temp fix until we understand why this broke cnn.com
#ANDROID_JPEG_NO_ASSEMBLER := true
ifeq ($(strip $(ANDROID_JPEG_NO_ASSEMBLER)),true)
LOCAL_SRC_FILES += jidctint.c jidctfst.c
else
LOCAL_SRC_FILES += jidctint.c jidctfst.S
endif
LOCAL_CFLAGS += -I"$(LOCAL_PATH)/./include" -DAVOID_TABLES
LOCAL_CFLAGS += -O3 -fstrict-aliasing -fprefetch-loop-arrays
#LOCAL_CFLAGS += -march=armv6j
LOCAL_MODULE:= jpeg
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := jpeg2
LOCAL_STATIC_LIBRARIES := jpeg
include $(BUILD_SHARED_LIBRARY)
Whilst neither of these are true solutions, as they don't address the underlying reason behind your problems, they may aid you, as they did me, in getting stuff working quickly and automatically.
I am attempting to compile an Android-9 project that calls Android NDK functions (such as "AAsset_close") by running "ndk-build" via the Cygwin terminal, but the "ndk-build" command returns an error message, stating that it is unable to find the function definitions.
The error messages from "ndk-build" are as follows:
[Android NDK path]/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld.exe: [project folder]/static library: in function [function name]:[file name]:39: error: undefined reference to 'AAsset_close'
etc.
My "Android.mk" file is as follows:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := <name of project>
LOCAL_C_INCLUDES := <folders where header files are located>
LOCAL_CFLAGS := $(LOCAL_C_INCLUDES:%=-I%) -O2 -Wall -D__ANDROID__ -DtyANDROID
LOCAL_CPPFLAGS := $(LOCAL_C_INCLUDES:%=-I%) -O2 -Wall -D__ANDROID__ -DtyANDROID
LOCAL_LDLIBS := -lm -lEGL -lGLESv2 -llog -lz -landroid
LOCAL_STATIC_LIBRARIES := android_native_app_glue
LOCAL_ARM_MODE := arm
LOCAL_SRC_FILES := <source files>
include $(BUILD_STATIC_LIBRARY)
...
My "Application.mk" makefile is as follows:
APP_ABI := armeabi armeabi-v7a x86
APP_PLATFORM := android-9
According to the "nm" Unix command, this function is defined within the Android NDK library "libandroid.so", which is present in the NDK path for all target platforms. As demonstrated above, I have included "-landroid" to the "LOCAL_LDLIBS" macro, which should allow me to link against that library. What else do I need to do to fix this compile error?
You show the Android.mk that builds a static library, at this step the linker is not called, threfore $(LOCAL_LDLIBS) is ignored. You probably have another Android.mk or a different section, where you have
include $(BUILD_SHARED_LIBRARY)
Please check, -landroid is probably missing in that section.
why is it that only some of my customers are experiencing an unsatisfied link error whilst it works flawlessly in most cases?
java.lang.UnsatisfiedLinkError: Couldn't load Foo: findLibrary returned null
I read about this problem before but couldn't find a solution. Any ideas?
Thanks
Edit: Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# disable thumb mode
LOCAL_ARM_MODE := arm
LOCAL_MODULE := Foo
#-Wno-psabi to remove warning about GCC 4.4 va_list warning
LOCAL_CFLAGS := -DANDROID_NDK -Wno-psabi -Wno-write-strings
LOCAL_DEFAULT_CPP_EXTENSION := cpp
LOCAL_SRC_FILES := \
source1.cpp \
source2.c
LOCAL_LDLIBS := -lGLESv1_CM -ldl -llog -lz
include $(BUILD_SHARED_LIBRARY)
One reason could be that you built the library for ARM v7 (i.e. with APP_ABI=armeabi-v7a) but not for ARM v6 (APP_ABI=armeabi). But maybe some of your customers are using MIPS, or x86 - powered devices?
If these explanations do not fit, please provide more info, e.g. show your Android.mk and Application.mk files.
I am trying to build an android application that calls into a C++ backend. This backend uses ZeroMQ for messaging. Per the android build page on the ZeroMQ guide, I have built a native toolchain of ndk version 6 and used that to (successfully) build ZeroMQ.
However, when I build my own .so with the JNI implementations, I can't seem to make everything load properly. Specifically, if I call System.LoadLibrary("zmq"), this completes successfully, but if I then call *System.LoadLibrary("my_lib")* I always get an UnsatisfiedLinkError complaining that:
Cannot load library reloc_library[1244]: 29 cannot locate zmq_msg_init'...
The libmy_lib.so has been generated several different ways, each with no success. After generating it, I always copies libmy_lib.so (as well as libzmq.so) to my android project's folder: libs/armeabi/.
# Compile all object files - this part was done for all options
/opt/android-toolchain/bin/arm-linux-androideabi-g++ -fpic -c Client_Events.cpp \
Client Wrapper.cpp jni.cpp -I /opt/android-root/include/ -I /my/project/specific/stuff
# Option 1 - Don't link the lib in at all
/opt/android-toolchain/bin/arm-linux-androideabi-g++ -shared \
-Wl,-soname,libmy_lib.so -o libmy_lib.so jni.o Client_Events.o Client_Wrapper.o
# Option 2 - Link ZeroMQ in statically
/opt/android-toolchain/bin/arm-linux-androideabi-g++ -shared \
-Wl,-soname,libmy_lib.so -o libmy_lib.so jni.o Client_Events.o Client_Wrapper.o \
libzmq.a libstdc++.a -Wl,--whole-archive
# Option 3 - Explicitly link ZeroMQ in dynamically
/opt/android-toolchain/bin/arm-linux-androideabi-g++ -shared \
-Wl,-soname,libmy_lib.so -o libmy_lib.so jni.o Client_Events.o Client_Wrapper.o \
-L /opt/android-root/lib/ -lzmq
With each of these options I tried both explicitly calling System.LoadLibrary("zmq") before loading my own library and not. Nothing varied the results. Using nm confirms that, at least in the case of option #2, the missing symbol *zmq_msg_init* is indeed present in libmy_lib.so.
Any ideas as to why it cannot find the ZeroMQ symbols that are linked in?
I just learnt how to compile a 2nd library and link it to my main library in android ndk. Let me see if I am of any use to you.
The following is how I create my 2nd library (In my case, I build bullet physics library and the irrlicht rendering engine as 2 separate libraries for my game).
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := HEADER FILES
LOCAL_MODULE := bullet
LOCAL_SRC_FILES := SRC FILES
LOCAL_ARM_MODE := arm
LOCAL_CFLAGS := $(LOCAL_C_INCLUDES:%=-I%) -O3 -DANDROID_NDK -DDISABLE_IMPORTGL
LOCAL_LDLIBS := -ldl -llog
include $(BUILD_SHARED_LIBRARY)
Then copy your libxxxx.so (In my case, libbullet.so and libirrlicht.so) to your jni folder. And in your main library .mk file add the following.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := (includes for bullet)
LOCAL_MODULE := bullet
LOCAL_SRC_FILES := libbullet.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := (includes for irrlicht)
LOCAL_MODULE := irrlicht
LOCAL_SRC_FILES := libirrlicht.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := (includes for bullet + includes for irrlicht + includes for main code)
LOCAL_SRC_FILES := main code src files
LOCAL_MODULE := gamescript
LOCAL_ARM_MODE := arm
LOCAL_CFLAGS := $(LOCAL_C_INCLUDES:%=-I%) -O3 -DANDROID_NDK -DDISABLE_IMPORTGL
LOCAL_LDLIBS := -lOpenSLES -landroid -ldl -llog
LOCAL_SHARED_LIBRARIES := bullet irrlicht
include $(BUILD_SHARED_LIBRARY)
And now, add all the libraries to your java code in right order.
System.loadLibrary("bullet");
System.loadLibrary("irrlicht");
System.loadLibrary("gamescript");