|
|
[color="Red"]BOOK Version: LFS-SVN 20060210
主要是帮助读者理解LFS的编译原理。诸如 为什么要分开两大章编译,调整toolchain的真正意义是什么 之类的问题,本文尝试给出解释。
抛砖引玉,欢迎评论。 。
[html]
文中术语:
库文件:library file:*.so 文件
动态连接库:Dynamic Linker:一般是指 ld-linux.so.2 这个文件。
[/html]
==========================================================================
5.3. Binutils-2.16.1 - Pass 1
一开始先安装基础的binutils包。里边包括了ar/nm/ld等最底层的编译工具。
具体作用是把编译的文件组合成系统可执行的文件。
make -C ld 的那一段:
重新编译 ld 这个程序,但是改变 LIB_PATH 这个参数。具体作用就是 这样产生的新的 ld-new 是利用 /tools/lib 里边的库来进行组合程序,而不是使用默认的 /lib:/usr/lib:/usr/local/lib 里边的库。/tools 是我们的临时系统存放点,这样做是要保证在第一次调整工具链后,不把原系统的那些库混杂进来,污染我们的临时系统。
我的推测:(我后来测试了,证实这个设想是正确的。)
LIB_PATH 可以通过 --with-lib-path 来指定。也就是说如果你喜欢,可以编译2次 binutils,在第二次编译的时候把 --with-lib-path=/tools/lib 传入 configure。编译后,保留 ld/ld-new 这个文件。
(指定 --with-lib-path 这个方法其实也是 5.12. Binutils-2.16.1 - Pass 2中用的方法。)
注意,我这里说的第二次不是 5.12. Binutils-2.16.1 - Pass 2,是这个 Pass 1 编译两次 binutils。
我测试了一下,2个文件 (ld-new) 虽然不一致,但是通过 strings ld-new 的结果却是一样的。而且 ldscripts 目录里边文件的内容全部一致。
(基本上来说,2个 ld-new 文件就是一样的了,从后边的讨论可以基本证实这点,谁能提出不同看法的话,非常欢迎!这样我会继续深究。)
最后补充两句:ld.so.conf 用来控制搜索范围。这个文件是在安装glibc的时候建立的。
我的新系统就是采用编译了2次binutils的方式,还没发现任何问题。
==========================================================================
5.7. Adjusting the Toolchain
到现在我们已经把 toolchain 做出来了。Linux-Libc-Headers 是给 glibc用的。接下来就是把所有的库连接都指向这个临时 toolchain,这样就不会受到 原系统 的影响了。
Binutils-2.16.1 - Pass 1
GCC-4.0.2 - Pass 1
Linux-Libc-Headers-2.6.12.0
Glibc-2.3.6
一改以前的作风,LFS现在只拷贝 ld 这一个文件,而不是以前的 make -C ld install 方式。这个也就是说其他都不用变,只有这个文件受到了改变,
这个让我感觉之前的我的推测应该是可以成立的,也就是第二次编译生成的 ld-new 可以用来代替第一次的那个。要的就是 LIB_PATH 这个参数的改变。
在用我说的第二次编译得到的 ld-new 覆盖了原来的 ld 文件后,效果是:From this point onwards, everything will link only against the libraries in /tools/lib。
说的具体清楚一点,就是编译过程中,所有的这些 -ldes -lXXX 这些都是从 /tools/lib 里边寻找,而不是在 /lib:/usr/lib:/usr/local/lib 里边找。
接下来的是 gcc 的动态工具链调节。
首先是 specs 文件的位置。因为 gcc 4.X 中,specs是默认不存在的。读取的是内部的specs文件(可用 gcc -dumpspecs 查看)。要创建该文件
才会使gcc去读取。至于是什么文件,你可以通过BOOK上的语句查看。实际上还有其他地方可以放置 specs 文件的。这个可以通过 strace gcc 来确定,也可以查看 cc dummy.c -Wl,--verbose &> dummy.log 的输出结果。
修改 specs 的具体作用是:让编译器用 /tools/lib/ld-linux.so.2 这个动态连接库(而不是/lib/ld-linux.so.2)来寻找相应的库文件,
配合 ld 这个命令,可以限定搜索范围了。
最后,清除那些错旧的header文件。效果就是 从host系统拷贝过来的header 统统不要。
修改完后,做一下测试。确保操作正确。
==========================================================================
5.11. GCC-4.0.2 - Pass 2
因为gcc的fixincludes问题,一开始就去掉。fixincludes 就是刚刚提到的那些 错旧headers 的生成脚本。
接着是调整优化参数 -fomit-frame-pointer。
打 gcc-4.0.2-specs-1.patch 补丁。这个补丁很重要,作用是把所有的体系的linker位置调整为/tools/lib下的新的linker。linker就是动态连结库。默认的 gcc 是去 /lib 寻找 linker 的。
==========================================================================
5.12. Binutils-2.16.1 - Pass 2
传入 --with-lib-path-,重新编译一次binutils。这次是其他的那些bfd什么的也跟着一起,不单单只有 ld 一个了。
在最后,旧计重施。重新编译一次 ld, 并且保存为 ld-new。二次编译的 ld 和原来不同的就是 新的会去/lib:/usr/lib去查找库文件 而不是 /tools/lib。
编译这次 binutils 的目的,主要是为第六章做工具链修改做准备。
稍微深入一下话题:
如果传入的 --with-lib-path 或者 LIB_PATH 值不一样的话,那么ld这个文件也会不一样。而且很不一样。最明显的就是文件包括的路径不一样。如下是diff出来的结果。
相信你们也能看出不同了:)。
diff <(strings b1/build/ld/ld-new) <(strings b2/build/ld/ld-new)
2088c2087
< SEARCH_DIR("/tools/i686-pc-linux-gnu/lib"); SEARCH_DIR("/ll");
---
> SEARCH_DIR("/tools/i686-pc-linux-gnu/lib"); SEARCH_DIR("/tools/lib");
==========================================================================
一直到后边都没什么好说的了,机械的编译所有需要的包。注意到的一点就是第五章的包能不打补丁的都不打,这些都在第六章进行的。
==========================================================================
6.12. Glibc-2.3.6
没什么好说的,这里是把主系统的glibc装上。glibc 是 self-contained的,就是说不会受到外界的影响。具体的表现是 只要规定了 --prefix,那么 glibc 就会装入这个目录,也因为glibc 是最基础的库,不需要任何依赖库,所以也就不受任何其他因素的影响。能成功安装就可以了!
临时系统里边已经有“干净”的 binutils/gcc/glibc 组合了,装glibc很容易。调整了 toolchain 后,马上就安装 binutils/gcc。
==========================================================================
6.13. Re-adjusting the Toolchain
重新调整工具链。把 5.12 中保留下来的那个 ld 暂时放上来,因为这个时候还没有安装新的 binutils。但是在马上要安装的 binutils中,就需要把库 link 到/lib下的glibc,而不是
/tools/ 中的glibc。这个是鸡蛋和鸡的问题。所以这里暂时用一下原来编译好的 ld 来顶替。接着马上就编译 binutils 来重新覆盖。
调整 gcc 的 linker 的话,和一开始的原理一样,就不复述了。不过这里多了一个东西,就是 startfile_prefix_spec。主要是为了让gcc能正确的找到相应的文件。这些文件是 crt1.o crti.o crtn.o 这3个文件。
为了保证操作正确,后边马上给出一系列的测试。
==========================================================================
6.14. Binutils-2.16.1
这里没什么特殊的,就是最后 make tooldir=/usr install 这里说一下。
ar as ld nm objdump ranlib strip 这几个是binutils提供的工具,主要是用来拼组文件用的。当然,不同的体系有不同的组合。体系一般用triplet来表示。如 i686-pc-linux-gnu。
binutils 的 tooldir 的安装位置应该是 /usr/[triplet]/bin 和 /usr/[triplet]/lib下。但是为了简便,LFS就把他直接安装到 /usr/bin 和 /usr/lib 下边,也就是说默认用的就是用当前体系编译。
这样做的后果是不能提供跨体系编译。不过一般来说也不需要。/usr/bin 提供的就是native toolchain的体系。/usr/[triplet]提供一般是用来跨体系编译的。
(几句话说的也不清楚,如果要搞明白的话,请 google 搜索更多的资料。我安装的时候是忽略 tooldir=/usr 这个参数的。)
==========================================================================
6.15. GCC-4.0.2
开始的几个sed,是为了调整一些设置。第一个是去掉libiberty的安装,因为binutils已经装了。fixincludes 和上边原因一样。至于其他的,似乎没什么好说的。基本上
系统已经开始成形了,剩下的就是那些软件的安装了。
==========================================================================
转载请保持完整。
by 终极幻想@LinuxSir.org |
|