交叉编译基本步骤

自己的项目经验,并不一定适用其他人。 首先 Makefile 基础必须掌握,可以参考GNU make rules

1 准备交叉编译工具链,配置相应的编译环境,依赖库,sysroot,头文件等,最好为该库准备一个 setenv.sh 的脚本。

2 一般开源库都是 cmake 工程,所有编译的第一步都是运行 configure 检查配置。交叉编译的区别是需要指定–host=arm-linux,如果需要指定编译后的存放目录–prefix.具体选项在configure --help里都有。

3 configure 成功运行后,可能会遇到错误,一般是头文件,库,或者依赖路径不对,版本不够,等等。依次解决就好。

libimobiledevice

libimobiedevice是一个非常有用的库,实现 ios 上的tcp over usb的基础。

交叉编译 imobiledevice 到安卓

  • 准备 android toolchain

直接用 ndk 的 build/tools/直接生成,android 和其他交叉编译平台只是工具链的区别。

./make_standalone_toolchain.py --api 23 --arch arm --install-dir /home/android-toolchain --stl libc++
  • configure 脚本

在源码目录,新建 build-android 文件夹 放入如下configure_android文件 执行它来配置 configure,表示交叉编译,prefix 指定目录,如有其他参数可以通过该脚本转发

	../configure  \
	--host=arm-linux \
	--prefix=/home/install-prefix/android \
	"$@"
  • 配置 gcc 的基本选项

一个准备 enviroment.sh 脚本配置 gcc 的基本选项,很重要。需要配置以下选项。

sysroot

交叉工具链目录(CC CXX AR LD 这些)

pgkconfig

编译参数 CPPFLAG CFLAGS

rpath

#!/bin/sh
export NDK_ROOT=/home/bravo/Android/Ndk/android-ndk-r12b
#to be compatable with , better use android-19
export SYS_ROOT=$NDK_ROOT/platforms/android-19/arch-arm
# generated by ndk standand tools
export TOOLCHAIN_ROOT=/home/android-toolchain
export TOOLCHAIN=$TOOLCHAIN_ROOT/bin/arm-linux-androideabi
#generate all the android libs here
#also other dependency library and header files put here
export INSTALL_PREFIX=/home/install-prefix/android
export PKG_CONFIG_PATH=$INSTALL_PREFIX/lib/pkgconfig


export CC="$TOOLCHAIN-gcc"
export CXX="$TOOLCHAIN-g++"
export CPP="$TOOLCHAIN-gcc -E"
export AR="$TOOLCHAIN-ar"
export LD="$TOOLCHAIN-ld"
export NM="$TOOLCHAIN-nm"
export STRIP="$TOOLCHAIN-strip"

export CPPFLAGS="-I${SYS_ROOT}/include -I${SYS_ROOT}/usr/include -I${INSTALL_PREFIX}/include -I${NDK_ROOT}/sources/android/support/include"
export LDFLAGS="-L. -L${SYS_ROOT}/usr/lib -L${INSTALL_PREFIX}/lib -L${TOOLCHAIN_ROOT}/lib "

export CFLAGS="-lusb1.0 -lc -lm -lz -pie -fPIE -fno-stack-protector -O0 -march=armv7-a -marm -mthumb-interwork -mfloat-abi=softfp -mfpu=neon -Wno-multichar -DHAVE_SYS_UIO_H -DHAVE_PTHREADS -Wno-multichar -DANDROID  -Wno-redundant-decls -Wno-shadow ${CPPFLAGS} ${LDFLAGS} -Wl,-rpath=../lib"
#set rpath , don't use LD_LIBRARY_PATH when executing
#export CXXFLAGS="${CFLAGS}"

  • 下载及编译相关库

git clone 可以直接拖.编译及依赖顺序是

	libxml2 -> libplist -> libusbmuxd -> libimobiledevice -> libideviceinstaller

问题记录

  • libxml2 error 1
../runtest.c:200:18: fatal error: glob.h: No such file or directory

找到glob.c glob.h 把 glob.c 放到environment.shINSTALL_PREFIX/lib

把 glob.h 放到 INSTALL_PREFIX/include

按下面命令单独生成 glob.o

$CC ${CFLAGS} -c glob.c

enviroment.sh里添加 -L/INSTALL_PREFIX/lib

configure_android.sh里添加 LIBS=INSTALL_PREFIX/lib/glob.o

可以弥补找不到 glob 的缺陷 ,binonic c 库相对 glibc 库做了裁剪

  • libxml2 error 2
/usr/include/python2.7/pyconfig.h:30:52: fatal error: arm-linux-gnueabi/python2.7/pyconfig.h: No such file or directory

首先添加 sysroot。

add --sysroot=${SYS_ROOT} in CFLAGS in environment.sh
add --with-sysroot=${SYS_ROOT}  in configure_android

问题仍然存在,直接下载python2.7-dev

解压:

dpkg -x /python2.7-dev /tmp/deb

把 arm-linxu-gnueabi 的头文件拷贝出来

cp /tmp/deb/usr/include/arm-linux-gnueabi INSTALL_PREFIX/include
  • libplist error 1

提示 libxml2.6.28 版本太低,将其升级. 下载2.9.4

解压重编译安装,但是还是报错 直接从可以从.lib/下 得到已经编译好的库 … 拷贝到 INSTALL_PREFIX/lib 下

  • libplist error 2
plistutil.o:plistutil.c:function main: error: undefined reference to 'malloc'
plistutil.o:plistutil.c:function main: error: undefined reference to 'strcmp'

错误是没有找到相应的头文件, 因此没有找到符号. 打开 Makfile 发现是 CPPFLAGS 为空 原本以为通过 configure_android 加进去了 最终发现 LIBS 也没加上-lc 干脆修改 environment.sh 将-lc 加到 CFLAGS 将 CPPFLAGS 和 LDFLAGS 都加到 CFLAGS 里

  • libusbmuxd error 1
libtool: warning: library '/home/install-prefix/android/lib/libplist.la' was moved.
/bin/sed: can't read /home/bravo/Android/Ndk/android-ndk-r12b/platforms/android-23/arch-arm/home/install-prefix/android/lib/libxml2.la: No such file or directory
libtool:   error: '=/home/install-prefix/android/lib/libxml2.la' is not a valid libtool archive
Makefile:420: recipe for target 'libusbmuxd.la' failed

这句话在=/home/install-prefix/android/lib/libplist.la 中出现,很奇怪 =/home/install-prefix/android/lib/libxml2.la 删除掉就好了

  • libusbmuxd error 2
/home/install-prefix/android/lib/libusbmuxd.so: error: undefined reference to 'rpl_malloc'
/home/install-prefix/android/lib/libusbmuxd.so: error: undefined reference to 'rpl_realloc'
/home/install-prefix/android/lib/libcrypto.so: error: undefined reference to 'bsd_signal'

在 lib-iphone 下 grep 了下 rpl_malloc 发现是 libusbmuxd 中用到了代替 malloc 的 既然找不到,那就不要编译,重新 config libusbmuxd。 修改 libusbmuxd/build-android/config.h 注释掉即可

//#define malloc rpl_malloc
//#define realloc rpl_realloc
  • libimobiledevice error 1
/home/android-toolchain/bin/../lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin/ld: error: cannot find -lssl
/home/android-toolchain/bin/../lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin/ld: error: cannot find -lcrypto

这是缺少 openssl 的库,自己就不编译了,网上找了一个

把库放到INSTALL_PREFIX/lib

把头文件放到INSTALL_PREFIX/include

重新编译,make clean make,只剩下 1 个错误了

  • libimobiledevice error 2
/home/install-prefix/android/lib/libcrypto.so: error: undefined reference to 'bsd_signal'

研究了很久! 网上说是 android-19 以上版本,去掉了该符号 只好用 android-19 来做 sysroot;

export SYS_ROOT=$NDK_ROOT/platforms/android-19/arch-arm
  • libimobiledevice error 3

运行时,提示找不到 libcrypt.so.1.0.0 看来不要用动态库的好

编译时将 libcrypt.so libssl.so 从 INSTALL_PREFIF/lib 移除

make clean && make

  • libidevicefinder error 1
../../src/ideviceinstaller.c:52:17: fatal error: zip.h: No such file or directory

找不到 zip 头文件..拷贝 1 个过去 同时把 CFLAGS 里添加-lz

缺乏的是 lzip 只能下载一个了

ndk 编译好的 libzip.a 后放在 INSTALL_PREFIX/lib 下

  • usbmuxd error 1
checking for pthread_create, pthread_mutex_lock in -lpthread... no

去掉 configure 关于 lpthread 的检查; 去掉有 pthread_cancel 的调用;binonic C 库里没有这个调用;

congfigure 16435 行 echo “good”

  • usbmuxd error 2

还是报错,一堆的定义不一致。 参考这个 commit

  • usbmuxd error 3

然后又出现了:

../../src/client.c:175: error: undefined reference to 'rpl_malloc'
../../src/client.c:179: error: undefined reference to 'rpl_malloc'
../../src/client.c:182: error: undefined reference to 'rpl_malloc'

这个前面已经遇到过了。

  • usbmuxd error 4
/home/android-toolchain/bin/../lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin/ld: error: cannot find -lusb-1.0
../../src/usb.c:84: error: undefined reference to 'libusb_cancel_transfer'
../../src/usb.c:89: error: undefined reference to 'libusb_cancel_transfer'

找不到 libusb-1.0, 加 1 个即可

  • runtime error

最后的最后,在 android 设备实测,发现所有 bin 都跑不起来!用 1 个 test 发现是参数-nostdlib 搞的鬼。

-nostdlib作用: 不连接系统标准启动文件和标准库文件,只把指定的文件传递给连接器。这个选项常用于编译内核、bootloader 等程序,它们不需要启动文件、标准库文件。 去掉重新编译 ok!

执行 ideviceinfo 返回了基本信息,大工告成。

相信能交叉编译这个库以后,没有什么库编译不了了。