Linking external libraries using NDK, Gradle & CMake in Android Studio - android

I've come back to Android development after a gap and my old ANT based build chain no longer seem to function (that's a separate issue) with the latest SDK, so I'm trying to do things the new way, which is based around gradle and CMake.
I have a number of pre-built static and dynamic 3rd party libraries that my project needs but I've been unable to link these successfully.
From what I can gather, these need to be specified in the 'CMakeLists.txt' file rather than the 'build.gradle' files but I'm new to both systems, so please correct me if I'm wrong.
Here's what I've tried so far:
first, I try to resolve the location of bullet. I've tried variants where I omit the 'lib' the '.a' and the 'armeabi-v7a' (hoping it'd pick up the right CPU variant) but none have worked
find_library(bullet_lib libBullet.a HINTS ${LIBBASE}bullet3/build3/Android/obj/local/armeabi-v7a)
I'm not sure how this differs from the libraries included in target_link_libraries
add_library(bullet_lib STATIC IMPORTED)
this finds the built-in libraries fine but I get linker errors for 'bullet' and other 3rd party libs
target_link_libraries(my_project_name android log EGL GLESv2 bullet_lib)
${LIBBASE} is the base dir for the 3rd party libraries and seems to be OK but, here's another thing: CMake errors don't seem to appear in android studio! I can sort of work out where it's having problems by running cmake . in the folder that contains the 'CMakeLists.txt' file but I'm not quite sure I'm calling that with the correct parameters: whatever Android Studio does with cmake and that file are a black box to me at this time.
The only messages I can see in android studio are linker errors (it doesn't mention CMake errors about not finding the libraries, which is the cause of these linker errors:)
Build command failed.
Error while executing process E:\prog\Android\cmake\3.6.4111459\bin\cmake.exe with arguments {--build E:\prog\anthracite\gradle\AnthracitePlayerAPI21\app\.externalNativeBuild\cmake\debug\x86_64 --target anthracite-lib}
[1/1] Linking CXX shared library ..\..\..\..\build\intermediates\cmake\debug\obj\x86_64\libanthracite-lib.so
FAILED: cmd.exe /C "cd . && E:\prog\Android\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --target=x86_64-none-linux-android --gcc-toolchain=E:/prog/Android/ndk-bundle/toolchains/x86_64-4.9/prebuilt/windows-x86_64 --sysroot=E:/prog/Android/ndk-bundle/sysroot -fPIC -isystem E:/prog/Android/ndk-bundle/sysroot/usr/include/x86_64-linux-android -D__ANDROID_API__=21 -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -Wa,--noexecstack -Wformat -Werror=format-security -std=c++11 -fexceptions -O0 -fno-limit-debug-info -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libatomic.a --sysroot E:/prog/Android/ndk-bundle/platforms/android-21/arch-x86_64 -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,libanthracite-lib.so -o ..\..\..\..\build\intermediates\cmake\debug\obj\x86_64\libanthracite-lib.so #CMakeFiles/anthracite-lib.rsp && cd ."
E:\prog\anthracite\src/CCmpPhysicsScene3D.cpp:237: error: undefined reference to 'btDbvtBroadphase::btDbvtBroadphase(btOverlappingPairCache*)'
E:\prog\anthracite\src/CCmpPhysicsScene3D.cpp:240: error: undefined reference to 'btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(btDefaultCollisionConstructionInfo const&)'
E:\prog\anthracite\src/CCmpPhysicsScene3D.cpp:242: error: undefined reference to 'btCollisionDispatcher::btCollisionDispatcher(btCollisionConfiguration*)'
E:\prog\anthracite\src/CCmpPhysicsScene3D.cpp:243: error: undefined reference to 'btSequentialImpulseConstraintSolver::btSequentialImpulseConstraintSolver()'
E:\prog\anthracite\src/CCmpPhysicsScene3D.cpp:246: error: undefined reference to 'btDefaultSoftBodySolver::btDefaultSoftBodySolver()'
E:\prog\anthracite\src/CCmpPhysicsScene3D.cpp:247: error: undefined reference to 'btSoftRigidDynamicsWorld::btSoftRigidDynamicsWorld(btDispatcher*, btBroadphaseInterface*, btConstraintSolver*, btCollisionConfiguration*, btSoftBodySolver*)'
E:\prog\anthracite\src/CCmpPhysicsScene3D.cpp:250: error: undefined reference to 'btDiscreteDynamicsWorld::btDiscreteDynamicsWorld(btDispatcher*, btBroadphaseInterface*, btConstraintSolver*, btCollisionConfiguration*)'
E:\prog\anthracite\src/CCmpPhysJointHinge.cpp:117: error: undefined reference to 'btHingeConstraint::btHingeConstraint(btRigidBody&, btVector3 const&, btVector3 const&, bool)'
clang++.exe: error: linker command failed with exit code 1 (use -v to see invocation)
ninja: build stopped: subcommand failed.
And running 'cmake .' from the command line gives:
-- Selecting Windows SDK version 10.0.16299.0 to target Windows 10.0.17133.
CMake Warning at CMakeLists.txt:447 (message):
resolved libraries:
CMake Warning at CMakeLists.txt:448 (message):
e:/prog/libs/bullet3/build3/Android/obj/local/armeabi-v7a
CMake Warning at CMakeLists.txt:449 (message):
bullet_lib-NOTFOUND
-- Configuring done
-- Generating done
-- Build files have been written to: E:/prog/anthracite/gradle/AnthracitePlayerAPI21/app
although, as I mentioned above, I'm not sure of the veracity of that output as the calling parameters to 'cmake' are likely to be quite different from inside Android Studio. (e.g it's defaulting to a windows build, so I'm not sure if it'd look for '.lib' libraries rather than '.a' or '.so')
Also, I'm using these lines in my 'CMakeLists.txt' file to report the status of the build:
message(WARNING "resolved libraries:")
message(WARNING ${LIBBASE}bullet3/build3/Android/obj/local/armeabi-v7a)
message(WARNING ${bullet_lib})
Anyway, I'm clearly missing something and I've not been able to find any clear guides regarding this. It seems a really simple and obvious thing to do (link a library) but it seems to be a massive pain.
I'd be grateful for any pointers.

You must take care of ABI incompatibility. You are building libanthracite-lib.so for x86_64, so you need the same variant of libBullet.a. If you only need armeabi-v7a, you must specify this in build.gradle, e.g.
android {
externalNativeBuild {
cmake {
path 'CMakeLists.txt'
}
}
defaultConfig {
ndk {
abiFilters 'armeabi-v7a'
}
externalNativeBuild {
cmake {
arguments '-DCMAKE_VERBOSE_MAKEFILE=ON'
}
}
}
}
In your E:\prog\anthracite\gradle\AnthracitePlayerAPI21\app\CMakeLists.txt
add_library(bullet_lib STATIC IMPORTED)
set_target_properties(bullet_lib PROPERTIES IMPORTED_LOCATION
${LIBBASE}/bullet3/build3/Android/obj/local/${ANDROID_ABI}/libBullet.a)
target_link_libraries(my_project_name bullet_lib android log EGL GLESv2)
The order of libraries in target_link_libraries may be important, so keep static libs on the left.
I guess you build libBullet.a with ndk-build. You can create a separate library module (let's call in bullet_module) to your AS Project, even if it has no Java files, and point it to the Android.mk:
apply plugin: 'com.android.library'
android {
compileSdkVersion 27
defaultConfig {
ndk {
abiFilters 'armeabi-v7a'
}
externalNativeBuild {
ndkBuild {
targets 'Bullet'
}
}
}
externalNativeBuild {
ndkBuild {
path "${LIBBASE}/bullet3/build3/Android/jni/Android.mk"
}
}
}
Now you can change your CMakeLists.txt to look at results of bullet_module build:
set_target_properties(bullet_lib PROPERTIES IMPORTED_LOCATION
<path/to/bullet_module>/build/intermediates/ndkBuild/debug/obj/local/${ANDROID_ABI}/libBullet.a)

Related

Will cmake compiled TFLite work on android?

I'm making a project with 2 variations, a desktop version and an android version. Both of them are using the same c++ code base. I want to use TFLite without getting into any android configuration like gradle or an aar file. I just want a pure .so file that my c++ can use thus android can through ndk. I know there are some complications like ndk using clang and requiring arm64 architecture, but I think it should be possible. Note that my project requires ndk version 22 and above.
Here is how I configured tflite for my desktop/debian project:
On ~/Desktop/ I ran git clone https://github.com/tensorflow/tensorflow.git tensorflow_src
mkdir tflite_build & cd ~/Desktop/tflite_build
cmake ../tensorflow_src/tensorflow/lite
cmake --build . I've removed the -J flag regardless of what the docs says because it causes my pc to freeze.
mkdir ~/Desktop/tf_test & cd ~/Desktop/tf_test
Create a CMakeLists.txt and a main.cpp file inside tf_testdirectory.
Put the main code from the minimal example on the github repo provided above then this code in CMake:
cmake_minimum_required(VERSION 3.16)
project(minimal C CXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTFLITE_DISABLE_TELEMETRY=1")
set(TENSORFLOW_SOURCE_DIR "" CACHE PATH
"Directory that contains the TensorFlow project" )
if(NOT TENSORFLOW_SOURCE_DIR)
get_filename_component(TENSORFLOW_SOURCE_DIR
"/home/user/Desktop/tensorflow_src" ABSOLUTE)
endif()
add_subdirectory(
"${TENSORFLOW_SOURCE_DIR}/tensorflow/lite"
"${CMAKE_CURRENT_BINARY_DIR}/tensorflow-lite" EXCLUDE_FROM_ALL)
add_executable(minimal minimal.cc)
target_link_libraries(minimal tensorflow-lite)
Created the folder tf_Test/build and ran cmake .. inside it.
After cmake is completed I run make inside the build directory
This works just fine on debian. However when I try to add this to my cmake on my android ndk project, connect my tablet and run the project I get all these errors:
...
- Looking for strtoull_l - found
-- Using toolchain file: /home/user/Android/Sdk/ndk/25.0.8775105/build/cmake/android.toolchain.cmake.
-- CMAKE_CXX_FLAGS: -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -frtti -fexceptions -fvisibility=hidden -std=c++17 -O0 -Wall -Wextra -Wshadow -Wnon-virtual-dtor -pthread -frtti -fexceptions
-- Found Python3: /usr/bin/python3.9 (found suitable version "3.9.2", minimum required is "3.5") found components: Interpreter
-- Downloading pthreadpool to /home/user/Desktop/native/examples/android/app/.cxx/Debug/5c1w1z3w/arm64-v8a/pthreadpool-source (define PTHREADPOOL_SOURCE_DIR to avoid it)
-- Configuring incomplete, errors occurred!
See also "/home/user/Desktop/native/examples/android/app/.cxx/Debug/5c1w1z3w/arm64-v8a/pthreadpool-download/CMakeFiles/CMakeOutput.log".
-- The ASM compiler identification is Clang with GNU-like command-line
-- Found assembler: /home/user/Android/Sdk/ndk/25.0.8775105/toolchains/llvm/prebuilt/linux-x86_64/bin/clang
-- Downloading FP16 to /home/user/Desktop/native/examples/android/app/.cxx/Debug/5c1w1z3w/arm64-v8a/FP16-source (define FP16_SOURCE_DIR to avoid it)
-- Configuring incomplete, errors occurred!
See also "/home/user/Desktop/native/examples/android/app/.cxx/Debug/5c1w1z3w/arm64-v8a/FP16-download/CMakeFiles/CMakeOutput.log".
-- Downloading FXdiv to /home/user/Desktop/native/examples/android/app/.cxx/Debug/5c1w1z3w/arm64-v8a/FXdiv-source (define FXDIV_SOURCE_DIR to avoid it)
-- Configuring incomplete, errors occurred!
See also "/home/user/Desktop/native/examples/android/app/.cxx/Debug/5c1w1z3w/arm64-v8a/FXdiv-download/CMakeFiles/CMakeOutput.log".
-- RUY is enabled.
-- Configuring incomplete, errors occurred!
See also "/home/user/Desktop/native/examples/android/app/.cxx/Debug/5c1w1z3w/arm64-v8a/CMakeFiles/CMakeOutput.log".
See also "/home/user/Desktop/native/examples/android/app/.cxx/Debug/5c1w1z3w/arm64-v8a/CMakeFiles/CMakeError.log".
CMake Warning at /home/user/Desktop/native/examples/android/app/.cxx/Debug/5c1w1z3w/arm64-v8a/abseil-cpp/CMakeLists.txt:70 (message):
A future Abseil release will default ABSL_PROPAGATE_CXX_STD to ON for CMake
3.8 and up. We recommend enabling this option to ensure your project still
builds correctly.
CMake Error: CMake was unable to find a build program corresponding to "Ninja". CMAKE_MAKE_PROGRAM is not set. You probably need to select a different build tool.
No such file or directory
CMake Error: Generator: execution of make failed. Make command was: &&
CMake Error at /home/user/Desktop/official_stuff/tensorflow_src/tensorflow/lite/CMakeLists.txt:167 (add_subdirectory):
add_subdirectory given source
"/home/user/Desktop/native/examples/android/app/.cxx/Debug/5c1w1z3w/arm64-v8a/pthreadpool-source"
which is not an existing directory.
CMake Error: CMake was unable to find a build program corresponding to "Ninja". CMAKE_MAKE_PROGRAM is not set. You probably need to select a different build tool.
No such file or directory
CMake Error: Generator: execution of make failed. Make command was: &&
CMake Error: CMake was unable to find a build program corresponding to "Ninja". CMAKE_MAKE_PROGRAM is not set. You probably need to select a different build tool.
No such file or directory
CMake Error: Generator: execution of make failed. Make command was: &&
CMake Error at /home/user/Desktop/native/examples/android/app/.cxx/Debug/5c1w1z3w/arm64-v8a/xnnpack/CMakeLists.txt:844 (ADD_SUBDIRECTORY):
ADD_SUBDIRECTORY given source
"/home/user/Desktop/native/examples/android/app/.cxx/Debug/5c1w1z3w/arm64-v8a/pthreadpool-source"
which is not an existing directory.
CMake Error at /home/user/Desktop/native/examples/android/app/.cxx/Debug/5c1w1z3w/arm64-v8a/xnnpack/CMakeLists.txt:884 (ADD_SUBDIRECTORY):
ADD_SUBDIRECTORY given source
"/home/user/Desktop/native/examples/android/app/.cxx/Debug/5c1w1z3w/arm64-v8a/FXdiv-source"
which is not an existing directory.
CMake Error at /home/user/Desktop/native/examples/android/app/.cxx/Debug/5c1w1z3w/arm64-v8a/xnnpack/CMakeLists.txt:908 (ADD_SUBDIRECTORY):
ADD_SUBDIRECTORY given source
"/home/user/Desktop/native/examples/android/app/.cxx/Debug/5c1w1z3w/arm64-v8a/FP16-source"
which is not an existing directory.
What's the right way to approach this? Following the android build documentation on tflite's website causes a lot of problems.
Update:
Installing ninja fixed almost all my problems, the only error I have now is:
In file included from /home/user/Desktop/official_stuff/tensorflow_src/tensorflow/lite/python/interpreter_wrapper/python_error_reporter.cc:16:
/home/user/Desktop/official_stuff/tensorflow_src/tensorflow/lite/python/interpreter_wrapper/python_error_reporter.h:19:10: fatal error: 'Python.h' file not found
python3 is in fact installed on my system, I used it on a c code before.
Update: Adding this to top of my cmake solved the python issue:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I/usr/include/python3.9 -I/usr/include/python3.9 -Wno-unused-result -Wsign-compare -g -ffile-prefix-map=/build/python3.9-RNBry6/python3.9-3.9.2=. -specs=/usr/share/dpkg/no-pie-compile.specs -fstack-protector -Wformat -Werror=format-security -DNDEBUG -g -fwrapv -Wall")
Update:
Now I get:
In file included from /home/user/Desktop/SmartAlpha/official_stuff/tensorflow_src/tensorflow/lite/python/interpreter_wrapper/numpy.cc:17:
In file included from /home/user/Desktop/SmartAlpha/official_stuff/tensorflow_src/tensorflow/lite/python/interpreter_wrapper/numpy.h:49:
In file included from /usr/include/python3.9/Python.h:8:
/usr/include/python3.9/pyconfig.h:9:12: fatal error: 'aarch64-linux-gnu/python3.9/pyconfig.h' file not found
LAST EDIT: You seem to completely overlook what I'm trying to explain you the whole time about different architectures. Your phone is not running on the same cpu architecture as your desktop. Your desktop machine is most likely running on amd64, while your phone is most likely arm64 which is also known as Aarch64 (do you now see what the latest error means? - It can't find the appropriate packages for the correct architecture - you can see that from the path in the error message).
You installed the amd64 package by issuing sudo apt-get install python-dev not the arm64 package. Check this official debian wiki on how to use MultiArch packages
You need to:
Update your system so that it can download the packages for different architectures
And sudo apt-get install python-dev:arm64
EDIT: Regarding the error in the updated question, you are most likely missing python development packages. Since you are on Debian I've looked for a possible package of interested and this might be it:
python-dev, try to apt-get it for the correct architecture that you need and maybe it will resolve your issues.
Make sure that Ninja is installed. CMake is trying to use it - this confuses a lot of users as they most commonly use Makefiles and don't know that an alternative exists. I don't see you explicitly stating that you use CMake + Ninja and hence I mention it.
If you have Ninja installed then the issue is most likely caused by the fact that it can't resolve the path via just the executable name. Take a look at CMAKE_MAKE_PROGRAM to better understand what I mean.
If 2. is your issue then you can try and set the whole path to this CMAKE_MAKE_PROGRAM variable, i.e. set(CMAKE_MAKE_PROGRAM /absolute/path/to/bin/ninja) and see if resolves the issue.

Unable to compile V8 9.9 for Android with use_custom_libcxx = false

I'm trying to update our V8 integration for Android from 9.1 to 9.9 and I'm unable to build 9.9 with the default NDK standard library (use_custom_libcxx = false).
Using Ubuntu 20.04 LTS 64-bit, I'm trying to build V8 9.9 with the following options:
target_os="android"
is_debug=true
target_cpu="x86"
is_component_build=false
v8_static_library=true
v8_monolithic=true
v8_enable_i18n_support=false
v8_use_external_startup_data=false
use_custom_libcxx=false
Build output is:
ninja -C out/Android_Debug_x86 ninja: Entering directory
`out/Android_Debug_x86' [385/3327] LINK
clang_x86/bytecode_builtins_list_generator FAILED:
clang_x86/bytecode_builtins_list_generator python3
"../../build/toolchain/gcc_link_wrapper.py"
--output="clang_x86/bytecode_builtins_list_generator" -- ../../third_party/llvm-build/Release+Asserts/bin/clang++ -pie
-fuse-ld=lld -Wl,--fatal-warnings -Wl,--build-id -fPIC -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--color-diagnostics -Wl,--no-call-graph-profile-sort -m32 -no-canonical-prefixes -Werror -rdynamic --sysroot=../../build/linux/debian_sid_i386-sysroot -Wl,-z,defs -Wl,--as-needed -pie -Wl,--disable-new-dtags -Wl,-O2 -Wl,--gc-sections -o "clang_x86/bytecode_builtins_list_generator" -Wl,--start-group #"clang_x86/bytecode_builtins_list_generator.rsp" -Wl,--end-group -latomic -ldl -lpthread -lrt ld.lld: error: ../../build/linux/debian_sid_i386-sysroot/usr/lib/gcc/i686-linux-gnu/10/libstdc++.so:
undefined reference to __divmoddi4#GCC_7.0.0
[--no-allow-shlib-undefined] clang++: error: linker command failed
with exit code 1 (use -v to see invocation) [390/3327] CXX
clang_x86/obj/torque_base/implementation-visitor.o ninja: build
stopped: subcommand failed.
I'm able to build V8 9.9 with use_custom_libcxx=true, but this will lead to conflicting standard libraries when trying to build the project that is later interfacing with V8. (Which is using the Android NDK with CMake and the standard libraries delivered with that respectively.)
Is there anything I can change to successfully build V8 9.9 without the custom standard library?
If the custom standard library is now mandatory, what would be the least difficult way to handle this? The API of V8 references standard library classes without customizable namespaces, so I assume I would have to build my own API around it, decoupled from either standard library, and put it all into a shared library.
In any case, I would definitely prefer getting the build with use_custom_libcxx=false going again since this method of embedding is a lot more convenient.
Edit: Since we are only using x86 for the emulator and would be able to skip it, I also attempted to build ARM/ARM64 (Debug & Release) on 9.9 and x86/ARM/ARM64 on 9.8 using the same build flags. They are also failing, but with different errors:
arm64 on 9.8
ninja -C out/Android_Debug_arm64
ninja: Entering directory `out/Android_Debug_arm64'
[399/3459] LINK ./torque-language-server
FAILED: torque-language-server exe.unstripped/torque-language-server
python3 "../../build/toolchain/gcc_link_wrapper.py" --output="./torque-language-server" --strip="../../third_party/llvm-build/Release+Asserts/bin/llvm-strip" --unstripped-file="./exe.unstripped/torque-language-server" -- ../../third_party/llvm-build/Release+Asserts/bin/clang++ -fuse-ld=lld -Wl,--fatal-warnings -Wl,--build-id -fPIC -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,-z,max-page-size=4096 -Wl,--color-diagnostics -Wl,--no-rosegment -Wl,--no-call-graph-profile-sort -Wl,--exclude-libs=libvpx_assembly_arm.a --unwindlib=none --target=aarch64-linux-android23 -Wl,-mllvm,-enable-machine-outliner=never -no-canonical-prefixes -Werror --sysroot=../../third_party/android_ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot -Wl,--warn-shared-textrel -Wl,-z,defs -Wl,--as-needed -pie -Bdynamic -Wl,-z,nocopyreloc -Wl,--warn-shared-textrel -Wl,-O2 -Wl,--gc-sections -o "./exe.unstripped/torque-language-server" -Wl,--start-group #"./torque-language-server.rsp" -Wl,--end-group -ldl -lm -llog
ld.lld: error: undefined symbol: _Unwind_Resume
>>> referenced by torque-language-server.cc:0 (../../src/torque/ls/torque-language-server.cc:0)
>>> obj/torque-language-server/torque-language-server.o:(v8::internal::torque::ls::WrappedMain(int, char const**))
>>> referenced by contextual.h:0 (../../src/torque/contextual.h:0)
>>> obj/torque-language-server/torque-language-server.o:(v8::internal::torque::ls::WrappedMain(int, char const**))
>>> referenced by fstream:0 (../../third_party/android_ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/c++/v1/fstream:0)
>>> obj/torque-language-server/torque-language-server.o:(v8::internal::torque::ls::WrappedMain(int, char const**))
>>> referenced 2144 more times
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
[416/3459] CXX clang_x64_v8_arm64/obj/torque_base/implementation-visitor.o
ninja: build stopped: subcommand failed.
arm 9.8
ninja -C out/Android_Debug_arm
ninja: Entering directory `out/Android_Debug_arm'
[3101/3433] ACTION //:run_mksnapshot_default(//build/toolchain/android:android_clang_arm)
FAILED: gen/embedded.S gen/snapshot.cc
python3 ../../tools/run.py ./clang_x86_v8_arm/mksnapshot --turbo_instruction_scheduling --target_os=android --target_arch=arm --embedded_src gen/embedded.S --embedded_variant Default --random-seed 314159265 --startup_src gen/snapshot.cc --native-code-counters --verify-heap
./clang_x86_v8_arm/mksnapshot: error while loading shared libraries: libatomic.so.1: cannot open shared object file: No such file or directory
Return code is 127
A summary of my current situation, debug and release both produce the same outcome:
9.9 x86: divmod undefined
9.9 arm: divmod undefined
9.9 arm64: _Unwind_Resume undefined
9.8 x86: _Unwind_Resume undefined
9.8 arm: libatomic.so.1 missing
9.8 arm64: _Unwind_Resume undefined
9.1 is still building when I switch back to it.
Seems like you're hitting this bug: crbug.com/v8/12673
So as that bug describes, one possible workaround is to use an older sysroot for the time being, e.g. the one used in V8 9.8.
Another possible workaround is to turn off sysroot usage by adding use_sysroot = false to your GN args (and you'll likely need treat_warnings_as_errors = false too then). That will use your system's libraries instead. Note that usually that's a liability: it means that when your system changes, that can affect your builds. So I wouldn't recommend that as a long-term solution. But it should avoid the problem until the bundled sysroot is fixed.
(FWIW this is unrelated to compiling for Android, as it seems to affect regular Linux ia32 builds as well. Android + ia32 is a rare combination, but I assume that you know what you're doing there.)

How can I build local/host OS C++ unit tests in Android Studio?

I'm working on a large project with many native modules and I'd like to introduce unit tests of the C++ code that are as simple/fast to run as Java JUnit local (i.e. running on the host OS, not instrumented) tests.
I've followed the official instructions for setting up gtest, but running my external native build results in a linker error:
> Task :app:externalNativeBuildDebug FAILED
Build GoogleTests x86_64
[1/2] Building CXX object CMakeFiles/GoogleTests.dir/googletest_unittests/shared/TautologyTe
sts.cpp.o
[2/2] Linking CXX executable GoogleTests
FAILED: cmd.exe /C "cd . && C:\Users\Jeffrey.Creswell\AppData\Local\Android\Sdk\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --target=x86_64-none-linux-android21 --gcc-toolchain=C:/Users/Jeffrey.Creswell/AppData/Local/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/windows-x86_64 --sysroot=C:/Users/Jeffrey.Creswell/AppData/Local/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/windows-x86_64/sysroot -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -fno-addrsig -Wa,--noexecstack -Wformat -Werror=format-security -stdlib=libc++ -std=c++14 -O0 -fno-limit-debug-info -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libatomic.a -static-libstdc++ -Wl,--build-id -Wl,--warn-shared-textrel -Wl,--fatal-warnings -Wl,--no-undefined -Qunused-arguments -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--gc-sections CMakeFiles/GoogleTests.dir/googletest_unittests/shared/TautologyTests.cpp.o CMakeFiles/GoogleTests.dir/googletest_unittests/Tautology.cpp.o -o GoogleTests C:/Users/Jeffrey.Creswell/androidstudio_projects/NativeAndroidSandbox/app/src/main/cpp/googletest_unittests/libs/windows/x86_64/gtestd.lib -latomic -lm && cd ."
C:\Users\Jeffrey.Creswell\androidstudio_projects\NativeAndroidSandbox\app\src\main\cpp\googletest_unittests\shared/TautologyTests.cpp:19: error: undefined reference to 'testing::internal::GetTestTypeId()'
C:\Users\Jeffrey.Creswell\androidstudio_projects\NativeAndroidSandbox\app\src\main\cpp\googletest_unittests\shared/TautologyTests.cpp:19: error: undefined reference to 'testing::internal::MakeAndRegisterTestInfo(char const*, char const*, char const*, char const*, testing::internal::CodeLocation, void const*, void (*)(), void (*)(), testing::internal::TestFactoryBase*)'
...
I built gtestd.lib in Visual Studio and referenced it as a prebuilt in CMakeLists.txt to try to simplify the equation somewhat:
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
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 them 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).
native-lib.cpp)
set(gtest_INC googletest_unittests/include)
include_directories(${gtest_INC})
add_library(gtest STATIC IMPORTED)
set_property(TARGET gtest PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/googletest_unittests/libs/windows/x86_64/gtestd.lib)
add_executable(GoogleTests
${CMAKE_CURRENT_SOURCE_DIR}/googletest_unittests/shared/TautologyTests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/googletest_unittests/Tautology.cpp)
target_link_libraries(GoogleTests gtest)
# todo: insert add_test() cmake commands once the linker error above is resolved
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries 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 this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
native-lib
# Links the target library to the log library
# included in the NDK.
${log-lib})
I think the main problem is the argument "--target=x86_64-none-linux-android21" to clang++.exe; it implies compilation of the test executable for Android/Linux, when what I really want is to compile for the host OS (Windows 10). I don't know if this could produce the linker error I'm seeing, but attempting to link a Linux executable to a Windows static library seems like it would fail similarly. How can I tell the Android NDK's clang++ to target the host OS (ideally by modifications to my CMakeLists.txt)? Assuming that's not the problem, is there a known way to get a local (running on host OS) C++ unit test scenario working within Android Studio?
NOTE: I looked at a similar question and the accepted answer appears to work, but generates an Android executable -- I would prefer a situation where I can ideally just hit the green arrow in Android Studio and have my C++ unit tests run automatically on the local machine.
Android Studio does not support host development.
If you want to build your tests against your host and run them there, you'll have to invoke CMake from outside Android Studio (command line would be an option, as would Visual Studio).

OpenCV - undefined reference to 'cv::CascadeClassifier::detectMultiScale()' after NDK update

Yesterday I updated my Android Studio included NDK to version 17.0.4754217and since then I can't run my app anymore. When I tried to rerun the code after the update it gave me the error ABIs [mips64, armeabi, mips] are not supported for platform. Supported ABIs are [armeabi-v7a, arm64-v8a, x86, x86_64] so I excluded them from the project in my app.gradle file the following way: abiFilters 'x86', 'x86_64', /*'armeabi',*/ 'armeabi-v7a', 'arm64-v8a'/*, 'mips', 'mips64'*/.
However, since then I'm having a problem with the C++-file where I use the OpenCV-function cv::CascadeClassifier::detectMultiScale.
It always displays the error: CMakeFiles/native-lib.dir/src/main/cpp/native-lib.cpp.o: In function detectAndDisplay(cv::Mat, double, int, std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >, cv::CascadeClassifier&)':
D:\Schule\OpenCV\ARcpp\app\src\main\cpp/native-lib.cpp:158: undefined reference to cv::CascadeClassifier::detectMultiScale(cv::_InputArray const&, std::__ndk1::vector<cv::Rect_<int>, std::__ndk1::allocator<cv::Rect_<int> > >&, double, int, int, cv::Size_<int>, cv::Size_<int>)'.
I call the function like this: cascadeClassifier.detectMultiScale(frame_gray, sights, scaleFactor, minNeighbours, 0 | CV_HAAR_SCALE_IMAGE, Size(30, 30));. The rest of the code is pretty much like shown in the OpenCV-tutorial https://docs.opencv.org/2.4/doc/tutorials/objdetect/cascade_classifier/cascade_classifier.html.
Additionally to the NDK I use CMake and LLDB and my included OpenCV-library is openCVLibrary320. Again, all of this worked until I downloaded the mentioned NDK update.
The rest of the error that always appears on building or executing the app is: Build command failed.
Error while executing process C:\Users\chris\AppData\Local\Android\Sdk\cmake\3.6.4111459\bin\cmake.exe with arguments {--build D:\Schule\OpenCV\ARcpp\app\.externalNativeBuild\cmake\debug\arm64-v8a --target native-lib}
[1/1] Linking CXX shared library ..\..\..\..\build\intermediates\cmake\debug\obj\arm64-v8a\libnative-lib.so
FAILED: cmd.exe /C "cd . && C:\Users\chris\AppData\Local\Android\Sdk\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --target=aarch64-none-linux-android --gcc-toolchain=C:/Users/chris/AppData/Local/Android/Sdk/ndk-bundle/toolchains/aarch64-linux-android-4.9/prebuilt/windows-x86_64 --sysroot=C:/Users/chris/AppData/Local/Android/Sdk/ndk-bundle/sysroot -fPIC -isystem C:/Users/chris/AppData/Local/Android/Sdk/ndk-bundle/sysroot/usr/include/aarch64-linux-android -D__ANDROID_API__=21 -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -Wa,--noexecstack -Wformat -Werror=format-security -std=c++11 -std=c++11 -frtti -fexceptions -O0 -fno-limit-debug-info -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libatomic.a -nostdlib++ --sysroot C:/Users/chris/AppData/Local/Android/Sdk/ndk-bundle/platforms/android-21/arch-arm64 -Wl,--build-id -Wl,--warn-shared-textrel -Wl,--fatal-warnings -LC:/Users/chris/AppData/Local/Android/Sdk/ndk-bundle/sources/cxx-stl/llvm-libc++/libs/arm64-v8a -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\arm64-v8a\libnative-lib.so CMakeFiles/native-lib.dir/src/main/cpp/native-lib.cpp.o -llog ../../../../src/main/jniLibs/arm64-v8a/libopencv_java3.so -latomic -lm "C:/Users/chris/AppData/Local/Android/Sdk/ndk-bundle/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/libc++_static.a" "C:/Users/chris/AppData/Local/Android/Sdk/ndk-bundle/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/libc++abi.a" && cd ."
clang++.exe: error: linker command failed with exit code 1 (use -v to see invocation)
ninja: build stopped: subcommand failed.
I`m really lost, hopefully someone knows an answer.
OpenCV is built with ANDROID_STL=gnustl_static. After upgrade, your NDK uses the default libc++ instead. You can set ANDROID_STL explicitly in your app/build.gradle:
android { defaultConfig { externalNativeBuild { cmake {
arguments '-DANDROID_STL=gnustl_static'
} } } }
(see an example here).
When linkin opencv with your project executables, you always have to link with the general library -lopencv_core. But some packages require additional link flags. For example,
if you use highgui as in
#include <opencv2/highgui/highgui.hpp>
you must add opencv_highgui link flag for : -lopencv_highgui.
In you case, CascadeClassifiers are defined in
#include "opencv2/objdetect.hpp"
and thus requires a link with opencv_objdetect -lopencv_objdetect.
The solution is to add the link flag -lopencv_objdetect when compiling.
A more complete answer for all the seekers out there. Using OpenCV prebuilt static libraries in your project with a native component.
This is what I have for the build.gradle:
defaultConfig {
minSdkVersion 21
targetSdkVersion 21
externalNativeBuild {
cmake {
cppFlags "-fexceptions -std=gnu++11"
arguments '-DANDROID_STL=gnustl_static'
}
}
ndk {
// Specifies the ABI configurations of your native
// libraries Gradle should build and package with your APK.
abiFilters 'armeabi-v7a', 'x86'
stl = "gnustl_shared"
}
}
This is the CMakeLists.txt:
set(OPENCV_LIBRARIES ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_NDK_ABI_NAME}/libopencv_video.a
${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_NDK_ABI_NAME}/libopencv_imgproc.a
${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_NDK_ABI_NAME}/libopencv_core.a
${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_NDK_ABI_NAME}/libopencv_highgui.a
${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_NDK_ABI_NAME}/libtbb.a
${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_NDK_ABI_NAME}/libcpufeatures.a
)
if (${ANDROID_ABI} STREQUAL "x86")
set(OPENCV_LIBRARIES ${OPENCV_LIBRARIES}
${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_NDK_ABI_NAME}/libippiw.a
${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_NDK_ABI_NAME}/libippicv.a
${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_NDK_ABI_NAME}/libittnotify.a
)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--exclude-libs,libippicv.a -Wl,--exclude-libs,libippiw.a")
endif()
if (${ANDROID_ABI} STREQUAL "armeabi-v7a")
set(OPENCV_LIBRARIES ${OPENCV_LIBRARIES}
${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_NDK_ABI_NAME}/libtegra_hal.a
)
endif()
(then use ${OPENCV_LIBRARIES} for your target_link_libraries)
The first comment on this link can save you many hours which I copy past below:
"I had similar issue. In turned out that you got to use similar Android NDK as one that was used to build OpenCV Android SDK, that in case of versions ~3.4 is Android NDK 10. Recently, OpenCV Android SDK 4.0.1 have been released and it works with the newest NDK version (19 at the time)."
At the time of this post, you can find the release 4.1.2. You can check if there's a latest release on this link.
After you select your latest version, in this case 4.1.2, download the file opencv-4.1.2-android-sdk.zip, unzip it and copy the sdk/native folder to yourprojectfolder/your-app/src/sdk/.
You're ready to roll.
I solved this problem by using mix with this OpenCV + contrib lib (opencv4_1_0_contrib) and official Java OpenCV classes (4.3). Successfully run official OpenCV FaceDetection example on Android 9.
Some usefull code:
App level build.gradle:
android{defaultConfig{
//...
externalNativeBuild {
cmake {
cppFlags "-frtti -fexceptions"
abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
//I import OpenCV as module and provide it path to CMake
arguments "-DOpenCV_DIR=/" + rootProject.projectDir.path + "/sdk/native"
}
}
}}
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
version "3.10.2"
}
}
My CMakeLists.txt:
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)
#Add OpenCV 4 lib
include_directories(${OpenCV_DIR}/jni/include) #Path from gradle to OpenCV Cmake
add_library( lib_opencv SHARED IMPORTED )
set_target_properties(lib_opencv PROPERTIES IMPORTED_LOCATION ${OpenCV_DIR}/libs/${ANDROID_ABI}/libopencv_java4.so)
#Add Your Native Lib
add_library(native-lib SHARED native-lib.cpp)
add_library(detection_based_tracker SHARED detectionbasedtracker_jni.cpp)
#Add&Link Android Native Log lib with others libs
find_library(log-lib log)
target_link_libraries(detection_based_tracker lib_opencv ${log-lib})
NDK version was 21.0.611669.
Also I don't use arguments for CMake like -DANDROID_STL=gnustl_static.

Building OpenCV for Android and using it with the NDK

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.
CROSS COMPILE OPENCV FROM SOURCE WITH EXTRA MODULES FOR ANDROID FROM WINDOWS10
* FIRST : prerequisites *
download OpenCV and unzip (say at '../opencv-source')
download OpenCV extra modules and unzip (say at '../opencv-contrib-source')
download Android NDK (say at '../ndk-dir')
download CMake (to say '../cmake-dir') and MinGW (to say '../mingw-dir')
install Android Studio
* SECOND : configure with CMake *
go to '../opencv-source/platforms' and create a folder named 'build_android_arm'
in CMake, fill the following first two fields with the following paths :
where is the source code : '../opencv-source'
where to build the binaries : '../opencv-source/platforms/build_android_arm'
add the following options via the 'Add Entry' :
ANDROID_NDK, type 'path', value '../ndk-dir'
ANDROID_NDK_HOST_X64, type 'bool', value 1
CMAKE_TOOLCHAIN_FILE, type 'path', value '../opencv-source/platforms/android/android.toolchain.cmake'
press 'Configure'
choose 'MinGW Makefiles' as the compiler
choose 'Specify toolchain file for cross-compiling'
press 'Next', and 'Finish'
note 1 : As long as you've got no error message, everything's good. Don't worry about the warning messages (like CMake telling you you're doing deprecated stuff).
note 2 : If you can't configure at that step, try to read the next few points, it might help.
change the following additional options via the 'Search' field :
EXTRA_MODULE_PATH, type 'path', value '../opencv-contrib-source/modules'
WITH_CAROTENE, type 'bool', value 0
BUILD_ZLIB, type 'bool', value 1
note : You MUST have configured already once before this step, because the variables created before are regrouped under the group 'Ungrouped entries', while the following variables are CMake automatically generated variables, and NEED to be grouped in the right groups (which is NOT 'Ungrouped entries').
verify that the following options are correctly set up (via the 'Search' field) :
ANDROID_NDK_HOST_X64, type 'bool', value 1
CMAKE_MAKE_PROGRAM, type 'path', value '../mingw-dir/bin/mingw32-make.exe'. This option, I actually DIDN'T have it in my CMake config. IF when you press 'Configure', it doesn't work AND you don't have this option, then you should try adding it (but I don't know how). IF when you press 'Configure' you don't have any problem, don't bother about that variable. This check comes from the original tutorial linked above.
CMAKE_TOOLCHAIN_FILE, type 'path', value '../opencv-source/platforms/android/android.toolchain.cmake'
press 'Configure'
choose 'MinGW Makefiles' as the compiler
choose 'Specify toolchain file for cross-compiling'
press 'Next', and 'Finish'
press 'Generate'
* THIRD : compile with mingw *
go to '../mingw-dir/msys/1.0' and run 'msys' bash file
navigate to '../opencv-source/platforms/android_arm'
run 'mingw32-make' command
run 'mingw32-make install' command
* FOURTH : android project *
launch Android Studio and create a new project :
select File -> New -> New Project...
fill the 'Application name' with let's say 'cOCV'
check the 'Include C++ Support' box
click 'Next'
choose your min SDK (let's say API 14: Android 4.0 (IceCreamSandwich)
click 'Next', 'Next' and 'Finish'
go to File -> New -> Import Module...
provide '../opencv-source/platforms/android_arm/install/sdk/java'
click 'Next' and 'Finish'
change the targets in build.gradle file in openCVLibraryXXX (imported module) folder :
compileSdkVersion and targetSdkVersion should be the same, greater or equal to 23
minSdkVersioon should be the same as the one specified when creating the project
in the build.gradle file in openCVLibraryXXX (imported module) folder :
replace 'apply plugin: com.android.application' as, 'apply plugin: com.android.library'
remove the line 'applicationId "org.opencv"'
note : That last step is done in order to avoid following error : 'unspecified on project app resolves to an APK archive which is not supported as a compilation dependency'.
add the imported library as a dependency to the 'app' module in File->'Project Structure'
create a jniLibs folder in 'app/src/main' :
right click 'app' in the Android view on the left menu
click 'New-Folder-JNI Folder'
check the 'Change Folder Location'
set the 'Target Source Set as 'app/src/main/jniLibs'
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
note : For example, my AndroidStudioProjects folder is located at 'C:\Users\JambonSama\AndroidStudioProjects'.
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)'
note 1 : THIS STEP MAY BE USELESS, because WRAP java is probably already written in the file.
note 2 : If 'python' is written too, it's fine, you let it be written where it is.
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)
note : These two lines pretty straight-forwardly give the paths for the include and link directories
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")
note : These are for easier linking commands, see next point.
the following paths, AS WRITTEN, in the 'target_link_libraries', after the 'native-lib' variable, and before the '${log-lib}' one :
${CVLIBS}
${PARTYLIBS}
${CVLIBS}
note : THAT IS THE TRICKY PART : because of cyclical dependencies, you have to write CVLIBS, PARTYLIBS, and then CVLIBS a second time, otherwise you won't stop having linking errors. By now, everything should be linked.
in the gradle.build of app, add the following code :
productFlavors {
armv7 {
ndk {
abiFilter "armeabi-v7a"
}
}
fat
}
at the end of the android block
note : This prevents the mips64 architecture error at build, by specifying once and for all the arm architecture
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
note : Because the string is not generated before the end of the function, you know, when you test, that if the string is indeed displayed on screen, the function has been gone through without problem, and that you're good (since the above provided code use some modules that are not on the stable realease as of 08/12/2016 (8th of december, I write dates with a dd/mm/yyyy format).
time to test :
sync the gradle
build
run on an arm device
You're good to go \ o \\ O // o /
Additional notes :
All the gradle.build files and the CMakeLists.txt file can be easily found on the Android View in the menu on the left of the window in AS.
Remember if you've got errors navigating in the command window that maybe your '/' should be '\' or the other way round. ('cd' command to navigate in a command window).
I run on Windows10.
If you're not quite sure what you should see on screen steps by steps, the tutorial I mentioned at the beginning of the answer should give you a good idea what you're supposed to see up until the AS project creation. Then, you can give a look at this tutorial, which explains how to setup OpenCV SDK in Android Studio project FOR THE OFFICIAL RELEASE. The steps I provided differs from BOTH those tutorials, but I put them here, because they can help you know what your screen / windows should look like.

Categories

Resources