linux系统构建——1.交叉编译工具链

1. GNU工具链包括

预编译,编译器,链接器,汇编器
相关的包
Binutils : 所有和二进制文件相关的工具都包括在Binutils中。主要包括:as,ld,objdump,strip,与编译器cpp 等。
GCC : 编译器包括在GCC中,包括C++编译器,Ada编译器等
Glibc : 包括 C库,动态连接器。
除了这三个软件包外,工具链还需要包括内核文件。用户空间中的很多操作都需要借助内核来完成,C库中很大部分是对内核服务的封装,某种意义上,内核头文件可以看作是内核和C库之间的协议,因此构建C库前,需要首先在工具链中安装内核头文件。
此外,gcc 并不是编译器,而是驱动程序,只会 编译过程的各个环节,如cc1负责编译,as负责汇编,ld负责链

2. 构建流程

由于C库和GCC互相依赖,
C99有两种实现,
hosted implementation:支持完整的C标准,包括语言标准和库标准
freestanding implementation : 完全支持C语言标准,但只要求支持部分库标准
先编译个 freestanding implementation 的gcc(不需要C库支持)
再用这个gcc编译 c库
再用C库编译hosted implementation的gcc
而编译C库时,需要链接器,所以需要编译 Binutils,Binutils几乎没有依赖,所以可以直接编译 Binutils.
另外需要内核头文件,内核头文件相当于内核和C库之间的协议,C库会根据内核头文件检查内核提供了哪些特性,需要在C库层面模拟哪些内核没有提供的服务。
所以,构建交叉编译器的步骤如下:
1.构建交叉 Binutils:包括as ld等
2.构建临时交叉编译器(仅支持freestanding)
3.安装目标内核头文件
4.构建目标系统C库
5.构建完整的交叉编译器(支持hosted 的 freestanding)

3. 构建

3.1 准备

创建普通用户
groupadd vita
useradd -m -s /bin/bash -g vita vita
-m 表示创建vita从属目录
-s /bin/bash表示使用bash shell
-g vita 表示将vita加入vita组

给vita超级权限
在/etc/sudoers.d/中添加一个文件vita,内容为
vita ALL=(ALL) NOPASSWD: ALL

建立工作目录
mkdir source build cross-tools cross-gcc-tmp sysroot
chown -R vita.vita /home/vita
source 存放源代码
build 用于编译
cross-tools保存交叉编译工具
cross-gcc-tmp保存临时的freestanding编译器
sysroot 编译好的目标机器上的文件安装到此目录,相对于目标系统的根目录。

定义环境变量
unset LANG
export HOST=x86_64-redhat-linux-gnu
export BUILD=$HOST
export TARGET=x86_64-none-linux-gnu
export CROSS_TOOL=/home/vita/cross-tools
export CROSS_GCC_TMP=/home/vita/cross-gcc-tmp
export SYSROOT=/home/vita/sysroot
PATH=$CROSS_TOOL/bin:$CROSS_GCC_TMP/bin:/sbin:/usr/sbin:$PATH
设置英文环境,使用unset LANG,以避免给一些脚本工具带来麻烦。
为使用交叉编译工具,我们将其目录添加到环境变量PATH中,包括临时GCC的存储目录,注意临时GCC的目录一定要在最终正式工具链目录的后面,确保安装最终的交叉编译器后,在编译时优先使用最终的交叉编译器

HOST和BUILD和TARGET的格式是 ARCH-VENDOR-OS 组合,若没有显示设置编译脚本会自动探测。
HOST表示程序运行环境
TARGET表示程序输出文件的运行环境
BUILD表示构建程序的环境
当HOST和TARGET相同,编译脚本构建本地运行,生成本地执行文件的编译工具
当HOST和TARGET不同,编译脚本构建本地运行,生成其他环境执行的文件的编译工具
由于我的平台都是x86-64所以,我修改vendor区域,以进行构造交叉编译编译工具。
对于本地环境可以用 echo $MACHTYPE查看
SYSROOT使最终的编译工具构建的程序,链接时,连接器查找目录为SYSROOT

2.1 构建binutils

mkdir binutils-build
cd binutils-build
../binutil/configure --prefix=$CROSS_TOOL --target=$TARGET --with-sysroot=$SYSROOT
--prefix=$CROSS_TOOL 通过--prefix参数指定安装脚本将编译好的二级制工具安装到保存交叉编译工具链的$CROSS_TOOL目录下
--target=$TARGET 若没有显示指定--host和--build,编译脚本会自动探测HOST和BUILD的值,这里HOST和BUILD的值相同,是本地环境。TARGET为其他环境,与HOST不同,所以编译脚本判断这是构建交叉编译工具链,继而指导宿主系统的工具链编译 运行在本机,但最后编译链接的程序、库是运行$TARGET的交叉二进制工具。
--with-sysroot=$SYSROOT 通过参数--with-sysroot告诉连接器,目标系统的根文件系统放置在$SYSROOT目录下,连接时到$SYSROOT目录下寻找相关的库。

2.2 构建gcc free standing

2.2.1 安装 mpc mpfr gmp

将mpc mpfr gmp 安装到 /home/vita下
并添加环境变量
export LD_LIBRARY_PATH=/home/vita/mpc/lib
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/vita/gmp/lib
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/vita/mpfr/lib
注意 LD_LIBRARY_PATH 必须 前后不能有 分号

2.2.2 构建gcc

mkdir gcc-build
cd gcc-build
../gcc-4.7.4/configure --prefix=$CROSS_GCC_TMP --target=$TARGET --with-sysroot=$SYSROOT --with-newlib --enable-languages=c --disable-threads --disable-shared --disable-decimal-float --disable-libquadmath --disable-libmudflap --disable-libgomp --disable-nls --disable-libssp --with-gmp=/home/vita/gmp --with-mpc=/home/vita/mpc --with-mpfr=/home/vita/mpfr
make && make install

--with-newlib : 按照 free-standing构建gcc,即gcc无其他依赖 如 glibc

注意:

  1. 若保 texinfo 错误,极可能是 texinfo版本太新或太旧, 也可以选择编译更新版本的GCC
  2. 不能在GCC目录遍历,否则会报错:libgcc.mvars: No such file or directory
  3. 编译失败,需删除源码,弄份全新的

cd cross-gcc-tmp
ln -s lib/gcc/i686-none-linux-gnu/4.7.4/libgcc_eh.a
glibc需要链接 libgcc_eh.a,但是gcc没有这个文件,但libgcc.a的内容和libgcc_eh.a相同,所以可以建立软链接

2.3 构建glibc

准备内核头文件,
应用程序不能直接使用内核服务,必须使用中断,
c库对内核服务器进行了封装,所以应用程序可以使用C库调用内核服务,
所以编译glibc必须要内核头文件。

2.3.1 安装内核头文件

cd linux-3.0.1
make mrproper
make ARCH=i386 headers_check
make ARCH=i386 INSTALL_HDR_PATH=$SYSROOT/usr headers_install

2.3.2 构建glibc

../glibc-2.15/configure --prefix=$SYSROOT --host=$TARGET --enable-kernel=3.7.4 --enable-add-ons --with-headers=$SYSROOT/usr/include libc_cv_forced_unwind=yes libc_cv_c_cleanup=yes libc_cv_ctors_header=yes
make && make install

2.4 构建完整 gcc

3. gcc命名 和 特点

3.1 abi

abi是二进制级别的标准,
符号abi的编译器生成符合abi的目标文件,这种目标文件能在 任意 符合abi且相同 arch的系统上运行。
eabi 是在abi基础上,针对嵌入式环境做了调整的标准。

3.2 gcc的命令

arch-vendor-os-abi-

arm-none-linux-gnueabi-
arm-none-eabi
关键是 arch 和 os
arch决定其目标文件的 arch。
os说明其使用的c库,
如 arm-none-linux-gnueabi-
os为linux,使用clib库,则在 编译器目录下 应该会提供相关的 c库(C库不应该有开发者构建,因为现有C库再有完整版gcc)。
arm-none-eabi
os为空,使用 -newlib构建的gcc,free standing模式,所以不提供c库。

posted on 2021-12-19 00:34  开心种树  阅读(1419)  评论(0编辑  收藏  举报