zoukankan      html  css  js  c++  java
  • Cross-compile GLib for Android

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


    Prepare cross-compile environment

    Install Android NDK and standalone toolchain

    First, you need to have Android NDK r10e installed, which can be downloaded from:

    • Darwin: https://dl.google.com/android/repository/android-ndk-r10e-darwin-x86_64.zip
    • Linux: https://dl.google.com/android/repository/android-ndk-r10e-linux-x86_64.zip
    • Windows: https://dl.google.com/android/repository/android-ndk-r10e-windows-x86_64.zip
    • Linux 32-bit (x86): http://dl.google.com/android/ndk/android-ndk-r10e-linux-x86.bin
    • Linux 64-bit (x86_64): http://dl.google.com/android/ndk/android-ndk-r10e-linux-x86_64.bin

    Pay attention to the NDK version we are using: r10e. This is the version that can successfully compile the GLib library for Android. As the time of writing, the newest NDK version is r12b. Yet using of this version is NOT RECOMMENDED, because some changes the GCC toolchain makes the compiling process fail (I will explain later).

    Then, make a standalone toolchain using the script at ${NDK}/build/tools/make-standalone-toolchain.sh. For more details, refer to my previous blog on Three Ways to Use Android NDK Cross Compiler or Android NDK doc.

    $ ${NDK}/build/tools/make-standalone-toolchain.sh 
    --toolchain=arm-linux-androideabi-4.9
    --stl=gnustl
    --arch=arm
    --ndk-dir=/home/midev/dev/android-ndk-r10e
    --system=linux-x86_64
    --package-dir=/home/midev/dev
    --install-dir=/home/midev/dev/android-ndk-toolchain
    --platform=android-19

    We have made a standalone NDK toolchain targeting Android arm architecture, API level 19, using gnustl C++ library, and GCC version 4.9, host system type is linux-86_64.

    Install necessary packages in Ubuntu

    Several packages needs to be installed because GLib and its dependencies use GNU Autotools.

    $ 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

    Then we need to specify Android version binutils for cross compiling and set proper compiler flags.I have a script to do the environment configuration.

    #!/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=${HOME}/dev

    # 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

    # The path of standalone NDK toolchain
    # Refer to https://developer.android.com/ndk/guides/standalone_toolchain.html
    export NDK_TOOLCHAIN=${DEV}/android-ndk-toolchain

    # 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"

    Save it, e.g. glib-env-prep.sh, and source it to make changes effective in current shell immediately:

    $ emacs glib-env-prep.sh
    $ source ./glib-env-prep.sh

    Compile and install dependency libraries

    The most haunting experience in compiling sources yourself is probably handling dependencies.We are out of no exception this time.To make it worse, we are cross-compiling GLib for Android, and that means we need to cross-compile not only GLib itself, but also three other dependencies: libiconv, libffi and gettext.You may also cross-compile PCRE but that’s not a mandatory dependency.

    Compile libiconv 1.14

    $ wget http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.14.tar.gz
    $ tar zxvf libiconv-1.14.tar.gz
    $ cd libiconv-1.14
    $ ./configure --build=${BUILD_SYS} --host=arm-eabi --prefix=${PREFIX} --disable-rpath
    $ make
    $ make install

    Then static library libiconv.a will be installed to /opt/android/lib.

    Notice here that for host arch we used arm-eabi instead of arm-linux-androideabi, because arm-eabi is meant for building Android kernel. In general these two are slightly different. Though arm-linux-androideabi may work, I have not verified it so I cannot give any gurantees. Also, no need to run autogen.sh as it may confuse the build system and host system architectures.

    Compile libffi 3.2.1

    libffi is the Portable Foreign Function Interface Library and is a prerequisite for building GLib. It is an interface that allows code written in one language to call code written in another language.

    $ wget ftp://sourceware.org/pub/libffi/libffi-3.2.1.tar.gz
    $ tar zxvf libffi-3.2.1.tar.gz
    $ cd libffi-3.2.1
    $ sed -e '/^includesdir/ s/$(libdir).*$/$(includedir)/' -i include/Makefile.in
    $ sed -e '/^includedir/ s/=.*$/=@includedir@/' -e 's/^Cflags: -I${includedir}/Cflags:/' -i libffi.pc.in
    $ ./configure --build=${BUILD_SYS} --host=arm-eabi --prefix=${PREFIX} --enable-static
    $ make
    $ make install

    The two lines beginning with sed is to make package install headers into the conventional ${PREFIX}/include instead of ${PREFIX}/lib/libffi-3.2.1/include.Thanks these instructions from LFS [1], otherwise we will be adding the -I and -L flags for libffi in our cross compile environment setting script.

    Compile gettext 0.18.3

    First get the source code for gettext 0.18.3

    $ wget http://ftp.gnu.org/pub/gnu/gettext/gettext-0.18.3.tar.gz
    $ tar zxvf gettext-0.18.3.tar.gz

    To compile gettext-0.18.3, a patch must be applied.In gettext-tools/src/msginit.c, change line 1088 from

    fullname = pwd->pw_gecos;

    to

    #ifndef __ANDROID__
    fullname = pwd->pw_gecos;
    #else
    fullname = "android";
    #endif

    I have made a patch for it:

    diff -Naur gettext-0.19.8/gettext-tools/src/msginit.c gettext-0.19.8-patched/gettext-tools/src/msginit.c
    --- gettext-0.19.8/gettext-tools/src/msginit.c 2016-05-30 05:12:33.000000000 -0400
    +++ gettext-0.19.8-patched/gettext-tools/src/msginit.c 2016-07-17 17:35:43.732076347 -0400
    @@ -1081,7 +1081,12 @@
    char *result;

    /* Return the pw_gecos field, up to the first comma (if any). */
    - fullname = pwd->pw_gecos;
    + // fullname = pwd->pw_gecos;
    + #ifndef __ANDROID__
    + fullname = pwd->pw_gecos;
    + #else
    + fullname = "android";
    + #endif
    fullname_end = strchr (fullname, ',');
    if (fullname_end == NULL)
    fullname_end = fullname + strlen (fullname);

    Save it as gettext-0.18.3-android.patch and apply it:

    $ emacs gettext-0.18.3-android.patch
    $ patch -p0 < gettext-0.18.3-android.patch

    Then configure and compile it.

    $ cd gettext-0.18.3
    $ ./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

    We disabled some non-necessary functions. Again, no need to run autogen.sh.

    Compile GLib

    Finally, let’s compile the latest glib-2.48.1.

    $ wget http://ftp.gnome.org/pub/gnome/sources/glib/2.48/glib-2.48.1.tar.xz
    $ tar xvf glib-2.48.1.tar.xz .
    $ cd glib-glib-2.48.1

    Cross-compiling GLib requires a “cache file”, which tells GLib how to set some of the variables manually.For more details see GLib’s official doc at https://developer.gnome.org/glib/stable/glib-cross-compiling.html.

    The cache file we will be using is called 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

    We will also make it read-only to prevent it from being overwritten by the automatic configure:

    $ emacs android.cache
    $ chmod a-x android.cache
    $ ./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

    Should you see any errors from executing autogen.sh, fix them.For example, it could tell you that no package ‘zlib’ or ‘libffi’ found, and that’s why we have installed it at the very beginning.

    If you don’t want waste your time compiling an additional PCRE library like I do, then the last argument --with-pcre=no will be your life saver.

    So, finally, we are done!! The ${PREFIX}/lib folder (/opt/android/lib in our case) will contain libglib-2.0.so, libgio-2.0.so, libgmodule-2.0.so, libgthread-2.0.so and other built libraries/binaries.

    References

    • [1] http://www.linuxfromscratch.org/blfs/view/svn/general/libffi.html
    • [2] https://groups.google.com/forum/#!topic/lcm-users/Ly-xvHphpcY
    • [3] http://mathslinux.org/?p=268
    • [4] https://www.gnu.org/software/libiconv/
    • [5] http://www.linuxfromscratch.org/lfs/view/development/chapter06/gettext.html
    • [6] https://mssun.me/blog/build-android-toolchain.html
    • [7] https://gist.github.com/mssun/19070cc35d7a38c9ea21
    • [8] https://android.googlesource.com/platform/prebuilts/android-emulator-build/qemu-android-deps/+archive/master.tar.gz
    • [9] http://forum.xda-developers.com/showthread.php?t=2723240
    • [10] https://dl.dropboxusercontent.com/u/23869279/Files/cc.sh
    • [11] https://mail.gnome.org/archives/gtk-devel-list/2011-March/msg00096.html
    • [12] https://gist.github.com/nddrylliog/4688209

    Appendix

    • I have tried NDK r12b with both API level 23 and 19. But both of them cannot compile. When compiling the gettext, API 23 will give error on “cannot find <stdio_ext.h>“ and API 19 will give error on “cannot find <search.h>“.

    • If you encountered an error complaining gets not defined when compiling libiconv, the following solutions may help you:

      • https://github.com/mxe/mxe/commit/8e4ab07b8e8ff9642148e411d58acebf43ae0a3b
      • https://gist.github.com/paulczar/5493708
    • If you want to use with-pcre=system when configuring GLib, you need to cross-compile PCRE 8.39 and install it:

      • ./configure --build=${BUILD_SYS} --host=arm-eabi --disable-rpath --prefix=${PREFIX} --enable-unicode-properties

    And good luck on fixing any error that may pop up.


  • 相关阅读:
    初学移动专题
    IE下a标签跳转失败
    c++中一个多态的实例
    字符串中是否有相同的字符
    求乘积最大的连续子序列
    跳跃游戏
    求一个非负整数的平方根 二分法
    罗马数 与 整数 相互转换
    二进制相加
    链表分割
  • 原文地址:https://www.cnblogs.com/ztguang/p/12644414.html
Copyright © 2011-2022 走看看