首页 > 其他分享 >交叉编译工具链构建原理

交叉编译工具链构建原理

时间:2024-03-14 15:36:17浏览次数:21  
标签:需要 头文件 交叉 编译 编译器 构建 工具 binutils

交叉编译工具链构建原理

这是与弗朗西斯科·图尔科(Francesco Turco)讨论的结果

弗朗西斯科为初学者提供了一个很好的教程(死链,Wayback机器没有存档版本),以及一个示例,从x86_64 Debian主机为ARM目标构建工具链的分步过程。

谢谢弗朗西斯科发起这个活动!

我想要一个交叉编译器!你说的这个工具链是什么?

交叉编译器实际上是不同工具的集合,这些工具被设置为紧密地协同工作。这些工具以某种级联方式链接在一起,其中一个工具的输出成为另一个工具的输入,最终产生在机器上运行的实际二进制代码。因此,我们称这种安排为“工具链”。当工具链要为运行它的机器之外的机器生成代码时,这被称为交叉工具链。

那么,工具链中的组件是什么?

在工具链中起作用的组件首先是编译器本身。编译器将源代码(用C、C++等语言)转换成汇编代码。选择的编译器是GNU编译器集合,众所周知的gcc

汇编程序解释汇编代码以生成目标代码。这是由二进制实用程序完成的,如GNU binutils。

一旦生成了不同的目标代码文件,它们就会聚集在一起形成最终的可执行二进制文件。这称为链接,通过使用链接器来实现。GNU binutils还附带了一个链接器。

到目前为止,我们得到了一个完整的工具链,能够将源代码转化为实际的可执行代码。根据目标上运行的操作系统,我们还需要C库。C库提供了一个执行基本任务的标准抽象层(例如分配内存、在终端上打印输出、管理文件访问……)。有许多C库,每个都针对不同的系统。对于Linux桌面,有glibceglibc甚至uClibc,对于嵌入式Linux,您可以选择eglibcuClibc,而对于没有操作系统的系统,您可以使用newlibdietlibc,甚至根本不使用。还有一些其他的C库,但它们没有被广泛使用,并且/或者是针对非常特殊的需求(例如,klibc是C库的一个非常小的子集,旨在构建受约束的初始ramdisks)。

在Linux下,C库需要知道内核的API,以决定存在什么特性,如果需要的话,为缺失的特性包含什么模拟。该API由内核头文件提供。注意:这是特定于Linux的(可能还有极少数其他操作系统),其他操作系统上的C库不需要内核头文件。

现在,所有这些组件是如何连接在一起的?

到目前为止,已经涵盖了所有主要组件,但它们需要按照特定的顺序构建。从我们最终要使用的编译器开始,我们可以看到依赖关系是什么。我们称该编译器为最终编译器

  • 最终的编译器需要C库来知道如何使用它,但是:
  • 构建C库需要编译器

A需要B,B需要A .这是典型的先有鸡还是先有蛋的问题……这可以通过构建一个精简的编译器来解决该编译器不需要C库,但能够构建C库。我们称之为引导初始核心编译器。这是新的依赖列表:

  • 最终的编译器需要C库来知道如何使用它
  • 构建C库需要核心编译器,但是:
  • 核心编译器需要C库头文件和启动文件来知道如何使用C库

B需要C,C需要B .又是先有鸡还是先有蛋。为了解决这个问题,我们需要构建一个只安装头文件和启动文件的C库启动文件(也称为C运行时CRT)是gcc需要在NPTL系统上启用线程本地存储(TLS)的极少数文件。所以现在我们有:

  • 最终的编译器需要C库来知道如何使用它
  • 构建C库需要一个核心编译器
  • 核心编译器需要C库头文件和启动文件来了解如何使用C库,但是:
  • 构建启动文件需要编译器

天啊… C需要D,D又需要C。因此我们需要构建一个更简单的编译器,它不需要头文件,但需要启动文件。这个编译器也是一个引导、初始或核心编译器。为了区分两个核心编译器,我们称之为一个核心通道1(core pass 1),而前者为一个核心通道2(core pass 2)。依赖性列表变成:

  • 最终的编译器需要C库来知道如何使用它
  • 构建C库需要编译器
  • 核心通道2编译器需要C库头文件和启动文件来了解如何使用C库
  • 构建启动文件需要编译器
  • 我们需要一个核心通道1编译器

正如我们前面所说的,C库也需要内核头文件。对内核头没有要求,所以在这种情况下故事结束了:

  • 最终的编译器需要C库来知道如何使用它
  • 构建C库需要一个核心编译器
  • 核心通道2编译器需要C库头文件和启动文件来了解如何使用C库
  • 构建启动文件需要编译器和内核头文件
  • 我们需要一个核心通道1编译器

我们需要增加一些新的要求。当我们为目标编译代码时,我们需要汇编程序和链接程序。当然,这样的代码是从C库构建的,所以我们需要在C库启动文件之前构建binutils,以及完整的C库本身。此外,gcc中的一些代码也将转而在目标上运行。幸运的是,对binutils没有要求。因此,我们的依赖链如下:

  • 最终的编译器需要C库来知道如何使用它,还需要binutils
  • 构建C库需要核心通道2编译器和binutils
  • 核心通道2编译器需要C库头文件和启动文件,以了解如何使用C库和binutils
  • 构建启动文件需要编译器、内核头文件和binutils
  • 核心通道1编译器需要binutils

依次构建组件:

  1. binutils
  2. 核心通道1编译器
  3. 内核头文件
  4. c库头文件和启动文件
  5. 核心通道2编译器
  6. 完整的C库
  7. 最终编译器

是啊!:-)但是我们结束了吗?

事实上,不是的,仍然有缺失的依赖项。就工具本身而言,我们不需要任何其他东西。

但是gcc有一些先决条件。它依靠一些外部库来执行一些重要的任务(比如处理常数中的复数……)。构建这些库有几种选择。首先,人们可能会认为依靠Linux发行版来提供这些库。唉,直到最近,它们才被广泛使用。因此,如果发行版不是太新的话,我们很有可能必须构建这些库(我们将在下面进行构建)。受影响的库包括:

  • GNU多精度算术库——GMP(GNU Multiple Precision Arithmetic Library);
  • 具有正确舍入的多精度浮点计算的C库——MPFR(Multiple-Precision Floating-point-computations with correct Rounding);
  • 复数算术的C语言库——MPC。

这些库的依赖关系如下:

  1. MPC需要GMP和MPFR
  2. MPFR需要GMP
  3. GMP没有先决条件

因此,构建顺序变为:

  1. GMP
  2. MPFR
  3. MPC
  4. binutils
  5. 核心通道1编译器
  6. 内核头文件
  7. C库头文件和启动文件
  8. 核心通道2编译器
  9. 完整的C库
  10. 最终编译器

是啊!或者更多?

这足以构建一个功能工具链。所以如果你现在已经受够了,你可以到此为止。或者如果你很好奇,你可以继续阅读。

gcc还可以利用其他一些外部库。这些额外的可选库用于启用gcc中的高级功能,如循环优化(GRAPHITE)链路时间优化(LTO, Link Time Optimisation)。如果要使用这些库,您需要另外三个库:

要启用GRAPHITE,根据GCC版本,可能需要以下一项或多项:

  1. PPL, Parma多面体库;
  2. ISL, 整数集库;
  3. CLooG/PPL, 使用PPL后端的Chunky循环生成器;
  4. CLooG, 使用ISL后端的Chunky循环生成器。

要启用LTO:-ELF对象文件访问库,libelf

这些库的依赖关系如下:

  1. PPL要求GMP
  2. CLooG/PPL需要GMP和PPL或ISL之一;
  3. ISL没有先决条件;
  4. libelf没有先决条件。

列表现在看起来像这样:

  1. GMP
  2. MPFR
  3. MPC
  4. CLooG/PPL(如果需要)
  5. ISL(如果需要)
  6. libelf(如果需要)
  7. binutils
  8. 核心通道1编译器
  9. 内核头文件
  10. C库头文件和启动文件
  11. 核心通道2编译器
  12. 完整的C库
  13. 最终编译器

这个列表现在已经完成了!哇哦!或者是?

但是为什么crosstool-NG的步骤更多呢?

从理论的角度来看,已经制定的十三个步骤是必要的步骤。然而在现实中,还是有一些小的不同。crosstool-NG中的额外步骤有三个不同的原因。

第一,GNU binutils不支持某些类型的输出。用binutils生成平面二进制文件是不可能的,所以我们必须使用另一个添加了这种支持的组件: elf2flt。elf2flt还需要zlib压缩库-如果我们正在构建加拿大的或跨本地的工具链,我们可能无法使用主机的zlib。

第二,工具链的本地化需要一些主机操作系统上的附加库: gettextlibiconv

第三,crosstool-NG还可以构建一些额外的调试实用程序在目标上运行。这是我们构建的地方,例如,cross-gdbgdbserver和原生gdb(最后两个在目标上运行,第一个在工具链所在的机器上运行)。其他工具(straceltraceDUMAdmalloc)与工具链完全无关,但在开发时非常有用,因此作为好东西包含在内(它们很容易构建,所以没问题;更复杂的东西不值得包含在crosstool-NG中)。

标签:需要,头文件,交叉,编译,编译器,构建,工具,binutils
From: https://www.cnblogs.com/hencins/p/18072938

相关文章

  • 【 React 】React 构建组件的方式有哪些?区别?
    1.组件是什么组件就是把图形、非图形的各种逻辑均抽象为一个统一的概念(组件)来实现开发的模式在React中,一个类、一个函数都可以视为一个组件降低整个系统的耦合度,在保持接口不变的情况下,我们可以替换不同的组件快速完成需求,例如输入框,可以替换为日历、时间、范围等组件......
  • 交叉编译之opencv-4.1.1
    编译环境:ubuntu22.04;编译工具CMake一、资料下载   opencv-4.1.1:https://github.com/opencv/opencv/archive/4.1.1.zip opencv_contrib-4.1.1:https://github.com/opencv/opencv_contrib/archive/refs/tags/4.1.1.tar.gz 安装cmakesudoaptinstallcmake-qt-gu......
  • Spring Cloud原理详解:构建云原生应用的利器
    SpringCloud原理详解:构建云原生应用的利器引言在当今云原生应用的潮流中,微服务架构已经成为了构建可扩展、高可用性系统的首选范式之一。而SpringCloud作为构建微服务架构的利器,不仅提供了丰富的解决方案,还拥有强大的生态系统,为开发人员提供了便利与效率。本文将深入探......
  • 精通Spring Boot单元测试:构建健壮的Java应用
    引言:在当今软件开发领域,单元测试已经成为确保应用质量和可维护性的关键步骤。特别是在Java生态系统中,SpringBoot框架作为一种广泛应用的解决方案,其对于单元测试的支持更是让开发者受益匪浅。本博客的目标是为开发者提供一份清晰易懂的指南,帮助他们利用SpringBoot框架构建......
  • Relay 的基本流程,包括定义 Relay 模型、编译模型、创建会话和执行模型。
    TVM(深度学习编译器堆栈)中的Relay是一个用于表示、优化和执行深度学习模型的中间表示语言。下面是一个简单的示例,展示了如何在TVM中使用Relay:importtvmfromtvmimportrelay#定义一个简单的Relay模型x=relay.var("x",shape=(3,3),dtype="float32")y=r......
  • 反编译aspose-words
    publicstaticvoidmain(String[]args)throwsException{ClassPool.getDefault().insertClassPath("F:/lib/aspose-words-21.6-jdk16.jar");//获取javassist默认类池ClassPoolpool=ClassPool.getDefault();//获取domain.Hello......
  • php-构建自己的composer包
    【windows】版1.安装composer,选择PHP版本https://getcomposer.org/Composer-Setup.exe2.安装githttps://objects.githubusercontent.com/github-production-release-asset-2e65be/23216272/2d1c35e2-ece0-4287-bc51-b221f43922b4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Cred......
  • C++工程(五):CMake+NDK交叉编译
    写一个HelloWorld#include<iostream>intmain(intargc,charconst*argv[]){for(inti=0;i<5;++i)std::cout<<"HelloWorld"<<std::endl;return0;}build_for_android.sh脚本文件#/bin/bashexportANDROID......
  • SaaS产品实践方法论:从0到N构建SaaS产品
      大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法行......
  • Linux内核编译(版本6.0以及版本v0.01)并用qemu驱动
    系统环境:ubuntu-22.04.1-desktop-amd64目标平台:x86i386内核版本:linux-6.0.1linux-0.0.1环境配置修改root密码sudopasswd修改软件源(非必要)vmtools安装(实现win-linux软件互传)安装一些必须的软件:sudoaptinstallbuild-essentialopenssh-servervimnet-toolsgc......