LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
楼主: youbest

[原创]CLFS2.0原理分析

[复制链接]
发表于 2008-7-18 20:43:34 | 显示全部楼层
而在CLFS2.0中,第一遍编译gcc,也确实为了编译glibc,而这个glibc却不是工具链中要用的,这是目标系统用的(这一点也可以通过第六章中没有编译glibc的部分来间接验证),并不是为了第二次编译gcc,让gcc链接到这个glibc用的,而且gcc也不能链接到这个glibc上,因为第一遍编译的交叉版本的gcc来编译出的glibc必然是目标体系平台的代码,所以在当前的体系平台上是运行不起来的,如果第二次编译的gcc链接到这个glibc上,那么这个gcc也就不能在当前的体系平台上运行了,所以CLFS2.0在工具链阶段的两次编译gcc,不是为了让gcc连接到新编译的glibc上。


老大的这几句话还有些地方需要探讨。

如果说编译出的 glibc 没有用到第 2 次 gcc 的编译过程中,那么编译 glibc 和第 2 次 gcc 完全可以不分先后,但实际上是有先后的,所以它这样安排肯定有道理的。

我在实际编译的过程中,在编译出 glibc 以后,第 2 次编译 gcc 的时候,曾经出错提示是找不到相关的一些库,而我把生成的 glibc 目录下的 libc.so 文件修改后,第 2 次的 gcc 编译就过了,这说明第 2 次的 gcc 编译还是需要使用编译出的 glibc 的。

所以我的理解是这样的:

第 2 次编译 gcc 需要用到 glibc,但并不是说编译 gcc 的时候链接 glibc 的库,而是用它来完成一些设置或者是其它作用,因为如果链接了编译出的 glibc,那么它就无法在主机上运行,但缺了它又无法编译 gcc,所以才觉得要用,但用在哪儿现在还不是特别的清楚。

请老大们关注一下,这部分一直都是存在争议,现在想弄个定论出来。
回复 支持 反对

使用道具 举报

发表于 2008-7-18 22:34:24 | 显示全部楼层
ls 你有必要搞清楚什么是CLFS2.0,什么是CLFS-Sysroot,什么是交叉编译工具链。
简单的说,你错大发了。
这部分没有争议,只有误解。

ls的做法正说明自己的步骤有问题,为什么要修改libc.so?

clfsv2问题请教:为什么需要编译第二次gcc

这个问题的根源在于Richard M. Stallman,甚至可追溯到c语言创建者Ken Thompson、Dennis Ritchie。

gnu工具链分散在三个软件包
binutils——汇编器、连接器
gcc——预处理器、编译器
glibc——c库
好处是灵活,可以使用其他c库,如uclibc、uc-libc、newlib,
坏处是gcc、glibc有循环依赖问题,交叉编译工具链自举时需要编译gcc两遍,
第一遍编译的gcc是裸编译器,也就是没有任何库支持的编译器,只能编译glibc、linux-kernel等一类完全自给自足的软件包,
之后才能编译glibc,
第二遍编译的gcc是全功能的编译器,有glibc的支持,可用来交叉编译任何能想象到的软件包,只是难易程度的问题。

交叉编译工具链的本质就是在宿主上生成目标机代码的工具,自然要链接到宿主c库,交叉编译工具链要处理目标机代码,自然需要目标机c库。

如果把3者整合到一个软件包,一遍编译工具链是可能的,可这样与unix哲学相违背。

如果你还要追问为什么这样,只有下面的名言适于你。

RTFSC (Read the F  **  ing Source Code :  -  )
        -- Linus Torvalds
回复 支持 反对

使用道具 举报

发表于 2008-7-18 23:26:30 | 显示全部楼层
多谢回答!!

不过我觉得 LS 没有回答我的问题。

Post by 聚焦深空;1876155
ls 你有必要搞清楚什么是CLFS2.0,什么是CLFS-Sysroot,什么是交叉编译工具链。
简单的说,你错大发了。
这部分没有争议,只有误解。



步骤没有问题,也没有争议,但原因和解释却还有些不一样。

ls的做法正说明自己的步骤有问题,为什么要修改libc.so?


我这么做是为了让 gcc 使用刚刚编译的 glibc,这是标准嵌入式做法,编译出来的程序就能在目标板上运行。

clfsv2问题请教:为什么需要编译第二次gcc

这个问题的根源在于Richard M. Stallman,甚至可追溯到c语言创建者Ken Thompson、Dennis Ritchie。

gnu工具链分散在三个软件包
binutils——汇编器、连接器
gcc——预处理器、编译器
glibc——c库
好处是灵活,可以使用其他c库,如uclibc、uc-libc、newlib,
坏处是gcc、glibc有循环依赖问题,交叉编译工具链自举时需要编译gcc两遍,
第一遍编译的gcc是裸编译器,也就是没有任何库支持的编译器,只能编译glibc、linux-kernel等一类完全自给自足的软件包,
之后才能编译glibc,
第二遍编译的gcc是全功能的编译器,有glibc的支持,可用来交叉编译任何能想象到的软件包,只是难易程度的问题。

交叉编译工具链的本质就是在宿主上生成目标机代码的工具,自然要链接到宿主c库,交叉编译工具链要处理目标机代码,自然需要目标机c库。

如果把3者整合到一个软件包,一遍编译工具链是可能的,可这样与unix哲学相违背。

如果你还要追问为什么这样,只有下面的名言适于你。

RTFSC (Read the F  **  ing Source Code :  -  )
        -- Linus Torvalds


你说的这些我都明白,但跟我前面的问题基本上关系不大。
回复 支持 反对

使用道具 举报

发表于 2008-7-19 08:46:28 | 显示全部楼层
Post by panly;1876164
我这么做是为了让 gcc 使用刚刚编译的 glibc,这是标准嵌入式做法,编译出来的程序就能在目标板上运行。

正常的CLFS-Sysroot两遍编译gcc,交叉编译工具链自然会使用刚刚编译的 glibc。
不妨展示一下你的方法,看看到底有没有必要。

嵌入式没有具体标准,目标就是满足需求、客户的需求,我做嵌入式开发的朋友在工程实践中大部分都还在使用2.4系列内核、uclibc;自己玩是另一回事,工程实践中各种苛刻条件、限制、历史遗留问题是你想都不会想到的。
Post by panly;1876164
  你说的这些我都明白,但跟我前面的问题基本上关系不大。

你如果真的明白,就没有所谓的问题了。
回复 支持 反对

使用道具 举报

发表于 2008-7-19 11:26:34 | 显示全部楼层
昨晚回的太急,所以有的地方没有说清楚!!

我在另外一个帖子里面也看到了 LS 的解释,请看:
http://www.linuxsir.cn/bbs/thread332457.html

下面是我回的一些原话,请过目一下:
glibc 只需要头文件,而 linux 内核头文件和链接库都不使用,所以它们是“完全自给自足”,所以第一遍的 gcc 能够编译这些。

但这并不是说,第一遍的不能编译其它的使用动态链接库的程序,只要你已经编译了 glibc 链接库,那么第一遍的 gcc 就能用已经编译出的 glibc 链接库来编译其它的程序,并且是动态链接,只是你在运行编译出的二进制文件时需要把相应的编译时使用的链接库拷贝过去。

不知道这算不算是明白了你的意思。

还有你说的嵌入式没有标准我同意,但总有些方法是通用的,我的做法是参数《构建嵌入式系统》做的。

第一遍编译过 gcc 后,用它再编译出目标板的 glibc,然后再用这个 gcc 和 glibc 编译出直接在目标板上运行的程序,虽然没有第二遍的 gcc,但完全可以动态编译 c 程序,然后再把编译出的目标板 glibc 拷贝到目标板系统就可以运行这些动态编译的 C 程序。

上面这些都是经过我实际验证过的,绝对可行。

至于 2.4 内核和 ulibc 这个要看应用,我用的芯片足够强,外围也足够多,跑 2.6 内核没有问题,我们这是个新产品,所以没有什么历史遗留问题,因为我们用到的一些地方 2.4 内核不支持。

我知道 gcc 需要两次编译,不过我想知道的是第二次编译会不会用到编译出的 glibc,因为从 youbest  老大的图上和叙述中是明确不会用到的,但我在实际编译的时候确实是用到了,所以想请教一下。

另外我也知道 LS 是行家,但总感到你说话有些太那个了,可能是我太敏感了。我只是有些疑问,并且又不是那种没有思考或者是实践直接问的那些低级问题,我是深入思考,实际测试过才问的,到现在为止,我还是不清楚答案,可能是高手觉得这个问题不是问题,不想浪费时间,但我是真的不明白,所以请直接给我个痛快的,用不用?有什么用?怎么用?

在下感激不尽!!
回复 支持 反对

使用道具 举报

发表于 2008-7-19 12:46:10 | 显示全部楼层
ls 你应当好好理解一下循环依赖、工具链自举、工具链源码结构。
这些东西真要解释起来,写本书都够的。

youbest已经给出了清晰的工具链脉络,是表层原因,
我上面也简单说明了为什么要这样建立工具链,是深层原因。
你现在应该做的是到binutils、gcc、glibc官方站点,翻翻相关文档,读读源代码,特别是Makefile相关部分,而不是一直问这些不合乎理论的问题。

至于glibc,你应该好好理解一下gcc、ld的工作原理。

ls 也应该理解[color="Red"]能运行、能正常运行的区别,你偷懒的方法应用到生产环境,如果出问题,查都查不出来的。

实践要和理论结合,否则是盲目的。
低级问题,并不会因为深入思考改变问题层次。
回复 支持 反对

使用道具 举报

发表于 2008-7-19 13:32:33 | 显示全部楼层
感谢回答!!

确实,我对工具链的源码结构现在不太了解,我想我的答案肯定在这里面,而工具链自举这个概念我也只是听说过而已,如果我完全弄明白了,肯定也就成高手了,但我现在没有那么多时间,暂时不想那么深入下去,所以只是想求证一下,然后明白结论就行了,但我知道,以后肯定我还是会去弄明白这些的,这些是绕不过去的。

youbest 的解释对我们的理解确实有很大帮助,可以说我从他那儿学了不少,你说是表层原因说的很对。

你前面解释的那些,确实是为什么整个工具链为什么要这么操作的根本原因,就好像我们的计算机是冯氏结构一样,编译、汇编、链接、加载,头文件和链接库,动态链接和静态链接,这些才是这所有操作的最最决定性的东西。

说实话,我对编译器、链接器和汇编器的工作原理还是比较清楚的,对 elf、exe 文件的结构也都分析过,链接、重定位我也研究过,就是有了这些了解,所以我才能容易的理解交叉工具链的实质。

你说的实践和理论结合,我承认,我保证我上面的做法就是《构建嵌入式Linux系统》(英文名《Building Embedded Linux》这本经典教材中介绍的做法,这也是很多嵌入式相关的书籍上介绍的办法,然后我又结合了 CLFS 的一些理论依据,最后完成的整个工具链,并且我一直在使用这个环境,交叉编译了内核、gcc、glibc、uclibc、busybox 等一大堆的程序,都能够很好的在目标板上运行,并且整个目标板上的系统就是我用这个环境建立起来的。

所以我不认为我的做法是偷懒,如果有区别,那我认为是 CLFS 和嵌入式开发的区别,我构建工具链的过程对 CLFS 有借鉴,但绝对不是完全拿过来用的,我使用的是它的思想,它提供的工具。

前面 youbest 也提过,用第一遍的 Gcc 编译出的 glibc 完全是目标板系统的,所以我用交叉编译器(第一遍的 gcc)来编译代码时,只要让它链接这个目标板 glibc,那么它肯定是在目标板上运行的。我想不出我这么做有什么地方不对,我的目的并不完全的做 clfs,而是建立交叉工具链,然后交叉编译 kernel、apps,最后让 kernel 和 apps 在目标板上跑起来,并且这一切都是我通过反复的实验验证和深入思考得到的结果。

我记得 youbest 的那个 5M 系统就提到过类似的做法,这不是偷懒,我觉得这更能体现出一个人思考的深度,根据实际的情况,我们要做一些调整,不能一些死守着那些步骤和理论上的解释,登山千条道,同仰一月高,但哪条道最近、最安全、最快捷、最好走才是重要的。

真的很感谢你的回复,让我思维更加活跃,对这些的理解也更加深入,作为一个技术人员,交流是提高的一个重要手段。
回复 支持 反对

使用道具 举报

发表于 2008-7-19 14:13:07 | 显示全部楼层
ls 最后提醒你一下,请注意[color="Red"]能运行、能正常运行的本质区别,多从工程角度考虑问题,而不是走所谓的捷径,好自为之。
回复 支持 反对

使用道具 举报

发表于 2008-7-19 14:20:52 | 显示全部楼层
多谢一直关注!!

虽然不是太明白,但我会认真考虑你的建议,看看到底是不是真的有什么地方还不够好,考虑的不充分,再充分的审视一下现在的做法,但更期待个中高手能指点明示!!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-7-21 22:41:53 | 显示全部楼层
第一次的交叉gcc只支持C,但可以用来编译glibc,这个基本上所有其它程序的基础库,因此如果想编译其它的程序就必须先将glibc完成,那么第二次的交叉gcc需要用到了C++,而C++用到了glibc库,所以C++的支持必须在glibc完成之后,但这里你要注意一点,第二次的交叉gcc并不是第一次的交叉所编译产生的,而是由主系统的gcc来完成的,但第二次的gcc的C++支持确是由第二次生成的gcc在编译过程中生成的。

不知道我说的大家是否能理解
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表