本文使用linaro公司制作的交叉编译gcc源代码进行安装,那种制作好的交叉编译工具链安装不是咱的追求,不在学习范围。
网上有很多安装说明都是针对现成的工具链安装,而且语焉不详,很多问题没有讲解清楚。使用源码编译安装,会加深对构建系
统的理解,窥探更为深入的部分,过程中会出现各种各样让人意想不到的,奇奇怪怪的没有遇到过的问题,甚至让人崩溃想放弃的问题。如果你淌过去了,你就进步了,学习计算机底层的技术,特别是这种开放源代码的嵌入式技术,更是这么一个过程,所以学习是充满曲折的,但同时也是有趣的,促使人进步的。
       arm-linux-gnueabihf-gcc是由 Linaro 公司基于GCC推出的的ARM交叉编译工具。可用于交叉编译ARM系统中所有环节的代码,包括裸机程序、u-boot、Linux kernel、filesystem和App应用程序。因手上有一块三星S5PV210的板子,选择了一个较为老一点的linaro-gcc源码进行编译,具体对应的源代码可到linaro公司的官网进行下载。下载地址:
https://www.linaro.org/downloads/
有用的参考网址:
https://elinux.org/images/1/15/Anatomy_of_Cross-Compilation_Toolchains.pdf
https://preshing.com/20141119/how-to-build-a-gcc-cross-compiler/
特别是后面这个链接,按照它的步聚,虽然有些小问题,几乎能完成编译,非常的不错,本文也按照它的步聚完成了编译,请注意先后顺序。国内的文章还是太少,也缺少相应的开发氛围,很多小伙伴们编译一次必定耗费几天精力。
另外这儿貌似有个对它的编译的,翻译的不太清楚,可以参考一下。
https://blog.csdn.net/fickyou/article/details/51671006

1.  编译源码和构建环境
1.1 linaro-gcc 源代码:
gcc-linaro-arm-linux-gnueabihf-4.9-2014.07_linux.tar.xz 
这是一个源码包,在这个文章里的链接下载的
https://blog.csdn.net/kunkliu/article/details/79695829
选择源代码列表里面的
gcc-linaro-arm-linux-gnueabihf-4.9-2014.07_src.tar.bz2
解压方法:
tar -zd gcc-linaro-arm-linux-gnueabihf-4.9-2014.07_linux.tar.xz 
会出现.bz2后缀的文件,然后解压
tar -jxvf gcc-linaro-arm-linux-gnueabihf-4.9-2014.07_linux.tar.bz2
里面包括编译需要的所有部件的包,有些包可能用不着:
binutils-linaro-2.24.0-2014.07-1          expat-2.1.0                       linux-3.1.1
binutils-linaro-2.24.0-2014.07-1.tar.bz2  expat-2.1.0.tar.gz                linux-3.1.1.tar
binutils.setup.sh                         gcc-linaro-4.9-2014.07            md5sum
build-binutils                            gcc-linaro-4.9-2014.07.tar        mpc-0.9
build-eglibc                              gcc-setup.sh                      mpc-0.9.tar.gz
build-linaro-gcc                          gdb-linaro-7.6.1-2013.10          mpfr-3.1.0
build-scripts                             gdb-linaro-7.6.1-2013.10.tar.bz2  mpfr-3.1.0.tar
cloog-0.18.0                              gmp-5.0.2                         pkg-config-0.25
cloog-0.18.0.tar.gz                       gmp-5.0.2.tar.bz2                 pkg-config-0.25.tar.gz
compile-eglibc-setup.sh                   isl-0.11.1                        
eglibc-linaro-2.19-2014.07                isl-0.11.1.tar.bz2                zlib-1.2.5
eglibc-linaro-2.19-2014.07.tar.bz2        zlib-1.2.5.tar.gz
1.2 编译主机(cent os 64)
cat /proc/version 显示如下
Linux version 3.10.0-957.el7.x86_64 (mockbuild@kbuilder.bsys.centos.org) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-36) (GCC) ) 
1.3 安装目录:/usr/local/arm-linux
将路径/usr/local/arm-linux/bin 加入path中,否则后期出现各种ld找不到文件,明明文件就在那里,这是关键的一步,切勿忽略。
vi /etc/profile
最后加入
export PATH=/usr/local/arm-linux/bin:$PATH
source /etc/profile

2. 先安装几个必段库:
2.1 首先编译gmp
cd gmp-5.0.2
./configure --prefix=/usr/local/gmp-5.0.2
make 
make install
2.2 编译mpfr,依懒gmp
cd mpfr-3.1.0
./configure --prefix=/usr/local/mpfr-3.1.0 --with-gmp=/usr/local/gmp-5.0.2
make 
make install
2.3 编译mpc,依懒gmp,mpfr

2.4 编译isl,依懒gmp
./configure --prefix=/usr/local/isl-0.11.1 --with-gmp=/usr/local/gmp-5.0.2
make 
make install
2.5 编译cloog,依懒gmp.
./configure --prefix=/usr/local/cloog-0.18.0 --with-gmp=/usr/local/gmp-5.0.2
make 
make install
3. 编译binutils,用的是主机的gcc编译工具。
注意,为了避免一些未知的错误,新建一个目录单独编译:
mkdir build-binutils
假设build-binutils与binutils-linaro-2.24.0-2014.07-1源码目录同级
cd build-binutils,编写一个脚本,配置脚本setup.sh如下:
#!/bin/sh
../binutils-linaro-2.24.0-2014.07-1/configure --prefix=/usr/local/arm-linux \
--build=$MACHTYPE \
--target=arm-linux-gnueabihf    \
--enable-shared --disable-multilib

$MACHTYPE不能写成$(MACHTYPE)

chmod 777 setup.sh
./setup.sh
make 
make install

编译完成后有安装目录这几个目录:
/usr/local/arm-linux/
/usr/local/arm-linux/arm-linux-gnueabihf 
/usr/local/arm-linux/bin
/usr/local/arm-linux/share
>>arm-linux-gnueabihf:这是目标目录,这个设置为sysroot系统目录,目录下有bin和ib。
bin下有这几个文件:ar  as  ld  ld.bfd  ld.gold  nm  objcopy  objdump  ranlib  strip
/usr/local/arm-linux/arm-linux-gnueabihf/bin/ar  
/usr/local/arm-linux/arm-linux-gnueabihf/bin/as  
/usr/local/arm-linux/arm-linux-gnueabihf/bin/ld  
/usr/local/arm-linux/arm-linux-gnueabihf/bin/ld.bfd
/usr/local/arm-linux/arm-linux-gnueabihf/bin/ld.gold  
/usr/local/arm-linux/arm-linux-gnueabihf/bin/nm  
/usr/local/arm-linux/arm-linux-gnueabihf/bin/objcopy  
/usr/local/arm-linux/arm-linux-gnueabihf/bin/objdump  
/usr/local/arm-linux/arm-linux-gnueabihf/bin/ranlib  
/usr/local/arm-linux/arm-linux-gnueabihf/bin/strip
lib下面有这个目录:ldscripts,其下又有一推的文件。
/usr/local/arm-linux/arm-linux-gnueabihf/lib/ldscripts
>>bin下面,有一堆的交叉编译工具(18个文件):
arm-linux-gnueabihf-addr2line  arm-linux-gnueabihf-c++filt  arm-linux-gnueabihf-gprof   arm-linux-gnueabihf-ld.gold  arm-linux-gnueabihf-objdump  arm-linux-gnueabihf-size
arm-linux-gnueabihf-ar         arm-linux-gnueabihf-dwp      arm-linux-gnueabihf-ld      arm-linux-gnueabihf-nm       arm-linux-gnueabihf-ranlib   arm-linux-gnueabihf-strings
arm-linux-gnueabihf-as         arm-linux-gnueabihf-elfedit  arm-linux-gnueabihf-ld.bfd  arm-linux-gnueabihf-objcopy  arm-linux-gnueabihf-readelf  arm-linux-gnueabihf-strip
path:/usr/local/arm-linux/bin
这是用来编译新系统的工具。
>> share
一些帮助文档

4. 第一次编译gcc,注意gcc要分三步编译,这一步是生成c,c++交叉编译工具。
同样单独建一个目录编译
mkdir build-gcc 
假设build-gcc与gcc源码gcc-linaro-4.9-2014.07同级目录
cd build-gcc,编译脚本setup.sh如下
#!/bin/sh
../gcc-linaro-4.9-2014.07/configure --prefix=/usr/local/arm-linux \
--build=$MACHTYPE --target=arm-linux-gnueabihf --with-gmp=/usr/local/gmp-5.0.2 \
--with-mpfr=/usr/local/mpfr-3.1.0 --with-mpc=/usr/local/mpc-0.9 --with-isl=/usr/local/isl-0.11.1 \
--with-cloog=/usr/local/cloog-0.18.0 --disable-multilib \
--enable-languages=c,c++ --with-float=hard  

注意,这里其实是c,c++都是可以选的,有些文章说不能选c++,而且列了一大堆配置项,经实践,这样简单配置,c++也可以选择。
chmod 777 setup.sh
./setup.sh
$ make -j4 all-gcc
$ make install-gcc
注意以上操作,只编译安装gcc部分,否则不通过。

所以编译eglibc之前,一定要先执行第一步编译gcc,使用的是本机的gcc工具编译.

编译完成后,这个目录下多了这几个目录
include  lib  libexec
>> include:空目录
>> lib:目录结构如下:
lib/gcc
lib/gcc/arm-linux-gnueabihf
lib/gcc/arm-linux-gnueabihf/4.9.1
lib/gcc/arm-linux-gnueabihf/4.9.1/crtbegin.o
lib/gcc/arm-linux-gnueabihf/4.9.1/crtbeginS.o
lib/gcc/arm-linux-gnueabihf/4.9.1/crtbeginT.o  
lib/gcc/arm-linux-gnueabihf/4.9.1/crtend.o
lib/gcc/arm-linux-gnueabihf/4.9.1/crtendS.o
lib/gcc/arm-linux-gnueabihf/4.9.1/include
lib/gcc/arm-linux-gnueabihf/4.9.1/include-fixed
lib/gcc/arm-linux-gnueabihf/4.9.1/install-tools
lib/gcc/arm-linux-gnueabihf/4.9.1/libgcc.a
lib/gcc/arm-linux-gnueabihf/4.9.1/libgcov.a
lib/gcc/arm-linux-gnueabihf/4.9.1/plugin
>>libexec
/usr/local/arm-linux/libexec
/usr/local/arm-linux/libexec/gcc
/usr/local/arm-linux/libexec/gcc/arm-linux-gnueabihf
/usr/local/arm-linux/libexec/gcc/arm-linux-gnueabihf/4.9.1
/usr/local/arm-linux/libexec/gcc/arm-linux-gnueabihf/4.9.1/cc1
/usr/local/arm-linux/libexec/gcc/arm-linux-gnueabihf/4.9.1/collect2
/usr/local/arm-linux/libexec/gcc/arm-linux-gnueabihf/4.9.1/install-tools  
/usr/local/arm-linux/libexec/gcc/arm-linux-gnueabihf/4.9.1/liblto_plugin.la  
/usr/local/arm-linux/libexec/gcc/arm-linux-gnueabihf/4.9.1/liblto_plugin.so  
/usr/local/arm-linux/libexec/gcc/arm-linux-gnueabihf/4.9.1/liblto_plugin.so.0  
/usr/local/arm-linux/libexec/gcc/arm-linux-gnueabihf/4.9.1/liblto_plugin.so.0.0.0  
/usr/local/arm-linux/libexec/gcc/arm-linux-gnueabihf/4.9.1/lto1  
/usr/local/arm-linux/libexec/gcc/arm-linux-gnueabihf/4.9.1/lto-wrapper  
/usr/local/arm-linux/libexec/gcc/arm-linux-gnueabihf/4.9.1/plugin

>>同时
/usr/local/arm-linux/bin目示下多出来几个东西
/usr/local/arm-linux/bin/
共有如下文件
arm-linux-gnueabihf-addr2line  arm-linux-gnueabihf-cpp      arm-linux-gnueabihf-gcc-4.9.1   arm-linux-gnueabihf-gcov    arm-linux-gnueabihf-ld.gold  arm-linux-gnueabihf-ranlib   arm-linux-gnueabihf-strip
arm-linux-gnueabihf-ar         arm-linux-gnueabihf-dwp      arm-linux-gnueabihf-gcc-ar      arm-linux-gnueabihf-gprof   arm-linux-gnueabihf-nm       arm-linux-gnueabihf-readelf
arm-linux-gnueabihf-as         arm-linux-gnueabihf-elfedit  arm-linux-gnueabihf-gcc-nm      arm-linux-gnueabihf-ld      arm-linux-gnueabihf-objcopy  arm-linux-gnueabihf-size
arm-linux-gnueabihf-c++filt    arm-linux-gnueabihf-gcc      arm-linux-gnueabihf-gcc-ranlib  arm-linux-gnueabihf-ld.bfd  arm-linux-gnueabihf-objdump  arm-linux-gnueabihf-strings
和只编译binutils相比,25个文件,多出7个文件,分别是
arm-linux-gnueabihf-gcc-4.9.1
arm-linux-gnueabihf-cpp
arm-linux-gnueabihf-gcc-ar
arm-linux-gnueabihf-gcc-nm
arm-linux-gnueabihf-gcc-ranlib
arm-linux-gnueabihf-gcov
arm-linux-gnueabihf-gcc

5. 编译内核头,编译eglibc需要用到内核头,进入内核源代码目录,执行以下命令
cd linux-3.1.1
make ARCH=arm headers_check
make ARCH=arm INSTALL_HDR_PATH=/usr/local/arm-linux/arm-linux-gnueabihf headers_install

6. 第一次编译eglibc库,编译安装c库标准头文件和启动文件
同样,这一步新建一个目录编译安装,注意配置项build与host.
mkdir build-eglibc
假设build-eglibc与eglibc源码同级目录
cd build-eglibc,编译安装脚本setup.sh如下
#!/bin/sh
../eglibc-linaro-2.19-2014.07/configure \
--prefix=/usr/local/arm-linux/arm-linux-gnueabihf \
--build=$(MACHTYPE) \
--host=arm-linux-gnueabihf \
--target=arm-linux-gnueabihf \
--with-headers=/usr/local/arm-linux/arm-linux-gnueabihf/include \
libc_cv_forced_unwind=yes
注意,这里要指定内核头文件,即5步编译安装的内核头文件。
./setup.sh
执行安装脚本后,执行命令:
make install-bootstrap-headers=yes install-headers
make -j4 csu/subdir_lib
install csu/crt1.o csu/crti.o csu/crtn.o /usr/local/arm-linux/arm-linux-gnueabihf/lib
arm-linux-gnueabihf-gcc -nostdlib -nostartfiles -shared -x c /dev/null -o /usr/local/arm-linux/arm-linux-gnueabihf/lib/libc.so
touch /usr/local/arm-linux/arm-linux-gnueabihf/include/gnu/stubs.h

这里,创建了两个虚拟文件libc.so 和 stubs.h,也是第7步编译的需要,否则出找不到libc.so之类的错误,实则在第7步他们会被替换掉。

7. 第二次编译gcc生成编译eglibc所需要的编译器支持库,这一步使用的编译工具是使用第4步编译出来的,这一步会生成第8步编译所需要的库. 
cd build-gcc
make -j4 all-target-libgcc
make install-target-libgcc

8. 第二次编译eglibc库,生成c语言标准库
cd build-eglibc
make -j4
make install

9. 第三次编译gcc,生成c++语言标准
cd build-gcc
make -j4
make install

这一次,有可能会出现如下错误:
fatal error: sys/sdt.h: No such file or directory
在我的代码里面,出错位置如下:
gcc-linaro-4.9-2014.07/libstdc++-v3/libsupc++/unwind-cxx.h:41:21: fatal error: sys/sdt.h: No such file or directory
找了许久没有找到优雅的解决办法,最后我的解决办法为:
在主机查sdt.h这个文件,发现在位置:/usr/include/sys/sdt.h
打开unwind-cxx.h这个文件,其内容有如下一句:
#include <sys/sdt.h>
为了编译,将其改为绝对路径
#include</usr/include/sys/sdt.h>

再将编译,这一次编译成功并安装。

经过以上9步的操作,生成的交叉编译器,编译生成的程序在s5pv210的开发板上测试过通过。

10. 编译可能会遇到的错误,大多与编译参数设置不当造成的,错误可能千奇百性,很是让人崩溃。下面是一些遇到的错误及原因:
>> 编译eglibc库时,一定要另建一个文件夹来编译安装,也要先编译内核头,不然出现如下类似错误:
configure: WARNING: using cross tools not prefixed with host triplet
../sysdeps/unix/sysv/linux/recv.S:5:20: fatal error: socket.S: No such file or directory
 #include <socket.S>
>> 编译顺序不当造成的错误:
checking whether -lc should be explicitly linked in... no
checking dynamic linker characteristics... configure: error: Link tests are not allowed after GCC_NO_EXECUTABLES.
make[1]: *** [configure-zlib] Error 1
>> 修改配置脚本后引起的错误,清空构建目录重新执行配置脚本
configure: error: `target_alias' has changed since the previous run:
configure: former value: i686-pc-linux-gnu
configure: current value: i386-rtems
configure: error: changes in the environment can compromise the build
configure: error: run `make distclean' and/or `rm ./config.cache' and start over
>> 配置主机和构建项不当造成的错误:
configure: error: cannot compute suffix of object files: cannot compile
注意build,host,target项的设置。


  

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐