Build Android Toolchain

Build Android Toolchain

JUNE 15, 2015

Gen­er­at­ing or build­ing a set of stand­alone An­droid tool­chain is not an easy task. This ar­ti­cle sum­ma­rizes sev­eral is­sues I met when I tried to build binu­tils for ARM An­droid plat­form (arm-linux-androideabi). My setup is a Ubuntu 14.04 ma­chine (x86_64-linux-gnu) with all AOSP build­ing en­vi­ron­ment.

Build on host=x86_linux-gnu

If you want a stand­alone tool­chain which can be used in your x86_64 ma­chine, you don't need to build from scratch. You can sim­ply gen­er­ate from An­droid NDK pack­age.

Build on host=arm-linux-androideabi

If you need a tool­chain run­ning on An­droid, things be­came a lit­tle com­pli­cated. For ex­am­ple, I want to run gcc or objdump on ARM An­droid. Be­cause we can­not get tool­chain build for ARM, let's try to build from scratch.

Prepa­ra­tion

Be­cause An­droid main­tain their own tool­chain forked from GNU, we need first clone the source code from Google's repos­i­tory.

repo init -u https://android.googlesource.com/toolchain/manifest 

Be­sides the tool­chain source codes, we also need An­droid NDK pack­age.

We can get some build­ing in­for­ma­tion from tool­chain/build/README file. This tool­chain only sup­ports:

1. Supported platforms.  The Android tool-chain supports the following hosts:  a. i686-linux-gnu (32-bit x86 Linux) b. x86_64-linux-gnu (64-bit x86 Linux) c. i686-apple-darwin* (OS X 10.4 and 10.5)  The Android toolchain supports the following targets:  a. arm-linux-androideabi b. arm-eabi (for Android kernel) c. arm-newlib-eabi (for runnng gcc regression tests) d. i[3456]86-*-linux-gnu, x86_64-*-linux-gnu (for x86 targets) 

The host means which ma­chine can run the tool­chain, and the target means which tar­get ma­chine is this tool­chain used for. What we need here is host=arm-linux-androideabiand target=arm-linux-androideabi. That's why we need some extra mod­i­fi­ca­tion on the source code.

Con­fig­ure & Make

Firstly, we find the source code of binu­tils in toolchain/binutils/binutils-2.25. Sec­ondly, cre­ate a build script with con­fig­ure in it like mine:

#!/bin/bash  export PWD=`pwd` export PREFIX=${PWD}/system export NDK_HOME=/xxx/android-ndk-r10e export CROSS_COMPILE=${NDK_HOME}/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi- export PATH=${NDK_HOME}/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin:$PATH export SYSROOT=${NDK_HOME}/platforms/android-21/arch-arm  make distclean rm */config.cache ./configure \ --prefix=$PREFIX \ --host=arm-linux-androideabi \ --target=arm-linux-androideabi \ --disable-option-checking \ CC=${CROSS_COMPILE}gcc \ CXX=${CROSS_COMPILE}g++ \ CFLAGS="-g -I -O2 -mandroid -mbionic -I${NDK_HOME}/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.9/include -I${SYSROOT}/usr/include/ --sysroot=${SYSROOT} -Wno-error -fPIE" \ LDFLAGS="-L${NDK_HOME}/platforms/android-21/arch-arm/usr/lib -pie" \ CPP=${CROSS_COMPILE}cpp \ CPPFLAGS="-I${NDK_HOME}/platforms/android-21/arch-arm/usr/include/" \ AR=${CROSS_COMPILE}ar  make -j4 mkdir -p $PREFIX make install 

Then, let's try it first with ./build.sh. How­ever, we may face these fol­low­ing er­rors.

Can­not find stdio_ext.h header:

./fopen_unlocked.c:76:23: fatal error: stdio_ext.h: No such file or directory #include ^ compilation terminated. checking for stdint.h... make[2]: *** [fopen_unlocked.o] Error 1 make[2]: Leaving directory `/media/mssun/1cb9a33d-c5f6-4bba-b0ed-b4c6cbad345c/aosp/toolchain/binutils/binutils-2.25/libiberty' make[1]: *** [all-libiberty] Error 2 make[1]: *** Waiting for unfinished jobs.... 

To solve this issue, just com­ment this in­clude state­ment in fopen_unlocked.c file.

$ find . -type f -name "fopen_unlocked.c" ./libiberty/fopen_unlocked.c 

com­ment the state­ments:

#ifdef HAVE_CONFIG_H #include "config.h" #endif #include /* #ifdef HAVE_STDIO_EXT_H */ /* #include */ /* #endif */ 

Can­not find sys/sysctl.h header

checking minix/config.h presence... ./physmem.c:52:25: fatal error: sys/sysctl.h: No such file or directory ## include <sys/sysctl.h> ^ compilation terminated. make[2]: *** [physmem.o] Error 1 make[2]: Leaving directory `/media/mssun/1cb9a33d-c5f6-4bba-b0ed-b4c6cbad345c/aosp/toolchain/binutils/binutils-2.25/libiberty' make[1]: *** [all-libiberty] Error 2 make[1]: *** Waiting for unfinished jobs.... 

The so­lu­tion is same as pre­vi­ous issue, com­ment this header in physmen.c file.

$ find . -type f -name physmem.c ./libiberty/physmem.c 

com­ments the header state­ments:

/* #if HAVE_SYS_SYSCTL_H */ /* # include <sys/sysctl.h> */ /* #endif */ 

Can­not find crtbegin_so.o and crtend_so.o

The last error is:

/android-ndk-r10e/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.9/../../../../arm-linux-androideabi/bin/ld: error: cannot open crtbegin_so.o: No such file or directory /android-ndk-r10e/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.9/../../../../arm-linux-androideabi/bin/ld: error: cannot open crtend_so.o: No such file or directory collect2: error: ld returned 1 exit status 

The so­lu­tion is copy these two files from NDK sys­root to ld di­rec­tory. So, change our build­ing scripts as:

#!/bin/bash  export PWD=`pwd` export PREFIX=${PWD}/system export NDK_HOME=/xxx/android-ndk-r10e export CROSS_COMPILE=${NDK_HOME}/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi- export PATH=${NDK_HOME}/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin:$PATH export SYSROOT=${NDK_HOME}/platforms/android-21/arch-arm  make distclean rm */config.cache ./configure \ --prefix=$PREFIX \ --host=arm-linux-androideabi \ --target=arm-linux-androideabi \ --disable-option-checking \ CC=${CROSS_COMPILE}gcc \ CXX=${CROSS_COMPILE}g++ \ CFLAGS="-g -I -O2 -mandroid -mbionic -I${NDK_HOME}/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.9/include -I${SYSROOT}/usr/include/ --sysroot=${SYSROOT} -Wno-error -fPIE" \ LDFLAGS="-L${NDK_HOME}/platforms/android-21/arch-arm/usr/lib -pie" \ CPP=${CROSS_COMPILE}cpp \ CPPFLAGS="-I${NDK_HOME}/platforms/android-21/arch-arm/usr/include/" \ AR=${CROSS_COMPILE}ar  ln -s ${NDK_HOME}/platforms/android-21/arch-arm/usr/lib/crtbegin_so.o ld/ ln -s ${NDK_HOME}/platforms/android-21/arch-arm/usr/lib/crtend_so.o ld/  make -j4 mkdir -p $PREFIX make install 

At last, we got:

$ ls system/bin/ addr2line ar as c++filt elfedit gprof ld ld.bfd nm objcopy objdump ranlib readelf size strings strip $ file system/bin/readelf system/bin/readelf: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked (uses shared libs), not stripped 

Re­marks

Pay at­ten­tion the -fPIE and -pie flags in com­pil­ing and link­ing. Be­cause An­droid only sup­port po­si­tion in­de­pen­dent ex­e­cutable, we need to add flags to make PIE bi­na­ries. For Arch Linux users, you may meet /lib/cpp error. Just link /usr/bin/cpp as lib/cpp will solve this issue.

At last, I haven't see any con­se­quences after delet­ing those head­ers. Per­haps, some re­lated func­tions will be af­fected. If you have any ques­tion or bet­ter so­lu­tion, please leave a com­ment. Thank you.

Ref­er­ence

posted @ 2018-03-15 14:47  hcyy2017  阅读(960)  评论(0)    收藏  举报