LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 2250|回复: 12

[原创]Multilib LFS For x86-64

[复制链接]
发表于 2008-2-27 20:20:05 | 显示全部楼层 |阅读模式
在x86_64位机器上安装Linux是一个挑战。使用现有的64位发行版,会有一些兼容性问题,例如Opera就因为没有64位的_包而在许多发行版上被拒绝安装。LFS是一个好办法,因为无论何时你需要安装一个软件时,你总能想到哄骗它使它安装成功的方法,无非就是找到它所依赖的软件,打上一个补丁而已。

不过,能这样做的前提是你拥有一个Multilib系统。如果系统是纯64位的,你怎么折腾也不可能让它支持32位,除非你做一个Cross LFS。

现在,我假定你有一个支持Multilib的宿主,比如Ubuntu。如果你按照LFS Book上面所说的去安装LFS,一般来说是会失败的。这是因为,默认情况下,gcc在64位系统下要进行更多的编译工作以支持Multilib。这可以通过--disable-multilib选项加以防止。如果加上了这个选项,那么你最终得到的是纯64位系统。

但我们的目的不是这个!我们要的是兼容性最好的系统!我们要运行32位代码!为了做到这点,就需要Multilib LFS了。那么如何做到这点呢?

实现Multilib LFS要面临很多兼容性挑战。最首要的一个,就是把不同架构的库存放在什么地点。一般来说,有以下几种安排:

                                /lib32             /lib             /lib64
某些发行版            32位库             64位库        到/lib的链接
工具链默认配置   到/lib的链接  32位库        64位库
本文采用配置       32位库              可变            64位库

某些Linux发行版,如Ubuntu,采用/lib32:/lib配置方式,并把/lib64设置为到/lib的符号链接。对于LFS来说,这种配置方式有个好处,就是在安装大多数32软件库的时候无须修改--libdir的设置,它自动就会装到/lib目录下。但是对于multilib,由于一般来说软件库必须安装两次,一次是32位安装,一次64位,其中至少要设置一次--libdir,那么其带来的方便还比不上它可能带来的错误。(比如,错把32位库安装到了64位的位置)

不幸的是,默认情况下,工具链以及CLFS采用的是另一种/lib:/lib64的配置方式。这种方式其实是最不方便的,一来容易带来错误(比如把64位库装到32位的位置),二来无法默认64位的库而必须设置--libdir。

我们在本文中推荐的方式是/lib32:/lib64的配置。采用这个配置能强迫你在安装软件库的时候,必须注意--libdir的设置,从而防止错误。而且,在出现因配置方式不同而出现的兼容性问题时,可以通过修改/lib符号链接的方式来修正。

现在,让我们进入LFS 5.3 Binutils 2.18。这里是Multilib LFS 开始出现差异的地方。
发表于 2008-2-28 08:51:22 | 显示全部楼层
期待继续,楼主加油哦!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-2-28 18:23:08 | 显示全部楼层
安装Binutils需要一个补丁,在http://svn.cross-lfs.org/svn/rep ... ts_multilib-1.patch
下载。
patch -Np1 -i ../binutils-2.18-genscripts_multilib-1.patch

然后创建编译目录
mkdir ../binutils-build
cd ../binutils-build

这里的参数跟LFS的差不多,就是多了一个--enable-64-bit-bfd,用于确保把64位二进制文件格式支持编译进去。此外,用-m64选项可确保编译出来的代码是64位(可选,一般这是默认选项)。
CC="gcc -m64 -B/usr/bin/" ../binutils-2.18/configure \
    --prefix=/tools --disable-nls --disable-werror \
    --enable-64-bit-bfd

以下步骤和LFS的一样
make
make install
make -C ld clean
make -C ld LIB_PATH=/tools/lib
cp  -v ld/ld-new /tools/bin

现在,我们要把Binutils的库挪到/lib64去,因为编译出来的代码是64位:
mv /tools/lib{,64}
ln -s /tools/lib{64,}

5.4 GCC 4.2.3
为了实施我们/lib32:/lib64的Multilib配置,编译GCC的时候需要进行一些调整:
cp gcc/config/i386/t-linux64{,.orig}
sed  -e 's@../lib64 ../lib@../lib64 ../lib32@g'  \
gcc/config/i386/t-linux64.orig > gcc/config/i386/t-linux64

创建编译目录
mkdir ../gcc-build
cd ../gcc-build

参数方面,GCC会自动在必要时候添加-m64,因此无须再加。此外,--enable-long-long 参数需要添加进去。--disable-bootstrap是可选的,目的是减少一点编译时间。
CC="gcc -B/usr/bin" ../gcc-4.2.3/configure --prefix=/tools \
      --with-local-prefix=/tools --disable-nls --enable-shared \
      --enable-languages=c --enable-long-long --disable-bootstrap

make
make install
ln -vs gcc /tools/bin/cc

5.5 Linux API headers 2.6.24
跟LFS完全一样,不需要更改:

make mrproper
make headers_check
make INSTALL_HDR_PATH=dest headers_install
cp -rv dest/include/* /tools/include

5.6 Glibc 2.7
对于Multilib,Glibc需要生成两次,一次32位,一次64位。

32位:
创建目录
mkdir ../glibc-build
cd ../glibc-build

在有些发行版上,可能检测forced_unwind和c_cleanup的时候会出错,如果不出错,以下这两行可以忽略。
echo "libc_cv_forced_unwind=yes">config.cache
echo "libc_cv_c_cleanup=yes" >> config.cache

这条命令是关键,用于设置libc.so的位置。
echo "slibdir=/tools/lib32">>configparms

和LFS相比,主要就是CFLAGS的设置方法不同(以下方法来自CLFS),以及需要添加--host=i686-pc-linux-gnu,CC需要明确加上-m32。
还有,如果你需要添加前述有关config.cache文件的命令,就要使用--cache-file选项。
BUILD_CC="gcc" CC="gcc -m32" CFLAGS="-march=i686 -mtune=generic -g -O2" ../glibc-2.7/configure --prefix=/tools --libdir=/tools/lib32 --host=i686-pc-linux-gnu --with-binutils=/tools/bin --with-headers=/tools/include --cache-file=config.cache --disable-profile --enable-add-ons --enable-kernel=2.6.0 --with-__thread --with-tls

make
make install

64位

mkdir ../glibc-build
cd ../glibc-build

echo "libc_cv_forced_unwind=yes">config.cache
echo "libc_cv_c_cleanup=yes" >> config.cache

再次提醒:这个命令是绝对必要!
echo "slibdir=/tools/lib64">>configparms

64位的配置比较简单,只要注意设置--libdir就可以了。--cache-file选项的使用条件同前。
../glibc-2.7/configure --prefix=/tools --libdir=/tools/lib64 --with-binutils=/tools/bin --with-headers=/tools/include --cache-file=config.cache --disable-profile --enable-add-ons --enable-kernel=2.6.0 --with-__thread --with-tls

make
make install

5.7 调整工具链
首先调整ld,这一步和LFS一样:
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
gcc -dumpspecs > `dirname $(gcc -print-libgcc-file-name)`/specs
vi `dirname $(gcc -print-libgcc-file-name)`/specs

在vi界面里,将/lib换成/tools/lib32,/lib64换成/tools/lib64,然后保存退出。

以下步骤和LFS一样,删除被GCC调整过的头文件:
GCC_INCLUDEDIR=`dirname $(gcc -print-libgcc-file-name)`/include &&
find ${GCC_INCLUDEDIR}/* -maxdepth 0 -xtype d -exec rm -rvf '{}' \; &&
rm -vf `grep -l "DO NOT EDIT THIS FILE" ${GCC_INCLUDEDIR}/*` &&
unset GCC_INCLUDEDIR

现在测试工具链:
echo "main(){}"  > dummy.c
cc dummy.c
readelf a.out -l
应该看到/tools/lib64的字样。
cc -m32 dummy.c
readelf a.out -l
应该看到/tools/lib32的字样。

好了,到这里,我们的完整工具链就完成了。接下来,该是时候构建临时系统了。
回复 支持 反对

使用道具 举报

发表于 2008-2-29 04:41:48 | 显示全部楼层
问一下:这个和 CLFS 有啥具体区别没?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-2-29 17:17:51 | 显示全部楼层
LFS和CLFS的区别何在?让我们对比一下。

1、CLFS需要两个工具目录:cross-tools用于存放交叉编译工具链,tools用于存放临时工具链。
    Multilib LFS只有一个工具目录。
2、CLFS的交叉编译工具链相当于LFS中的第一遍工具链 ,但LFS的第一遍工具链只用于生成GLibc(以及一些测试用的包如Tcl等),随后就被第二遍工具链覆盖。而CLFS的交叉工具链要一直用到临时系统构建完毕。
    Multilib LFS的第一遍工具链也将被第二遍的覆盖。
3、根据宿主系统的不同,CLFS在临时系统之后有Boot和Chroot的选择,LFS只有Chroot。
   Multilib LFS只有Chroot。
4、CLFS需要设置很多环境变量。LFS相对较少。
   Multilib LFS跟LFS的环境变量差不多。
5、CLFS的交叉编译工具链是静态链接的,新版LFS的第一遍工具链是动态链接的。
   Multilib LFS的第一遍工具链是动态链接的。
回复 支持 反对

使用道具 举报

发表于 2008-3-1 20:07:03 | 显示全部楼层
加油吧,我太久没基础 LFS了,细节都忘光了。。谢谢提醒。:)
回复 支持 反对

使用道具 举报

发表于 2008-3-13 16:06:00 | 显示全部楼层
楼主这样做LFS其实就是把LFS的pure64的模式里加了一个支持32位编译的工具链吧,我觉得最大的好处就是可以装grub了
回复 支持 反对

使用道具 举报

发表于 2008-3-15 07:29:30 | 显示全部楼层
楼主加油啊,您的大作是偶的指南 :)
回复 支持 反对

使用道具 举报

发表于 2008-3-26 09:46:45 | 显示全部楼层
我下了2.6.24的kernel,怎么里面没有asm-x86_64等这些平台代码?不会有影响吗?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-3-26 18:11:16 | 显示全部楼层
现在asm-x86_64的平台代码已经合并在x86里面,全凭一些编译参数选择。所以没有影响的。
回复 支持 反对

使用道具 举报

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

本版积分规则

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