I. 基本流程
1.设置环境变量
(资料图片)
建议去官网下载最新版本的NDK,老版本很多宏定义缺失,比较麻烦。同时,之前用android-ndk-r10d,需要安装32位库环境。
yum install libstdc++-devel.i686yum install libzip.i686
#!/bin/bash# environment settingexport ANDROID_NDK_PATH=/opt/android-ndk-r14bexport TOOLCHAINS_PATH=${ANDROID_NDK_PATH}/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/binexport PATH=${PATH}:${TOOLCHAINS_PATH}export SYSROOT_PATH=${ANDROID_NDK_PATH}/platforms/android-22/arch-armexport LIBSTD_PATH=${ANDROID_NDK_PATH}/sources/cxx-stl/gnu-libstdc++/4.9export CC=arm-linux-androideabi-gccexport CXX=arm-linux-androideabi-g++export AR=arm-linux-androideabi-arexport CFLAGS="-DANDROID -fPIC -std=c++11 -ffunction-sections -funwind-tables -fstack-protector -no-canonical-prefixes -fexceptions -frtti -marm -march=armv7-a -mtune=cortex-a8 -mfloat-abi=softfp -mfpu=neon -mthumb -fno-strict-aliasing -finline-limit=64 -Wa,--noexecstack -Wformat -Werror=format-security -g -Wall --sysroot=${SYSROOT_PATH} -I${LIBSTD_PATH}/include -I${LIBSTD_PATH}/libs/armeabi/include -I${ANDROID_NDK_PATH}/sources/android/cpufeatures/"export LDFLAGS="--sysroot=${SYSROOT_PATH} -L${LIBSTD_PATH}/libs/armeabi -lgnustl_shared -lgcc -no-canonical-prefixes -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -lstdc++ -lsupc++ -lc -lm -pthread"
只要事先运行脚本,基本能应对一般的库(包括开源库)的编译。 因为C编译CFLAGS中不存在-std=c++11和-frtti,也不需要STL库gnustl_shared和C++库supc++ ,所以编译纯C库的时候建议移除他们
2.修改Makefile模板,针对EXE情况做特殊处理
GCC=$(CROSS)gccGXX=$(CROSS)g++AR=$(CROSS)arifeq ($(CROSS),arm-linux-androideabi-)ifdef EXE_TARGETCFLAGS += -pie -fPIELDFLAGS += -pie -fPIEendifendif
##3.PTLIB的configure参数 注意,这里的configure文件我做了少量修改。仅个人记录用。
./configure --enable-exceptions --host=armv7-a-android --disable-openssl --disable-shmaudio --enable-shmvideo=no --disable-resolver --enable-serial=no --disable-v4l2
II. 心得
1.主要的头文件目录
/opt/android-ndk-r14b/platforms/android-22/arch-arm/usr/include
/opt/android-ndk-r14b/sources/cxx-stl/gnu-libstdc++/4.9/include
##2.编译错误解决 1)部分原来是/usr/include/sys下的头文件路径可能有变化,直接在incude目录下。 2)出现链接错误时,务必用arm-linux-androideabi-nm检查下是否没实现。存在头文件与库文件不一致的现象。
2.ifaddrs.h不存在
1)使用libuv库内的 android-ifaddrs即可。部分版本可能有坑。 **注意更新,libuv也迭代了几个版本过。
III. ADB使用
以Linux版本的adb为例;Win的版本也可以,但是总体操作Linux下的方便很多
#!/bin/bash#连接adb connect#进入shelladb shell#如果有多个链路,可以这样选择,端口缺省5555adb -s:shell#传输文件adb push 1.txt /storage/emulated/0/#所有动态库需要放置在/system/lib目录下,需要赋予/system目录读写权限,或设置LD_LIBRARY_PATHmount -o remount,rw /system#大多数命令需要busybox驱动,例如vi,ifconfig等busybox vi 1.txt
IV.查看依赖(类似于ldd)
使用readelf函数可以读取动态库或EXE的依赖,下面是示例:
arm-linux-androideabi-readelf -d libjanus_streaming.so Dynamic section at offset 0x25bd8 contains 42 entries: Tag Type Name/Value 0x00000003 (PLTGOT) 0x26d80 0x00000002 (PLTRELSZ) 1256 (bytes) 0x00000017 (JMPREL) 0x2784 0x00000014 (PLTREL) REL 0x00000011 (REL) 0x22b4 0x00000012 (RELSZ) 1232 (bytes) 0x00000013 (RELENT) 8 (bytes) 0x6ffffffa (RELCOUNT) 145 0x00000006 (SYMTAB) 0x148 0x0000000b (SYMENT) 16 (bytes) 0x00000005 (STRTAB) 0xd88 0x0000000a (STRSZ) 3651 (bytes) 0x00000004 (HASH) 0x1bcc 0x00000001 (NEEDED) Shared library: [libcurl.so] 0x00000001 (NEEDED) Shared library: [libssl.so.1.1] 0x00000001 (NEEDED) Shared library: [libcrypto.so.1.1] 0x00000001 (NEEDED) Shared library: [libz.so] 0x00000001 (NEEDED) Shared library: [libglib-2.0.so.0] 0x00000001 (NEEDED) Shared library: [libpcre.so] 0x00000001 (NEEDED) Shared library: [libintl.so] 0x00000001 (NEEDED) Shared library: [libiconv.so] 0x00000001 (NEEDED) Shared library: [libjansson.so] 0x00000001 (NEEDED) Shared library: [libgnustl_shared.so] 0x00000001 (NEEDED) Shared library: [libstdc++.so] 0x00000001 (NEEDED) Shared library: [libc.so] 0x00000001 (NEEDED) Shared library: [libm.so] 0x00000001 (NEEDED) Shared library: [libdl.so] 0x0000000e (SONAME) Library soname: [libjanus_streaming.so.0] 0x0000001a (FINI_ARRAY) 0x26bcc 0x0000001c (FINI_ARRAYSZ) 8 (bytes) 0x00000019 (INIT_ARRAY) 0x26bd4 0x0000001b (INIT_ARRAYSZ) 4 (bytes) 0x0000000f (RPATH) Library rpath: [/opt/android-libs/lib] 0x00000010 (SYMBOLIC) 0x0 0x0000001e (FLAGS) SYMBOLIC BIND_NOW 0x6ffffffb (FLAGS_1) Flags: NOW 0x6ffffff0 (VERSYM) 0x20f0 0x6ffffffc (VERDEF) 0x2278 0x6ffffffd (VERDEFNUM) 1 0x6ffffffe (VERNEED) 0x2294 0x6fffffff (VERNEEDNUM) 1 0x00000000 (NULL) 0x0
V.GDB使用
android下使用gdbserver和gdb配套使用。两个版本必须一致。建议用你NDK目录下的那一对。 整体思路和一般的ARM设备调试类似。
拷贝gdbserver到Android设备上
cd /opt/android-ndk-r14b/prebuilt/android-arm/gdbserveradb push gdbserver /sdcard/share
在Android下启动gdbserver
端口可以随意调整,本文以9999为例
#手工跑./gdbserver 0.0.0.0:9999 ./test_program args#附加进程./gdbserver --attach 0.0.0.0:9999 pid
在调试机上运行gdb 可以在Linux下也可以在Windows下运行,以Linux下运行为例:
cd /opt/android-ndk-r14b/prebuilt/linux-x86_64/bin#windows下的话就是D:\android-ndk-r14b\prebuilt\windows-x86_64\binadb pull /system/lib/libc.so .adb pull /system/lib/libm.so .……需要把所有依赖的动态库,都放置到当前准备调试的目录下系统相关的动态库也必须补齐,否则堆栈无法正确分析……./gdbtarget remote:9999c
后面就和普通的gdb无差别了