在 Linux From Scratch (V6.6) 的 4.4 节中有一段脚本, 其中定义了一个环境变量: LFS_TGT=$(uname -m)-lfs-linux-gnu 原文中并没有对这个变量的取值做任何说明, 但是如果随意更改的话, 将会使后面的 glibc 无法编译!
这个变量指明了目标系统的类型. 使用 - 作为分隔符号: 第一个 $(uname -m) 调用 uname -m 命令来获取当前的 CPU 架构, 其值通常为 i686, i386 ... 等等; 第二个值 ifs 指明了厂商类型, 比如像 redhat 之类的, 你可以修改这个值来表示你自己的版本; 最后的部分是操作系统的类型. 修改这个值的时候一定要小心, 按照原来的格式进行修改. 我一开始不知道就随意修改成了: LFS_TGT=$(uname -m)-aslinux-gnu. 等执行到 5.7 编译 glibc 的时候就出问题了:
执行
$ ../glibc-2.11.1/configure --prefix=/tools --host=$LFS_TGT --build=$(../glibc-2.11.1/scripts/config.guess) --disable-profile --enable-add-ons --enable-kernel=2.6.18 --with-headers=/tools/include libc_cv_forced_unwind=yes libc_cv_c_cleanup=yes
时出现了如下错误:
checking for i386 TLS support.... yes
running configure fragment for sysdeps/mach/hurd
configure: Warning: --prefix= (empty) is required for GNU/Hurd to work normally
checking Hurd header version... bad
configure: error: Hurd headers not installed or too old
其中错误提示中的 Hurd 是 GNU 组织自己开发的 unix 内核, 不过它至今还没有开发出来. (GNU 开发了非常多的优秀软件, 试图组建一个自由的 unix 系统, 其内核 Hurd 比 linux 更早就开始了, 但是仍然没有完成. 后来由于 linux 也接受了 GPL 协议, 所以就有了以 linux 作为内核加上 GNU 的软件来搭建的 GNU/Linux 操作系统. 似乎组建自由 unix 系统的目标已经达成了, 但是 GNU 不愿意放弃 Hurd, 所以 Hurd 仍然在继续开发. 如果 linux 早点出来, Hurd 就不会存在了.) 显然, 我们是要搭建 linux 内核的系统, 这里却打印出了 Hurd 的错误出来, 应该是某个地方的配置错了!
通过反复查看 configure 脚本终于找到了原因所在, glibc 把 host 参数按 - 分段来得到 host_cpu, host_vendor, host_os 参数:
host=$ac_cv_host
ac_save_IFS=$IFS; IFS='-'
set x $ac_cv_host
shift
host_cpu=$1
host_vendor=$2
shift; shift
host_os=$*
由于我修改了 $LFS_TGT 变量, 使得原本应该是 linux-gnu 的 host_os 变量变成了 gnu 了. 然后在判断操作系统的时候, 所有 gnu 开头的都被认为是 Hurd 了:
test "x$base_os" != x || case "$os" in
gnu*)
base_os=mach/hurd ;;
netbsd* | 386bsd* | freebsd* | bsdi*)
base_os=unix/bsd/bsd4.4 ;;
osf* | sunos* | ultrix* | newsos* | dynix* | *bsd*)
base_os=unix/bsd ;;
sysv* | isc* | esix* | sco* | minix* | irix4* | linux*)
base_os=unix/sysv ;;
irix6*)
base_os=unix/sysv/irix6/$os ;;
solaris[2-9]*)
base_os=unix/sysv/sysv4 ;;
hpux*)
base_os=unix/sysv/hpux/$os ;;
aix4.3*)
base_os=unix/sysv/aix/aix4.3 ;;
none)
base_os=standalone ;;
esac
找到了原因后就好处理了, 最好的当然是修改 $LFS_TGT 变量成符合脚本要求的格式: $(uname -m)-as-linux-gnu. 但是这样的话之前的 gcc, binutils 都得重新编译了. 还有一个方法就是修改 configure 脚本, 这样之前编译的东西就不用重新编译了. 修改的方法很简单, 就是把 gnu 开头的系统也判断成 unix/sysv:
test "x$base_os" != x || case "$os" in
gnu*)
base_os=unix/sysv ;;
netbsd* | 386bsd* | freebsd* | bsdi*)
...
修改完成后 configure 就可以正确执行了: