1 环境
linux 16.04
2 所需源文件
binutils-2.23.1.tar.bz2
glibc-2.18.tar.gz
gcc-4.8.2.tar.bz2
gmp-5.1.3.tar.bz2
mpfr-3.1.2.tar.bz2
mpc-1.0.1.tar.gz
linux-2.6.34.14.tar.bz2
3 设置环境变量
export SRCDIR=~/workbench/gcc-4.8.2/xtools/src
export BUILDDIR=~/workbench/gcc-4.8.2/xtools/build
export TARGET=arm-linux-gnueabi
export PREFIX=/usr/local/arm/4.8.2
export TARGET_PREFIX=$PREFIX/$TARGET
export PATH=$PATH:$PREFIX/bin
4 创建工作区
$mkdir -pv ~/workbench/gcc-4.8.2/xtools
$mkdir $SRCDIR
$cd $SRCDIR
5 下载源代码
5.1 binutils
$wget http://ftp.gnu.org/gnu/binutils/binutils-2.23.1.tar.bz2
$tar -pxjf binutils-2.23.1.tar.bz2
5.2 glibc
$wget http://ftp.gnu.org/gnu/glibc/glibc-2.18.tar.gz
$tar -pxzf glibc-2.18.tar.gz
$wget http://ftp.gnu.org/gnu/glibc/glibc-linuxthreads-2.5.tar.bz2
5.3 gcc
$wget http://ftp.gnu.org/gnu/gcc/gcc-4.8.2/gcc-4.8.2.tar.bz2
$wget http://ftp.gnu.org/gnu/gmp/gmp-5.1.3.tar.bz2
$wget http://ftp.gnu.org/gnu/mpfr/mpfr-3.1.2.tar.bz2
$wget ftp://gcc.gnu.org/pub/gcc/infrastructure/mpc-1.0.1.tar.gz
$tar -pxjf gcc-4.8.2.tar.bz2
$cd gcc-4.8.2/
$tar -pxjf ../gmp-5.1.3.tar.bz2
$tar -pxjf ../mpfr-3.1.2.tar.bz2
$tar -pxzf ../mpc-1.0.1.tar.gz
$cd $SRCDIR
5.4 kernel
cd $BINUTILS_SRC
$wget https://www.kernel.org/pub/linux/kernel/v2.6/longterm/v2.6.34/linux-2.6.34.14.tar.xz
$xz -d linux-2.6.34.14.tar.xz
$tar -xf linux-2.6.34.14.tar
6 build
6.1 为宿主机安装gmp、mpfr、mpc
6.1.1 build gmp
cd $ BUILDDIR
mkdir gmp
cd $BUILDDIR/gmp
$SRCDIR/gmp-5.1.3/configure --prefix=/usr/local/gmp --build=x86_64-linux-gnu
make
sudo make install
make check
6.1.2 build mpfr
cd $ BUILDDIR
mkdir mpfr
cd $BUILDDIR/mpfr
$SRCDIR/mpfr-3.1.2/configure --build=x86_64-linux-gnu --prefix=/usr/local/mpfr --with-gmp=/usr/local/gmp
make
sudo make install
6.1.3 build mpc
cd $ BUILDDIR
mkdir mpc
cd $BUILDDIR/mpc
$SRCDIR/mpc-1.0.1/configure --build=x86_64-linux-gnu --prefix=/usr/local/mpc --with-gmp=/usr/local/gmp --with-mpfr=/usr/local/mpfr
make
sudo make install
6.2 获得kernel header
编译glibc的时候需要这些头文件。
cd $SRCDIR/linux-2.6.34.14
make menuconfig
不做修改,直接退出。
sudo make include/linux/version.h
sudo cp -r ./include/linux/ $TARGET_PREFIX/include
sudo cp -r ./include/asm-generic/ $TARGET_PREFIX/include
sudo cp -r ./arch/arm/include/asm/ $TARGET_PREFIX/include
6.3 build binutils
6.3.1 build binutils
cd $ BUILDDIR
mkdir binutils
cd $BUILDDIR/binutils
$SRCDIR/binutils-2.23.1/configure --prefix=$PREFIX --target=$TARGET
make
sudo make install
完成后,去$PREFIX中检查一下生成的工具。
# cd $PREFIX/bin
# ll
有如下文件:
arm-linux-addr2line*
arm-linux-ar*
arm-linux-as*
arm-linux-C++filt*
arm-linux-elfedit*
arm-linux-gprof*
arm-linux-ld*
arm-linux-ld.bfd*
arm-linux-nm*
arm-linux-objcopy*
arm-linux-objdump*
arm-linux-ranlib*
arm-linux-readelf*
arm-linux-size*
arm-linux-strings*
arm-linux-strip*
这些生成的文件的作用分别为:
arm-linux-addr2line:将你要找的地址转成文件和行号,它要使用 debug 信息
arm-linux-ar:产生、修改和解开一个存档文件
arm-linux-as:GNU的汇编器
arm-linux-c++filt:C++ 和 Java 中有一种重载函数,所用的重载函数最后会被编译转化成汇编的标,c++filt 就是实现这种反向的转化,根据标号得到函数名
arm-linux-elfedit:用途暂时未知
arm-linux-gprof:GNU汇编器预编译器
arm-linux-ld:GNU的连接器
arm-linux-ld.bfd:用途暂时未知
arm-linux-nm:列出目标文件的符号和对应的地址
arm-linux-objcopy:将某种格式的目标文件转化成另外格式的目标文件
arm-linux-objdump:显示目标文件的信息
arm-linux-ranlib:为一个存档文件产生一个索引,并将这个索引存入存档文件中
arm-linux-readelf:显示 elf 格式的目标文件的信息
arm-linux-size:显示目标文件各个节的大小和目标文件的大小
arm-linux-strings:打印出目标文件中可以打印的字符串,有个默认的长度,为4
arm-linux-strip:剥掉目标文件的所有的符号信息
6.3.2 常见错误
(1) bfd错误
描述:
bfd.h:529:65: error: right-hand operand of comma expression has no effect [-Werror=unused-value]
#define bfd_set_cacheable(abfd,bool) (((abfd)->cacheable = bool), TRUE)
^
opncls.c:261:5: note: in expansion of macro ‘bfd_set_cacheable’
bfd_set_cacheable (nbfd, TRUE);
^
cc1: all warnings being treated as errors
Makefile:1312: recipe for target ‘opncls.lo’ failed
make[6]: *** [opncls.lo] Error 1
make[6]: Leaving directory ‘/srv/jenkins-slave/workspace/sid-goto-cc-sdcc/sdcc-3.4.0+dfsg/support/sdbinutils/bfd’
Makefile:1354: recipe for target ‘all-recursive’ failed
make[5]: *** [all-recursive] Error 1
原因:
源码版本比较老,使用gcc4.1版本编译没有问题,更改的gcc版本对此不太规范的写法会报错误。
解决方法:
cd $BUILDDIR/bfd
vim Makefile
找到里面的-Werror 选项,删除它。
因为 binutils 、gas、ld模块也有此问题,与上述解决方法一样,分别进入这些模块,删除Makefile 里面的 -Werror 参数。
6.4 build initial gcc(不带glibc支持)
cd $SRCDIR
tar -xjvf gcc-4.8.2.tar.bz2
删除原有的mpfr, mpc, gmp,重新解压:
rm -rf mpfr-3.1.2 mpc-1.0.1 gmp-5.1.3
tar -xjvf gmp-5.1.3.tar.bz2
mv gmp-5.1.3 gmp
mv ./gmp ./gcc-4.8.2
tar -xjvf mpfr-3.1.2.tar.bz2
mv mpfr-3.1.2 mpfr
mv ./mpfr ./gcc-4.8.2
tar -xzvf mpc-1.0.1.tar.gz
mv mpc-1.0.1 mpc
mv ./mpc ./gcc-4.8.2
cd $BUILDDIR
mkdir gcc-4.8.2
cd gcc-4.8.2
$SRCDIR/gcc-4.8.2/configure --prefix=$PREFIX --target=$TARGET --without-headers --enable-languages=c --disable-threads --with-newlib --disable-shared --disable-libmudflap --disable-libssp --disable-decimal-float
make all-gcc
sudo make install-gcc
make all-target-libgcc
sudo make install-target-libgcc
完成之后,$PREFIX/bin下又多了几个文件:
arm-linux-cpp*
arm-linux-gcc*
arm-linux-gcc-4.8.2*
arm-linux-gcov*
这些生成的文件的作用分别为:
arm-linux-cpp:GNU的C的预编译器
arm-linux-gcc:GNU的C语言编译器
arm-linux-gcc-4.8.2:GNU的c语言编译器,其实和arm-linux-gcc是一样的
arm-linux-gcov:gcc 的辅助测试工具,用来分析和优化程序
6.5 build glibc
Glibc是交叉编译环境的运行库。
cd $SRCDIR
tar -pxjf glibc-2.18.tar.bz2
tar -pxjf glibc-linuxthreads-2.5.tar.bz2 --directory=./glibc-2.18/
cd $BUILDDIR
mkdir glibc
cd glibc
export CC=$TARGET-gcc
export CFLAGS="-g -O2 -march=armv7-a"
(注释:TI 3354板是armv7,AM335x 微处理器基于 ARM Cortex-A8 处理器,使用的是armv7-a架构。三星2440板是 armv4t)
(架构选得不对,会有错误提示:configure:2763: arm-linux-gnueabi-gcc -c -g -O2 -march=armv7l conftest.c >&5
arm-linux-gnueabi-gcc: error: unrecognized argument in option ‘-march=armv7l’
arm-linux-gnueabi-gcc: note: valid arguments to ‘-march=’ are: armv2 armv2a armv3 armv3m armv4 armv4t armv5 armv5e armv5t armv5te armv6 armv6-m armv6j armv6k armv6s-m armv6t2 armv6z armv6zk armv7 armv7-a armv7-m armv7-r armv7e-m armv8-a iwmmxt iwmmxt2 native)
sudo ln -s /usr/local/arm/4.8.2/lib/gcc/arm-linux-gnueabi/4.8.2/libgcc.a /usr/local/arm/4.8.2/lib/gcc/arm-linux-gnueabi/4.8.2/libgcc_eh.a
创建config.cache配置文件:
vim config.cache,写入:
libc_cv_forced_unwind=yes
libc_cv_c_cleanup=yes
libc_cv_arm_tls=yes
$SRCDIR/glibc-2.18/configure --host=$TARGET --target=$TARGET --prefix=$TARGET_PREFIX --enable-add-ons --disable-profile --cache-file=config.cache --with-binutils=$PREFIX/bin --with-headers=$TARGET_PREFIX/include
make all
sudo make install
常见问题:
(1) 报错说make too old
原因:make 版本不对,4.1太高。换3.82 就可以了。
下载make-3.82
wget http://ftp.gnu.org/gnu/make/make-3.82.tar.bz2
tar -pxjf make-3.82.tar.bz2
./configure
make
然后将 make 文件的路径加入PATH
export PATH=<make路径>:$PATH
(2) 报错:checking sysdep dirs… configure: error: The arm is not supported
这个问题就是下载glibc-ports的原因,直接复制解压后的glibcports复制到glibc目录下,重命名为ports
6.6 build full gcc
注意:编译 gcc 时,我们是要生成交叉编译器本身,我们并不是要用交叉编译器编译交叉编译器。因此,需要unset交叉编译的变量,回复gcc编译。
unset CC
unset CFLAGS
cd $BUILDDIR/gcc-4.8.2
清除上次编译的文件:
rm -rf *
S
R
C
D
I
R
/
g
c
c
−
4.8.2
/
c
o
n
f
i
g
u
r
e
−
−
p
r
e
f
i
x
=
SRCDIR/gcc-4.8.2/configure --prefix=
SRCDIR/gcc−4.8.2/configure−−prefix=PREFIX --target=$TARGET --enable-shared --enable-languages=c,c++
make
sudo make install
完成之后,$PREFIX/bin下又多了几个文件:
arm-linux-c++*
arm-linux-g++*
这些生成的文件的作用分别为:
arm-linux-g++:GNU的c++编译器
arm-linux-c++:等同于arm-linux-g++
6.7 build gdb for arm
cd $SRCDIR
tar -pxjf gdb-7.6.1.tar.bz2
cd $BUILDDIR
mkdir gdb
cd gdb
$SRCDIR/gdb-7.6.1/configure --prefix=$PREFIX --target=$TARGET
make
sudo make install
6.8 创建交叉编译器可执行文件的链接
cd $PREFIX/bin
sudo ln -s arm-linux-gnueabi-addr2line arm-linux-addr2line
sudo ln -s arm-linux-gnueabi-ar arm-linux-ar
sudo ln -s arm-linux-gnueabi-as arm-linux-as
sudo ln -s arm-linux-gnueabi-c++ arm-linux-c++
sudo ln -s arm-linux-gnueabi-c++filt arm-linux-c++filt
sudo ln -s arm-linux-gnueabi-cpp arm-linux-cpp
sudo ln -s arm-linux-gnueabi-elfedit arm-linux-elfedit
sudo ln -s arm-linux-gnueabi-g++ arm-linux-g++
sudo ln -s arm-linux-gnueabi-gcc arm-linux-gcc
sudo ln -s arm-linux-gnueabi-gcc-4.6.3 arm-linux-gcc-4.6.3
sudo ln -s arm-linux-gnueabi-gcov arm-linux-gcov
sudo ln -s arm-linux-gnueabi-gdb arm-linux-gdb
sudo ln -s arm-linux-gnueabi-gdbtui arm-linux-gdbtui
sudo ln -s arm-linux-gnueabi-gprof arm-linux-gprof
sudo ln -s arm-linux-gnueabi-ld arm-linux-ld
sudo ln -s arm-linux-gnueabi-ld.bfd arm-linux-ld.bfd
sudo ln -s arm-linux-gnueabi-nm arm-linux-nm
sudo ln -s arm-linux-gnueabi-objcopy arm-linux-objcopy
sudo ln -s arm-linux-gnueabi-objdump arm-linux-objdump
sudo ln -s arm-linux-gnueabi-ranlib arm-linux-ranlib
sudo ln -s arm-linux-gnueabi-readelf arm-linux-readelf
sudo ln -s arm-linux-gnueabi-run arm-linux-run
sudo ln -s arm-linux-gnueabi-size arm-linux-size
sudo ln -s arm-linux-gnueabi-strings arm-linux-strings
sudo ln -s arm-linux-gnueabi-strip arm-linux-strip
6.9 设置环境变量
cd ~
vim .profile
```export PATH=$PATH:/usr/local/arm/4.8.2/bin
7 检验
新建一个源文件:hello.c
#include <stdio.h>
int main(int argc, char* argv[]) {
printf("hello\n");
return 0;
}
arm-linux-gcc -static hello.c -o hello
file hello
输出:
hello: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, for GNU/Linux 2.6.32, not stripped
表示初步检验成功。