GNU toolchain for ARM 编译笔记
时间:2007-02-28 来源:loughsky
交叉编译GNU工具链真是折磨人的差事阿……以后再也不做了。
以下是编译笔记
______________________________________________
构建自己的arm-linux toolchain:
生成工具链目录结构:
/usr/armtools
`----arm-linux 目标平台相关内容
| `----bin gcc内部使用的编译/连接工具
| `----lib gcc的内部库/c++ 库
| | `----ldscripts ld的连接脚本
| `----target-root 目标平台根目录
| `----etc 目标平台设置(ld.so.cache)
| `----lib 目标平台glibc库
| `----usr
| `----include glibc头文件
`----bin + arm-linux-gcc,arm-linux-ld,...
`----include
`----c++ c++ 标准头文件
`----lib
| `----gcc gcc内部库核心cc1,collect2
| `----...
`----libexec
| `----gcc gcc内部使用的辅助工具
| `----...
`----man man for gcc/glib/binutils
`----info info for gcc/glib/binutils
`----share Locale等
该目录结构由binutils, gcc, glibc的目录复合而成,可变性很差, 稍有差错就可能导致工具链无法使用。 目录的结构由以下几个配置参数决定:
--prefix=chain/root 工具链根目录, 缺省为/usr/local
虽然gcc/binutils支持multi-lib方式,可以使用/usr/local作为工具链根目录而不与本地gcc发生冲突, 但glibc并不支持这一特性。因此一般使用prefix把根目录指定到某一特定目录,比如/usr/armtools。
但对于glibc,此目录同时也是glibc的库文件工作的时候(在target上运行应用程序的时候)寻找文件所用路径,因此应该设置为缺省的/usr,而使用install_root来指定安装路径。
--with-sysroot 目标板根目录。gcc将由此开始按照标准linux目录结构寻找编译所需的头文件和库。binutils目前对此参数支持还不是很好,如果不配合make时使用LIB_PATH,ld会无法为so文件找到其所需的其它so文件。
LIB_PATH 辅助指定库所在路径
install_root 指定glibc安装路径。倘若不指定此参数,prefix=/usr的情况make install会导致系统本地glibc库被覆盖。
1 Binutils:
GNU二进制文件处理工具,核心工具为ld和as。构造arm-linux-gcc时需要用到arm-linux-ld
和arm-linux-as来生成g++的arm-elf库,构造glibc时同样需要用到。
binutils是toolchain的基础,如果配置不正确,会给后来的编译带来诸多问题。
./configure --prefix=/usr/armtools --target=arm-linux --with-sysroot=/usr/armtools/arm-linux/target-root
make LIB_PATH=/usr/armtools/arm-linux/target-root/lib tooldir=/usr/armtools
make install
/usr/armtools
|----arm-linux 供GCC/Binutils内部使用
| |----bin 内部命令 ld,as...
| `----lib 内部库
| `----ldscripts ld的连接脚本。如果用到的so库中使用了其他so库,则搜索路径在这里指定
|----bin 供用户使用的命令 arm-linux-*
|----info info
|----lib 用户使用的库
`----man man
`----man1 binutils manual
make需要autoconf, automake, m4, flex, yacc, gettext支持。
如果make时出现:/bin/bash: no command not found一类的错误时,需要更新gettext,或者configure时加上 --disable-nls 关闭本地化语言支持。
arm-linux-ld将会/usr/armtools/arm-linux/lib中寻找连接时使用的.so文件。如果找不到,则在glibc编译完成后,gcc无法编译动态链接的文件,提示:
warning: ld-linux.so.2, needed by /libc.so.6, not found
唯有同时指定--with-sysroot 和 LIB_PATH可解决此问题。
binutils2.15 同 gcc3.4.3 + glibc2.3.2面向ARM时冲突。该冲突尚未解决(2005.3.1)
2 Kernel Source
Linux 内核源代码的头文件是编译glibc必需的。 获取Linux初始源代码并针对架构打上补丁,以Xscale为例:
获取:
linux-2.4.19.tar.gz 初始源代码
patch-2.4.19-rmk7.bz2 针对ARM的补丁
diff-2.4.19-rmk7-pxa2.gz 针对Xscale的补丁
打补丁:
tar -xzf linux-2.4.19.tar.gz
cd linux-2.4.19/
bzcat ../patch-2.4.19-rmk7.bz2 | patch -p1
zcat ../diff-2.4.19-rmk7-pxa2.gz | patch -p1
配置内核并设置头文件依赖:
make ARCH=arm menuconfig
选择Processor Type 为 PXA210/250,
选择适当的开发平台
保存退出
make dep
复制header:
mkdir /usr/armtools/arm-linux/usr
mkdir /usr/armtools/arm-linux/usr/include
cp -rD linux-2.4.19/include/arm-asm/ /usr/armtools/arm-linux/target-root/usr/include/
cp -rD linux-2.4.19/include/linux/ /usr/armtools/arm-linux/target-root/usr/include/
在/toolschain/rootdir/arm-linux下建立了include目录
make dep 会要求arm-linux-gcc存在...
3 GCC-Core
GCC本身的编译分为两个部分. 首先是建立运行在Host平台上的一系列交叉编译工具arm-linux-gcc/g++/java..., 另一个是编译特定语言写成的应用程序时所需要的静态库(.a)和动态库(.so)文件. 例如c++的libstdc++.*和java的libjava.*. c本身的库文件glibc(libc.*)需要单独编译。
由于g++和java等编译器使用glibc,因此,在完全没有编译环境的情况下,只能够先编译gcc-core(gcc),然后利用生成的gcc编译glibc, 最后生成其他语言的编译器。
获取:
gcc-core-3.4.3.tar.bz2 GNU C Core &Compiler
编译时按照编译要求,最好将源代码和生成的OBJ分开放置:
tar -xjf gcc-core-3.4.3.tar.bz2
mkdir gccobj
cd gccobj
由于目前没有glibc, 需要修改编译条件,使编译过程中不使用glibc:
vi gcc-3.4.3/gcc/config/arm/t-linux
将
TARGET_LIBGCC2_CFLAGS = -fomit-frame-pointer -fPIC
改为
TARGET_LIBGCC2_CFLAGS = -fomit-frame-pointer -fPIC -Dinhibit_libc -D__gthr_posix_h
配置并编译:
export PATH=$/toolchain/rootdir/bin:$PATH
../gcc-3.4.3/configure --prefix=/usr/armtools --target=arm-linux --with-sysroot=/usr/armtools/arm-linux/target-root --enable-languages=c --disable-threads -disable-shared
make
make install
配置参数说明:
--prefix gcc安装的根目录,缺省为/usr/local
--target 目标平台
--without-headers 不使用头文件。gcc编译的时候会引用目标平台的linux和libc头文件。
指定此选项避免出现"stdio.h: file not found"一类的错误
--enable-languages=c 只生成c编译器
--disable-threads gcc使用线程来提高编译速度,但现在还没有Target的glibc
--disable-shared 生成Target平台的so文件需要glibc,现在还没有
4 Glibc
如果需要编译在target上运行的用户空间程序,则glibc是必需的。
获取:
glibc-2.3.2.tar.gz
glibc-linuxthreads-2.3.2.tar.bz2
设置编译目录:
tar -xzf glibc-2.3.2.tar.gz
cd glibc-2.3.2
tar -xjf ../glibc-linuxthreads-2.3.2.tar.bz2
cd ..
mkdir glibcobj
配置并编译:
cd glibcobj
BUILD_CC=gcc CC=arm-linux-gcc AR=arm-linux-ar RANLIB=arm-linux-ranlib ../glibc-2.3.2/configure --build=i386-linux --host=arm-linux --prefix=/usr --enable-add-ons --with-headers=/usr/armtools/arm-linux/target-root/usr/include/
make
make install install_root=/usr/armtools/arm-linux/target-root
修改Glibc为ARM编译的ld脚本bug:
去掉.../target-root/usr/lib中*.so文件中的***BUG.....***一行
*** configure: error: cannot compute sizeof (long double)
如果不指定--build,configure会以为在进行本地编译,从而运行测试程序,导致配置不成功。这应该是glibc2.3.2的bug
*** "crti.S:96: Error: can't resolve : `_GLOBAL_OFFSET_TABLE_' {*UND* section} ..."