I was trying to add some __android_log_print in Tensorflow Lite source code. I use the following command to generate Tensorflow Lite library (libtensorflowlite.jar and libtensorflowlite_jni.so).
bazel build -c opt --cxxopt='--std=c++11' //tensorflow/contrib/lite/java:tensorflowlite \
--crosstool_top=//external:android/crosstool \
--host_crosstool_top=#bazel_tools//tools/cpp:toolchain \
--cpu=armeabi-v7a
I used those two files (.jar and .so) for TFLiteCameraDemo app, which was built via Android Studio.
However, when I opened the app on my android device (Android 7.1), it showed the following errors.
02-18 16:36:35.990 25543-25543/android.example.com.tflitecamerademo W/System.err: TensorFlowLite: failed to load native library: dlopen failed: cannot locate symbol "__android_log_print" referenced by "/data/app/android.example.com.tflitecamerademo-1/lib/arm/libtensorflowlite_jni.so"...
02-18 16:36:35.992 25543-25543/android.example.com.tflitecamerademo W/System.err: TensorFlowLite: failed to load native library: dlopen failed: cannot locate symbol "__android_log_print" referenced by "/data/app/android.example.com.tflitecamerademo-1/lib/arm/libtensorflowlite_jni.so"...
02-18 16:36:35.992 25543-25543/android.example.com.tflitecamerademo E/art: No implementation found for long org.tensorflow.lite.NativeInterpreterWrapper.createErrorReporter(int) (tried Java_org_tensorflow_lite_NativeInterpreterWrapper_createErrorReporter and Java_org_tensorflow_lite_NativeInterpreterWrapper_createErrorReporter__I)
02-18 16:36:35.992 25543-25543/android.example.com.tflitecamerademo D/AndroidRuntime: Shutting down VM
By the way, I have already included these lines in my build.gradle.
ndk {
abiFilters "${cpuType}"
ldLibs "log"
}
The NDK version I use is r14b.
Is there any solution to this problem?
ndk.ldLibs relates to deprecated NDK plugin. These days, we use different Android Studio integration syntax.
At any rate, bazel silently ignores this.
You can pass -llog to bazel via --linkopt flag:
bazel build -c opt --cxxopt='--std=c++11' --linkopt='-llog' …
BTW, if I am not missing something, you should use --android_cpu instead of --cpu, but you can just as well skip it, because armeabi-v7a is the default for --android_cpu.
Related
I am new to this build system, but I've spent dozens of hours trying to get qmake + clang to produce a working android binary. I would appreciate any help or advice. Here is as simple an example as I can come up with:
First, here is a working build command. It gives me a shared object that I can call from android (with Unity, using C# native interops):
C:\Users\deltav\AppData\Local\Android\Sdk2\ndk\21.3.6528147\toolchains\llvm\prebuilt\windows-x86_64\bin\clang.exe ^
-target aarch64-none-linux-android21 -shared -v ^
-DANDROID_ABI=arm64-v8a -DANDROID_ARM_MODE=arm -DANDROID ^
M:\simpleExample\simpleExample.c ^
-o M:\simpleExample\libsimpleExample.so
Here is the verbose output of running that command: https://pastebin.com/18HcnDYh
On the other hand, here is the simpleExample.pro file that is NOT giving me a good binary: https://pastebin.com/wxrx6Myc
Here is the qmake output for building in release mode: https://pastebin.com/KWavwrb7
As you will know, qmake uses a kit to execute the project. My kit: https://imgur.com/a/Ehtmgin
The specific issue that has pushed me down this debugging path is from C# trying to load my shared object like this:
[DllImport("simpleExample")]
public static extern float getSpeedY();
The error that I get is this:
"DllNotFoundException: Unable to load DLL 'simpleExample': The
specified module could not be found."
Again, this error is not an issue if I just build from the CLI without qmake. I do not beleive this is a unity or C# error, as I worked the problem from that side first.
What I have tried so far:
I have used multiple ELF & DWARF tools to compare the ABIs of the generated binaries, which all told me the binaries were identical.
I tweaked and shaved down the clang calls that qmake generated until I got a vaild build command. Unfortunately I can't just replace qmake with the complile command because there are other projects that I need to apply this fix to.
QMake version 3.1
Ironically, CMake basically works out of the box.
Answer: Looking at the clang linking call, you can see QMake 3.1 was adding "libc++shared" as a dependency. I'm not sure why, as this was a C project.
The equivalent CMake project did not do this.
Packaging libc++shared with my binary fixed the issue.
I am creating an Android library that uses OpenCV via NDK. It doesn't require any Java parts of OpenCV, native parts only, so I decided not to use OpenCV for Android to reduce the size of the OpenCV code the library needs.
Now I need to download and build the native (C++) part of OpenCV using CMake so that the library won't require its users to download and install OpenCV on their own.
Currently my module's build.gradle contains this:
externalNativeBuild {
cmake {
cppFlags '-std=c++11 -frtti -fexceptions'
arguments '-DANDROID_ARM_NEON=TRUE'
}
}
And my CMakeLists.txt is:
cmake_minimum_required(VERSION 3.18.1)
project("mylib")
set(OPENCV_INSTALL_DIR ${CMAKE_BINARY_DIR}/opencv-install)
include(ExternalProject)
ExternalProject_Add(opencv
GIT_REPOSITORY https://github.com/opencv/opencv.git
GIT_TAG 4.5.5
UPDATE_DISCONNECTED TRUE
CMAKE_ARGS
<OpenCV arguments I need>
-DCMAKE_INSTALL_PREFIX=${OPENCV_INSTALL_DIR}
)
include_directories(${OPENCV_INSTALL_DIR}/include)
link_directories(${OPENCV_INSTALL_DIR}/lib)
set(OPENCV_LIBRARIES <OpenCV modules I use>)
add_library(mylib SHARED mylib.cpp)
add_dependencies(mylib opencv)
find_library(log-lib log)
target_link_libraries(mylib ${log-lib} ${OPENCV_LIBRARIES})
I am using Android Studio. When I try to build the library, the downloading process goes fine, but at the configure step I get the following error:
FAILED: opencv-prefix/src/opencv-stamp/opencv-configure
cmd.exe /C "cd /D <my lib module path>\.cxx\Debug\612145b5\x86_64\opencv-prefix\src\opencv-build && <my Android SDK path>\cmake\3.18.1\bin\cmake.exe -DBUILD_TESTS=OFF -DBUILD_PERF_TESTS=OFF -DBUILD_EXAMPLES=OFF -DBUILD_opencv_apps=OFF -DBUILD_JAVA=OFF -DBUILD_FAT_JAVA_LIB=OFF -DBUILD_opencv_python2=OFF -DBUILD_opencv_python3=OFF -DWITH_GTK=OFF -DWITH_WIN32UI=OFF -DWITH_FFMPEG=OFF -DWITH_V4L=OFF -DCPU_BASELINE=NEON -DCMAKE_INSTALL_PREFIX=<my lib module path>/.cxx/Debug/612145b5/x86_64/opencv-install -GNinja <my lib module path>/.cxx/Debug/612145b5/x86_64/opencv-prefix/src/opencv && <my Android SDK path>\cmake\3.18.1\bin\cmake.exe -E touch <my lib module path>/.cxx/Debug/612145b5/x86_64/opencv-prefix/src/opencv-stamp/opencv-configure"
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.
CMake Error: CMAKE_CXX_COMPILER not set, after EnableLanguage
CMake Error: CMAKE_C_COMPILER not set, after EnableLanguage
As I see, CMake cannot find the following components:
Ninja
C++ compiler
C compiler
I can get rid of the first error, if I add ninja's path from NDK to the PATH variable, I don't think thats how it should be done though. Neither do I want to pass CMAKE_CXX_COMPILER and CMAKE_C_COMPILER to CMake manually, as it seems like it should be done automatically by Android Studio.
So, how can I fix this?
I am trying to integrate the Hyperledger indy SDK. However, when running my code I get the error
E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.UnsatisfiedLinkError: dlopen failed: library "libgnustl_shared.so" not found
at java.lang.Runtime.loadLibrary0(Runtime.java:1016)
at java.lang.System.loadLibrary(System.java:1657)
I am trying to follow the documentation provided in the project repo. I tried using the sample project on this blog .
I was able to build the *.so libraries under a linux virtual machine, the copied the built files in my android studio project on windows.
I added the files inside my project's jniLibs forlder for each architecture.
Added the code to load the library inside my mainActivity
static{
System.loadLibrary("indy");
}
Tried creating a CMake file
cmake_minimum_required(VERSION 3.4.1)
add_library(indy SHARED IMPORTED)
include_directories(src/main/jniLibs/${ANDROID_ABI}/include)
My gradle file includes:
android{
defaultconfig{
...
ndk{
moduleName "indy"
abiFilters 'armeabi-v7a'
}
}
...
sourceSets {
main {
jniLibs.srcDir 'src/main/jniLibs'
}
}
externalNativeBuild {
cmake {
path file('../CMakeLists.txt')
}
}
}
Still, keep on getting the same error when I launch the app.
I am aware that the bash script that builds the libraries on linux uses the android-ndk-r16b-linux-x86_64 tools so I tried downgrading my ndk in android studio to use the same version but had no luck.
The output of the build script is
include/
indy_anoncreds.h
indy_core.h
...
lib/
libindy.a
libindy.so
libindy_shared.so
How can I use this libraries in my android studio project?
The issue is mainly related to the nature of libraries. Libraries are dynamic in Android and needs to be linked at runtime.
libindy.so depends on stl, openssl, libsodium and libzmq.
You will find libgnustl_shared.so in NDK.
All the other needed prebuilt libraries are also available here.
What you need to do is make sure these libraries are present in the jniLibs folder and load these in order libraries before libindy.
System.loadLibrary("libgnustl_shared");
.
.
System.loadLibrary("indy");
Alternate approach:
There is a subproject in Indy where we are using libindy as dependency and we try to create a one fat dynamic library which has all the dependencies.
Link
If you follow the steps like vcx you dont have to have all the defendant l libraries in jniLibs as they will be already part of final .so file
The command which make one fat dynamic library with all the symbols and dependencies is this (from the link pasted above)
${LIBVCX}/target/${CROSS_COMPILE}/release/libvcx.a \
${TOOLCHAIN_DIR}/sysroot/usr/${NDK_LIB_DIR}/libz.so \
${TOOLCHAIN_DIR}/sysroot/usr/${NDK_LIB_DIR}/libm.a \
${TOOLCHAIN_DIR}/sysroot/usr/${NDK_LIB_DIR}/liblog.so \
${LIBINDY_DIR}/libindy.a \
${TOOLCHAIN_DIR}/${CROSS_COMPILE_DIR}/${NDK_LIB_DIR}/libgnustl_shared.so \
${OPENSSL_DIR}/lib/libssl.a \
${OPENSSL_DIR}/lib/libcrypto.a \
${SODIUM_LIB_DIR}/libsodium.a \
${LIBZMQ_LIB_DIR}/libzmq.a \
${TOOLCHAIN_DIR}/${CROSS_COMPILE_DIR}/${NDK_LIB_DIR}/libgnustl_shared.so -Wl,--no-whole-archive -z muldefs
I'm trying to build PJSIP with FFMPEG for Android.
For building FFMPEG with rtmp and openssl, I use this project:
https://github.com/cine-io/android-ffmpeg-with-rtmp
and it compiles pretty well.
Then I'm compiling pjsip 2.6 with ffmpeg. Here is the part from my build file:
APP_PLATFORM=android-${TARGET_ANDROID_API} NDK_TOOLCHAIN_VERSION=4.9 TARGET_ABI=$arch ./configure-android --use-ndk-cflags \
--with-ssl="${OPENSSL_BUILD_OUT_PATH}/libs/${arch}" \
--with-ffmpeg="${BASE_DIR}/ffmpeg-output"
>>"${FINAL_BUILD_LOGS}/${arch}.log" 2>&1
My target ABI is armeabi.
Also, i've defined these two flags:
#define PJMEDIA_HAS_VIDEO 1
#define PJMEDIA_HAS_FFMPEG 1
But the build failed with a bunch of these two errors:
error: cannot find -lbz2
error: cannot find -lasound
A have libasound2-dev and bzip2 installed on my Ubuntu 16.04 LTS VM.
Before that, I've successfully made pjsip builds with OpenH264 with no errors like this.
Is there any way to tell linker(or whatever it is) how to find those packages?
Solve that problem (thx #NandhaKumar) by compiling .a libs for each library above and adding them to pjsip library path:
Build .a libs.
Copy libs to {PJPROJECT}/third_party/lib/ folder.
Go to the build.mak.in file in your PJSIP project folder.
Add the following lines:
APP_THIRD_PARTY_LIB_FILES += $(PJ_DIR)/third_party/lib/libbz2.a
APP_THIRD_PARTY_LIB_FILES += $(PJ_DIR)/third_party/lib/libasound.a
In my case (and I still don't know why) second line and defining another line
(APP_THIRD_PARTY_LIBS += -lsound or APP_THIRD_PARTY_LIBS += -lasound) doesn't help, so I just copied this library into the android_ndk folder:
android-ndk-r10e/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.9/libasound.a
I compiled libVlc for android by following the procedure from here The compiled project don't show any error in eclipse but when I run it on device, it throws the following error
05-21 14:37:50.834: D/dalvikvm(14423): GC_CONCURRENT freed 181K, 8% free 9633K/10439K, paused 17ms+7ms, total 62ms
05-21 14:37:51.034: E/VLC/LibVLC/Util(14423): WARNING: Unable to read libvlcjni.so; cannot check device ABI!
05-21 14:37:51.034: E/VLC/LibVLC/Util(14423): WARNING: Cannot guarantee correct ABI for this build (may crash)!
05-21 14:37:51.065: W/VLC/LibVLC(14423): Unable to load the iomx library: java.lang.UnsatisfiedLinkError: Couldn't load iomx-ics: findLibrary returned null
05-21 14:37:51.065: E/VLC/LibVLC(14423): Can't load vlcjni library: java.lang.UnsatisfiedLinkError: Couldn't load vlcjni: findLibrary returned null
Please help me to solve the issue, thanks in advance
You're getting this error because you haven't exported your device's abi, as mentioned in the instructions. I'm going to assume you also didn't follow the section 'Environment Setup' in the documentation. So, do as follows:
Make sure you've downloaded the NDK, and then run this(with your path) in your terminal:
export ANDROID_NDK=/path/to/android-ndk>
Then, compile the .sh file and export your device's (or emulator's abi) as well. The compilation of the .sh file is directly linked to the abi issue since the script handles the abi. You can see this in the code for the script (compile.sh):
# try to detect NDK version
REL=$(grep -o '^r[0-9]*.*' $ANDROID_NDK/RELEASE.TXT 2>/dev/null|cut -b2-)
case "$REL" in
9*)
GCCVER=4.8
CXXSTL="/"${GCCVER}
;;
8?*)
# we don't use 4.4.3 because it doesn't handle threads correctly.
# TODO : clang?
if test -d ${ANDROID_NDK}/toolchains/arm-linux-androideabi-4.7
# if gcc 4.7 is present, it's there for all the archs (x86, mips, arm)
then
# since r8d
GCCVER=4.7
else
GCCVER=4.6
fi
CXXSTL="/"${GCCVER}
;;
7|8|*)
echo "You need the NDKv8b or later"
exit 1
;;
esac
export GCCVER
export CXXSTL
# Set up ABI variables
if [ ${ANDROID_ABI} = "x86" ] ; then
TARGET_TUPLE="i686-linux-android"
PATH_HOST="x86"
HAVE_X86=1
PLATFORM_SHORT_ARCH="x86"
elif [ ${ANDROID_ABI} = "mips" ] ; then
TARGET_TUPLE="mipsel-linux-android"
PATH_HOST=$TARGET_TUPLE
HAVE_MIPS=1
PLATFORM_SHORT_ARCH="mips"
else
TARGET_TUPLE="arm-linux-androideabi"
PATH_HOST=$TARGET_TUPLE
HAVE_ARM=1
PLATFORM_SHORT_ARCH="arm"
fi
I suggest going over the Android Compile documentation again, and follow the instructions step by step.
If your are using Android Studio, please move *.so to src/jniLibs/armeabi-v7a