如何构建GCC交叉编译器

GCC不仅仅是一个编译器。它是一个开源项目,可以让你构建各种编译器。有些编译器支持多线程;一些支持共享库;一些支持multilib。这完全取决于在构建编译器之前如何配置它。
本指南将演示如何构建交叉编译器,交叉编译器是为另一台机器构建程序的编译器。您所需要的只是一个类unix环境,其中已经安装了GCC的最新版本。

在本指南中,我将使用Debian Linux为AGARC64构建一个完整的C++交叉编译器,这是一个64位的指令集,可在最新的ARM处理器中使用。我实际上没有AArch64设备——我只是想要一个AArch64编译器来验证这个bug。
必需的程序包
从一个干净的Debian系统开始,您必须首先安装几个软件包:

$ sudo apt-get install g++ make gawk

其他一切都将从源头构建。在某处创建一个新目录,并下载以下源包。(如果您以后遵循这个指南,每个包都会有更最新的版本。通过将每个URL粘贴到浏览器中而不带文件名来检查更新版本。例如: http://ftpmirror.gnu.org/binutils/)

$ 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

前四个包(Binutils, GCC、Linux内核和Glibc)是主要的。我们本可以使用系统的包管理器以二进制形式安装接下来的三个包,但这往往会提供较旧的版本。最后两个包,ISL 和CLooG,是可选的,但是它们可以在我们将要构建的编译器中进行更多的优化。
各部分如何组合在一起
当我们完成的时候,我们已经建立了下面的每个程序和库。首先,我们将构建左侧的工具,然后使用这些工具构建右侧的程序和库。我们实际上不会构建目标系统的Linux内核,但是我们确实需要内核头文件来构建目标系统的标准C库。

左边的编译器将调用汇编器和链接器作为其工作的一部分。我们下载的所有其他包,如MPFR、GMP和MPC,都将链接到编译器本身。
右边的图表代表了在目标操作系统上运行的示例程序a.out,它使用交叉编译器构建,并与目标系统的标准C和c++库相链接。标准c++库调用标准C库,C库直接对AArch64 Linux内核进行系统调用。
注意,与使用Glibc作为标准C库实现不同,我们可以使用Newlib,这是另一种实现。Newlib是嵌入式设备的一个流行的C库实现。与Glibc不同,Newlib不需要目标系统上有一个完整的操作系统——只需要一个名为Libgloss的瘦硬件抽象层。Newlib没有定期发布;相反,您应该直接从Newlib CVS存储库中提取源代码。Newlib的一个限制是,目前它似乎不支持为AArch64构建多线程程序。这就是为什么我在这里不使用它的原因。
构建步骤
提取所有源程序包。

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

创建从GCC目录到其他一些目录的符号链接。这五个包是GCC的依赖项,当符号链接出现时,GCC的构建脚本将自动构建它们。

$ 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找到aarch64-linux-gcc和其他主机工具。

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

请特别注意安装在/opt/cross/aarch64-linux/下的内容。此目录被认为是虚构的AArch64 Linux目标系统的系统根。理论上,自托管的AArch64 Linux编译器可以使用此处放置的所有头文件和库。显然,为主机系统构建的程序(如交叉编译器本身)都不会安装到此目录中。

  1. 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的 configure 脚本会认识到这个目标与我们所构建的机器不同,并因此配置一个交叉汇编器和交叉链接器。这些工具将被安装到/opt/cross/bin目录下,它们的名字前缀为aarch64-linux-。
• --disable-multilib 意味着我们只希望我们的Binutils安装使用AArch64指令集的程序和库,而不是任何相关指令集,如AArch32。
2. Linux内核头文件
这个步骤将Linux内核头文件安装到/opt/cross/aarch64-linux/include,这将最终允许使用我们的新工具链构建的程序在目标环境中对AArch64内核进行系统调用。

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

•我们甚至可以在安装Binutils之前完成此操作。
•Linux内核头文件直到第6步(我们构建标准C库时)才会真正使用,尽管第4步中的configure脚本预计它们已经安装。
•因为Linux内核是一个不同于其他内核的开源项目,所以它有一种不同的方法来识别目标CPU体系结构:ARCH=arm64
剩下的所有步骤都涉及到构建GCC和Glibc。关键在于GCC的某些部分依赖于Glibc的某些部分,反之亦然。我们不能在一个步骤中构建任何一个包;我们需要在两个包之间来回切换,以满足它们的依赖关系的方式构建它们的组件。

3.C / c++编译器
这一步将只构建GCC的C和c++交叉编译器,并将它们安装到/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,构建脚本会查找我们在步骤1中构建的以aarch64-linux-前缀命名的Binutils交叉工具。同样,C/C++编译器的名称将以aarch64-linux-作为前缀。
•–enable-languages=c,c++阻止GCC套件中的其他编译器,如Fortran, Go或Java被构建。
4. 标准C库头文件和启动文件
在这一步中,我们将Glibc的标准C库头文件安装到/opt/cross/aarch64-linux/include。我们还使用步骤3中内置的C编译器来编译库的启动文件,并将它们安装到/opt/cross/aarch64-linux/lib。最后,我们创建两个dummy文件libc.so 和 stubs.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 告诉Glibc的configure脚本,它应该在哪里安装头和库。注意,它与通常的–prefix不同。
•尽管有一些矛盾的信息,Glibc的configure 脚本目前要求我们指定所有三种类型–build, --host 和 --target系统类型。
•MACHTYPE是一个预定义的环境变量,它描述运行构建脚本的计算机−−build=MACHTYPE是一个预定义的环境变量,它描述运行构建脚本的计算机 --build=MACHTYPE是一个预定义的环境变量,它描述运行构建脚本的计算机−−build=MACHTYPE是必需的,因为在步骤6中,构建脚本将编译一些作为构建过程本身一部分运行的其他工具。
•–host在这里的意义与我们迄今为止使用的不同。在Glibc的配置中,–host和–target选项都用来描述Glibc库最终运行的系统。
•我们手动将C库的启动文件crt1.o、crti.o和crtn.o安装到安装目录。似乎没有一个规则在没有其他副作用的情况下做到这一点。
5.编译器支持库
此步骤使用步骤3中构建的交叉编译器来构建编译器支持库。编译器支持库包含一些C++异常处理样板代码,等等。此库取决于步骤4中安装的启动文件。步骤6中需要库本身。与其他指南不同,我们不需要重新运行GCC的配置。我们只是在同一配置中构建额外的目标。

$ cd build-gcc
$ make -j4 all-target-libgcc
$ make install-target-libgcc
$ cd ..

•在/opt/cross/lib/gcc/aarch64-linux/4.9.2/中安装了两个静态库libgcc.a 和 libgcc_eh.a。
•共享库libgcc_s.so安装到/opt/cross/aarch64-linux/lib64。
6.标准C库
在这一步中,我们完成了Glibc包,它构建了标准C库并将其文件安装到 /opt/cross/aarch64-linux/lib/。静态库名为libc.a,共享库名为libc.so。

$ cd build-glibc
$ make -j4
$ make install
$ cd ..

7、标准C++库
最后,我们完成了GCC包,它构建了标准的C++库并安装到/opt/cross/aarch64-linux/lib64/。它取决于步骤6中构建的C库。生成的静态库名为libstdc++.a,共享库为 libstdc++.so。

$ cd build-gcc
$ make -j4
$ make install
$ cd ..

处理构建错误
如果在构建过程中遇到任何错误,有三种可能:

  1. 您在构建系统中缺少一个必需的包或工具。
  2. 您试图以不正确的顺序执行构建步骤。
  3. 您所做的一切都是正确的,但是在您试图构建的配置中有一些东西被破坏了。
    您必须检查构建日志以确定哪种情况适用。GCC支持很多配置,其中一些可能不会立即构建。一个配置越不受欢迎,它被破坏的可能性就越大。作为一个开源项目,GCC依赖于其用户的贡献来保持每个配置工作。
    自动化上述步骤
    我已经编写了一个名为build_cross_gcc的小型bash脚本来执行上述所有步骤。你可以在GitHub上找到它。在我的Core 2 Quad Q9550 Debian机器上,从开始到结束需要13分钟。在跑步前根据自己的喜好定制。

build_cross_gcc也支持Newlib配置。当您构建基于newlib的交叉编译器时,上面的步骤4、5和6可以合并为一个单独的步骤。(事实上,许多现有指南都是这样做的。)为了支持Newlib,编辑脚本选项如下:

TARGET=aarch64-elf
USE_NEWLIB=1
CONFIGURATION_OPTIONS="--disable-multilib --disable-threads"

构建GCC交叉编译器的另一种方法是使用组合树,其中Binutils, GCC和Newlib的源代码被合并到单个目录中。只有当GCC和Binutils捆绑的intl和lilibty库相同时,组合树才能工作,而本文使用的版本不是这样的。组合树也不支持Glibc,所以它不适合这种配置。
有一些流行的构建脚本,即crosstool-NG 和 EmbToolkit,它们可以自动构建交叉编译器的整个过程。我使用crosstool-NG得到了混合的结果,但是它帮助我在编写本指南时理解构建过程。
测试交叉编译器
如果一切构建成功,让我们检查交叉编译器是否有拨码音:

$ aarch64-linux-g++ -v
Using built-in specs.
COLLECT_GCC=aarch64-linux-g++
COLLECT_LTO_WRAPPER=/opt/cross/libexec/gcc/aarch64-linux/4.9.2/lto-wrapper
Target: aarch64-linux
Configured with: ../gcc-4.9.2/configure --prefix=/opt/cross --target=aarch64-linux --enable-languages=c,c++ --disable-multilib
Thread model: posix
gcc version 4.9.2 (GCC)

我们可以从前面的帖子编译C++ 14程序,然后分解它:

$ aarch64-linux-g++ -std=c++14 test.cpp
$ aarch64-linux-objdump -d a.out
...
0000000000400830 <main>:400830:       a9be7bfd        stp     x29, x30, [sp,#-32]!400834:       910003fd        mov     x29, sp400838:       910063a2        add     x2, x29, #0x1840083c:       90000000        adrp    x0, 400000 <_init-0x618>...

这是我第一次尝试构建交叉编译器。我写这个指南基本上是为了记住我学到的东西。我认为上面的步骤可以作为构建其他配置的一个很好的模板;我也使用build_cross_gcc来构建TARGET=powerpc-eabi。您可以从任何包中浏览 config.sub ,以查看支持哪些其他目标环境。

如何构建GCC交叉编译器相关推荐

  1. vxworks gcc linux,针对VxWorks的GCC交叉编译器无法编译C++

    我试图移植Linux库以在VxWorks上运行.我已经成功构建了binutils和gcc,目标为i486-wrs-vxworks,我可以成功构建一个简单的C程序.但是,当我尝试编译C++时,事情就会中 ...

  2. linux交叉编译出现的问题,,Ubuntu 14.10下安装GCC交叉编译器遇到问题及解决方法

    Ubuntu 14.10下安装GCC交叉编译器遇到问题及解决方法 一.下载gcc-arm-none-eabi-4_9 安装成功后上报错误: ./gcc-arm-none-linux-gnueabi-g ...

  3. 2019-11-07 检查gcc交叉编译器预定义宏(ARM32/ARM64/X86-64)以及对浮点数的支持情况

    预备知识1 armel.armhf和arm64区别选择 https://www.veryarm.com/872.html 预备知识2 https://www.veryarm.com/872.html ...

  4. armgcc交叉编译的文件无法运行_认识GCC交叉编译器

    一.GCC 简介 GCC(GNU Compiler Collection)是一套功能强大.性能优越的编程语言编译器,它是GNU计划的代表作品之一.GCC 是 Linux 平台下最常用的编译器,GCC ...

  5. linux下mips裸机编译,裸机交叉编译器输入

    裸机交叉编译器的输入限制是什么-因为它不编译带有指针或mallocs的程序-或任何需要比底层硬件更多的东西-.还有1如何找到这些局限性.. 我还想问一下-我为目标mips构建了交叉编译器..我需要使用 ...

  6. linux交叉编译 windows,从Windows到Linux的C ++交叉编译器

    慕码人8056858 crosstool-ng支持使用cygwin host构建交叉编译器.概述:使用开发包安装cygwin下载 crosstool-ng提取压缩包(tar xvjf crosstoo ...

  7. powerpc linux交叉编译器,[转载]搭建PowerPC交叉编译器 二

    第三部分 搭建过程 3.1 创建过程概述 这个GUN工具链的创建过程可以分为5步 Step 1:安装基于PowerPC的linux头文件: 备注:创建头文件是编译库文件所必须的,这一步只要在创建gli ...

  8. W5300E01-ARM 交叉编译器(Cross Compiler)用户手册

    W5300E01-ARM是基于W5300的ARM功能测试评估板: 1      简介 当用户的开发环境与目标系统不同时就会用到交叉编译器. 例如,当开发基于ARM的嵌入式系统时,用户就需要在电脑上写出 ...

  9. iTOP4412交叉编译器构建

    嵌入式开发离不开交叉编译器,虽然也可以从网上下载交叉编译器,但是有时需要构建属于自己配置的交叉编译器.下面将讲解如何用crosstool-ng构建自己的交叉编译工具链,可以参考http://cross ...

  10. 交叉编译器的命名规则及详细解释(arm/gnu/none/linux/eabi/eabihf/gcc/g++)

    在linux系统下搞嵌入式开发,交叉编译器那肯定是必备工具.用的场合多了,就会见到各种各样的编译工具,比如: arm-linux-gcc arm-linux-gnueabi-gcc arm-none- ...

最新文章

  1. SQL与NoSQL区别-查询方式
  2. oracle报错无效列类型,jooq oracle存储过程与ARRAY,无效列类型:1111
  3. 数据结构——链式队列解析(C语言版)
  4. LeetCode【11--盛水最多的容器】LeetCode【12 -- 整数转罗马数字】
  5. ORA-01830:日期格式图片在转换整个输入字符之前结束
  6. labelImg标注工具(win10安装)
  7. 2019数据安装勾选_Solidworks 2019安装包免费下载附安装教程
  8. 线性回归介绍之十——多因素分析策略
  9. 【JZOJ】 【NOIP2014】【模拟试题】保镖排队
  10. 如何彻底对chrome降级
  11. 人性深处的探究与还原-《少年派的奇幻漂流》的四个故事
  12. 关于npm i 的那点事
  13. 幼儿剑桥英音版Super Safari123级别学生书PDF+练习册PDF+教师书PDF+白板课件
  14. 1399元千元真旗舰,360手机N5“能耐”在哪?
  15. 按行遍历和按列遍历哪一个更快一些?
  16. 在cmd中怎么进入mysql?
  17. 2021四川省资阳市高考成绩查询,2021资阳中考查询系统
  18. pandas数据分析模块(二)
  19. 超乎想象!关于5G无人机的最强科普!
  20. 引入PageHelper.startPage(pageNum,pageSize);后报错

热门文章

  1. 禾川Q1系列PLC官方教程
  2. ubuntu16.04安装搭建RED5流媒体服务器
  3. 计算机网络自顶向下方法 第六章 复习题答案
  4. jflash添加芯片_Jflash用于烧录
  5. Linux下编译DCMTK,ACE问题记录
  6. Filenet 周报丨2020.01.06-2020.01.19
  7. JSP内置对象out对象的功能简介说明
  8. T100服务端接口开发步骤
  9. java如何把汉字转换成机内码_如何用java随机生成一个汉字?
  10. 车标识别 深度学习车标识别 cnn车标识别 神经网络车标识别 常见汽车车标识别 yolo算法 效果棒