前期准备
首先板子跑的是android 4.4,编译需要Android NDK,打算以嵌入式linux的方式交叉编译FreeSwitch,并能够后台运行FreeSwitch。
为何是4.4,因为公司的板子是4.4,理论上后续的版本,也是一样的。工具链下了官网的android-ndk-r10e-linux-x86_64.zip,下载比较慢,用迅雷速度还是可以的!
设置Android交叉编译的一些全局参数:
#!/bin/bash ANDROID_VERSION=19 NDK_PATH=$NDK HOST=arm-linux-androideabi SYSROOT=${NDK_PATH}/platforms/android-${ANDROID_VERSION}/arch-arm ANDROID_CFLAGS="-march=armv7-a -mfloat-abi=softfp -fprefetch-loop-arrays --sysroot=${SYSROOT}" TOOLCHAIN_VERSION=4.9 BUILD_PLATFORM=linux-x86_64 CXX_STL=gnu-libstdc++ TARGET_ARCH=armeabi TOOLCHAIN=${NDK_PATH}/toolchains/${HOST}-${TOOLCHAIN_VERSION}/prebuilt/${BUILD_PLATFORM} CXX_STL_PATH=${NDK_PATH}/sources/cxx-stl/${CXX_STL}/${TOOLCHAIN_VERSION}/ CXX_STL_CPPFLAGS="-I${CXX_STL_PATH}/include -I${CXX_STL_PATH}/libs/${TARGET_ARCH}/include" CXX_STL_LDFLAGS="-L${CXX_STL_PATH}/libs/${TARGET_ARCH}/" export PKG_CONFIG_PATH="${SYSROOT}/usr/lib/pkgconfig/:${SYSROOT}/usr/local/lib/pkgconfig/" export CPP=${TOOLCHAIN}/bin/${HOST}-cpp export AR=${TOOLCHAIN}/bin/${HOST}-ar export AS=${TOOLCHAIN}/bin/${HOST}-as export NM=${TOOLCHAIN}/bin/${HOST}-nm export CC=${TOOLCHAIN}/bin/${HOST}-gcc export LD=${TOOLCHAIN}/bin/${HOST}-ld export RANLIB=${TOOLCHAIN}/bin/${HOST}-ranlib export OBJDUMP=${TOOLCHAIN}/bin/${HOST}-objdump export STRIP=${TOOLCHAIN}/bin/${HOST}-strip export CXX=${TOOLCHAIN}/bin/${HOST}-g++ export PATH=${TOOLCHAIN}/bin:$PATH
在编译的终端设置了这些变量后,开始编译。目前编译使用虚拟机centos 7.3.1611,为了保证后续的成功运行,我们使用的版本与centos 7所自带的版本一致。
编译依赖库
FreeSwitch的依赖库较多,因此对应的依赖库,一个个来编译。
libjpeg-turbo
使用libjpeg-turbo-1.5.2版本,进行编译,其中github编译有开启–with-simd,不过实测,开启了会编译不过,所以关闭了选项,编译开关如下:
autoreconf -fi && ./configure --host=${HOST} CFLAGS="${ANDROID_CFLAGS} -O3 -fPIE" CPPFLAGS="${ANDROID_CFLAGS}" \ LDFLAGS="${ANDROID_CFLAGS} -pie" --without-simd --prefix=${SYSROOT}/usr/
需要注意的是,1.2.90版本的–host要配置成arm,否则还不能识别HOST为arm-linux-androideabi,可以正常编译成功。
openssl
使用官方1.0.1e版本,进行编译,编译如下:
CFLAGS="${ANDROID_CFLAGS} -O3 -fPIE -I${SYSROOT}/usr/include " CPPFLAGS="${ANDROID_CFLAGS} -L${SYSROOT}/usr/lib" LDFLAGS="${ANDROID_CFLAGS} -pie"\ ANDROID_DEV="${SYSROOT}/usr" ./Configure android-armv7 --openssldir=${SYSROOT}/usr/ssl/ --prefix=${SYSROOT}/usr/ shared no-ssl2 no-ssl3 no-comp no-hw CFLAGS="${ANDROID_CFLAGS} -O3 -fPIE -I${SYSROOT}/usr/include " CPPFLAGS="${ANDROID_CFLAGS} -L${SYSROOT}/usr/lib" LDFLAGS="${ANDROID_CFLAGS} -pie" \ ANDROID_DEV="${SYSROOT}/usr" make && make install_sw
pcre
autoreconf -fi && CFLAGS="${ANDROID_CFLAGS} -O3 -fPIE -I${SYSROOT}/usr/include" CPPFLAGS="${ANDROID_CFLAGS} -L${SYSROOT}/usr/lib ${CXX_STL_CPPFLAGS}" \ LDFLAGS="${ANDROID_CFLAGS} -pie ${CXX_STL_LDFLAGS}" ./configure --prefix=${SYSROOT}/usr/ --build=x86_64-redhat-linux \ --host=arm --with-sysroot=${SYSROOT} LIBS="-lgnustl_static" --enable-shared
–build=x86_64-redhat-linux –host=arm参数要带上去,–build是因为我虚拟机使用的是centos 7 64bit,而这个版本的host用arm的即可,还不支持android。
ncurses
使用的版本是5.9版本,不过5.9版本需要打上补丁才行:
diff -Nrup ncurses-5.9.orig/form/fty_num.c ncurses-5.9/form/fty_num.c --- ncurses-5.9.orig/form/fty_num.c 2010-01-23 22:14:36.000000000 +0100 +++ ncurses-5.9/form/fty_num.c 2013-08-30 17:12:04.953720863 +0200 @@ -40,7 +40,7 @@ MODULE_ID("$Id: fty_num.c,v 1.28 2010/01 #include <locale.h> #endif -#if HAVE_LOCALE_H +#if HAVE_LOCALE_H && !defined(__BIONIC__) #define isDecimalPoint(c) ((c) == ((L && L->decimal_point) ? *(L->decimal_point) : '.')) #else #define isDecimalPoint(c) ((c) == '.') @@ -96,7 +96,7 @@ Generic_This_Type(void *arg) argn->low = args->low; argn->high = args->high; -#if HAVE_LOCALE_H +#if HAVE_LOCALE_H && !defined(__BIONIC__) argn->L = localeconv(); #else argn->L = NULL;
编译选项如下:
CFLAGS="${ANDROID_CFLAGS} -O3 -fPIE -I${SYSROOT}/usr/include " CPPFLAGS="${ANDROID_CFLAGS} -L${SYSROOT}/usr/lib" LDFLAGS="${ANDROID_CFLAGS} -pie" \ ./configure --prefix=${SYSROOT}/usr/ --host=${HOST} --without-cxx --without-cxx-binding
libedit
libedit本来是打算要编译的,结果这个库自己也依赖不少库,因此最后就把FS的configure开关中把libedit给去掉了。所以暂时不编译libedit,如果需要编译,libedit也依赖ncurses。
sqlite
sqlite本来也打算跟随centos 7的版本,不过对应版本发布比较早,编译起来比较费尽,所以去sqlite官网下了sqlite-autoconf-3190300版本编译,方便了很多。编译开关如下:
autoreconf -fi && CFLAGS="${ANDROID_CFLAGS} -O3 -fPIE" CPPFLAGS="${ANDROID_CFLAGS} -L${SYSROOT}/usr/lib" LDFLAGS="${ANDROID_CFLAGS} -pie" ./configure --prefix=${SYSROOT}/usr/ \ --host=${HOST} --with-sysroot=${SYSROOT}
freetype
freetype使用的是与centos7 一致的2.4.11版本。也不需要打补丁之类的。编译开关如下:
./autogen.sh && CFLAGS="${ANDROID_CFLAGS} -O3 -fPIE" CPPFLAGS="${ANDROID_CFLAGS} -L${SYSROOT}/usr/lib" LDFLAGS="${ANDROID_CFLAGS} -pie" ./configure --prefix=${SYSROOT}/usr/ \ --host=${HOST} --with-sysroot=${SYSROOT}
libpng
libpng使用1.6.30版本,为何不使用centos7所使用的1.5.13版本是因为FS对libpng的1.5.x版本会调用到函数setjmp,而setjmp在目前需要的android 4.4上有些问题,懒得去找问题了,所以换用1.6.30的省事一些。不过目前libpng的1.6.30关闭了neon的支持,可能会影响一些性能。
autoreconf -fi && CFLAGS="${ANDROID_CFLAGS} -O3 -fPIE" CPPFLAGS="${ANDROID_CFLAGS} -L${SYSROOT}/usr/lib"\ LDFLAGS="${ANDROID_CFLAGS} -pie" ./configure --prefix=${SYSROOT}/usr/ --host=${HOST} \ --with-sysroot=${SYSROOT} --enable-arm-neon=off
libogg
libogg没有使用centos7所带的1.3.0版本,而是使用1.3.2版本,比较好编译,libogg被speex所依赖。
autoreconf -fi && CFLAGS="${ANDROID_CFLAGS} -O3 -fPIE" CPPFLAGS="${ANDROID_CFLAGS} -L${SYSROOT}/usr/lib" LDFLAGS="${ANDROID_CFLAGS} -pie" ./configure --prefix=${SYSROOT}/usr/ \ --host=${HOST} --with-sysroot=${SYSROOT}
speexdsp
使用speexdsp-Speex-1.2rc2版本,也是被speex所依赖。这个编译也比较容易。
./autogen.sh && CFLAGS="${ANDROID_CFLAGS} -O3 -fPIE" CPPFLAGS="${ANDROID_CFLAGS} -L${SYSROOT}/usr/lib" LDFLAGS="${ANDROID_CFLAGS} -pie" ./configure --prefix=${SYSROOT}/usr/ \ --host=${HOST} --with-sysroot=${SYSROOT}
要先执行autogen.sh生成configure文件。
speex
使用的是1.2.0版本,编译选项也不复杂,能够成功编译:
autoreconf -fi && CFLAGS="${ANDROID_CFLAGS} -O3 -fPIE" CPPFLAGS="${ANDROID_CFLAGS} -L${SYSROOT}/usr/lib" LDFLAGS="${ANDROID_CFLAGS} -pie" ./configure --prefix=${SYSROOT}/usr/ \ --host=${HOST} --with-sysroot=${SYSROOT}
libuuid
FS需要依赖libuuid,在centos上的并非是单独的libuuid,而是被包含在util-linux-2.23.2中,我们去SF上下载libuuid-1.0.3,编译开关大同小异,可以编译通过。
autoreconf -fi && CFLAGS="${ANDROID_CFLAGS} -O3 -fPIE" CPPFLAGS="${ANDROID_CFLAGS} -L${SYSROOT}/usr/lib" LDFLAGS="${ANDROID_CFLAGS} -pie" ./configure --prefix=${SYSROOT}/usr/ \ --host=${HOST} --with-sysroot=${SYSROOT} --with-pic
libsndfile
libsndfile使用1.0.26版本,比较好编译,去其github下载对应版本就行。
autoreconf -fi && CFLAGS="${ANDROID_CFLAGS} -O3 -fPIE -gstabs " CPPFLAGS="${ANDROID_CFLAGS} -L${SYSROOT}/usr/lib" \ LDFLAGS="${ANDROID_CFLAGS} -pie" CXXFLAGS="${CXXFLAGS} -gstabs -fno-exceptions --sysroot=${SYSROOT} -I${SYSROOT}/usr/include ${CXX_STL_CPPFLAGS}" \ ./configure --prefix=${SYSROOT}/usr/ --host=${HOST} --with-sysroot=${SYSROOT}
由于有使用到C++,因此需要设置C++的一些相关参数。
ldns
使用1.7.0版本
autoreconf -fi && ./configure --host=${HOST} CFLAGS="${ANDROID_CFLAGS} -O3 -fPIE" CPPFLAGS="${ANDROID_CFLAGS}" LDFLAGS="${ANDROID_CFLAGS} -pie" \ --prefix=${SYSROOT}/usr/ --with-sysroot=${SYSROOT} --with-ssl=${SYSROOT}/usr/ --disable-dane-verify
opus
使用最新的1.2.1版本
autoreconf -fi && ./configure --host=${HOST} CFLAGS="${ANDROID_CFLAGS} -O3 -fPIE" CPPFLAGS="${ANDROID_CFLAGS}" LDFLAGS="${ANDROID_CFLAGS} -pie" \ --prefix=${SYSROOT}/usr/ --with-sysroot=${SYSROOT}
由于lua也是需要libreadline的,而目前我们不编译libreadline,所以要把modules.conf
#languages/mod_lua
lua模块注释掉。
如果以上的库都编译成功后,那么,接下来,则可以编译FS了。
编译FS
FS我是用的是1.6.11版本,需要打上一些补丁才行,目前还不支持android。而由于上文中,我们并没有编译libedit,因此这里的话,我们需要–disable-core-libedit-support这个开关来关闭对libedit的支持。libvpx需要单独编译,因为目前FS工程中的参数是写死的。
libvpx
对于1.6.11这个版本的FS对于libvpx参数的设定,并不能成功编译出android版本,因此可以单独去libs/libvpx进行编译:
CFLAGS="${ANDROID_CFLAGS} -O3 -fPIE" CPPFLAGS="${ANDROID_CFLAGS} -L${SYSROOT}/usr/lib" LDFLAGS="${ANDROID_CFLAGS} -pie ${CXX_STL_LDFLAGS}" CPPLDFLAGS="${ANDROID_CFLAGS} ${CXX_STL_LDFLAGS}" \ ./configure --prefix=${SYSROOT}/usr/ --target=armv7-android-gcc --enable-pic --disable-docs --disable-examples --disable-install-bins --disable-install-srcs --cpu=cortex-a8 --sdk-path=$NDK
由于libvpx编译成安卓版本,会依赖cpu-features,因此需要单独编译下cpu-features:
$CC ${ANDROID_CFLAGS} -fPIE -I${SYSROOT}/usr/inclue -c $NDK_PATH/sources/android/cpufeatures/cpu-features.c -o cpu-features.o $AR crs libcpu-features.a cpu-features.o
之后FS需要多链接-lcpu-features
autoreconf -fi && ./rebootstrap.sh && PKG_CONFIG_PATH=$PKG_CONFIG_PATH ./configure --with-sysroot=${SYSROOT} --host=${HOST} --prefix=${SYSROOT}/usr/ --disable-core-libedit-support \ CC="$CC" LD="$LD" NM="$NM" AR="$AR" CPP="$CPP" CXX="$CXX" CFLAGS="${ANDROID_CFLAGS} -fPIE -I${SYSROOT}/usr/inclue ${CXX_STL_CPPFLAGS}" CPPFLAGS="${ANDROID_CFLAGS} ${CXX_STL_CPPFLAGS}" \ LDFLAGS="${ANDROID_CFLAGS} -pie -Wl,-rpath-link=${SYSROOT}/usr/lib -L${SYSROOT}/usr/lib -L${SYSROOT}/usr/lib ${CXX_STL_LDFLAGS}" CPPLDFLAGS="${ANDROID_CFLAGS} ${CXX_STL_LDFLAGS}" \ CXXFLAGS="${ANDROID_CFLAGS} ${CXX_STL_CPPFLAGS}" CXXLDFLAGS="${ANDROID_CFLAGS} ${CXX_STL_LDFLAGS}" \ --with-pkgconfigdir="$PKG_CONFIG_PATH" LIBS="-lgnustl_static -lsupc++ -lcpu-features"
后续我会将这些可以编译的版本,以及补丁上传到github上,如果有兴趣的,可以去支持下,先整理这些。后续还需要调试很多东西才行。github地址在:https://github.com/elkpi/freeswitch-android
出现的一些问题
编译出现的错误,还是不少的,FS需要改动一些源码。其中可能会经常遇到的是:crtend_so.o以及crtbegin_so.o未能被找到并编译,这两个其实NDK中已经有提供了已经编译好的文件了。解决办法是:
CFLAGS+=--sysroot=${SYSROOT} CPPFLAGS+=--sysroot=${SYSROOT} CXXFLAGS+=--sysroot=${SYSROOT}
也就是所有的编译参数中,都要指定–sysroot参数,这样NDK提供的工具链就可以自己找到crtend_so.o以及crtbegin_so.o。至于其余的问题,我也忘记记录了。
转载请注明: 转载自elkPi.com
本文链接地址: 移植FreeSwitch到Android 4.4