I'm trying to add firebase c++ sdk to my cocos2d-x 3.14 game. So far I've create Android.mk in firebase_cpp_sdk directory:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := firebase-prebuilt
LOCAL_SRC_FILES := libs/android/$(TARGET_ARCH_ABI)/c++/libapp.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := firebase-analytics
LOCAL_SRC_FILES := libs/android/$(TARGET_ARCH_ABI)/c++/libanalytics.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)
Then in my project in Android.mk I've added:
LOCAL_C_INCLUDES += /Users/piotr/Documents/pierdoly/firebase_cpp_sdk/include
LOCAL_STATIC_LIBRARIES += firebase-prebuilt firebase-analytics
$(call import-add-path, /Users/piotr/Documents/pierdoly/firebase_cpp_sdk)
I can sync gradle and build project.
I also can
#include <firebase/app.h>
in AppDelegate.cpp (or h) and it works fine. Even Android studio can see all firebase headers and I can inspect them.
Now, in applicationDidFinishLaunching I've added this:
#if (CC_TARGET_PLATFORM != CC_PLATFORM_ANDROID)
::firebase::App* app = ::firebase::App::Create(::firebase::AppOptions());
#else
::firebase::App* firebaseApp = ::firebase::App::Create(::firebase::AppOptions(), cocos2d::JniHelper::getEnv(), cocos2d::JniHelper::getActivity());
#endif
There's also alternative version via JNICALL from AppActivity.java (to pass correct activity as some say solution above doesn't work):
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
JNIEXPORT void JNICALL Java_org_cocos2dx_cpp_AppActivity_initFirebase(JNIEnv* env, jobject thiz)
{
::firebase::App* app = ::firebase::App::Create(::firebase::AppOptions(), env, thiz);
}
#endif
Yet my problem is: it won't even compile. There's linker error:
Error:(141) undefined reference to 'firebase::App::Create(firebase::AppOptions const&, _JNIEnv*, _jobject*)'
I can clearly "go" into this function in Android Studio and I've rechecked twice parameters I'm giving. They're fine. Yet linker yells at me.
How can I fix linker? What am I missing here?
I had the same problem but found the answer:
It's about the order of the libraries being linked.
You just have to rearrange it like this:
LOCAL_STATIC_LIBRARIES += firebase-analytics firebase-prebuilt
And it should work.
Say thanks to the guys in this github issue
Cocos uses different utils for native libraries build, it can be cmake or ndk util, so check in your frameworks/runtime-src/proj.android/gradle.properties option PROP_BUILD_TYPE and change if it needs from cmake to ndk-build
then look on build.gradle at frameworks/runtime-src/proj.android/app/build.gradle it must use ndk-build correctly.
I use PTAM code taken from here. I try to make an android application with this code.
The PTAM code uses libcvd, TooN, gvars3 library. I generate a .so file from my c++ test file using ndk-build.
Firstly, I try to run below code on android phone :
#include <string.h>
#include <jni.h>
extern "C" {
int returnInt()
{
int returnVal = 4;
return returnVal;
}
}
It can generate .so file without any errors. If I add #include < TooN/TooN.h > , `ndk-build says that
fatal error: TooN/TooN.h: No such file or directory
#include <TooN/TooN.h>
^
compilation terminated.
Android.mk is :
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := test-jni
LOCAL_SRC_FILES := test-jni.cpp
include $(BUILD_SHARED_LIBRARY)
How can I solve this error message?
fatal error: TooN/TooN.h: No such file or directory
#include <TooN/TooN.h>
When you use <> with #include, the compiler will search for the file in your include path (and possibly other predefined directories).
To add a directory to your include path when building a module in Android.mk you would add it to LOCAL__INCLUDES. For example, if the full path to TooN.h is /home/foobar/TooN/TooN.h you should do this:
LOCAL_C_INCLUDES += /home/foobar
I get fatal error: iostream: No such file or directory.There is no folder named iostream under usr/include or usr/local/include.
The iostream class is part of the STL, so you need to specify an STL implementation to build against. This can be done using the APP_STL variable in Application.mk. For example:
APP_STL := gnustl_shared
See this page for a list of STL implementations available with the NDK.
So I'm attempting to use libopus on my native code for an Android application.
My Android.mk file looks like this:
PLATFORM_PREFIX := /opt/android-ext/
LOCAL_PATH := $(PLATFORM_PREFIX)/lib
include $(CLEAR_VARS)
LOCAL_MODULE := libopus
LOCAL_SRC_FILES := libopus.a
include $(PREBUILT_STATIC_LIBRARY)
# I have to redeclare LOCAL_PATH because the library is in /opt/android-ext/
# and my project is somewhere else. Not very elegant.
LOCAL_PATH := /home/sergio/workspace/Project/jni
include $(CLEAR_VARS)
LOCAL_MODULE := opusUtilsNative
LOCAL_SRC_FILES := opusUtilsNative.c
LOCAL_C_INCLUDES += $(PLATFORM_PREFIX)/include
LOCAL_STATIC_LIBRARIES := android_native_app_glue libopus
include $(BUILD_SHARED_LIBRARY)
And my code in opusUtilsNative.c looks like this:
#include "opusUtilsNative.h"
#include <opus/opus.h>
#include <opus/opus_types.h>
JNIEXPORT jbyteArray JNICALL Java_Project_OpusUtils_encode
(JNIEnv * je, jclass jc, jbyteArray data){
int rc;
opus_int16 * testOutBuffer;
unsigned char* opusBuffer;
OpusDecoder *dec;
dec = opus_decoder_create(48000, 2, &rc);
return data;
}
And when I try to build it, it works fine only if I remove the line that uses the "opus_decoder_create" function. Else I will get this:
error: undefined reference to 'opus_decoder_create'
I can see that opus_decoder_create is clearly defined on opus.h, which is clearly being included since if I exclude that line, I'll get an error regarding the opus_int16 and OpusDecoder declarations. How come some definitions are being included and some aren't?
Any help will be greatly appreciated.
This was tricky. After digging around for a bit, I realized I hadn't cross-compiled the opus library correctly, and I didn't have an ARM binary after all.
A good way to verify if your library was cross-compiled correctly:
cd /opt/android-ext/lib #Or wherever the .a file is
ar x libopus.a
file tables_LTP.o #Or any of the .o files generated by ar x
The output should look like this:
tables_LTP.o: ELF 32-bit LSB relocatable, ARM, version 1 (SYSV), not stripped
Otherwise, you might want to double-check your cross-compilation process.
It's error from linker, not from compiler. You forgot to add reference to correspondent libraries to your Android.mk file, do smth like this:
LOCAL_LDLIBS += -lopus
I forgot to integrate one key library
LOCAL_LDLIBS := -lGLESv2
This fixed my problem.
I've seen questions similar to this one, but the scenarios are not exactly the same, nor can I get an answer that works on my problem.
I have the source code for a C++ library. We need to use this library as part of an android application but it also needs to be available for third party to use as a C++ library.
I have a makefile that generates the .a file out of the library's source code, using ndk's compiler. That's the pure C++ part.
On the Java part, I have a simple demo project with a simple activity containing a button. When the button is pressed a call to native code is made.
Everything works fine as long as I don't try to call a function from the library from the JNI function.
Here are the sources for the library:
SimpleMath.h
int Add(int aNumber1, int aNumberB);
SimpleMath.cpp
#include "SimpleMath.h"
int Add(int aNumberA, int aNumberB)
{
return aNumberA + aNumberB;
}
The makefile
APP = simple_app
LIBRARY = simple_library.a
OBJECTS = SimpleMath.o
CFLAGS = -Wall -pedantic
NDK_PATH = /home/jug/perforce/jug_navui_personal_main/Env/Linux/Android/ndk/r7c
CXX = $(NDK_PATH)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/arm-linux-androideabi-g++
AR = $(NDK_PATH)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/arm-linux-androideabi-ar
SYSTEM_LIBS = -lstdc++ -lm
INCLUDE_PATH += ${NDK_PATH}/platforms/android-9/arch-arm/usr/include
all: $(LIBRARY)
$(LIBRARY):
$(CXX) -c SimpleMath.c
$(AR) rcs simple_library.a SimpleMath.o
clean:
rm *.o *.a
On the java side, these are the files:
hello-jni.c
#include <string.h>
#include <jni.h>
#include "../../../native/simple_library/SimpleMath.h"
jstring Java_com_amstapps_samples_draft08jni_MainActivity_helloJni(JNIEnv* env, jobject obj)
{
// Uncommenting the line below results in undefined-symbol compile error
//int d = Add(1, 2);
return (*env)->NewStringUTF(env, "Hello from JNI!");
}
Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := my_simple_library
LOCAL_ARM_MODE := arm
LOCAL_SRC_FILES := ../../../native/simple_library/simple_library.a
include $(PREBUILT_STATIC_LIBRARY)
#include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := eng
LOCAL_ARM_MODE := arm
#LOCAL_PRELINK_MODULE := false
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := hello-jni.c
LOCAL_C_INCLUDES := ../../../android/native/simple_library
LOCAL_STATIC_LIBRARIES := my_simple_library
#LOCAL_WHOLE_STATIC_LIBRARIES := my_simple_library
include $(BUILD_SHARED_LIBRARY)
Application.mk
APP_MODULES := my_simple_library hello-jni
As I said, the problem comes when I to actually make use of the functionality in the library from the jni native code in java application.
Now, I'm not longer sure whether my problem is in the static-library's makefile or on the Android.mk. I first thought it must have to do with the generation of the library itself, but at this point, after seeing there are so many options I didn't know about in Android.mk, I have to admit I have no clue.
What else..?
Oh, yes, I also noticed my pure C++ library is using cpp extension whereas the jni code in java project is using c extension. I tried to have the latter using cpp as well, but compiler complains. Could this be part of the problem?
The error code that I get when trying to compile the Android.mk file is "undefined symbol", so, is the list of functions in simple_library.a (there's actually 1 function) not visible to hello-jni.c because of it being C++ and not plain C?
Another thing you might notice is I'm trying to build the static library on its own makefile as opposed to generating it with Android.mk; there's a reason for that, but at this point I would also be happy if I had to have it in generated by Android.mk if that's what it takes.
I don't see any way to add an attachment in here so that to share a zip with the project.
Let me know if there's something I'm missing.. Otherwise the code is in a depot in bitbucket, so I can easily share it with anyone having an account there too.
Thanks for you answers.
You write a lot of correct things, but you're missing just one.
The function's name gets mangled in C++. And in the .so file you do not get "Add" symbol, but something like "Add#8i". To avoid mangling just use the
extern "C" int Add(int x, int y)
declaration in the .cpp file and in the .h.
Usually one also adds the
/// Some .h file
#ifdef __cplusplus
extern "C" {
#endif
/// Your usual C-like declarations go here
#ifdef __cplusplus
} // extern "C"
#endif
And the
extern "C"
for each of the exported functions in the .cpp file.
What is wrong with my make file?
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := foo
LOCAL_SRC_FILES := foo.c
LOCAL_EXPORT_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)
foo.c
#include <string.h>
#include <jni.h>
#include <android/log.h>
#define LOG_TAG "foo"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
void test() {
LOGI("test");
}
ndk-build
foo.c:9: undefined reference to `__android_log_print'
You need to add
LOCAL_LDLIBS := -llog
to Android.mk
Try the following in your Android.mk file:
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
If you use Android Studio and gradle, it ignores Android.mk. Add this to your build.gradle file:
android {
defaultConfig {
ndk {
moduleName "your_module_name"
ldLibs "log"
}
}
}
For Android Studio 2.2 and tools.build:gradle:2.2.0 using CMake add or edit row in CMakeLists.txt:
target_link_libraries(<your_library_name>
android
log)
Thats connecting log library to yours.
If you upgrade to Android Studio 2.1, above answers do not work, need use ldLibs.add() to load the lib as below:
android.ndk {
moduleName = "[the_module_name]"
ldLibs.addAll(['android', 'log'])
}
In case the project you are working on has the following characteristics that differ from other 'standard' answers:
Not using Android Studio
Not using gradle and the integrated CMake
No Android.mk or Application.mk used at all for build
Using CMake and the toolchain directly (maybe your project is Qt based and without using QtCreator neither)
The following target_link_libraries usage makes it:
find_library(ANDROID_LOG_LIB log)
target_link_libraries(${TARGET_NAME} ${ANDROID_LOG_LIB})
Being TARGET_NAMEthe name of the target to build (having set it up before with add_library or add_executable).
find_library is equally important as well as setting up the toolchain properly (use the toolchain provided by Android SDK at ANDROID_SDK_HOME/cmake/<version>/android.toolchain.cmake so it sets up CMAKE_SYSROOTwhich is used by find_ commands).
We can link a shared library in Android in 3 ways.
In below 3 cases, the lines mentioned should be added in Android.mk
So here are the three ways.
1. LOCAL_LDLIBS way
LOCAL_LDLIBS := -llog
For some reason if 1 doesnt work(it did not work for me), You can try below 2 ways
2. LOCAL_LDFLAGS way
LOCAL_LDFLAGS := -llog
3. LOCAL_SHARED_LIBRARIES way
LOCAL_SHARED_LIBRARIES += liblog
Of course you also need to include #include <android/log.h> in your C/H file.
Yes, you do need to add: LOCAL_LDLIBS := -llog as the other answers/comments have specified, however the original question did not specify if he use the jni library as: LOCAL_JNI_SHARED_LIBRARIES or as LOCAL_REQUIRED_MODULES.
I can pretty much say for sure that he has it used it as: LOCAL_REQUIRED_MODULES because of the LOCAL_EXPORT_LDLIBS := -llog in the question... unless that was added after an edit.
If you use LOCAL_REQUIRED_MODULES the shared library is installed in /system/lib instead of into the apk, because it is a required module. Therefore you will need to add LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog instead of just LOCAL_LDLIBS := -llog so that when the build system is building & linking the jni shared library, it will have the -llog definitions in the correct place, available to be built under $OUT/root/system/lib. Otherwise you will continue to get the same answer, even if you only add LOCAL_LDLIBS := -llog.
So, those who commented that the -L is not needed, and the other answer was correct, they were actually incorrect in this situation.
In lieu with
If using the new Gradle NDK integration in Android Studio 1.3, you need to add ldLibs = ["android", "log"] to your android.ndk options – Stephen Kaiser Sep 24 at 4:20
use ldLibs.addAll(["android", "log"]) for the experimental plugin
Add
LOCAL_SHARED_LIBRARIES:= \
libbinder \
liblog \
to Android.mk
-DCMAKE_CXX_FLAGS="-llog" helps me
This helped for me:
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := nativeDemo
LOCAL_SRC_FILES := main.cpp
LOCAL_LDLIBS += -llog
include $(BUILD_SHARED_LIBRARY)
for the case who use CMakeLists.txt to make
externalNativeBuild {
cmake {
path 'src/main/cpp/CMakeLists.txt'
}
}
just add -llog into target_link_libraries:
target_link_libraries(<your_library_name> -llog)
the env I used are :
gradle-6.5-all.zip
classpath 'com.android.tools.build:gradle:4.1.1'
Android Studio Arctic Fox | 2020.3.1 Patch 1
Build #AI-203.7717.56.2031.7621141, built on August 8, 2021
In the android studio version 2.2 and higher, there is inbuilt support for CPP when you create a new project. Also, the liblog.so is included by default. Nothing to be done apart from including the header file (android/log.h).
Checkout app/CMakeLists.txt that is created by the studio when we create new android studio project. We can see that the find_library() block and target_link_libraries() block for loglib are already present.
Also, pay attention towards the function syntax. It should be:
__android_log_print (int priority, const char *tag, const char *fmt,...);
In my case, I had left out tag parameter and ended up spending good 3 days in figuring it out.
More about CMake: Add C and C++ Code to Your Project
add
LOCAL_SHARED_LIBRARIES:= liblog
to Android.mk can solve my isuue.
This is because the __android_log_print is defined in libLog
TO build with Android.bp, follow the below solution:
In this -android_log_print is defined in NDK, so for this, there is already a library is available. Use "liblog" library using shared_libs tag, take reference of the below code:
target: {
android: {
cppflags: [
"-g",
"-DUSE_LIBLOG",
],
shared_libs: ["liblog"], // can use other dependency if required.
},
darwin: {
enabled: false,
},
},