构建gcc交叉编译工具链

如何构建一个GCC交叉编译工具链

GCC不仅是一个编译器,它是一个开源工程,可以让你建立各种编译器。一些编译器支持多线程,一些支持共享库,一些支持Multilib(典型的应用是在64位机上运行32位应用程序),这些都取决于在编译 编译器 时的配置。

本文档将说明怎么建立一个交叉编译器。你需要一个已经安装gccUnix-like环境。

 

一、需要的包

Debian系统,首先需要安装一些包

$ sudo apt-get install g++ make gawk

其他的包将使用源代码来编译。在根文件系统的某个地方新建一个文件夹,下载下面的包。本文是2014年写的,你看到时,可能有更新的包可以使用,所以你可以使用更新的包。

$ wget http://ftpmirror.gnu.org/binutils/binutils-2.24.tar.gz

$ wget http://ftpmirror.gnu.org/gcc/gcc-4.9.2/gcc-4.9.2.tar.gz

$ wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.17.2.tar.xz

$ wget http://ftpmirror.gnu.org/glibc/glibc-2.20.tar.xz

$ wget http://ftpmirror.gnu.org/mpfr/mpfr-3.1.2.tar.xz

$ wget http://ftpmirror.gnu.org/gmp/gmp-6.0.0a.tar.xz

$ wget http://ftpmirror.gnu.org/mpc/mpc-1.0.2.tar.gz

$ wget ftp://gcc.gnu.org/pub/gcc/infrastructure/isl-0.12.2.tar.bz2

$ wget ftp://gcc.gnu.org/pub/gcc/infrastructure/cloog-0.18.1.tar.gz

最开始的四个包:binutilsgccLinux kernelglibc是主要要用的包。后面三个mpfrgmpmpc你可以使用系统自带的package manager安装,但是可能比较旧。最后两个包ISLCLooG是可选的,它们支持一些优化。

 

二、它们是怎么有机结合在一起的呢?

当我们完成时,我们会构建如下的程序和库。首先,构建左边的工具,然后使用这些工具来构建右边的程序和库。我们将不构建目标系统的Linux kernel,但是我们需要kernel header来构建目标系统标准C库。

左边的编译器将调用汇编器和链接器。其他的包MPFRGMPMPC将连接到编译器中。

右边图中的a.out,运行在目标OS上,使用交叉编译器,连接目标系统标准C库和C++库。C++标准库调用标准C库,C库直接调用Linux kernel

注意,除了使用glibc外,还可以使用其他替代的C库实现,比如Newlibcuclibc等,其他替代的C库用在嵌入式中较多,比glibc库要小,功能没有glibc全面。

 

三、构建步骤

解压所有的包。

$ for f in *.tar*; do tar xf $f; done

创建一些其他目录的符号连接,这5个包依附于gcc,如果存在符号连接,gcc脚本将自动build这些包。

$ cd gcc-4.9.2

$ ln -s ../mpfr-3.1.2 mpfr

$ ln -s ../gmp-6.0.0 gmp

$ ln -s ../mpc-1.0.2 mpc

$ ln -s ../isl-0.12.2 isl

$ ln -s ../cloog-0.18.1 cloog

$ cd ..

选择一个安装路径,确保有写的权限。下面步骤中,我将安装新的工具链到/opt/cross

$ sudo mkdir -p /opt/cross

$ sudo chown jeff /opt/cross

整个构建过程中,确保安装的bin子目录在你的PATH环境变量中。后续你可以从PATH中移除该目录,但是大部分构建步骤将会默认通过PATH来查找aarch64-linux-gcc和其他host工具。

$ export PATH=/opt/cross/bin:$PATH

注意/opt/cross/aarch64-linux/目录下的文件。该目录被认为是虚拟的aarch64 linux目标系统的根目录。理论上,可以使用里面所有的头文件和库。

 

1. Binutils

构建binutils、安装交叉汇编器、链接器和其他工具的步骤:

$ mkdir build-binutils

$ cd build-binutils

$ ../binutils-2.24/configure --prefix=/opt/cross --target=aarch64-linux --disable-multilib

$ make -j4

$ make install

$ cd ..

我们制定aarch64-linux作为目标系统类型,binutils的配置脚本将识别到它与正在进行编译的主机系统不一样,配置一个交叉汇编器和交叉链接器。这些工具将安装到/opt/cross/bin,名字以arm-linux-开头。

--disable-multilib意味着我们只希望我们的程序和库使用aarch64指令集,而不使用aarch32的指令集。

 

2. Linux Kernel Headers

Linux kernel 头文件安装到/opt/cross/aarch64-linux/include, 使用新工具链构建的程序会调用这些目标环境中的aarch64 kernel

$ cd linux-3.17.2

$ make ARCH=arm64 INSTALL_HDR_PATH=/opt/cross/aarch64-linux headers_install

$ cd ..

我们也可以在构建binutils之前做这件事。

尽管第4步,configure脚本期望linux kernel header依据安装,但是实际上在步骤6之前,当我们编译标准C库时,linux kernel headers不会被用到。

因为Linux kernel和其他开源工程不一样,它有一个不同的方式来识别目标CPU架构: ARCH=arm

剩下的步骤涉及构建GCCGlibc。这里有个道道,就是部分gcc需要部分glibc被构建,而部分glibc又需要gcc被构建。我们不能一步搞定这些编译,而是要分成几步。我们要这几个包之间来往几次。


3. C/C++ Compilers

该步将构建gccCC++编译器,并安装到/opt/cross/bin,目前还不能引用这些编译器来构建库。

$ mkdir -p build-gcc

$ cd build-gcc

$ ../gcc-4.9.2/configure --prefix=/opt/cross --target=aarch64-linux --enable-languages=c,c++ --disable-multilib

$ make -j4 all-gcc

$ make install-gcc

$ cd ..

因为我们指定了--target=aarch64-linux,构建脚本会依据aarch64-linux-前缀查找第一步安装的binutils工具。同样,C/C++编译器的名字也会带上aarch64-linux-前缀。

--enable-languages=c,c++避免了在GCC套件中出现其他的编译器,比如FortranJava等。

 

4. Standard C Library Headers and Startup Files

安装标准C库头文件到/opt/cross/aarch64-linux/include。我们会使用第三步构建的C编译器来编译库的startup files并安装到/opt/cross/aarch64-linux/lib。最后我们创建几个傀儡文件,libc.sostubs.h,在第5步会用到,但是第6步会替换为真的。

$ mkdir -p build-glibc

$ cd build-glibc

$ ../glibc-2.20/configure --prefix=/opt/cross/aarch64-linux --build=$MACHTYPE --host=aarch64-linux --target=aarch64-linux --with-headers=/opt/cross/aarch64-linux/include --disable-multilib libc_cv_forced_unwind=yes

$ make install-bootstrap-headers=yes install-headers

$ make -j4 csu/subdir_lib

$ install csu/crt1.o csu/crti.o csu/crtn.o /opt/cross/aarch64-linux/lib

$ aarch64-linux-gcc -nostdlib -nostartfiles -shared -x c /dev/null -o /opt/cross/aarch64-linux/lib/libc.so

$ touch /opt/cross/aarch64-linux/include/gnu/stubs.h

$ cd ..

--prefix=/opt/cross/aarch64-linux告诉configure脚本它要安装头文件和库到这里。注意这个和普通的--prefix

Glibcconfigure需要我们制定所有的--build--host--target系统类型。

$MACHTYPE是一个预定义的环境变量,表示正在运行build脚本的机器。--build=$MACHTYPE是必须的,因为在第六步中,该build脚本将编译一些额外的工具,这些工具是build进程的一部分。

--host,在glibcconfigure中,--host--target选项都指glibc库最终运行的系统。

我们手动安装Cstartup文件,ctr1.o ctri.octrn.o。其他的方法好像都有副作用。

 

5. Compiler Support Library

使用第三步的交叉编译器构建compiler support library,编译器支持的库包含一些C++异常处理样板代码等等。该库依赖第四步安装的startup file。第六步需要该库。不像其他的指导手册,我们不需要重新运行gcc configure。只需要在相同配置下构建额外的target即可。

$ cd build-gcc

$ make -j4 all-target-libgcc

$ make install-target-libgcc

$ cd ..

两个静态库,libgcc.alibgcc_eh.a,安装到/opt/cross/lib/gcc/aarch64-linux/4.9.2.

共享库,lingcc_s.so,安装到/opt/cross/aarch64-linux/lib64.

 

6. Standard C Library

这步完成glibc的安装。安装标准C库到/opt/cross/aarch64-linux/lib中。静态库名字为libc.a,动态库为libc.so

$ cd build-glibc

$ make -j4

$ make install

$ cd ..

 

7. Standard C++ Library

最后完成gcc的安装,构建标准C++库,安装到/opt/cross/aarch64-linux/lib64。它依赖第六步的C库。目标静态库名字为libstdc++.a,动态库为libstdc++.so

$ cd build-gcc

$ make -j4

$ make install

$ cd ..

 

 

How to Build a GCC Cross-Compiler

http://preshing.com/20141119/how-to-build-a-gcc-cross-compiler/

 

 

 

 

 

 

  • 2
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值