6.10. 再次调整工具链
最后更新于:2022-04-01 22:49:19
# 6.10\. 再次调整工具链
现在,最终的 C 库已经安装好了,我们需要再次调整工具链,让本章随后编译的那些工具都连接到这个库上。基本上,就是把 [Chapter 5](../chapter05/chapter05.html) 中"调整工具链"那里做的调整给取消掉。在 [Chapter 5](../chapter05/chapter05.html) 中,工具链使用的库是从宿主系统的 `/{,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 文件,使它指向新的动态链接器,这样 GCC 才能知道在哪能发现开始文件。应用一个 `perl` 命令:
```
gcc -dumpspecs | \
perl -p -e 's@/tools/lib/ld-linux.so.2@/lib/ld-linux.so.2@g;' \
-e 's@\*startfile_prefix_spec:\n@$_/usr/lib/ @g;' > \
`dirname $(gcc --print-libgcc-file-name)`/specs
```
修改之后,用你的眼睛亲自检查一下 specs 文件,确保已经改正确了。
### 重要
如果你的系统平台上,动态连接器的名字不是 `ld-linux.so.2` ,你必须把上面命令里的"ld-linux.so.2"换成你的系统平台上动态连接器的名字。若有必要,请参见 [Section 5.2 "工具链技术说明"](../chapter05/toolchaintechnotes.html "5.2. Toolchain Technical Notes")。
现在有必要停下来,检查一下新工具链的基本功能(编译和连接)是否正常,我们进行一个简单的合理性检查:
```
echo 'main(){}' > dummy.c
cc dummy.c -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].* .*' dummy.log
```
如果一切正常,应该不会出错,而且最后一个命令的结果应该是:
```
/usr/lib/crt1.o succeeded
/usr/lib/crti.o succeeded
/usr/lib/crtn.o succeeded
```
接下来要做的是验证新的链接器是否在正确的搜索路径内:
```
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
```
如果一切正常,应该不会出错,而且最后一个命令的结果应该是:
```
attempt to open /lib/libc.so.6 succeeded
```
最后,确保 GCC 正在使用正确的动态链接器:
```
grep found dummy.log
```
如果一切正常,应该不会出错,而且最后一个命令的结果应该是(某些特殊平台上动态连接器的名称可能与此处不同):
```
found ld-linux.so.2 at /lib/ld-linux.so.2
```
如果输出与上面不同或者没有输出,那么就有大问题了。你需要检查一下前面的操作,看看问题出在哪里,并改正过来。在改正之前,不要继续后面的部份,因为没什么意义。大多数情况下,出错都是因为上面的 specs 文件没改对。当然,如果你的平台上动态连接器的名字不是 ld-linux.so.2 ,上面的结果也会不同。在继续之前要解决所有的问题。
在确定一切正常后,删除测试文件:
```
rm -v dummy.c a.out dummy.log
```
';