交叉编译工具链
在当前平台下(例如 x86 架构的 PC)下,直接编译出来程序(或者库文件),其不可以直接在当前的平台运行(或使用),必须放到目标平台上(例如 ARM)才可以运行(或使用),这个过程就叫做交叉编译,使用的编译工具叫做交叉编译工具链。例如 PC 中的 armcc、iar、特定架构的 GCC、特定架构的 LLVM 等。
由于历史原因,我们说到交叉编译工具链通常就是指 GCC
交叉编译工具链又可以根据是否支持 Linux 系统分为 裸机程序交叉编译工具链 和 Linux 程序交叉编译工具链 这两大类。我们上面的举例中,armcc、iar 都属于裸机交叉编译工具链;而特定架构的 GCC、特定架构的 LLVM 则根据需要可以支持 Linux 系统,也可以不支持 Linux 系统,因此它既有裸机程序交叉编译工具链,也有 Linux 程序交叉编译工具链。
裸机程序交叉编译工具链不能编译 Linux 应用程序,但是,可以用于编译一些嵌入式实时操作系统(FreeRTOS、RT-Thread 等)
Linux 程序交叉编译工具链不止可以编译 linux 应用程序,也可以编译裸机程序
本地编译工具链
在当前平台(例如 x86 架构的 PC)下,直接编译出来程序(或者库文件),其可以直接在当前的平台运行(或使用)。这个过程就叫做本地编译,使用的编译工具叫做本地编译工具链(简称编译工具链)。例如 PC 上的 VC、GCC、LLVM、TCC 等。
The xPack Project
The xPack Project 是一个开源项目,其提供了一系列开发工具(重点是裸机下的 C/C++ 相关的)在不同平台的下的构建实例,其中就包含各平台的 GCC 交叉编译工具链,它使用一个多版本依赖管理器来管理各个实例。
实际开发中,我们经常会独立使用它提供的某些工具。例如,Eclipse 的嵌入式 C/C++ 插件 Eclipse Embedded CDT 就包含一些 xPack 提供的工具,以此来实现创建、构建、调试和管理 Arm 和 RISC-V 项目。
xPack Windows Build Tools:包括在 Windows 上执行构建所需的额外工具( make、rm 等)
xPack GNU Arm Embedded GCC:ARM 维护的官方 GNU ARM 嵌入工具链的一个代替,可以用于 Windows,MacOS和 GNU/Linux 平台。
GCC
我们使用最多交叉编译工具链就是特定架构的 GNU 工具链,也就是我们我们常说的 GCC 交叉编译工具链。注意,armcc、iar 也属于交叉编译工具链,但是,一说起交叉编译工具链,大家往往首先想到的就是 GCC,例如,ARM 官方提供的 Arm GNU Toolchain。
随着开源运动的兴起,自由软件基金会开发了自己的开源免费的 C 语言编译器 GNU C Compiler,简称 GCC。GCC 中提供了 C Preprocessor 这个 C 语言的预处理器,简称 CPP。后来 GCC 又加入了对 C++ 等其它语言的支持,所以他的名字也改为 GNU Compiler Collection。
构建 gcc 比构建 binutils 要复杂的多
Linux Kernel headers:构建需要支持 Linux 系统时必须提供。这些头文件定义了用户空间与内核之间的接口(系统调用、数据结构等)。
为了构建一个 C 库,需要 Linux 内核头文件中系统调用号的定义、各种结构类型和定义。
在内核中,头文件被分开:
用户空间可见的头文件,存储在 uapi 目录中:include/uapi/、arch/<ARCH>/include/uapi/asm
内部的内核头文件
在安装过程中需要使用
安装包括一个清理过程,用于从头文件中删除特定于内核的结构体
从 Linux 4.8 开始,安装 756 个头文件
内核到用户空间 ABI 通常是向后兼容的。Kernel headers 的版本必须等于或者小于目标 Linux 的版本
C library:
提供 POSIX 标准函数的实现,以及其他几个标准和扩展
基于 Linux 系统调用
几个可用的实现
glibc:The GNU C Library 是 Linux C 库的事实标准,我们常见的 Linux 发行版中都使用它。支持众多的架构和操作系统,但是不支持没有 MMU 的平台,不支持静态链接。早些年由于硬件限制及 glibc 本身太大基本不能直接用于嵌入式,如今貌似也可以了。
uClibc-ng:以前叫 uClibc,始于 2000 年,支持非常灵活的配置。支持架构很多(包括一些 glibc 不支持的),但是仅支持 Linux 操作系统。支持多种没有 MMU 的架构,如 ARM noMMU、Blackfin 等,支持静态链接。
STM32F MCU 没有 MMU,其嵌入式 Linux 环境中编译工具链就是用的它。
musl:始于 2011 年,开发非常积极,最近添加了对于 noMMU 的支持。它非常小,尤其是在静态链接时。兼容性好,并且严格遵循 C 标准。
bionic:安卓系统使用
其他一些特殊用途的:newlib(用于裸机)、dietlibc、klibc
musl 的作者对于 Linux 常用的这几个库做了一个对比,以下是对比情况图:
在编译和安装之后,提供了:
动态链接器 ld.so
C 库本身 libc.so,及其配套库:libm、librt、libpthread、libutil、libnsl、libresolv、libcrypt
C 库的头文件:stdio.h、string.h 等等。
LLVM
LLVM 是一组工具链和编译器技术。回顾 GCC 的历史,虽然它取得了巨大的成功,但开发 GCC 的初衷是提供一款免费的开源的编译器,仅此而已。可后来随着 GCC 支持了越来越多的语言,GCC 架构的问题也逐渐暴露出来。