Context : I am currently developing an app on Android Studio for the Moverio BT 200 augmented reality glasses. I am using OpenCV, and specifically, the arUco module of the library. This module has to be used with the NDK. Also, it is not on the stable release, so I compiled the library myself (using this guide : https://zami0xzami.wordpress.com/2016/03/17/building-opencv-for-android-from-source/). The build of the library went well. After that, I made a android studio project (customOCVtest). I did it the way I always do when using OpenCV with Android Studio and the NDK, except this time it was with the custom build. I checked if the library was correctly loaded :
private static final String OCVdevTAG = "OCVmainAct";
static {
System.loadLibrary("native-lib");
if(!OpenCVLoader.initDebug()) {
Log.d(OCVdevTAG, "OpenCV not loaded");
} else {
Log.d(OCVdevTAG, "OpenCV loaded");
}
}
The library is indeed loaded when I build.
Now comes the problem : When I try to actually use the arUco module in my native code (here is my native-lib.cpp) :
#include <jni.h>
#include <string>
#include <opencv2/aruco.hpp>
extern "C" {
jstring
Java_com_jambonsama_customocvtest_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
std::string hello = "Hello from C++";
cv::Ptr<cv::aruco::Dictionary> dict = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250);
cv::Mat marker;
cv::aruco::drawMarker(dict, 25, 200, marker, 1);
return env->NewStringUTF(hello.c_str());
}
}
the gradle sync works, but I can't build. I get the following error :
Error:FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:externalNativeBuildDebug'.
> Build command failed.
Error while executing 'C:\Users\JambonSama\AppData\Local\Android\Sdk\cmake\3.6.3155560\bin\cmake.exe' with arguments {--build C:\Users\JambonSama\AndroidStudioProjects\customOCVtest\app\.externalNativeBuild\cmake\debug\mips64 --target native-lib}
[1/1] Linking CXX shared library ..\..\..\..\build\intermediates\cmake\debug\obj\mips64\libnative-lib.so
FAILED: cmd.exe /C "cd . && C:\Users\JambonSama\AppData\Local\Android\sdk\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe -target mips64el-none-linux-android -gcc-toolchain C:/Users/JambonSama/AppData/Local/Android/sdk/ndk-bundle/toolchains/mips64el-linux-android-4.9/prebuilt/windows-x86_64 --sysroot=C:/Users/JambonSama/AppData/Local/Android/sdk/ndk-bundle/platforms/android-21/arch-mips64 -fPIC -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -Wa,--noexecstack -Wformat -Werror=format-security -fno-exceptions -fno-rtti -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -Wa,--noexecstack -Wformat -Werror=format-security -fno-exceptions -fno-rtti -O0 -fno-limit-debug-info -O0 -fno-limit-debug-info -Wl,--build-id -Wl,--warn-shared-textrel -Wl,--fatal-warnings -Wl,--no-undefined -Wl,-z,noexecstack -Qunused-arguments -Wl,-z,relro -Wl,-z,now -Wl,--build-id -Wl,--warn-shared-textrel -Wl,--fatal-warnings -Wl,--no-undefined -Wl,-z,noexecstack -Qunused-arguments -Wl,-z,relro -Wl,-z,now -shared -Wl,-soname,libnative-lib.so -o ..\..\..\..\build\intermediates\cmake\debug\obj\mips64\libnative-lib.so CMakeFiles/native-lib.dir/src/main/cpp/native-lib.cpp.o C:/Libs/opencv_src/opencv/platforms/build_android_arm/install/sdk/native/libs/armeabi-v7a/libopencv_core.a C:/Libs/opencv_src/opencv/platforms/build_android_arm/install/sdk/native/libs/armeabi-v7a/libopencv_aruco.a -llog -lm "C:/Users/JambonSama/AppData/Local/Android/sdk/ndk-bundle/sources/cxx-stl/gnu-libstdc++/4.9/libs/mips64/libgnustl_static.a" && cd ."
C:/Users/JambonSama/AppData/Local/Android/sdk/ndk-bundle/toolchains/mips64el-linux-android-4.9/prebuilt/windows-x86_64/lib/gcc/mips64el-linux-android/4.9.x/../../../../mips64el-linux-android/bin\ld: C:/Libs/opencv_src/opencv/platforms/build_android_arm/install/sdk/native/libs/armeabi-v7a/libopencv_core.a(alloc.cpp.o): Relocations in generic ELF (EM: 40)
C:/Users/JambonSama/AppData/Local/Android/sdk/ndk-bundle/toolchains/mips64el-linux-android-4.9/prebuilt/windows-x86_64/lib/gcc/mips64el-linux-android/4.9.x/../../../../mips64el-linux-android/bin\ld: C:/Libs/opencv_src/opencv/platforms/build_android_arm/install/sdk/native/libs/armeabi-v7a/libopencv_core.a(alloc.cpp.o): Relocations in generic ELF (EM: 40)
C:/Users/JambonSama/AppData/Local/Android/sdk/ndk-bundle/toolchains/mips64el-linux-android-4.9/prebuilt/windows-x86_64/lib/gcc/mips64el-linux-android/4.9.x/../../../../mips64el-linux-android/bin\ld: C:/Libs/opencv_src/opencv/platforms/build_android_arm/install/sdk/native/libs/armeabi-v7a/libopencv_core.a(alloc.cpp.o): Relocations in generic ELF (EM: 40)
C:/Users/JambonSama/AppData/Local/Android/sdk/ndk-bundle/toolchains/mips64el-linux-android-4.9/prebuilt/windows-x86_64/lib/gcc/mips64el-linux-android/4.9.x/../../../../mips64el-linux-android/bin\ld: C:/Libs/opencv_src/opencv/platforms/build_android_arm/install/sdk/native/libs/armeabi-v7a/libopencv_core.a(alloc.cpp.o): Relocations in generic ELF (EM: 40)
C:/Users/JambonSama/AppData/Local/Android/sdk/ndk-bundle/toolchains/mips64el-linux-android-4.9/prebuilt/windows-x86_64/lib/gcc/mips64el-linux-android/4.9.x/../../../../mips64el-linux-android/bin\ld: C:/Libs/opencv_src/opencv/platforms/build_android_arm/install/sdk/native/libs/armeabi-v7a/libopencv_core.a(alloc.cpp.o): Relocations in generic ELF (EM: 40)
C:/Users/JambonSama/AppData/Local/Android/sdk/ndk-bundle/toolchains/mips64el-linux-android-4.9/prebuilt/windows-x86_64/lib/gcc/mips64el-linux-android/4.9.x/../../../../mips64el-linux-android/bin\ld: C:/Libs/opencv_src/opencv/platforms/build_android_arm/install/sdk/native/libs/armeabi-v7a/libopencv_core.a(alloc.cpp.o): Relocations in generic ELF (EM: 40)
C:/Users/JambonSama/AppData/Local/Android/sdk/ndk-bundle/toolchains/mips64el-linux-android-4.9/prebuilt/windows-x86_64/lib/gcc/mips64el-linux-android/4.9.x/../../../../mips64el-linux-android/bin\ld: C:/Libs/opencv_src/opencv/platforms/build_android_arm/install/sdk/native/libs/armeabi-v7a/libopencv_core.a(alloc.cpp.o): Relocations in generic ELF (EM: 40)
C:/Users/JambonSama/AppData/Local/Android/sdk/ndk-bundle/toolchains/mips64el-linux-android-4.9/prebuilt/windows-x86_64/lib/gcc/mips64el-linux-android/4.9.x/../../../../mips64el-linux-android/bin\ld: C:/Libs/opencv_src/opencv/platforms/build_android_arm/install/sdk/native/libs/armeabi-v7a/libopencv_core.a(alloc.cpp.o): Relocations in generic ELF (EM: 40)
C:/Users/JambonSama/AppData/Local/Android/sdk/ndk-bundle/toolchains/mips64el-linux-android-4.9/prebuilt/windows-x86_64/lib/gcc/mips64el-linux-android/4.9.x/../../../../mips64el-linux-android/bin\ld: C:/Libs/opencv_src/opencv/platforms/build_android_arm/install/sdk/native/libs/armeabi-v7a/libopencv_core.a(alloc.cpp.o): Relocations in generic ELF (EM: 40)
C:/Libs/opencv_src/opencv/platforms/build_android_arm/install/sdk/native/libs/armeabi-v7a/libopencv_core.a: error adding symbols: File in wrong format
clang++.exe: error: linker command failed with exit code 1 (use -v to see invocation)
ninja: build stopped: subcommand failed.
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
In particular, this error message tells me that I tried to build with the following argument :
{--build C:\Users\JambonSama\AndroidStudioProjects\customOCVtest\app\.externalNativeBuild\cmake\debug\mips64 --target native-lib}
This argument is automatically generated by AS, and I can't find the file where it is passed. I believe that if I can find it, I can build for arm (which is what I want), instead of mips. The thing is, I can't find it. (And I'm not even sure that is indeed what I'm looking for. I'm just trying to make my project build for my glasses.)
Here after is my CMakeLists.txt :
# Sets the minimum version of CMake required to build the native
# library. You should either keep the default value or only pass a
# value of 3.4.0 or lower.
cmake_minimum_required(VERSION 3.4.1)
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds it for you.
# Gradle automatically packages shared libraries with your APK.
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
# Associated headers in the same location as their source
# file are automatically included.
src/main/cpp/native-lib.cpp )
include_directories(C:/Libs/opencv_src/opencv/platforms/build_android_arm/install/sdk/native/jni/include)
# Searches for a specified prebuilt library and stores the path as a
# variable. Because system libraries are included in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in the
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
native-lib
C:/Libs/opencv_src/opencv/platforms/build_android_arm/install/sdk/native/libs/armeabi-v7a/libopencv_core.a
C:/Libs/opencv_src/opencv/platforms/build_android_arm/install/sdk/native/libs/armeabi-v7a/libopencv_aruco.a
# Links the target library to the log library
# included in the NDK.
${log-lib} )
here is my app build.gradle :
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion "25.0.1"
defaultConfig {
applicationId "com.jambonsama.customocvtest"
minSdkVersion 14
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags ""
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
sourceSets { main { jni.srcDirs = ['src/main/jni', 'src/main/jniLibs/'] } }
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.0.1'
testCompile 'junit:junit:4.12'
compile project(':openCVLibrary310dev')
}
and my openCVLibrary310dev build.gradle
apply plugin: 'com.android.library'
android {
compileSdkVersion 25
buildToolsVersion "23.0.2"
defaultConfig {
ndk {
abiFilter("armeabi-v7a")
}
minSdkVersion 14
targetSdkVersion 25
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
}
What I tried, mainly by just copying stuff that helped other people solve problems that seemed similar to mines :
#set(CMAKE_SYSTEM_NAME Android)
or
#set(CMAKE_TOOLCHAIN_FILE "Toolchain file" CACHE FILEPATH "C:/Libs/opencv_src/opencv/platforms/android.toolchain.cmake")
or
#set( CMAKE_CXX_COMPILER "C:/Libs/android-ndk-r13b/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin/arm-linux-androideabi-g++.exe" )
in the CMakeLists.txt
and
splits {
abi {
enable true
reset()
include 'armeabi-v7a'
universalApk true
}
}
or
tasks.getByPath(":app:linkMipsDebugRemoteDesktopSharedLibrary").enabled = false
in the build.gradle (I tried both because I didn't know which one was supposed to have it).
Except for the very last bit of code (the task.getByPath...), the sync worked, but I couldn't build. For the last one, I couldn't even sync.
I also tried to rebuild the library for mips, since the architecture seems to be the problem, but I have no idea how to do that.
Where can I find the file where the following argument :
{--build C:\Users\JambonSama\AndroidStudioProjects\customOCVtest\app\.externalNativeBuild\cmake\debug\mips64 --target native-lib}
is passed when building? And / or how do I make Android Studio build my project for arm architecture?
So the mips architecture problem can be solved by adding the following code to the gradle.build of app, at the end of the android block :
productFlavors {
armv7 {
ndk {
abiFilter "armeabi-v7a"
}
}
fat
}
But then, other problems arised. Notably, the library is built with the carotene options, which Android Studio doesn't like, and then, the gzlib misses, so Android Studio can't build and / or run. So after MANY trials, I finally achieved what I wanted : cross-compilation of openCV with extra modules for Android on Windows, and building an AS project with said built library so that it works. I documented my whole proccess, from downloading the openCV sources up until running my application on my arm-architected device, I'll just copy paste it here for anyone who needs to do that too. The following instructions are mainly based on this tutorial (thank you to Zamrath Nizam who wrote it). The only problem with that tutorial is that it's probably a little old, so some options / steps need to be altered.
* FIRST : prerequisites *
* SECOND : configure with CMake *
change the following additional options via the 'Search' field :
verify that the following options are correctly set up (via the 'Search' field) :
press 'Configure'
* THIRD : compile with mingw *
* FOURTH : android project *
go to File -> New -> Import Module...
change the targets in build.gradle file in openCVLibraryXXX (imported module) folder :
in the build.gradle file in openCVLibraryXXX (imported module) folder :
add the imported library as a dependency to the 'app' module in File->'Project Structure'
create a jniLibs folder in 'app/src/main' :
copy libraries of OpenCV from 'opencv-source/platforms/android_arm/install/sdk/native/libs' into the newly created folder (jniLibs) inside the 'AndroidStudioProjects/cOCV/app/src/main/jniLibs' folder
in 'opencv-contrib-source/modules/module_you_desperately_need/CMakeLists.txt', change 'ocv_define_module(module_you_desperately_need opencv some other modules)' for 'ocv_define_module(module_you_desperately_need opencv some other modules WRAP java)'
in CMakeLists.txt, add :
the following two lines after the 'add_library' block and before the 'find_library' block :
include_directories(../opencv_src/opencv/platforms/build_android_armn/install/sdk/native/jni/include)
link_directories(../AndroidStudioProjects/cOCVn/app/src/main/jniLibs/armeabi-v7a)
the following lines after the 'find_library' block and before the 'target_link_libraries' block :
file(GLOB PARTYLIBS "../opencv_src/opencv/platforms/build_android_armn/install/sdk/native/3rdparty/libs/armeabi-v7a/*.a")
file(GLOB CVLIBS "../opencv_src/opencv/platforms/build_android_armn/install/sdk/native/libs/armeabi-v7a/*.a")
the following paths, AS WRITTEN, in the 'target_link_libraries', after the 'native-lib' variable, and before the '${log-lib}' one :
${CVLIBS}
${PARTYLIBS}
${CVLIBS}
in the gradle.build of app, add the following code :
productFlavors {
armv7 {
ndk {
abiFilter "armeabi-v7a"
}
}
fat
}
at the end of the android block
in the native-lib.cpp :
try the following code in the 'stringFromJNI' function (this one is automatically generated by AS when the project is created)
cv::Mat test;
cv::VideoCapture camera;
camera.open(0);
cv::Ptrcv::aruco::Dictionary dict = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250);
cv::Mat marker;
cv::aruco::drawMarker(dict, 25, 200, marker, 1);
std::string hello = "Hello from C++";
return env-NewStringUTF(hello.c_str());
don't forget the following includes :
#include jni.h
#include string
#include opencv2/aruco.hpp
#include opencv2/videoio.hpp
time to test :
You're good to go \ o \\ O // o /
Additional notes :
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With