工具链构造彻底剖析
时间:2008-03-25
来源:互联网
LFS/CLFS工具链是一套用于从C/C++源代码生成可执行文件的软件组件适当地组合在一起形成的系统。它包括4大部分,缺一不可:
1、一套头文件,包含了这些源代码所需要访问的系统接口。
2、binutils,包含一些处理二进制可执行文件所需的工具,如汇编器、连接器等等。
3、gcc,包含了编译C/C++源代码所需的工具,并且还能自动调用相关的binutils工具来完成生成源代码的工具
4、glibc,包含了系统接口的具体实现。
在上面的定义中,请注意这些软件必须适当地组合,才能形成完整的工具链。那么怎么才算适当组合呢?当然,这个工具链必须能够发挥作用,也就是确实能够编译出目标代码,然后才能算适当组合。
那么,一个适当组合的工具链应当具有什么特点呢?一般我们把工具链运行的机器称为host,所产生的代码称为target。那么对于工具链的要求便是:它必须要能在host上运行,所产生的代码必须能在target上运行。再进一步分析:
1、头文件:必须是针对target的,因为使用这个工具链编译的源代码需要访问的系统接口是trget上的。
2、binutils:必须能在host上运行,然而产生target的代码。
3、gcc:和binutils一样。不过这里要注意的是,gcc自身带有一个库,称为libgcc,它必须是target上的代码。
4、glibc:必须是target上的代码。
有了这些基本认识,让我们来看一看一些实际的工具链构造过程。
LFS工具链构造顺序:binutils p1->gcc p1->头文件->glibc->adjust->gcc p2->binutils p2
其中最后两步应该可以互换,但头两步不行。如果你有留意编译过程,会发现,当gcc编译的时候,一旦内部编译第一次gcc完成,产生了xgcc文件,随后的编译就会利用新编译的gcc以及第一遍的binutils,而不是宿主的gcc和binutils。
正如youbest指出的,第一遍的binutils和gcc存在的意义,仅仅是为了能编译出glibc。而glibc的编译需要工具链所有其它内容,包括binutils,gcc和头文件。
LFS不使用交叉编译,因此host和target永远是一样的。在编译参数中,我们永远看不到--host和--target的身影。但是,由于工具链的引用路径需要反复变化,因此我们需要通过修改specs来更改。这点是LFS比较容易出错的地方。
CLFS顾名思义,是要采用交叉编译的。其构造顺序如下:
头文件->cross binutils->cross-gcc c->glibc->gcc final (c/c++)
我们首先看到头文件被放在了开头。这不是必须的,它完全可以放在glibc之前。cross-gcc只能编译出C编译器,因为这时候工具链还不全,glibc还不存在,不可能编译出C++编译器。然后构建glibc。之后,我们才能编译出C++编译器,完成我们的工具链。
CLFS-SYSROOT的工具链稍有不同,顺序如下:
头文件->cross-binutils->glibc头文件->cross-gcc c->gibc->gcc-final (c/c++)
我们看到这里多了一个glibc头文件的安装。事实上,这是由于这里编译的gcc是要用sysroot的缘故。在gcc/configure里面有一段代码,大家在vi里面输入/inhibit_libc=false就可以发现,在交叉编译,而没有SYSROOT的情况下,inhibit_libc的值会成为true,而要是sysroot了,就false了。
这个变量的作用,如同有关的注释所述,是用来关闭gcc对glibc头文件的依赖。因此,在sysroot下我们才会需要这样一个安装glibc头文件的步骤。
我想在sysroot下消除这个步骤,之前测试过这个补丁可行:
使用这个sed命令打个补丁即可:
cp gcc/configure{,.orig}
sed -e 's/inhibit_libc=false/inhibit_libc=true/g' gcc/configure.orig > gcc/configure
不过最近发现有更简单的方法:在configure的时候加个参数--with-newlib即可。建议采用这个方法,因为不需要打任何补丁。
在此再说一句,工具链构建过程中,编译脚本对于是否交叉编译的判断非常简单,只要host!=target,就会被认为正在交叉编译。这也就是为什么CLFS中使用的$CLFS_HOST通常都是i686-cross-linux-gnu这样的形式。原因很简单,因为要确保$CLFS_HOST与$CLFS_TARGET不同。这样,你完全可以在i686上"交叉编译"i686的代码。
这点非常重要,这意味着我们不需要打任何补丁,即可利用CLFS和CLFS-SYSROOT代替LFS来完成系统。对于想做Multilib的朋友,这也是一个福音。毕竟,CLFS-SYSROOT比起CLFS和LFS来,节省了大量的编译过程。
最后,我们来理解一下如何作CCLFS工具链。这意味着我们要在一个平台上构建在第二个平台上运行、生成第三个平台上代码的工具链。我们用build表示构建工具链的机器,host表示工具链要运行的机器,target表示工具链生成的代码所在机器。而在工具链组件上,host-target binutils表示该binutils在host上运行,要生成target的代码。
步骤如下:
host 头文件->build-host binutils->build-host gcc c->host glibc->target 头文件->build-target binutils->build-target gcc c->target glibc->host-target binutils->host-target gcc final (c/c++)
注意事项如下。首先,头文件必须在相应的glibc之前安装。其次,build-target的binutils和gcc在这里的目的是生成target glibc。而build-host binutils 还会被构建host-target binutils和gcc的过程使用到。最后,前两次的gcc都可以只生成c编译器,因为他们的目的都只是生成glibc。只有最后一次gcc需要完整生成。
暂时也没想到别的可写的了,就到这。大家有疑问的我尽量解答。
作者: 地球发动机 发布时间: 2008-03-25
作者: renmepiao 发布时间: 2008-03-25
作者: qyc6810 发布时间: 2008-03-25
最后一个 CC 的我没试过,以前琢磨过,可是后来没去研究了,太懒了。hoho。
作者: 晨想 发布时间: 2008-03-25
作者: 晨想
写的好。赞一个。思路清晰。
最后一个 CC 的我没试过,以前琢磨过,可是后来没去研究了,太懒了。hoho。 |
作者: 地球发动机 发布时间: 2008-03-27
作者: 许木木 发布时间: 2008-03-27
建立工具链后,编译的application运行在低版本的linux上会有问题吗?
因为编译gcc时用了linux的头文件和glibc。
而编译目标板的application用的库文件也肯定是工具链中用到的,这个如果和目标板上的Linux版本不同会怎样呢?
作者: foo2008 发布时间: 2008-03-27
作者: foo2008
关于CLFS想问个问题!
建立工具链后,编译的application运行在低版本的linux上会有问题吗? 因为编译gcc时用了linux的头文件和glibc。 而编译目标板的application用的库文件也肯定是工具链中用到的,这个如果和目标板上的Linux版本不同会怎样呢? |
此外,要更正你的一点是,视编译参数的不同,gcc的编译可能需要glibc的头文件(可以参见主贴,介绍了如何关闭这个依赖性的方法),但绝对不会需要内核头文件。
作者: 地球发动机 发布时间: 2008-03-27
和这里解释了为什么叫这么怪异的名字:http://www.mewburn.net/luke/papers/build.sh.pdf
一个可以做Canadian cross compilation 的工具crosstool http://kegel.com/crosstool/current/d...ool-howto.html
-----------------------------
Canadian cross compilation 小贴示
The sources of a compiler are compiled (i.e. built) on machine X
X is called as the Build system
• The built compiler runs on machine Y
Y is called as the Host system
• The compiler compiles code for target Z
Z is called as the Target system
• Note: The built compiler itself runs on the Host machine and
generates executables that run on Target machine!!!
The built compiler itself runs on the Host machine and
generates executables that run on Target machine!!!
A few interesting permutations of X, Y and Z are:
X = Y = Z Native build
X = Y != Z Cross compiler
X != Y != Z Canadian Cross compiler
作者: 不开花 发布时间: 2008-03-28
作者: 不开花 发布时间: 2008-03-28
作者: 地球发动机
你这个可能有问题。如果你能确定目标版本最好在同一版本上编译CLFS。不过一般来说glibc用到的内核头文件并不会有太大变化,glibc应该没有问题。应用程序大多数通过glibc调用内核,也没什么。但是util,module-tools,udev等组件和内核关系密切,估计版本不同是有问题的。我没试过。
此外,要更正你的一点是,视编译参数的不同,gcc的编译可能需要glibc的头文件(可以参见主贴,介绍了如何关闭这个依赖性的方法),但绝对不会需要内核头文件。 |
但是gcc编出来的东西还是想不明白到底是咋回事。
首先,我没有给目标板的linux安装glibc,那目标板的linux要加载应用程序的时候,如何找到动态链接库呢?是不是编目标板linux的时候,交叉编译工具链的动态库已经包含在vmlinux里了?
作者: foo2008 发布时间: 2008-03-28
作者: foo2008
哦,gcc需要glibc,glibc需要linux header!
但是gcc编出来的东西还是想不明白到底是咋回事。 首先,我没有给目标板的linux安装glibc,那目标板的linux要加载应用程序的时候,如何找到动态链接库呢?是不是编目标板linux的时候,交叉编译工具链的动态库已经包含在vmlinux里了? |
2. 如果你采用动态链接,目标机器不安装libc那是无法运行的。如果选择静态链接就没有问题。
作者: 地球发动机 发布时间: 2008-03-28
作者: 地球发动机
1. 嵌入式系统一般使用uclibc而不是glibc。
|
作者: 地球发动机
2. 如果你采用动态链接,目标机器不安装libc那是无法运行的。如果选择静态链接就没有问题。
|
作者: foo2008 发布时间: 2008-03-28
作者: 地球发动机
我就是发现你们之前的讨论没到点子上。要生成一个交叉编译器,host和target的glibc一个都不能少。这正是为什么CC工具链需要三步而不是两步的原因。
|
作者: 不开花
楼主所说的CCLFS叫Canadian cross compilation ,具体定义在这里: http://www.airs.com/ian/configure/configure_6.html
和这里解释了为什么叫这么怪异的名字:http://www.mewburn.net/luke/papers/build.sh.pdf 一个可以做Canadian cross compilation 的工具crosstool http://kegel.com/crosstool/current/d...ool-howto.html ----------------------------- Canadian cross compilation 小贴示 The sources of a compiler are compiled (i.e. built) on machine X X is called as the Build system • The built compiler runs on machine Y Y is called as the Host system • The compiler compiles code for target Z Z is called as the Target system • Note: The built compiler itself runs on the Host machine and generates executables that run on Target machine!!! The built compiler itself runs on the Host machine and generates executables that run on Target machine!!! A few interesting permutations of X, Y and Z are: X = Y = Z Native build X = Y != Z Cross compiler X != Y != Z Canadian Cross compiler |
作者: 晨想 发布时间: 2008-03-28
作者: foo2008
在目标机上用的动态库?host上运行的交叉编译gcc用的glibc也要被替换成uclibc吗?
嗯,说的对,终于是搞明白这个问题了:) |
我们应该搞清楚,交叉编译器需要host和target的两个libc都存在,才能成功构建。在嵌入式的情况下,host的glibc不应替换,也不可以替换。只有target的libc需要替换为uclibc。
使用uclibc的理由是它更小型化,占用资源更少,更适合于嵌入式环境使用。
作者: 地球发动机 发布时间: 2008-03-28
地球啊,you are my star!
作者: d00m3d 发布时间: 2008-03-29
作者: 地球发动机
回答你的前一个问题。是,uclibc是一般在目标机器上使用。host上的交叉编译器用宿主的libc,一般是glibc。
我们应该搞清楚,交叉编译器需要host和target的两个libc都存在,才能成功构建。在嵌入式的情况下,host的glibc不应替换,也不可以替换。只有target的libc需要替换为uclibc。 使用uclibc的理由是它更小型化,占用资源更少,更适合于嵌入式环境使用。 |
生成交叉编译器需要host的glibc(x86)和target的uclibc(mips)(如有的是空间glibc(mips)更好),这个交叉编译器生成目标板用的application就在目标机上用uclibc(mips)(或者相同glibc(mips))!
hoho,太谢谢了
作者: foo2008 发布时间: 2008-03-29
作者: d00m3d
看完本篇又再看 CLFS 手冊一遍,理解又再清釋了一遍
地球啊,you are my star! |
作者: 晨想 发布时间: 2008-03-29
no need to install glibc headers to build bootstrap gcc?
This depends on the architecture. MIPS and sparc don't require the
glibc-headers to be built
but x86, x86_64, and alpha require them. If you don't build them gcc
will fail.
所以对下面这一段强烈质疑
作者: 地球发动机
CLFS-SYSROOT的工具链稍有不同,顺序如下:
头文件->cross-binutils->glibc头文件->cross-gcc c->gibc->gcc-final (c/c++) 我们看到这里多了一个glibc头文件的安装。事实上,这是由于这里编译的gcc是要用sysroot的缘故。在gcc/configure里面有一段代码,大家在vi里面输入/inhibit_libc=false就可以发现,在交叉编译,而没有SYSROOT的情况下,inhibit_libc的值会成为true,而要是sysroot了,就false了。 这个变量的作用,如同有关的注释所述,是用来关闭gcc对glibc头文件的依赖。因此,在sysroot下我们才会需要这样一个安装glibc头文件的步骤。 要想在sysroot下消除这个步骤,使用这个sed命令打个补丁即可: cp gcc/configure{,.orig} sed -e 's/inhibit_libc=false/inhibit_libc=true/g' gcc/configure.orig > gcc/configure |
作者: 1987a 发布时间: 2008-04-10
此外,你看到那篇文章似乎老了点,是2年前的。估计也不是现在这个版本。所以情况有所不同,也是很正常的。此外可以告诉你,早期的CLFS的确需要先安装Glibc头文件,但现在已经不需要了,只有SYSROOT CLFS还需要。这个补丁是专门针对SYSROOT的,如果你不用SYSROOT,那么就不需要这个补丁。
作者: 1987a
今天偶然看到http://linuxfromscratch.org/pipermai...er/000033.html提到
no need to install glibc headers to build bootstrap gcc? This depends on the architecture. MIPS and sparc don't require the glibc-headers to be built but x86, x86_64, and alpha require them. If you don't build them gcc will fail. 所以对下面这一段强烈质疑 lz有没有亲自测试过上面提到的“补丁”,误人子弟就不好了。 |
作者: 地球发动机 发布时间: 2008-04-10
作者: 地球发动机
请放心使用,这个补丁是在GCC 4.2.3下完整测试过了的。
此外,你看到那篇文章似乎老了点,是2年前的。估计也不是现在这个版本。所以情况有所不同,也是很正常的。此外可以告诉你,早期的CLFS的确需要先安装Glibc头文件,但现在已经不需要了,只有SYSROOT CLFS还需要。这个补丁是专门针对SYSROOT的,如果你不用SYSROOT,那么就不需要这个补丁。 |
作者: 1987a 发布时间: 2008-04-10
作者: shooter 发布时间: 2008-04-10
作者: 晨想 发布时间: 2008-04-11
作者: shooter
看了,很多地方不懂,有些基本的东西先问问,为什么要在i686上交叉编译i686(或者还是这仅仅是各option供用户选择),都是相同的平台,用LFS就行了嘛,效率上有所变化吗?如果都是x86构架的cpu,比如intel和amd,这两个平台上的系统需要用到交叉编译吗?用不用到都有什么区别?
|
作者: 地球发动机 发布时间: 2008-04-11
作者: 1987a
既然测试过,lz应当向LFS官方提供该patch,让整个社区受益,而不只是我们受益,是不是?
|
作者: 地球发动机 发布时间: 2008-04-11
作者: 地球发动机
那么,一个适当组合的工具链应当具有什么特点呢?一般我们把工具链运行的机器称为host,所产生的代码称为target。那么对于工具链的要求便是:它必须要能在host上运行,所产生的代码必须能在target上运行。再进一步分析:
1、头文件:必须是针对target的,因为使用这个工具链编译的源代码需要访问的系统接口是trget上的。 2、binutils:必须能在host上运行,然而产生target的代码。 3、gcc:和binutils一样。不过这里要注意的是,gcc自身带有一个库,称为libgcc,它必须是target上的代码。 4、glibc:必须是target上的代码。 |
作者: 地球发动机
LFS不使用交叉编译,因此host和target永远是一样的。在编译参数中,我们永远看不到--host和--target的身影。但是,由于工具链的引用路径需要反复变化,因此我们需要通过修改specs来更改。这点是LFS比较容易出错的地方。
|
CLFS顾名思义,是要采用交叉编译的。其构造顺序如下: 头文件->cross binutils->cross-gcc c->glibc->gcc final (c/c++) 我们首先看到头文件被放在了开头。这不是必须的,它完全可以放在glibc之前。cross-gcc只能编译出C编译器,因为这时候工具链还不全,glibc还不存在,不可能编译出C++编译器。然后构建glibc。之后,我们才能编译出C++编译器,完成我们的工具链。 |
在此再说一句,工具链构建过程中,编译脚本对于是否交叉编译的判断非常简单,只要host!=target,就会被认为正在交叉编译。这也就是为什么CLFS中使用的$CLFS_HOST通常都是i686-cross-linux-gnu这样的形式。原因很简单,因为要确保$CLFS_HOST与$CLFS_TARGET不同。这样,你完全可以在i686上"交叉编译"i686的代码。 |
最后,我们来理解一下如何作CCLFS工具链。这意味着我们要在一个平台上构建在第二个平台上运行、生成第三个平台上代码的工具链。我们用build表示构建工具链的机器,host表示工具链要运行的机器,target表示工具链生成的代码所在机器。 |
而在工具链组件上,host-target binutils表示该binutils在host上运行,要生成target的代码。 |
上面是我的一些理解,还请 LZ 指点一二??
作者: panly 发布时间: 2008-07-17
作者: 地球发动机
我们应该搞清楚,交叉编译器需要host和target的两个libc都存在,才能成功构建。在嵌入式的情况下,host的glibc不应替换,也不可以替换。只有target的libc需要替换为uclibc。
|
但后面的说法不是太明白,是不是可以这样理解:
host 宿主机的原生 glibc 链接库不需要替换,因为交叉编译器需要使用它来运行,但 host 宿主机构建好的 交叉编译过的 用在 target 目标机上的 glibc 必须要替换,因为在用交叉编译器交叉编译其它的 target 目标机上的应用程序时,需要链接到这个链接库,如果这儿不替换,那么在 target 目标机上运行应用程序时必须把交叉编译过的 glibc 链接库拷贝过去才行。
说的比较绕,总的意思如下:
我们在 host 宿主机上构建的交叉编译器,它本身的运行需要 host 宿主机原生的 glibc 链接库,但它要编译出 target 目标机上运行的程序,就必须要用链接器链接 target 目标机上的 glibc 链接库。
不知道 LZ 是不是同意我的看法?
作者: panly 发布时间: 2008-07-17
作者: fghgje 发布时间: 2008-10-24
热门阅读
-
office 2019专业增强版最新2021版激活秘钥/序列号/激活码推荐 附激活工具
阅读:74
-
如何安装mysql8.0
阅读:31
-
Word快速设置标题样式步骤详解
阅读:28
-
20+道必知必会的Vue面试题(附答案解析)
阅读:37
-
HTML如何制作表单
阅读:22
-
百词斩可以改天数吗?当然可以,4个步骤轻松修改天数!
阅读:31
-
ET文件格式和XLS格式文件之间如何转化?
阅读:24
-
react和vue的区别及优缺点是什么
阅读:121
-
支付宝人脸识别如何关闭?
阅读:21
-
腾讯微云怎么修改照片或视频备份路径?
阅读:28