c,c++
分类: 嵌入式
2016-01-05 10:00:03
一、编译准备:
工作电脑的环境是Ubantu10.04。
确认 Ubantu是否已经安装 gmp 和 mpfr 。
若没有,下载安装,地址如下:
1.
编译工具链需要的源码包:
建立编译工作目录/home/huazi/cross_compile,目录下建立三个子目录build-tools、kernel、tools
$ mkdir -p /home/huazi/cross_compile
$ cd /home/huazi/cross_compile
$ mkdir build-tools kernel tool
$ ls
build-tools kernel tool
各文件夹作用如下:
build-tools : 保存binutils、gcc 和 glibc的源代码和用来编译这些源代码的目录。
kernel : 保存内核源代码。
tools : 保存编译好的交叉编译工具和库。
在build-tools文件夹中建立如下子文件夹:
$ cd build-tools
$ mkdir build-binutils build-boot-gcc build-glibc build-gcc
build-binutils :编译binutils的目录
build-boot-gcc : 编译boot gcc的目录
build-glibc :编译glibc的目录
build-gcc :编译 full gcc的目录
将下载好的源码压缩文件放入相应的文件夹。
linux kernel文件放入 kernel 文件夹
$mv linux- 2.6.34.tar.gz /home/huazi/cross_compile/kernel/
其他几个(binutils-2.20.tar.gz gcc-4.3.5.tar.bz2 glibc-2.11.tar.gz
glibc-linuxthreads-2.5.tar.bz2 glibc-ports-2.11.tar.bz2)放入 build-tools 文件夹
$mv *.tar.gz *.tar.bz2 /home/huazi/cross_compile/build-tools/
设置环境变量:
这里设置环境变量只是为了方便,因为每个工具的config都需要输入类似的变量,不如放在环境变量里。
在命令行下打开vi ~/.bashrc,在文档最后输入下面几行,然后注销当前用户,重新登录
export PRJROOT=/home/huazi/cross_compile
export TARGET=arm-none-linux-gnueabi
export PREFIX=$PRJROOT/tools
export TARGET_PREFIX=$PREFIX/$TARGET
export PATH=$PREFIX/bin:$PATH
各变量的具体意义如下:
PRJROOT : 整个工程的根目录
TARGET : 目标文件对应的体系结构,arm-linux代表编译出来的 target只能在arm体系结构中运行
PREFIX : 设置目标文件夹的路径前缀
TARGET_PREFIX : 设置目标文件夹的路径前缀路径
PATH : 添加可执行文件的路径,这里主要是中间编译工具等
二、建立内核include文件
$cd $PRJROOT/kernel/
$tar zxvf linux-2.6.34.tar.gz
$cp -r /home/huazi/cross_compile /kernel/linux-2.6.34/include/linux
TARGET_PREFIX/include/linux
$cp -r /home/huazi/cross_compile /kernel/linux-2.6.34/include/ include/asm-generic
TARGET_PREFIX/include/ asm-generic
$cp -r /home/huazi/cross_compile /kernel/linux-2.6.34/arch/arm/include/asm
TARGET_PREFIX/include/asm
编译生成version头文件,这是编译glibc需要的一个头文件
$cd linux-2.6.34
$ make include/linux/version.h
三、建立binutils
$cd $PRJROOT/build-tools/
$tar zxvf binutils-2.20.tar.gz
$cd $PRJROOT/build-tools/build-binutils
$ ../binutils-2.20/configure --target=$TARGET --prefix=$PREFIX
$make
出错:
../../binutils-2.20/gas/config/tc-arm.c: In function ‘make_mapping_symbol’:
../../binutils-2.20/gas/config/tc-arm.c:2489: error: suggest braces around empty body in an ‘if’ statement
打开文件binutils-2.20/gas/config/tc-arm.c,把2490行的语句,用一对大括号括起来就可以了,
else没有括起来!
安装: make install
完成后检查一下$PREFIX文件夹,多了三个子文件夹,bin, lib, share,在bin里面生成了14个可执行文件:
$ls $PREFIX/bin
arm-none-linux-gnueabi-addr2line
arm-none-linux-gnueabi-as
arm-none-linux-gnueabi-gprof
arm-none-linux-gnueabi-nm
arm-none-linux-gnueabi-objdump
arm-none-linux-gnueabi-readelf
arm-none-linux-gnueabi-strings arm-none-linux-gnueabi-ar
arm-none-linux-gnueabi-c++filt
arm-none-linux-gnueabi-ld
arm-none-linux-gnueabi-objcopy
arm-none-linux-gnueabi-ranlib
arm-none-linux-gnueabi-size
arm-none-linux-gnueabi-strip
功能分别是:
add2line :将你要找的地址转成文件和行号,它要使用 debug 信息。
ar :产生、修改和解开一个存档文件
as :gnu的汇编器
c++filt :C++ 和 java 中有一种重载函数,所用的重载函数最后会被编译转化成汇编的标,c++filt 就是实现这种反向的转化,根据标号得到函数名
gprof :gnu 汇编器预编译器
ld :gnu 的连接器
nm :列出目标文件的符号和对应的地址
objcopy :将某种格式的目标文件转化成另外格式的目标文件
objdump :显示目标文件的信息
ranlib :为一个存档文件产生一个索引,并将这个索引存入存档文件中
readelf :显示 elf 格式的目标文件的信息
size :显示目标文件各个节的大小和目标文件的大小
strings :打印出目标文件中可以打印的字符串,有个默认的长度,为4
strip :剥掉目标文件的所有的符号信息
四、建立初始编译器(bootstrap gcc)
我们为什么要建立bootstrap gcc,而不能一次性成功?原因有两点:
一是由于平台本身的gcc编译器可能和我们要建立的gcc版本不同,第一次用平台本身的编译器去build目标版本的gcc编译器的时候,新生成的目标编译器(相当于初始编译器编译链接生成的可执行文件)必然带有初始编译器的特征。所以我们可以用新生成的编译器再次编译自身,可去掉这些差异性。
二是因为gcc编译器依赖于glibc,而当前glibc是基于工作编译机的,所以首先要build基于arm体系结构的glibc,而后在此glibc的基础上生成基于arm体系结构的gcc。
$cd $PRJROOT/build-tools/
$tar -xvzf gcc-4.3.5.tar.bz2
在我们编译并安装 gcc 前,我们先要改一个文件 $PRJROOT/build-tools/gcc-4.3.5/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
$cd build-boot-gcc
$../gcc-4.3.5/configure --target=$TARGET --prefix=$PREFIX --without-headers --enable-languages=c --disable-threads --with-newlib --disable-shared --disable-libmudflap --disable-libssp
编译安装gcc
$make all-gcc
$make install
编译安装libgcc,这个是后面编译glibc需要的
$make all-target-libgcc
$make install-target-libgcc
安装完成后,在$PREFIX/bin下又多了几个文件:
arm-none-linux-gnueabi-cpp : gnu的 C 的预编译器
arm-none-linux-gnueabi-gcc : gnu的 C 语言编译器
arm-none-linux-gnueabi-gcc-4.3.5 : gnu的 C 语言编译器,arm-none-linux-gnueabi-gcc的一个软连接
arm-none-linux-gnueabi-gccbug : 一个可执行脚本
arm-none-linux-gnueabi-gcov : gcc 的辅助测试工具,用来分析和优化程序
五、建立glibc
把glibc源码解压到build-tool下
把glibc-linuxthreads-2.5.tar.bz2解压到glibc根目录下
把glibc-ports-2.11.tar.bz2解压到glibc根目录下,并且命名为ports
进入文件夹build-glibc,创建config.cache文件,并且在文件中输入以下内容
libc_cv_forced_unwind=yes
libc_cv_c_cleanup=yes
libc_cv_arm_tls=yes
$BUILD_CC="gcc" CC=$TARGET-gcc ../glibc-2.11/configure --host=$TARGET --target=$TARGET --prefix=/usr --enable-add-ons --disable-profile --cache-file=config.cache --with-binutils=$PREFIX/bin/ --with-headers=$TARGET_PREFIX/include/
编译
$make
出错:/arm-linux/bin/ld: cannot find
-lgcc_eh
打开glibc根目录下Makeconfig文件,去掉第541,546行中的-lgcc_eh,重新make
安装
$make install_root=$TARGET_PREFIX prefix="" install
修改$PRJROOT/tools/arm-none-linux-gnueabi/lib/libc.so:
用vi或gedit打开libc.so文件,将文件中的:
GROUP ( /lib/libc.so.6 /lib/libc_nonshared.a AS_NEEDED ( /lib/ld-linux.so.2 ) )
更改为
GROUP ( libc.so.6 libc_nonshared.a )
保存后退出
六、建立完整版gcc
cd $PRJROOT/build-tools/build-gcc
配置
$../gcc-4.3.5/configure --target=$TARGET --prefix=$PREFIX --enable-languages=c,c++ --disable-libgomp
编译
$make all
安装:
make install
安装完成后,在$PREFIX/bin下多了gnu的c++编译器:
arm-none-linux-gnueabi-gcc
arm-none-linux-gnueabi-c++
到此,我们的ARM交叉编译环境arm-none-linux-gnueabi-gcc v4.3.5就编译创建成功了!
$ ls $PREFIX/bin
arm-none-linux-gnueabi-addr2line arm-none-linux-gnueabi-gprof
arm-none-linux-gnueabi-ar arm-none-linux-gnueabi-ld
arm-none-linux-gnueabi-as arm-none-linux-gnueabi-nm
arm-none-linux-gnueabi-c++ arm-none-linux-gnueabi-objcopy
arm-none-linux-gnueabi-c++filt arm-none-linux-gnueabi-objdump
arm-none-linux-gnueabi-cpp arm-none-linux-gnueabi-ranlib
arm-none-linux-gnueabi-g++ arm-none-linux-gnueabi-readelf
arm-none-linux-gnueabi-gcc arm-none-linux-gnueabi-size
arm-none-linux-gnueabi-gcc-4.3.5 arm-none-linux-gnueabi-strings
arm-none-linux-gnueabi-gccbug arm-none-linux-gnueabi-strip
arm-none-linux-gnueabi-gcov