I built ffmpeg executable binary with shared libraries on Android. But when I run it on Marshmallow, I got the following error, the executable can't run.
$ LD_LIBRARY_PATH=./lib ./bin/ffmpeg
CANNOT LINK EXECUTABLE: cannot find "libavformat.so" from verneed[0] in DT_NEEDED list for "./bin/ffmpeg"
page record for 0xb6eee00c was not found (block_size=16)
I already added --extra-ldexeflags="-pie" when compiled the binary.
The executable binary run properly on pre Marshmallow device.
I didn't encounter such problem before, did I miss something important? How can I make this binary work on Marshmallow?
More information about my environment.
I used android-ndk-r10e with
SYSROOT=$ANDROID_NDK_ROOT/platforms/android-19/arch-arm and toolchains version is
arm-linux-androideabi-gcc (GCC) 4.9 20140827 (prerelease)
If I built ffmpeg into a single executable binary (build the static libraries and then build into binary), it run properly.
After a lot of searching, I found a similar issue from here. There is a problem with my share libraries.
FFmpeg build script disable SONAME for android build, so there is no SONAME found when reading library by command
arm-linux-androideabi-readelf -d libavutil.so |grep soname
Change the configuration script like following, it will work.
android)
disable symver
enable section_data_rel_ro
SLIB_INSTALL_NAME='$(SLIBNAME)'
SLIB_INSTALL_LINKS=
# soname not set on purpose
# soname should set for new version Android
SHFLAGS='-shared -Wl,-soname,$$(word 1,$$(subst ., ,$$(#F))).so'
# SHFLAGS=-shared
After then, recompile ffmpeg to generate share libraries, and I got the result I want,
$ arm-linux-androideabi-readelf -d libavutil.so |grep soname
0x0000000e (SONAME) Library soname: [libavutil.so]
Then, the executable binary run properly.
Related
I'm having an Error in my Native C++ Code in Android NDK Application
My main.cpp
#include <stdio.h>
int main()
{
printf("Hello, world\n");
return 0;
}
The main.c is exactly the same.
If i run
/home/rip/Music/android-ndk-r19b/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android26-clang -pie main.c
then
adb push a.out /data/local/tmp
and
adb shell /data/local/tmp/a.out
all works fine. But if i run
/home/rip/Music/android-ndk-r19b/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android26-clang++ -pie main.cpp
then
adb push a.out /data/local/tmp
and
adb shell /data/local/tmp/a.out
The error message is:
CANNOT LINK EXECUTABLE "/data/local/tmp/a.out": library "libc++_shared.so" not found
Then i tried to run
/home/rip/Music/android-ndk-r19b/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android26-clang++ -pie hello1.cpp /home/rip/Music/android-ndk-r19b/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/libc++_shared.so
to link the library, but it doesn't work anyway.
The error message is:
CANNOT LINK EXECUTABLE "/data/local/tmp/a.out": library "libc++_shared.so" not found
That's the expected behavior. Unlike the standard C library (to which your program is linking when building with simple *-clang), C++ is not a system library. You have to make it available on the device just like any other third party library.
Quoted from official documentation:
Note: libc++ is not a system library. If you use libc++_shared.so, it must be included in your APK. If you're building your application with Gradle this is handled automatically.
And:
If you're using clang directly in your own build system, clang++ will use c++_shared by default. To use the static variant, add -static-libstdc++ to your linker flags.
So either link with C++ statically by passing -static-libstdc++ to compiler. Or copy the libc++_shared.so (from <NDK>/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/ in your case) and run like:
adb push a.out libc++_shared.so /data/local/tmp/
adb shell
cd /data/local/tmp/
LD_LIBRARY_PATH=. ./a.out
Other than the LLVM's Standard C++ library discussed above, there's also a limited system C++ runtime (/system/lib(64)/libstdc++.so) which "provides support for the basic C++ Runtime ABI". But "The system STL will be removed in a future NDK release."
I compiled the same "hello world" code in a .c and .cpp file and didn't have the same issue when I pushed the application to my device. I assume you're having the same issue as in this topic:
Application can't find libc++_shared.so
The issue may come from your toolchain or toolchain parameters as you are calling clang manually.
I created a simple project that you can run and test:
android-ndk-example
add_executable( # Sets the name of the library.
ndk_example_c
# Provides a relative path to your source file(s).
main.c
)
add_executable( # Sets the name of the library.
ndk_example_cpp
# Provides a relative path to your source file(s).
main2.cpp
)
In generated cmake script, I can see the following definition for cpp compiler:
rule CXX_COMPILER__ndk_example_cpp
depfile = $DEP_FILE
deps = gcc
command = D:\Users\$USER\AppData\Local\Android\Sdk\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --target=armv7-none-linux-androideabi19 --gcc-toolchain=D:/Users/$USER/AppData/Local/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/windows-x86_64 --sysroot=D:/Users/$USER/AppData/Local/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/windows-x86_64/sysroot $DEFINES $INCLUDES $FLAGS -MD -MT $out -MF $DEP_FILE -o $out -c $IN_ABS
description = Building CXX object $out
I write a new Answer for the Solution because i cannot edit my question.
The Solution is the following command for android devices with armv7:
/home/tony/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++ --target=armv7-none-linux-androideabi19 --gcc-toolchain=/home/tony/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64 --sysroot=/home/tony/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/sysroot main.cpp
For aarch64 armv8 the command is:
/home/tony/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++ --target=aarch64-none-linux-android21 --gcc-toolchain=/home/tony/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64 --sysroot=/home/tony/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/sysroot main.cpp
A CMakeLists.txt file should look as:
cmake_minimum_required(VERSION 3.1)
set(CMAKE_CXX_COMPILER /home/tony/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++)
project(Test CXX)
set(CMAKE_CXX_FLAGS "--target=aarch64-none-linux-android21 --gcc-toolchain=/home/tony/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64 --sysroot=/home/tony/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/sysroot")
set(SOURCES
main.cpp
)
add_executable(Test ${SOURCES})
Then can the app build with
cmake
make
adb push Test /data/local/tmp
adb shell /data/local/tmp/Test
I want to install compile Boost 1.61 with clang 3.6 for android with the NDK 11 but this software : https://github.com/moritz-wundke/Boost-for-Android isn't updated and doesn't support this versions.
I want to know if anyone has managed to this !
Thank you !
Build boost_1_62_0 for Android-21 under Windows64.
Assuming NDK installed to C:\Programs\Android\sdk\ndk-bundle and boost in c:\boost_1_62_0.
Install mingw: using msys2-x86_64 from MSYS2
Install build tools from mingw prompt (something like this):
$ pacman -S gcc binutils
Create android.clang.jam file in C:\boost_1_62_0\ with such text content:
import os ;
local AndroidNDKRoot = C:/Programs/Android/sdk/ndk-bundle ;
using clang : android
:
C:/Programs/Android/toolchain21/bin/clang++
:
<compileflags>-fexceptions
<compileflags>-frtti
<compileflags>-fpic
<compileflags>-ffunction-sections
<compileflags>-funwind-tables
<compileflags>-Wno-psabi
<compileflags>-march=armv7-a
<compileflags>-mfloat-abi=softfp
<compileflags>-mfpu=vfpv3-d16
<compileflags>-fomit-frame-pointer
<compileflags>-fno-strict-aliasing
<compileflags>-finline-limit=64
<compileflags>-I$(AndroidNDKRoot)/platforms/android-21/arch-arm/usr/include
<compileflags>-Wa,--noexecstack
<compileflags>-DANDROID
<compileflags>-D__ANDROID__
<compileflags>-DNDEBUG
<compileflags>-O2
#<compileflags>-g
<compileflags>-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.9/include
<compileflags>-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi/include
<architecture>arm
<compileflags>-fvisibility=hidden
<compileflags>-fvisibility-inlines-hidden
<compileflags>-fdata-sections
<cxxflags>-D__arm__
<cxxflags>-D_REENTRANT
<cxxflags>-D_GLIBCXX__PTHREADS
;
Setup boost from mingw prompt:
$ export NDK=/c/Programs/Android/sdk/ndk-bundle
$ echo ensure msi-installed Python is on path (not msys version):
$ export PATH=/c/Python27:$PATH
$ $NDK/build/tools/make_standalone_toolchain.py --arch arm --api 21 --install-dir /c/Programs/Android/toolchain21
$ ./bootstrap.sh --with-toolset=gcc
$ ./b2 --user-config=android.clang.jam threading=multi link=static \
runtime-link=static toolset=clang-android target-os=linux \
threadapi=pthread --stagedir=android --with-chrono \
--with-program_options --with-system --with-thread --with-random \
--with-regex
Yes, the repository you mentioned is apparently not maintained anymore. The author also seems not to answer any mails on the subject. If you look you'll see that each new boost version supported there required a lot of work (many special flags in the config files). That's presumably why he doesn't have time to maintain it any longer.
I also tried to update to 1.64 using a fork but gave up after countless error messages and instead used a different method based on a crystax script. Its simple and should work for pretty much any version. You can find the details and the script (simple and painless to execute) here: http://silverglint.com/boost-for-android/
Works with clang and gcc.
Also included is a sample app that shows you how to use the boost binaries thus built.
I'm at the end of my rope on this one.
I'm new to Android development. I've read the GCC install documentation and parts of Embedded Android. I'm trying to cross-compile gcc 4.7 using an Android NDK toolchain built with the make-standalone-toolchain.sh script. I'm using the gcc and binutils source files from the NDK toolchain sources.
I copied the gcc-4.7 and binutils-2.23 into a directory gcc-src and created a 'build' directory alongside both, as follows:
gcc-src/gcc-4.7
gcc-src/binutils-2.23
gcc-src/build
I've symlinked the sources for
bfd,
gas,
gprof,
ld,
gprof
opcodes
from binutils to the gcc-4.7 source directory. I also ran the script in contrib/ that downloads the relevant sources for
gmp,
mpfr
mpc
and creates the appropriate symlinks
I've run configure with the (latest) following options:
sh ../gcc-4.7/configure --prefix=/usr/arm --disable-option-checking --host=arm-linux-eabi
--target=arm-linux-eabi --with-sysroot=/usr/sysroot --with-build-sysroot=/usr/sysroot --with-build-time-tools=/usr/bin --program-prefix=arm-
--disable-multilib --with-cpu=arm7 --enable-languages=c,c++,lto --disable-werror --disable-nls CC=arm-linux-androideabi-gcc GCC=arm-linux-androideabi-gcc
CFLAGS='-Wall -g -mfloat-abi=softfp -mbionic -mandroid -Wl,-lsupc++ -Wl,-lgnustl_shared'
CPPFLAGS='-Wall -g -mbionic -mandroid' LDFLAGS='-Wl,-lsupc++ -Wl,-lgnustl_shared' CXX=arm-linux-androideabi-g++
LD=arm-linux-androideabi-ld STRIP=arm-linux-androideabi-strip OBJDUMP=arm-linux-androideabi-objdump READELF=arm-linux-androideabi-readelf
AS=arm-linux-androideabi-as NM=arm-linux-androideabi-nm
LIBS='-lc -ldl -lm' CC_FOR_TARGET=arm-linux-androideabi-gcc CPP_FOR_TARGET=arm-linux-androideabi-gcc CXX_FOR_TARGET=arm-linux-androideabi-g++
GCC_FOR_TARGET=arm-linux-androideabi-gcc RANLIB_FOR_TARGET=arm-linux-androideabi-gcc-ranlib LD_FOR_TARGET=arm-linux-androideabi-ld
AS_FOR_TARGET=arm-linux-androideabi-as NM_FOR_TARGET=arm-linux-androideabi-gcc-nm AR_FOR_TARGET=arm-linux-androideabi-gcc-ar
READELF_FOR_TARGET=arm-linux-androideabi-readelf
OBJDUMP_FOR_TARGET=arm-linux-androideabi-objdump STRIP_FOR_TARGET=arm-linux-androideabi-strip
host_configargs=--with-headers=/usr/sysroot/usr/include target_configargs=/usr/sysroot/usr/include
When I run make -d...or make -d all-host...it constantly fails when it tries to compile gen-fac_ui.c because it can't find the includes stdio.h, stdint.h or string.h.
I'll add the exact error tomorrow after I re-set my build directory and start again, but I wanted to post the details and problem tonight before I pass out.
Any help...is greatly appreciated. I'm at a loss on this one.
QUICK NOTE: I noticed that the binutils src directory contains an include/ folder...I'll try symlinking that into the gcc src directory and running 'make distclean' then '../gcc-4.7/configure && make again.'
UPDATE: symlinking include/ did not fix the problem. Here's the error I'm continuously getting
make[2]: Entering directory `/project/android/tc-src/gcc/gcc-src/build/gmp'
gcc `test -f 'gen-fac_ui.c' || echo '../../gcc-4.7/gmp/'`gen-fac_ui.c -o gen-fac_ui
Putting child 0x007ddd30 (gen-fac_ui) PID 25531 on the chain.
Live child 0x007ddd30 (gen-fac_ui) PID 25531
../../gcc-4.7/gmp/gen-fac_ui.c:20:19: error: stdio.h: No such file or directory
../../gcc-4.7/gmp/gen-fac_ui.c:21:20: error: stdlib.h: No such file or directory
In file included from ../../gcc-4.7/gmp/gen-fac_ui.c:23:
../../gcc-4.7/gmp/dumbmp.c:42:20: error: string.h: No such file or directory
In file included from ../../gcc-4.7/gmp/gen-fac_ui.c:23:
I successfully compiled gen-fac_ui by doing the following:
Uninstalling the build gcc which is not (I think) needed as I'm using the cross-compiler toolchain generated by the make-standalone-toolchain.sh script from the Android NDK
Configuring the appropriate variables to set up the cross-compiler tools as the BUILD tools.
I have a different problem now, which I'll post in a different question. Basically, while gen-fac_ui compiles, it (of course) won't run.
I've build the Android NDK toolchain manually. Everything works except when I use the compiler it can't find basic STL stuff like . So it can't compile code containing STL because it doesn't know where to look for the headers by default. I've never had this problem before using a custom or prebuilt toolchain. However if I manually add the include directories like
-I$(NDK_TOOLCHAIN)/arm-linux-androideabi/include/c++/4.6/
Then it works just fine. It is a pain to add every important dir manually (there is more than this one). Surely something broken in the process.
These are the steps I followed to get it build:
sudo apt-get install git-core gnupg flex bison gperf build-essential zip curl
Download NDK
Untar NDK to [SOME_LOCATION], using /opt/ndk/
Set NDK_ROOT=/opt/ndk/
./build/tools/download-toolchain-sources.sh src/
Download MPC 0.9
Move mpc tar to ./src/mpc/
./build/tools/build-gcc.sh --gmp-version=4.3.2 --mpc-version=0.9 --mpfr-version=2.4.2 --binutils-version=2.21 $(pwd)/src $(pwd) arm-linux-androideabi-4.6
./build/tools/build-gcc.sh --gmp-version=4.3.2 --mpc-version=0.9 --mpfr-version=2.4.2 --binutils-version=2.21 $(pwd)/src $(pwd) x86-4.6
./build/tools/build-gcc.sh --gmp-version=4.3.2 --mpc-version=0.9 --mpfr-version=2.4.2 --binutils-version=2.21 $(pwd)/src $(pwd) mipsel-linux-android-4.6
All the STL files exist in the proper location. All the headers and compiled libraries for each version if I build a STANDALONE toolchain after using as reference these custom built toolchains.
==
UPDATE
Forcing gcc to spit out its include search paths:
echo "#include <bogus.h> int main(){}" > t.c; /opt/android-9_arm/bin/arm-linux-androideabi-gcc -v t.c; rm t.c
This contains a search path under includes:
/opt/android-9_arm/bin/../lib/gcc/arm-linux-androideabi/4.6.x-google/../../../../arm-linux-androideabi/include
At that location is indeed the following ./cxx/4.6/STL_HEADERS
Comparing the output with a NDK build from google does indeed differ in serious spots. The real question is now how do I guarantee my custom build of GCC points to the appropriate G++ STL header location.
It turned out to be a bug in make-standalone-toolchain.sh. The fix was:
mv $NDK_TOOLCHAIN/arm-linux-androideabi/include/c++/4.6 $NDK_TOOLCHAIN/arm-linux-androideabi/include/c++/4.6.x-google
That fixed it for the most part. However now that the ndkr8b has released with official GCC 4.6 support this bug stills exists (as of july 25 2012). More details on some bugs related to the standalone toolchain (http://code.google.com/p/android/issues/detail?id=35279).
I have a really simple helloworld.cpp program
#include <iostream>
using namespace std;
int main ()
{
cout << "Hello World!";
return 0;
}
And I'm trying to compile it for android x86 with the cross-compiler from the toolchain:
/Users/me/android-ndk-r8/toolchains/x86-4.4.3/prebuilt/darwin-x86/bin/i686-android-linux-g++ helloworld.cpp -L "/Users/me/android-ndk-r8/sources/cxx-stl/stlport/libs/x86/" -lstlport_static
However, I get errors:
helloworld.cpp:2:20: error: iostream: No such file or directory
Any idea why?
Check the documentation.html file included with the NDK, under "Standalone Toolchain". It says that if you invoke the compiler in this way you won't be able to "use any C++ STL". However it is possible, as the documentation explains, if you first create a "customized" toolchain installation, using something like the following command:
$NDK/build/tools/make-standalone-toolchain.sh --platform=android-8 --install-dir=/tmp/my-android-toolchain --arch=x86
where $NDK is the path to your NDK directory. Note the --arch=x86 which means that the toolchain is prepared specifically for the x86 Android. This prepares what you need in one directory, including the STL headers and folders. You should then be able to use -lstdc++ to link against the STL (static version), i.e. something like:
/tmp/my-android-toolchain/bin/i686-android-linux-g++ helloworld.cpp -lstdc++
For a more complete explanation, please see the NDK documentation.
The NDK documentation is not entirely accurate, at least not currently. In fact, it states when using the prebuilt toolchain "You won't be able to use any C++ STL (either STLport or the GNU libstdc++) with it.", but this is out of date. I created a small hello world program using the include with the same error. It can be solved without creating your own toolchain though, which is nice if you don't want to have to add one more step to your configuration process and allows you to always use the latest SDK platform without creating a new toolchain every time.
The NDK ships with the source code for several versions of standard C++ libraries: GAbi++, STLport, and GNU STL. Each flavor comes with prebuilt shared and static libs as well. My example below will use stlport.
To use the stand-alone toolchain at its installed location, you can do something like this:
export CXX='$NDK_ROOT/toolchains/arm-linux-androideabi-4.8/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-g++ --sysroot="$NDK_ROOT/platforms/android-19/arch-arm"'
This, for example, would set your CXX compiler to compile ARM on the OS X system using SDK platform level 19. This much you probably already knew. Also, you would want to export your CC, CPP, LD, AR, and RANLIB if you use it. I also personally create an envar for READELF.
To add support for C++ libs, you could do something like follows:
$CXX helloworld.cpp -I$NDK_ROOT/sources/cxx-stl/stlport/stlport -L$NDK_ROOT/sources/cxx-stl/stlport/libs/armeabi -lstlport_shared
Note that this will link the libstlport_shared.so which will now be required at runtime, so you may need to add a relative path to the command above to support that, depending on your APK structure. If you want to just test this simple case, you can just run this on the emulator as follows:
adb push a.out /data
adb push $NDK_ROOT/sources/cxx-stl/stlport/libs/armeabi/libstlport_shared.so /data
adb shell
# su
# cd /data
# chmod 777 a.out
# ./a.out
To get rid of the headache of dealing with shared library paths, you can also statically link the C++ library in by changing "-lstlport_shared" to "-lstlport_static". There are some consequences of doing this, as explained in the NDK Dev Guide. The biggest issue is due to having the static library linked in multiple places, causing:
- memory allocated in one library, and freed in the other would leak or even corrupt the heap.
- exceptions raised in libfoo.so cannot be caught in libbar.so (and may simply crash the program).
- the buffering of std::cout not working properly
A useful tool is also included to see what dependencies your program has, the readelf tool.
To see what other shared libraries your program requires, you can run the following:
$NDK_ROOT/toolchains/arm-linux-androideabi-4.8/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-readelf -a a.out | grep NEEDED
Other cool standard tools:
addr2line - convert a stack trace address to a line of code
nm - Displays the symbol table
objdump - displays info on an object
i call one of the functions from gnustl after it runs fine from prebuilt aosp arm-linux-androideabi-gcc --std=c++11 and after crashing error i cant get a backtrace from logs or reason, my hope is turning to crossbuilt qemu-linux-user to run host compiled i686 binary on the arm, difficulty is interacting with crosshost libs aapt from adt always crashes on any other than platform specific libs, unless kernel module packaged update is possible...