6.10. 再次调整工具链

现在,最终的 C库已经安装好了, 我们需要再次调整工具链, 让本章随后编译的那些工具都连接到这个库上。 基本上,就是把 Chapter 5 中"调整工具链"那里做的调整给取消掉。 在 Chapter 5 中,工具链使用的库是从宿主系统的 /{,usr/}lib 转向新安装的/tools/lib 目录。同样的,现在工具链使用的库将从临时的 /tools/lib 转向 LFS 系统最终的 /{,usr/}lib 目录。

首先,备份 /tools 目录下的链接, 用我们在第 5 章中编译的链接器来替换。 我们还要创建一个链接到 /tools/$(gcc -dumpmachine)/bin 的副本:

mv -v /tools/bin/{ld,ld-old}
mv -v /tools/$(gcc -dumpmachine)/bin/{ld,ld-old}
mv -v /tools/bin/{ld-new,ld}
ln -sv /tools/bin/ld /tools/$(gcc -dumpmachine)/bin/ld

接下来,修正 GCC 的 specs 文件,使它指向新的动态链接器,只需要删除“/tools” 的所有实例, 就会留下指向动态连接器的正确路径。 也要调整specs文件, 这样 GCC 才能知道在哪能找到正确的头文件和Glibc开始文件。 运行一个 sed 命令:

gcc -dumpspecs | sed -e 's@/tools@@g' \
    -e '/\*startfile_prefix_spec:/{n;s@.*@/usr/lib/ @}' \
    -e '/\*cpp:/{n;s@$@ -isystem /usr/include@}' > \
    `dirname $(gcc --print-libgcc-file-name)`/specs

最好用你的眼睛亲自检查一下 specs 文件,以确保已经改正确了。

现在有必要停下来,检查一下调整过的工具链的基本功能(编译和连接)是否正常, 我们进行下面的合理性检查:

echo 'main(){}' > dummy.c
cc dummy.c -v -Wl,--verbose &> dummy.log
readelf -l a.out | grep ': /lib'

如果一切正常,应该不会出错,而且最后一个命令的结果应该是(某些特殊平台上动态连接器的名称可能与此处不同):

[Requesting program interpreter: /lib/ld-linux.so.2]

注意现在 /lib 应该是动态连接器的前缀。

现在确保我们设置使用正确的开始文件:

grep -o '/usr/lib.*/crt[1in].*succeeded' dummy.log

如果一切正常,应该不会出错,而且最后一个命令的结果应该是:

/usr/lib/crt1.o succeeded
/usr/lib/crti.o succeeded
/usr/lib/crtn.o succeeded

验证编译器在搜索正确的头文件::

grep -B1 '^ /usr/include' dummy.log

这个命令应该成功的返回下面的输出:

#include <...> search starts here:
 /usr/include

接下来要做的是验证新的链接器是否在正确的搜索路径内:

grep 'SEARCH.*/usr/lib' dummy.log |sed 's|; |\n|g'

如果一切正常,应该不会出错,而且最后一个命令的结果应该是(某些特殊平台上的输出可能与此处不同):

SEARCH_DIR("/tools/i686-pc-linux-gnu/lib")
SEARCH_DIR("/usr/lib")
SEARCH_DIR("/lib");

下面,确保我们正在使用正确的libc:

grep "/lib.*/libc.so.6 " dummy.log

如果一切正常,应该不会出错,而且最后一个命令的结果应该是 (在64位宿主系统上,是 lib64 目录):

attempt to open /lib/libc.so.6 succeeded

最后,确保 GCC 正在使用正确的动态链接器:

grep found dummy.log

如果一切正常,应该不会出错,而且最后一个命令的结果应该是(某些特殊平台上动态连接器的 名称可能与此处不同, 在64为系统上,是 lib64 目录):

found ld-linux.so.2 at /lib/ld-linux.so.2

如果输出与上面不同或者没有输出,那么就有大问题了。你需要检查一下前面的操作,看看问题出在哪里,并改正过来。 大多数情况下,出错都是因为上面的 specs 文件没改对。 在继续之前要解决所有的问题。

在确定一切正常后,删除测试文件:

rm -v dummy.c a.out dummy.log