2

I am building a C++ executable for android using NDK. The executable (./main )source file main.c is very simple:

#include <stdio.h>
#include <stdlib.h>
int main()
{
     printf("Hello World\n");
     return 0;
}

I can build it with cmake and android-cmake-toolchain. After that I put it on the Android device:

# this script is used to put binary to the device
import subprocess

output_executable = 'libs/armeabi-v7a/main  /data/local/tmp/main'

# step 1: push
push_cmd = 'adb push '+output_executable
subprocess.check_call(push_cmd,stderr=subprocess.STDOUT, shell=True)

# step 2: change mode
mod_cmd = 'adb shell chmod 777 '+output_executable
subprocess.check_call(mod_cmd,stderr=subprocess.STDOUT, shell=True)

# step 3: run the program
run_cmd = 'adb shell '+output_executable
subprocess.check_call(run_cmd,stderr=subprocess.STDOUT, shell=True)

Everything works fine. However, if I just change main.c to main.cpp, and then do the same, the compilation is fine. But when it is put on the Android device, I receive the following error message:

soinfo_link_image(linker.cpp:1635): could not load library "libgnustl_shared.so" needed by "/data/local/tmp/main"; ....

It seemed to me that I should indicate the location of the stl library in Android platform according to the error message. Any ideas will be appreciated.

feelfree
  • 11,175
  • 20
  • 96
  • 167

1 Answers1

0

.cpp extension makes NDK build to use c++ compiler and to link with some c++ libraries. You should use -nodefaultlibs option and explicitly define libraries to link with.

Also, look at SO: g++, static initialization and -nostdlib.

Update.

Added logs (for unbelievers).

When file has .c extension:

C:\Dev\Projects\NdkTest\jni>ndk-build -B V=1 

[armeabi] Compile thumb : hello-jni <= main.c

C:/Dev/Tools/Android/ndk-r10d/toolchains/arm-linux-androideabi-4.8/pre 
built/windows-x86_64/bin/arm-linux-androideabi-gcc -MMD -MP -MF 
C:\Dev\Projects\NdkTest/ob j/local/armeabi/objs/hello-jni/main.o.d 
-fpic -ffunction-sections -funwind-tables -fstack-protector 
-no-canonical-prefixes -march=armv5te -mtune=xscale -msoft-f loat 
-mthumb -Os -g -DNDEBUG -fomit-frame-pointer -fno-strict-aliasing 
-finline-limit=64 -IC:\Dev\Projects\NdkTest/jni -DANDROID 
-Wa,--noexecstack -Wformat -We rror=format-security 
-IC:/Dev/Tools/Android/ndk-r10d/platforms/android-3/arch-arm/usr/inclu 
de -c C:\Dev\Projects\NdkTest/jni/main.c -o C:\Dev\Projects\NdkTe 
st/obj/local/armeabi/objs/hello-jni/main.o 

[armeabi] Executable : hello-jni 

C:/Dev/Tools/Android/ndk-r10d/toolchains/arm-linux-androideabi-4.8/pre 
built/windows-x86_64/bin/arm-linux-androideabi-g++ -Wl,--gc-sections 
-Wl,-z,nocopyreloc -- 
sysroot=C:/Dev/Tools/Android/ndk-r10d/platforms/android-3/arch-arm 
-Wl,-rpath-link=C:/Dev/Tools/Android/ndk-r10d/platforms/android-3/arch 
-arm/usr/lib -Wl,-rpath 
-link=C:\Dev\Projects\NdkTest/obj/local/armeabi 
C:\Dev\Projects\NdkTest/obj/local/armeabi/objs/hello-jni/main.o -lgcc 
-no-canonical-prefixes -Wl,--no-undefined -Wl,-z,noexecstack 
-Wl,-z,relro -Wl,-z,now -mthumb -lc -lm -o 
C:\Dev\Projects\NdkTest/obj/local/armeabi/hello-jni 

[armeabi] Install : hello-jni => libs/armeabi/hello-jni 

copy /b/y "C:\Dev\Projects\NdkTest\obj\local\armeabi\hello-jni" 
"C:\Dev\Projects\NdkTest\libs\armeabi\hello-jni" > NUL 
C:/Dev/Tools/Android/ndk-r10d/toolchains/arm-linux-androideabi-4.8/pre 
built/windows-x86_64/bin/arm-linux-androideabi-strip --strip-unneeded 
C:\Dev\Projects\Ndk Test/libs/armeabi/hello-jni 

When file has .cpp extension:

C:\Dev\Projects\NdkTest\jni>ndk-build -B V=1 

[armeabi] Compile++ thumb: hello-jni <= main.cpp

C:/Dev/Tools/Android/ndk-r10d/toolchains/arm-linux-androideabi-4.8/pre 
built/windows-x86_64/bin/arm-linux-androideabi-g++ -MMD -MP -MF 
C:\Dev\Projects\NdkTest/ob j/local/armeabi/objs/hello-jni/main.o.d 
-fpic -ffunction-sections -funwind-tables -fstack-protector 
-no-canonical-prefixes -march=armv5te -mtune=xscale -msoft-f loat 
-fno-exceptions -fno-rtti -mthumb -Os -g -DNDEBUG -fomit-frame-pointer 
-fno-strict-aliasing -finline-limit=64 
-IC:/Dev/Tools/Android/ndk-r10d/sources/cxx-s tl/system/include 
-IC:\Dev\Projects\NdkTest/jni -DANDROID -Wa,--noexecstack -Wformat 
-Werror=format-security -IC:/Dev/Tools/Android/ndk-r10d/platforms/and 
roid-3/arch-arm/usr/include -c C:\Dev\Projects\NdkTest/jni/main.cpp -o 
C:\Dev\Projects\NdkTest/obj/local/armeabi/objs/hello-jni/main.o 

[armeabi] StaticLibrary : libstdc++.a 

C:/Dev/Tools/Android/ndk-r10d/toolchains/arm-linux-androideabi-4.8/pre 
built/windows-x86_64/bin/arm-linux-androideabi-gcc-ar crsD 
C:\Dev\Projects\NdkTest/obj/loc al/armeabi/libstdc++.a 

[armeabi] Executable : hello-jni 

C:/Dev/Tools/Android/ndk-r10d/toolchains/arm-linux-androideabi-4.8/pre 
built/windows-x86_64/bin/arm-linux-androideabi-g++ -Wl,--gc-sections 
-Wl,-z,nocopyreloc -- 
sysroot=C:/Dev/Tools/Android/ndk-r10d/platforms/android-3/arch-arm 
-Wl,-rpath-link=C:/Dev/Tools/Android/ndk-r10d/platforms/android-3/arch 
-arm/usr/lib -Wl,-rpath 
-link=C:\Dev\Projects\NdkTest/obj/local/armeabi 
C:\Dev\Projects\NdkTest/obj/local/armeabi/objs/hello-jni/main.o 
C:\Dev\Projects\NdkTest/obj/local/armeabi/libstd c++.a -lgcc 
-no-canonical-prefixes -Wl,--no-undefined -Wl,-z,noexecstack 
-Wl,-z,relro -Wl,-z,now -mthumb 
-LC:/Dev/Tools/Android/ndk-r10d/platforms/android-3/a rch-arm/usr/lib 
-lstdc++ -lc -lm -o 
C:\Dev\Projects\NdkTest/obj/local/armeabi/hello-jni 

[armeabi] Install : hello-jni => libs/armeabi/hello-jni 

copy /b/y "C:\Dev\Projects\NdkTest\obj\local\armeabi\hello-jni" 
"C:\Dev\Projects\NdkTest\libs\armeabi\hello-jni" > NUL 
C:/Dev/Tools/Android/ndk-r10d/toolchains/arm-linux-androideabi-4.8/pre 
built/windows-x86_64/bin/arm-linux-androideabi-strip --strip-unneeded 
C:\Dev\Projects\Ndk Test/libs/armeabi/hello-jni 

As you can see, renaming of file extension to .cpp makes ndk-build to use different compiler and to link with additional libs.

Update 2.

1) In case if you do not need gnustl_shared, update your Android.mk

LOCAL_CXXFLAGS += -nostdinc++ -I...
LOCAL_LDFLAGS += -nodefaultlibs -L...
LOCAL_LDLIBS += lc -lm -ldl -l...

2) In case you do need gnustl_shared, update your deploy script

import subprocess

output_dir = 'libs/armeabi-v7a/'
output_files = ['main', 'libgnustl_shared.so']
target_dir = '/data/local/tmp/'
target_executable = target_dir+'main'

# step 1: push
for f in output_files:
    push_cmd = 'adb push '+output_dir+f+' '+target_dir+f
    subprocess.check_call(push_cmd,stderr=subprocess.STDOUT, shell=True)

# step 2: change mode
mod_cmd = 'adb shell chmod 777 '+target_executable
subprocess.check_call(mod_cmd,stderr=subprocess.STDOUT, shell=True)

# step 3: run the program
run_cmd = 'adb shell LD_LIBRARY_PATH='+target_dir.rstrip('/')+':$LD_LIBRARY_PATH '+target_executable
subprocess.check_call(run_cmd,stderr=subprocess.STDOUT, shell=True)

Why you should update LD_LIBRARY_PATH see SO: Android – how to load shared library?

Community
  • 1
  • 1
Dmitry Sokolov
  • 3,118
  • 1
  • 30
  • 35
  • Thanks, but this is not the point of the question. If it is a C++ program, how can I compile and run it on Android? – feelfree Feb 18 '15 at 08:05