天天看点

用于Android系统的pango + cairo交叉编译

        做Android系统下的开发也有几年了,这几年间也遇到过很多问题,大多是从网上搜索解决办法,虽然不是都能找到完美的解决办法,但是基本对于结局问题是有帮助的,所以一直也没有整理遇到的问题(主要是太懒了!!!)。但本次遇到的问题要求时间急短,又苦于网上没有介绍的相关文章,着实让我头疼了两天,好在靠着不错的运气解决了问题。痛苦过后痛定思痛,决定将这几天的成果总结一下,方便自已和有需要的人吧。

        废话不多说了,先介绍一下我调查的背景吧。我们可以算是在Android系统上做二次开发吧,framework层也修改了很多,其中有应用使用cairo描画,但是由于cairo对于字体的描画支持的很简单,不能正确显示阿拉伯语等语言,所以经过调查后决定使用pango + cairo解决这一问题。

        看起来是两个库,但是真正编译时却需要很多依赖,需要依次编译:libiconv, libffi, gettext, glibc, freetype, fontconfig, libpng, zlib, pixman, cairo, lilbxml2, pango这些库,并且首先需要下载Android NDK。

安装NDK

        从下面这个链接下载r10e版本,不要问我为什么是r10e,我也不知道,国外大大说的。。。

        https://developer.android.google.cn/ndk/downloads

        解压NDK,然后在用里面的工具创建单独的工具链:

$ ${NDK}/build/tools/make-standalone-toolchain.sh \
--toolchain=arm-linux-androideabi-4.9 \
--stl=gnustl \
--arch=arm \
--ndk-dir=/opt/android-ndk-r10e \
--system=linux-x86_64 \
--install-dir=/opt/android-ndk-toolchain-10e \
--platform=android-18
           

安装需要的工具包

$ sudo apt-get update && sudo apt-get upgrade
$ sudo apt-get install build-essential
$ sudo apt-get install pkg-config automake autoconf libtool
$ sudo apt-get install zlib1g-dev libffi-dev libtool-bin
           

下面的是编译需要的环境变量,这里copy了别的大大的:

#!/bin/sh
# Android cross-compile environment setup script for Glib
# Author  : Zengwen Yuan
# Date    : 2016-07-16
# Version : 2.1
 
# Android NDK sources and standalone toolchain is put here
export DEV=/opt
 
# All the built binaries, libs and their header will be installed here
export PREFIX=/opt/android
 
# Don't mix up .pc files from your host and build target
export PKG_CONFIG_PATH=${PREFIX}/lib/pkgconfig
 
# GCC for Android version to use
# 4.9 is the only available version since NDK r11!
export GCC_VER=4.9
 
# The building system we are using (Linux x86_64)
export BUILD_SYS=x86_64-linux-gnu
 
# Set Android target API level
export ANDROID_API=19
 
# Set Android target arch
export ANDROID_ARCH=arm
 
# Set Android target name, according to Table 2 in
# https://developer.android.com/ndk/guides/standalone_toolchain.html
export ANDROID_TARGET=armv5te-none-linux-androideabi
 
# The cross-compile toolchain we use
export TOOLCHAIN=arm-linux-androideabi
 
# This is a symlink pointing to the real Android NDK r10e
export NDK=${DEV}/android-ndk-r10e
 
# The path of standalone NDK toolchain
# Refer to https://developer.android.com/ndk/guides/standalone_toolchain.html
export NDK_TOOLCHAIN=${DEV}/android-ndk-toolchain-10e
 
# Set Android Sysroot according to API and arch
export SYSROOT=${NDK_TOOLCHAIN}/sysroot
# this one is the absolute, prebuilt path
# export SYSROOT=${NDK}/platforms/android-${ANDROID_API}/arch-${ANDROID_ARCH}
 
# Binutils path
export CROSS_PREFIX=${NDK_TOOLCHAIN}/bin/${TOOLCHAIN}
# this one is the absolute, prebuilt path
# export CROSS_PREFIX=${NDK}/toolchains/${TOOLCHAIN}-${GCC_VER}/prebuilt/linux-x86_64/bin/${TOOLCHAIN}
 
# Non-exhaustive lists of compiler + binutils
export AR=${CROSS_PREFIX}-ar
export AS=${CROSS_PREFIX}-as
export LD=${CROSS_PREFIX}-ld
export NM=${CROSS_PREFIX}-nm
export CC=${CROSS_PREFIX}-gcc
export CXX=${CROSS_PREFIX}-g++
export CPP=${CROSS_PREFIX}-cpp
export CXXCPP=${CROSS_PREFIX}-cpp
export STRIP=${CROSS_PREFIX}-strip
export RANLIB=${CROSS_PREFIX}-ranlib
export STRINGS=${CROSS_PREFIX}-strings
 
# Set build flags
# Refer to https://developer.android.com/ndk/guides/standalone_toolchain.html
export PATH=$PATH:${PREFIX}/bin:${PREFIX}/lib
export CFLAGS="--sysroot=${SYSROOT} -I${SYSROOT}/usr/include -I${PREFIX}/include -fPIE -DANDROID -Wno-multichar"
export CXXFLAGS=${CFLAGS}
export CPPFLAGS="--sysroot=${SYSROOT} -I${SYSROOT}/usr/include -I${NDK_TOOLCHAIN}/include/c++/ -DANDROID -DNO_XMALLOC -mandroid"
export LIBS="-lc"
export LDFLAGS="-Wl,-rpath-link=-I${SYSROOT}/usr/lib -L${SYSROOT}/usr/lib -L${PREFIX}/lib -L${NDK_TOOLCHAIN}/lib"
           

保存上面的脚本:env-setup.sh,并且source命令加载:

source ./env-setup.sh
           

编译和安装库文件

libiconv 1.16

下载并解压 libiconv 1.16: 

 https://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.16.tar.gz

编译命令:

./configure --build=${BUILD_SYS} --host=arm-eabi --prefix=${PREFIX} --disable-rpath --enable-shared CFLAGS="-fPIC"
make
make install
           

libffi-3.2.1

下载并解压 libffi-3.2.1:

https://github.com/libffi/libffi/tree/v3.2.1

编译命令:

sed -e '/^includesdir/ s/$(libdir).*$/$(includedir)/' -i include/Makefile.in
sed -e '/^includedir/ s/=.*$/[email protected]@/' -e 's/^Cflags: -I${includedir}/Cflags:/' -i libffi.pc.in
./configure --build=${BUILD_SYS} --host=arm-eabi --prefix=${PREFIX} --enable-static
make
make install
           

前两行的sed命令是让安装的时候安装在${PREFIX}/include 而不是 ${PREFIX}/lib/libffi-3.2.1/include

gettext-0.20

下载并解压 gettext-0.20:

https://ftp.gnu.org/pub/gnu/gettext/

编译前需要修改gettext-tools/src/msginit.c,将

fullname = pwd->pw_gecos
修改为:
#ifndef __ANDROID__
	fullname = pwd->pw_gecos;
#else
	fullname = "android";
#endif
           

编译命令:

./configure --build=${BUILD_SYS} --host=arm-eabi  --prefix=${PREFIX} --disable-rpath --disable-libasprintf --disable-java --disable-native-java --disable-openmp --disable-curses
make
make install
           

glib-2.48.1

下载并解压 glib-2.48.1:

http://ftp.gnome.org/pub/gnome/sources/glib/2.48/

编译glib前需要将下面的配置保存为android.cache,并将权限修改为只读,同时复制到解压出来的根目录里:

glib_cv_long_long_format=ll
glib_cv_stack_grows=no
glib_cv_sane_realloc=yes
glib_cv_have_strlcpy=no
glib_cv_va_val_copy=yes
glib_cv_rtldglobal_broken=no
glib_cv_uscore=no
glib_cv_monotonic_clock=no
ac_cv_func_nonposix_getpwuid_r=no
ac_cv_func_posix_getpwuid_r=no
ac_cv_func_posix_getgrgid_r=no
glib_cv_use_pid_surrogate=yes
ac_cv_func_printf_unix98=no
ac_cv_func_vsnprintf_c99=yes
ac_cv_func_realloc_0_nonnull=yes
ac_cv_func_realloc_works=yes
           

编译命令:

执行前可以先运行./autogen.sh,检查一下环境配置,如果缺少什么安装上就是,也可能会有错误但是不影响后面编译(我这里就报一个编译错误,但后面的编译都正常)

./configure --build=${BUILD_SYS} --host=${TOOLCHAIN} --prefix=${PREFIX} --disable-dependency-tracking --cache-file=android.cache --enable-included-printf --enable-static --with-pcre=no
make
make install
           

freetype-2.5.3

下载并解压 freetype-2.5.3:

https://download.savannah.gnu.org/releases/freetype/

编译命令:

./configure --build=${BUILD_SYS} --host=arm-eabi --prefix=${PREFIX} --enable-static
make
make install
           

expat-2.0.1

下载并解压 expat-2.0.1:

https://github.com/libexpat/libexpat/releases/tag/R_2_0_1

编译命令:

./configure --build=${BUILD_SYS} --host=arm-eabi --prefix=${PREFIX} --enable-static
make
make install
           

libpng-1.2.59

下载并解压 libpng-1.2.59

https://sourceforge.net/projects/libpng/files/libpng12/1.2.59/

编译命令:

./configure --build=${BUILD_SYS} --host=arm-eabi --prefix=${PREFIX} --enable-static
make
make install
           

fontconfig-2.9.91

下载并解压 fontconfig-2.9.91:

https://www.freedesktop.org/software/fontconfig/release/

编译fontconfig时会出现如下error,大概看了是一个内部的strtod函数的封装,果断将没用的部分注掉,只保留最后“v = strtod (s, end);”部分,编译通过

fcxml.c:1225:14: error: 'struct lconv' has no member named 'decimal_point'
  (locale_data->decimal_point[0] != 0x2e ||
              ^
fcxml.c:1226:14: error: 'struct lconv' has no member named 'decimal_point'
   locale_data->decimal_point[1] != 0))
              ^
fcxml.c:1230:32: error: 'struct lconv' has no member named 'decimal_point'
  int dlen = strlen (locale_data->decimal_point);
                                ^
fcxml.c:1244:42: error: 'struct lconv' has no member named 'decimal_point'
      strcpy (buf + (dot - s), locale_data->decimal_point);
           

编译命令:

./configure --build=${BUILD_SYS} --host=arm-eabi --prefix="${PREFIX}" --with-arch=arm EXPAT_CFLAGS="-I${PREFIX}/include" EXPAT_LIBS="-L${PREFIX}/lib -lexpat"
make
make install
           

zlib-1.2.11

下载并解压 zlib-1.2.11:

http://www.zlib.net/

编译命令:

./configure --prefix="${PREFIX}"
make
make install
           

pixman-0.32.8

下载并解压 pixman-0.32.8:

https://www.cairographics.org/releases/

pixman 依赖cpufeatures,源码在${NDK}/sources/android/cpufeatures,将它放在Android工程里编译即可,或者Android工程里有将头文件和库文件copy出来也可以,这里就不多说了

编译命令:

./configure --build=${BUILD_SYS} --host=arm-eabi --prefix=${PREFIX} --enable-static --disable-libpng LDFLAGS="-L${PREFIX}/lib -lz -lcpufeatures"
make
make install
           

cairo-1.14.2

下载并解压 cairo-1.14.2:

https://www.cairographics.org/releases/

我这里由于之前有cairo的库,所以本次对backend没有过多的设置。

编译命令:

./configure --build=${BUILD_SYS} --host=arm-eabi --prefix=${PREFIX} --enable-static -without-x --disable-xlib --disable-xlib-xrender --disable-directfb  --disable-win32 --disable-pdf --disable-ps --disable-svg --enable-png --disable-interpreter --disable-xlib-xcb --disable-xcb --disable-xcb-shm --enable-ft --enable-fc FONTCONFIG_CFLAGS="-I${PREFIX}/include" FONTCONFIG_LIBS="-L${PREFIX}/lib -lfontconfig -lexpat" 
make
make install
           

pango-1.28.4

下载并解压 pango-1.28.4:

http://ftp.gnome.org/pub/GNOME/sources/pango/

编译命令:

./configure --prefix="${PREFIX}" --host=arm-eabi CFLAGS="--sysroot ${SYSROOT}" FONTCONFIG_CFLAGS="-I${PREFIX}/include" FONTCONFIG_LIBS="-L${PREFIX}/lib -lfontconfig"  CAIRO_CFLAGS="-I${PREFIX}/include -I${PREFIX}/include/cairo" CAIRO_LIBS="-L${PREFIX}/lib -lcairo -lcairo-gobject -lpng -lpng12" GLIB_CFLAGS="-I${PREFIX}/include -I${PREFIX}/glib-2.0" GLIB_LIBS="-L${PREFIX}/lib -lgio-2.0 -lglib-2.0 -lgmodule-2.0 -lgobject-2.0 -lgthread-2.0" --with-included-modules=yes --with-dynamic-modules=yes
make
make install
           

到这里已经编译出了需要的库文件了,可以使用了。如果有什么问题欢迎指正。

参考文档:

https://zwyuan.github.io/2016/07/17/cross-compile-glib-for-android/