I am building an Android App with native support. The app compiles and runs when I'm using a Mac. Now I want to switch to a Windows for development, I get this error when I try to run the app. I'm probably just missing the obvious here, any ideas?
Error:Execution failed for task ':app:compileMyApp_moduleArm64-v8aDebugSharedLibraryMyApp_moduleMainC'.
No tool chain is available to build for platform 'arm64-v8a':
- Tool chain 'ndk-gcc' (GNU GCC): Could not find C compiler 'aarch64-linux-android-gcc'. Searched in:
- C:\AndroidDevelopment\android-ndk-r10e\toolchains\arm-linux-androideabi-4.9\prebuilt\windows-x86_64\bin
- C:\AndroidDevelopment\android-ndk-r10e\toolchains\arm-linux-androideabi-4.9\prebuilt\windows-x86_64\bin
- C:\AndroidDevelopment\android-ndk-r10e\toolchains\aarch64-linux-android-4.9\prebuilt\windows-x86_64\bin
- C:\AndroidDevelopment\android-ndk-r10e\toolchains\x86-4.9\prebuilt\windows-x86_64\bin
- C:\AndroidDevelopment\android-ndk-r10e\toolchains\x86_64-4.9\prebuilt\windows-x86_64\bin
- C:\AndroidDevelopment\android-ndk-r10e\toolchains\mipsel-linux-android-4.9\prebuilt\windows-x86_64\bin
- C:\AndroidDevelopment\android-ndk-r10e\toolchains\mips64el-linux-android-4.9\prebuilt\windows-x86_64\bin
The .c file related to the error:
#include <jni.h>
JNIEXPORT jstring JNICALL
Java_co_mhmt_myapp_ui_activities_MainActivity_nativeFun(JNIEnv *env, jclass type) {
return (*env)->NewStringUTF(env, "Hello from the other side");
}
It happens with NDK installations, especially on Windows. In most cases, simple reinstall (preferably - automatic via Android Studio upgrade) solves the problem. Note that the new release 11 has been released recently.
The problem was, as others stated, related to the NDK installation. Possibly because I had downloaded and extracted the NDK manually. Doing so through Android Studio solved the problem.
Related
I compiled the gRPC Android example from here.
I want to run the program as executable from adb shell.
Added these lines to grpc-helloworld.cc:
#include <iostream>
int main() {
std::cout << "qwerty" << std::endl;
return 0;
}
And these lines to its CMakeLists.txt:
add_executable(avocado
src/main/cpp/grpc-helloworld.cc)
target_include_directories(avocado
PRIVATE ${HELLOWORLD_PROTO_HEADERS})
target_link_libraries(avocado
helloworld_proto_lib
android
${log-lib})
Then I pushed the generated executable and libs file and tried to run it:
LD_LIBRARY_PATH=. ./avocado
I got the following error:
[libprotobuf FATAL
/home/buga/grpc/third_party/protobuf/src/google/protobuf/stubs/common.cc:79]
This program was compiled against version 3.0.0 of the Protocol Buffer
runtime library, which is not compatible with the installed version
(3.5.1). Contact the program author for an update. If you compiled
the program yourself, make sure that your headers are from the same
version of Protocol Buffers as your link-time library. (Version
verification failed in
"out/soong/.intermediates/frameworks/av/drm/libmediadrm/libmediadrm/android_arm64_armv8-a_kryo300_shared_core/gen/proto/frameworks/av/drm/libmediadrm/protos/plugin_metrics.pb.cc".)terminating
with uncaught exception of type google::protobuf::FatalException: This
program was compiled against version 3.0.0 of the Protocol Buffer
runtime library, which is not compatible with the installed version
(3.5.1). Contact the program author for an update. If you compiled
the program yourself, make sure that your headers are from the same
version of Protocol Buffers as your link-time library. (Version
verification failed in
"out/soong/.intermediates/frameworks/av/drm/libmediadrm/libmediadrm/android_arm64_armv8-a_kryo300_shared_core/gen/proto/frameworks/av/drm/libmediadrm/protos/plugin_metrics.pb.cc".)
Aborted
What am I doing wrong?
We realized that there is a version of the protobuf library called libprotobuf-cpp-full.so and libprotobuf-cpp-lite.so, and it seems that their version is 3.0.0. This is conflicting with our version (3.5.1) which is compiled into either a static lib, or as a shared lib.
I'm not quite sure why this happens. Something about once the linker loads helloworld_proto_lib, it overrides all loaded protobuf symbols, and for some reason another library that you had nothing to do with crashes your program. But that's not telling you anything new.
Here's one way to solve this problem:
1. Changes to grpc-helloworld.cc
Make the main extern "C", and change its name maybe. For example:
extern "C" int my_main() {
std::cout << "qwerty" << std::endl;
return 0;
}
2. Add file grpc-avocado.cc
This will contain the actual main of the executable, which will dynamically load the libraries helloworld_proto_lib and grpc-helloworld. Here's how to do it:
#include <iostream>
#include <android/dlext.h>
#include <dlfcn.h>
int main() {
android_dlextinfo extinfo;
extinfo.flags = ANDROID_DLEXT_FORCE_LOAD;
void* proto_lib = android_dlopen_ext("/path/to/libhelloworld_proto_lib.so", RTLD_LAZY, &extinfo);
void* helloworld = dlopen("/path/to/libgrpc-helloworld.so", RTLD_LAZY);
int (*my_main)() = (int (*)())dlsym(helloworld, "my_main");
return my_main();
}
The function android_dlopen_ext from #include <android/dlext.h>, and its flag argument, are described here: https://developer.android.com/ndk/reference/group/libdl . In the above code we pass the flag ANDROID_DLEXT_FORCE_LOAD, which is documented as:
When set, do not use stat(2) to check if the library has already been loaded.
This flag allows forced loading of the library in the case when for some reason multiple ELF files share the same filename (because the already-loaded library has been removed and overwritten, for example).
Note that if the library has the same DT_SONAME as an old one and some other library has the soname in its DT_NEEDED list, the first one will be used to resolve any dependencies.
I think the text in bold is what explains why this solution works.
3. Change CMakeLists.txt
Since you'll be loading helloworld_proto_lib dynamically, you can now remove it from the executable definition, and there's no need for any proto headers:
add_executable(avocado
src/main/cpp/grpc-avocado.cc)
target_link_libraries(avocado
android
${log-lib})
Build, push, and run
You can now build, push the executable avocado and the two libraries libgrpc-helloworld.so, libhelloworld_proto_lib.so, and run. You don't need LD_LIBRARY_PATH. Good luck with the rest of your project!
I have an Android native library (C++ code base) called:
libserverapp.so
And I cannot get the Android build to find it:
"DllNotFoundException: serverapp"
I am using an internal build system, but when I parse the output of the build process, I can see many calls of the form:
android-ndk/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/arm-linux-androideabi-g++.exe -march=armv7-a
After building my Android app, I inspect the resulting APK (renaming to .zip and extracting), and can see my library file here:
lib/armeabi-v7a/libserverapp.so
I can confirm that "ARMv7" is the target architecture in the Android Player settings, and I access the library, in C#, via:
[DllImport("serverapp", CallingConvention = CallingConvention.Cdecl)]
private static extern void run_sim(StringBuilder matchInput, StringBuilder results, int randomSeed);
I have built a Windows DLL of the C++ code, to use in the Editor, and everything works great. However, when I move to Android, the .so cannot be found. The import settings for libserverapp.so are:
Platform: Android; CPU: ARMv7; Path: Assets/Plugins/Android/libserverapp.so; Type: Native
Given that the final APK includes the .so where I expect it to be (lib/armeabi-v7a/), I assume my Unity settings are correct? Also, I am not using IL2CPP for the Android build.
Finally, when I do an object dump of the library file (using arm-linux-androideabi-objdump.exe), the file format of the library file is "elf32-littlearm".
I feel that the issue here is simply finding the .so, not the functionality within it. Any ideas on what's going on here?
Thanks!
I ended up solving the problem. I mentioned that was using an internal build system. Well, there seems to be a bug in it. I ported things over to official Android NDK makefiles, and then it "just worked". So in this case, the library could be found, but its contents weren't valid.
I am working on a project using Android and native code through JNI.
Android Studio editor keeps telling me that it cannot resolve the native method yet it compiles an executes my program fine.
// In the Java file
private native void startROSNode();
// In the C++ file
JNIEXPORT void JNICALL Java_com_laas_lumusapp_ROSThread_startROSNode(JNIEnv* env, jobject obj)
Is there something I am missing ? (even if it is not project critical it bugs me to see that red line in my editor :))
Thank you in advance !
There might be several reasons, most likely this is due to the ndk 'experimental plugin' (Assuming you have not migrated to CMake). Take a look here, perhaps this will help you: Android Studio 2.0's inline compiler does no longer recognize native code
I have a project that's fully functional in Xcode but not compiling in Eclipse ADT. I have successfully compiled and run android applications in the past, but this is my first time to create a custom class. To replicate the issue:
I create a new project, then add the following 2 files:
//Enemy.cpp
#include "Enemy.h"
USING_NS_CC;
bool Enemy::init()
{
if(!Layer::init())
return false;
return true;
}
//Enemy.h
#ifndef __ColorMirror__Enemy__
#define __ColorMirror__Enemy__
#include <iostream>
#include "cocos2d.h"
USING_NS_CC;
class Enemy : public cocos2d::Layer{
public:
CREATE_FUNC(Enemy);
virtual bool init();
};
#endif
I am able to see them in Eclipse in the list of classes.
Then I create a new enemy in HelloWorldScene.cpp as follows:
Enemy *newEnemy = Enemy::create();
This compiles and runs as expected in Xcode, but when I run build_native.py I get the following errors:
jni/../../Classes/Enemy.h:19: error: undefined reference to 'Enemy::init()'
jni/../../Classes/Enemy.h:19: error: undefined reference to 'vtable for Enemy'
Checking in the jni/../../Classes file, I am able to find Enemy.h and Enemy.cpp.
I have seen several explanations for fixes in other versions of Eclipse, and the suggestion it's a linker error, but I haven't figured out how to fix it in ADT.
Thanks!
So I'm not entirely sure which of these steps fixed the problem, and it may very well have been multiple issues, but here's what I did:
1) Added Enemy.cpp into Android.mk as follows:
Browse to game folder /proj.android/jni and open Android.mk
Open with TextEdit
Below the AppDelegate.cpp in LOCAL_SRC_FILES: added this:
../../Classes/Enemy.cpp \
Save
(still didn't work, so I took it out)
2) Changed workspace for Eclipse (which is specified on opening eclipse) and deleted old workspace
3) Downloaded and set up newest ADT package (Eclipse JUNO)
4) Upgraded Cocos2d-x from 3.1 to 3.2
(still didn't work)
5) Added Enemy.cpp to Android.mk again
Upon completing all those steps, everything works great and compiles as before.
Thanks to Wez Sie Tato for confirming that Enemy.cpp did in fact need to be added to Android.mk... Based on some comments I've seen elsewhere, it appears that my ADT package may have gotten damaged somehow, in conjunction with not having the proper line in Android.mk
I am trying to get cocos2d-android (cocos2d-2.0-rc2-x-2.0.1) "Helloworld" sample to run under windows. I am using latest version of cygwin along side with android ndk r6, android sdk API 8. And I tried the manual here
after a lot of challenges I am down to this problem which I think is in linking the classes at compile time. when I try to run the *build_native.sh* script I get an error stating that in CCGL.h, PFNGLDELETEVERTEXARRAYSOESPROC which is defined as extern, does not name a type.
//declare here while define in CCEGLView_android.cpp
extern PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOESEXT;
extern PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOESEXT;
extern PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArraysOESEXT;
'PFNGLDELETEVERTEXARRAYSOESPROC' is declared in CCEGLView.h.
#if CC_TEXTURE_ATLAS_USE_VAO
#include <EGL/egl.h>
PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOESEXT = 0;
PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOESEXT = 0;
PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArraysOESEXT = 0;
#endif
I tried to add the header address to android.mk under jni directory, to LOCAL_C_INCLUDES, as suggested here,but there were no rules to make them. so can anybody help me with how to compile/link this, it would be much appreciated.
I had this problem, and using a higher version of NDK worked. Try to get the most recent version, reset the environment variables, and run build_native.sh again.
http://developer.android.com/tools/sdk/ndk/index.html