构建工具链过程疑惑总结
扫描二维码
随时随地手机看文章
本文是对《深度探索linux操作系统系统构建和原理解析》的笔记,目的是为了理解操作系统,重点放在了各种依赖关系上,没有刻意去记录细节。
1.疑惑构建目标系统的时候,即使目标系统和宿主系统运行在同一个体系架构上,为什么也不能使用宿主系统的工具链?
编译程序时,如果使用了宿主系统的链接器,链接器将在宿主系统的文件系统中找依赖的动态库,会导致目标系统的程序链接宿主系统的某些库,导致目标系统依赖宿主系统。
直观表现为程序编译顺利通过,在目标系统运行的时候,出现未定义符号错误。 目标系统使用的工具链的版本通常不同于宿主系统,这也要求为目标系统构建一套新的工具链。
2.构建工具链的意义和目的
工具链在开发中占据位置非常重要,实际中经常用到的是别人构建好的工具链,别人的普遍使用保证了正确性,缺点是没有针对具体的硬件平台优化,有时候也要借助某些辅助工
只对特定硬件进行配置优化,半自动为系统构建编译工具链。对我来说也就是为了了解操作系统。
3.工具链组成:
Binutils:包含所有二进制相关的工具,as,ld,objdump,strip还有预处理器cpp
GCC:各种编译器C,C++,Fortan,C++启动文件
Glibc:C库,动态连接器。C的启动文件。
内核头文件,C库的大多数函数是对内核服务的封装,C库的很大一部分函数是对内核服务的封装,内核头文件是C库和内核的桥梁。
4.构建步骤工具链的步骤
1.构建交叉的Binutils,包括汇编器as,链接器ld等
2.构建临时的交叉编译器仅仅支持freestanding
3.安装目标内核头文件
4.构建目标系统的C库
5.构建完整的交叉编译器。
步骤确定的原因:GNU把编译器和C库放在了两个不同的软件包里面,使得工具链可选择不同的C库,但是带来了编译器和C库的循环依赖问题,编译C库需要编译器,编译器
也依赖C库,但是C99针对运行在操作系统上的程序和运行在没有操作系统上的程序提供了两种实现方式,分别是hosted implementation和freestanding implementation,后
者不依赖C库,解决了鸡和蛋的问题,但是Binutils 什么也不依赖,所以先构建它。
5.编译器为什么会依赖C库,不是翻译为汇编语言吗?
C编译器需要知道C库的某些特性,来决定支持那些特性。C++库和编译器需要C库的支持,如异常处理部分和栈回溯部分。GCC不仅包含编译器还包含一些库,这些库通常依
赖C库,C编译器本身也会使用C库的一些函数。
6.编译目标的C库安装了什么?
C库
Glibc除了将最基本、最常用的函数封装在libc中外,又将功能相近的一些函数封装到一些子库里,比如将线程相关函数封装在libpthread中,将与加密算法相关的函数封装在
libcrypt中,等等。
Glibc除了安装库文件本身外,还建立了符号链接,动态链接时使用的共享库符号链接。其命名格式一般为:libLIBRARY_NAME. so.MAJOR_REVISION_VERSION
比如数学库的共享库及其符号链接如下:
vita@baisheng:/vita/sysroot/lib$ ls -l libm*
-rwxr-xr-x 1 vita vita 792815 Jan 23 10:29 libm-2.15.so
lrwxrwxrwx 1 vita vita 12 Jan 23 10:29 libm.so.6 -> libm-2.15.so
-rwxr-xr-x 1 vita vita 42195 Jan 23 10:29 libmemusage.so
lrwxrwxrwx 1 vita vita 17 Jan 29 17:17 libmount.so.1 ->
libmount.so.1.1.0
-rwxr-xr-x 1 vita vita 746758 Jan 29 17:17 libmount.so.1.1.0
其中,libm-2.15.so是数学库的共享库本身,libm.so.6是运行时使用的符号链接,libm.so
是编译链接时使用的符号链接
动态链接器
Glibc亦提供了加载共享库的工具——动态加载器
头文件
Glibc为应用程序的开发提供了头文件,安装在$SYSROOT/usr/include目录下。
工具
Glibc也提供了一些可执行的便利工具,这类工具一般安装在sbin、usr/bin、usr/sbin目录下,比如用来转换文件字符编码的工具iconv。
启动文件
Glibc提供了启动文件,包括crt1.o、crti.o、crtn.o等,这类文件在编译链接时将被链接,器链接到最后的可执行文件中,Glibc将其安装在$SYSROOT/usr/lib目录下。
7.最终的交叉编译器安装的主要文件如下:
驱动程序
GCC安装的最主要的是交叉编译器的驱动程序,包括i686-none-linux-gnu-gcc、i686-none-linux-gnu-g++等。
目标系统的库和头文件,GCC中也包含了一些用于目标系统的运行时库及头文件,它们安装在$CROSS_TOOL/,i686-none-linux-gnu目录下。在该目录下,子目录lib存放包括目标系统的运行时库以及供目标系统编译程序使用的静态库,子目录include下包含开发目标系统上的程序需要的C++头文件。
helper program
前面我们提到,gcc仅仅是一个驱动程序,它将调用具体的程序完成具体的任务,这些
程序被GCC安装在libexec目录下,典型的有编译器cc1,链接过程调用的collect2等
freestanding实现文件
启动文件
与C++相关的启动文件在GCC中,包括crtbegin.o、crtend.o等