LinuxSir.cn,穿越时空的Linuxsir!

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

Sysroot 方式从源码构建完全本地编译的 GNU/Linux 系统

[复制链接]
发表于 2008-4-24 19:45:38 | 显示全部楼层 |阅读模式
本文用于解决如下问题:

  • 以 Sysroot 方式,从源码构建完全本地编译的 GNU/Linux 系统。
  • 官方 CLFS-Sysroot x86 方法中 Basic System 为交叉编译产物,本文方法中 Basic System 完全本地编译生成。
  • 官方 CLFS-Sysroot 无 x86_64 系统构建方法,本文提供 CLFS-Sysroot x86_64-Pure64 方法,并且 Basic System 完全本地编译生成。
  • 理论上,本文提供的方法亦适用其它平台架构。不具备本地编译条件的嵌入式平台请使用官方方法。
2008.6.11更新(添加官方资源)
2008.5.25除错(不再需要静态bash,第一次启动过程中udev也不再报错)
2008.4.24创建(谨以本文纪念中国A股印花税恢复为0.1%)


本文提供方法,最初使用的各软件包版本和补丁是参考 CLFS-SYSROOT-SVN-0.0.1-20080121CLFS-TRUNK-SVN-20080228 中 x86、x86_64 部分。
CLFS-SYSROOT-SVN手册:
  1. svn co [URL]http://svn.cross-lfs.org/svn/repos/cross-lfs/branches/clfs-sysroot/BOOK/[/URL]
复制代码
CLFS-TRUNK-SVN手册:
  1. svn co [URL]http://svn.cross-lfs.org/svn/repos/cross-lfs/branches/clfs-sysroot/BOOK/[/URL]
复制代码
推荐参考官方手册最新版本 (2008.6.11 添加)


一、构建 x86 GUN/Linux 系统:

  • 参考 CLFS-SYSROOT-SVN手册 x86 II.2. II.3. II.4.,根据自己需要完成设置。
  • 参考 CLFS-SYSROOT-SVN手册 x86 III.5. 完成 toolchian。
  • 参考 CLFS-TRUNK-SVN手册 x86 IV.6. 软件包编译顺序,按照 CLFS-SYSROOT-SVN手册 x86 IV.6. 提供的编译参数完成 Temporary System,交叉编译阶段到此为止。其中交叉编译 bash 时配置过程比较特殊,使用下面的步骤:
    1. cat > config.cache << eof
    2. ac_cv_func_mmap_fixed_mapped=yes
    3. ac_cv_func_strcoll_works=yes
    4. ac_cv_func_working_mktime=yes
    5. bash_cv_func_sigsetjmp=present
    6. bash_cv_getcwd_malloc=yes
    7. bash_cv_job_control_missing=present
    8. bash_cv_printf_a_format=yes
    9. bash_cv_sys_named_pipes=present
    10. bash_cv_ulimit_maxfds=yes
    11. bash_cv_under_sys_siglist=yes
    12. bash_cv_unusable_rtsigs=no
    13. gt_cv_int_divbyzero_sigfpe=yes
    14. eof
    15. ./configure --prefix=/usr  \
    16.      --build=${CLFS_HOST} \
    17.      --host=${CLFS_TARGET} \
    18.      --bindir=/bin \
    19.      --without-bash-malloc \
    20.      --cache-file=config.cache
    复制代码
  • 根据自己需要,参考 CLFS-TRUNK-SVN手册 x86 IV.7. 或 IV.8. 软件包编译顺序,按照 CLFS-SYSROOT-SVN手册 x86 III.5. 提供的编译参数完成 Temporary System 剩余部分。如果启动 Temporary System 发现 udev 报错,并且 /dev 下有设备文件,可安全忽略这些错误, 完成 Basic System 后就不会再报错了。(2008.5.25 已修正)
  • 如果不准备运行各软件包测试,可以跳过这一步,参考 CLFS-TRUNK-SVN手册 x86 IV.9. 完成支持测试的软件包,请把/tools 替换为 /usr 或 /usr/local。
  • 参考 CLFS-TRUNK-SVN手册 x86 IV.10. Temporary Perl 或 Perl 编译参数,完成Temporary Perl,请把/tools 替换为 /usr 或 /usr/local。
  • 参考 CLFS-TRUNK-SVN手册 x86 IV.10. bash,完成一份临时的静态编译bash,请在运行 ./configure 时添加 --disable-shared,安装为 /bin/bash.static 并建立连接为/bin/sh。如果不做这一步,下一步安装 Ncurses 时,系统会挂起,完成 Basic System 后,可以删除 /bin/bash.static 并建立连接指向 /bin/bash 的 /bin/sh。(2008.5.25 不再需要)
  • 参考 CLFS-TRUNK-SVN手册 x86 IV.10 软件包编译顺序,完成除 Temporary Perl 外所有软件包,完成本地编译的 Basic System。
二、构建 x86_64-Pure64 GUN/Linux 系统:
仿照上面构建 x86 GUN/Linux 系统的方法, 根据 CLFS-TRUNK-SVN手册 x86_64-64 修改相关变量, 并根据 CLFS-TRUNK-SVN手册 x86_64-64 使用相关pure64补丁, 即可完成本地编译的 Basic System.

  • 参考 CLFS-SYSROOT-SVN手册 x86 II.2. II.3. II.4. 与 CLFS-TRUNK-SVN手册 x86_64-64 II.2. II.3. II.4.,根据自己需要完成设置。
  • 参考 CLFS-SYSROOT-SVN手册 x86 III.5 与 CLFS-TRUNK-SVN手册 x86_64-64 III.5 提供的 pure64 补丁,完成 toolchian。
  • 参考 CLFS-TRUNK-SVN手册 x86_64-64 IV.6. 软件包编译顺序及pure64补丁,仿照 CLFS-SYSROOT-SVN手册 IV.6. 提供的编译参数,完成 Temporary System,交叉编译阶段到此为止。其中交叉编译 bash 时配置过程比较特殊,使用下面的步骤:
    1. cat > config.cache << eof
    2. ac_cv_func_mmap_fixed_mapped=yes
    3. ac_cv_func_strcoll_works=yes
    4. ac_cv_func_working_mktime=yes
    5. bash_cv_func_sigsetjmp=present
    6. bash_cv_getcwd_malloc=yes
    7. bash_cv_job_control_missing=present
    8. bash_cv_printf_a_format=yes
    9. bash_cv_sys_named_pipes=present
    10. bash_cv_ulimit_maxfds=yes
    11. bash_cv_under_sys_siglist=yes
    12. bash_cv_unusable_rtsigs=no
    13. gt_cv_int_divbyzero_sigfpe=yes
    14. eof
    15. ./configure --prefix=/usr  \
    16.      --build=${CLFS_HOST} \
    17.      --host=${CLFS_TARGET} \
    18.      --bindir=/bin \
    19.      --without-bash-malloc \
    20.      --cache-file=config.cache
    复制代码
  • 根据自己需要,参考 CLFS-TRUNK-SVN手册 x86_64-64 IV.7. 或 IV.8. 软件包编译顺序及 pure64 补丁,仿照 CLFS-SYSROOT-SVN手册 x86 III.5. 提供的编译参数完成 Temporary System 剩余部分。如果启动 Temporary System 发现 udev 报错,并且 /dev 下有设备文件,可安全忽略这些错误,完成 Basic System 后就不会再报错了。(2008.5.25 已修正)
  • 如果不准备运行各软件包测试,可以跳过这一步,参考 CLFS-TRUNK-SVN手册 x86_64-64 IV.9. 完成支持测试的软件包,请把/tools 替换为 /usr 或 /usr/local。
  • 参考 CLFS-TRUNK-SVN手册 x86_64-64 IV.10. Temporary Perl 或 Perl编译参数,完成Temporary Perl,请把/tools 替换为 /usr 或 /usr/local。
  • 参考 CLFS-TRUNK-SVN手册 x86_64-64 IV.10. bash,完成一份临时的静态编译bash,请在运行 ./configure 时添加 --disable-shared,安装为 /bin/bash.static 并建立连接为/bin/sh。如果不做这一步,下一步安装 Ncurses 时,系统会挂起,完成 Basic System 后,可以删除 /bin/bash.static 并建立连接指向 /bin/bash 的 /bin/sh。(2008.5.25 不再需要)
  • 参考 CLFS-TRUNK-SVN手册 x86_64-64 IV.10 软件包编译顺序及 pure64 补丁,完成除 Temporary Perl 外所有软件包,完成本地编译的 Basic System。
 楼主| 发表于 2008-4-24 19:46:32 | 显示全部楼层
我一直在使用上文中所述方法建立 GUN/Linux 系统,目前使用的系统是2008.3.31建立的。

使用的各软件包是截止2008.3.31的稳定版或rc版,
www.linuxfromscratch.org 官方补丁均使用 sed 手工修补,
例外有三处,
一是使用了 E2fsprogs-1.40.2,因为 E2fsprogs-1.40.6 与 grub-0.97 不兼容,
一是使用了bash的GNU官方补丁,
一是使用了自己编写的启动脚本,
另用于支持测试的软件包 Tcl Expect DejaGNU Tree 请使用官方推荐版本否则可能安装失败。


如果对 gcc-4.3 或 multilib方式 感兴趣,
请参考 地球发动机 大作
[color="Blue"]用GCC 4.3-20040810构造SYSROOT工具链
[color="blue"]最新LFS实践播报:SYSROOT Multilib LFS -注意不是CLFS

youbest 大作
[color="blue"]从源代码建立Linux系统之(Sysroot LFS 1.0)
回复 支持 反对

使用道具 举报

发表于 2008-4-25 10:24:33 | 显示全部楼层
呵呵,恭喜你完成了这一步。不过,我现在正在尝试新的Native Sysroot方法,并取得初步成功。

上次我发的帖子里面,需要build 2次glibc,或者2次gcc。但是现在,我已经找到方法,可以只build 1次。

窍门是,第一遍工具链,binutils +(gmp+mpfr+flex,如果用GCC 4.3)+GCC,并使用--with-sysroot=/的参数。这个GCC只要一次就够用,所以要bootstrap和允许c,c++等。

然后,我们来构建Glibc。先安装Linux头文件,然后在configure的时候,我们设置CC="gcc --sysroot=$SLFS"并加上$BUILD32/$BUILD64 变量。

完成Glibc之后,
export CC="gcc --sysroot=$SLFS"
export CXX="g++ --sysroot=$SLFS"
然后照常编译其他工具包。

这个方法我还在测试中,呵呵
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-4-25 14:12:44 | 显示全部楼层
Post by 地球发动机;1842301
呵呵,恭喜你完成了这一步。不过,我现在正在尝试新的Native Sysroot方法,并取得初步成功。

上次我发的帖子里面,需要build 2次glibc,或者2次gcc。但是现在,我已经找到方法,可以只build 1次。

窍门是,第一遍工具链,binutils +(gmp+mpfr+flex,如果用GCC 4.3)+GCC,并使用--with-sysroot=/的参数。这个GCC只要一次就够用,所以要bootstrap和允许c,c++等。

然后,我们来构建Glibc。先安装Linux头文件,然后在configure的时候,我们设置CC="gcc --sysroot=$SLFS"并加上$BUILD32/$BUILD64 变量。

完成Glibc之后,
export CC="gcc --sysroot=$SLFS"
export CXX="g++ --sysroot=$SLFS"
然后照常编译其他工具包。

这个方法我还在测试中,呵呵


客气了。
其实我一直在使用上文中所述方法建立系统,我目前使用的系统是2008.3.31建立的。

近几月中我建立系统次数不下百次,第一次建立系统用时断断续续近一月,建立系统的同时也是编写自动建立系统脚本的过程。因为,我尽力使用最新版软件(大部分情况新版本更好),用脚本手工打补丁(不信任LFS官方补丁),自己建立启动脚本(不喜欢LFS官方启动脚本),中间还有误操作推倒重来的,仅仅拿官方文挡作为自己建立系统的参考。
付出是值得的、有回报的,目前我已经把建立基本系统时间缩减到不到6小时。并且在这6小时内,在单机同时并行建立 x86 x86_64-pure64 两套基本系统,有时间我会把方法贴出来。
相信以目前大众化的硬件,使用脚本建立系统的兄弟大都可以把建立系统时间缩减到这个程度。如果不像我这样偏执非要求基本系统完全本地编译,时间可以再缩减到3小时。

按我自己的标准,www.linuxfromscratch.org 官方给出的方法能保证系统纯净的只有 CLFS-1.0.0 和 标准LFS 两类,本地编译也是系统纯净的一个必要要求。

标准LFS 方法烦琐,而且建立的系统与 host 系统有一样的 MACHTYPE,如 host 系统使用i386版的debian etch 完成的系统是 i486-pc-linux-gnu。
CLFS-1.0.0 方法与 标准LFS 方法 类似,优点是对 host 系统要求宽泛,可建立各种target系统,甚至非GNU/Linux系统。(你也可以进行同架构的伪交叉编译。最好不要这样做,找一个不同架构的系统很简单的,如在x86_64硬件环境下跑i686-pc-linux-gnu,在P4上跑i486-pc-linux-gnu。我的经验表明伪交叉编译不能保证 toolchain 纯净,自然无法保证系统纯净)

相对来说,CLFS 有最大的自由度,标准LFS 方法可以放弃。

Sysroot方法可以简化 CLFS-1.0.0 方法 与 标准LFS 方法,所以使用这种方法是大方向。

通过上面的讨论,标准LFS 方法 的 sysroot 变种其实也可以放弃的。当然你的尝试是应该肯定的。

你使用的是multilib的系统,正好和我形成补充,我这里是单机同时运行x86_64 x86两套系统。
我们两种系统各有优劣。我的系统大部分软件是双份,所以你的系统相对体积稍小。我这里不用考虑multilib,所以相对编译参数简单。我这里是两套系统并存,配置稍显麻烦。如果要向一台x86机器移植系统,我这里直接移植x86系统即可,你却要重头建立。

有时间我会整理一个并行运行、并行编译的帖子。
回复 支持 反对

使用道具 举报

发表于 2008-4-25 15:09:13 | 显示全部楼层
说点题外的话,我最近在构建好sysroot toolchain之后,把target分区上的glibc删除了重建。结果,install了32bit库之后configure 64bit失败。我想这不应该发生的,因为不然的话32bit的库怎么就能成功呢?然后跟踪了一下,原来因为有32bit库的存在,sysrooted的gcc就以为sysroot上的glibc已经装好了,glibc的configure脚本调用的时候就会给出错误的检测结果。

解决的方法是:建立glibc32和glibc64两个目录,分别configure,make,都成功之后才安装。

此外,原来ncurses包也是支持分离build目录的。这种方式比直接在源码目录下build好多了。我在考虑是否对所有的包检测这种build方式的可行性,呵呵
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-4-25 16:22:10 | 显示全部楼层
Post by 地球发动机;1842418
说点题外的话,我最近在构建好sysroot toolchain之后,把target分区上的glibc删除了重建。结果,install了32bit库之后configure 64bit失败。我想这不应该发生的,因为不然的话32bit的库怎么就能成功呢?然后跟踪了一下,原来因为有32bit库的存在,sysrooted的gcc就以为sysroot上的glibc已经装好了,glibc的configure脚本调用的时候就会给出错误的检测结果。

解决的方法是:建立glibc32和glibc64两个目录,分别configure,make,都成功之后才安装。

此外,原来ncurses包也是支持分离build目录的。这种方式比直接在源码目录下build好多了。我在考虑是否对所有的包检测这种build方式的可行性,呵呵

这正是multilib方式麻烦的地方。

分离build目录的方式是挺好,不过不是完全必要的。在这个方向浪费时间不值得,保持原样就好。就像你坚持multilib方式,我坚持非multilib方式,两种方式都可以正常工作嘛!
如果你非要试试,也许可以考虑使用gnu标准方法(autoconf automake)重新生成软件包configure,这样大部分软件包(除了少部分手工编写Makefile的软件包)应可以使用分离build目录的方式。

确实跑题了。

动态编译的 bash 依赖 ncurses,在完成 basic system 过程中,安装 ncurses 过程中会破坏原有交叉编译版本,安装 ncurses 过程中会调用 /bin/sh,动态编译的 bash 就会在安装过程中失效,使系统失去响应,所以这里要临时安装一份静态编译的 bash.static。
如果不介意交叉编译版本的存在,则可以跳过已经交叉编译的软件包,直接安装剩余的其它软件包,完成 basic system。同时也不必安装静态编译的 bash.static。
回复 支持 反对

使用道具 举报

发表于 2008-4-25 18:30:09 | 显示全部楼层
Post by 1987a;1842434

动态编译的 bash 依赖 ncurses,在完成 basic system 过程中,安装 ncurses 过程中会破坏原有交叉编译版本,安装 ncurses 过程中会调用 /bin/sh,动态编译的 bash 就会在安装过程中失效,使系统失去响应,所以这里要临时安装一份静态编译的 bash.static。
如果不介意交叉编译版本的存在,则可以跳过已经交叉编译的软件包,直接安装剩余的其它软件包,完成 basic system。同时也不必安装静态编译的 bash.static。

如果是Multilib系统,这个问题倒是有一个解决方案。安装bash的时候同时安装32bit和64bit两个版本,然后进入32bit的bash,安装64bit的ncurses;进入64bit的bash,安装32bit的ncurses

具体可以(假设用chroot方式)
chroot /mnt/clfs /bin/bash32 进入32bit
chroot /mnt/clfs /bin/bash64 进入64bit
如果是boot方式,需要修改grub配置,并设置两个init level指向不同的bash版本。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-4-25 19:01:36 | 显示全部楼层
Post by 地球发动机;1842501
如果是Multilib系统,这个问题倒是有一个解决方案。安装bash的时候同时安装32bit和64bit两个版本,然后进入32bit的bash,安装64bit的ncurses;进入64bit的bash,安装32bit的ncurses

具体可以(假设用chroot方式)
chroot /mnt/clfs /bin/bash32 进入32bit
chroot /mnt/clfs /bin/bash64 进入64bit
如果是boot方式,需要修改grub配置,并设置两个init level指向不同的bash版本。


呵呵,够坚持,不过还是静态编译方式通用。
另,主系统保留一份静态编译的shell同时也可用于非常时期救急。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-5-25 23:16:00 | 显示全部楼层
2008.5.25更新:
不再需要静态bash,第一次启动过程中udev也不再报错。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-5-25 23:47:03 | 显示全部楼层
Post by 1987a;1842434
动态编译的 bash 依赖 ncurses,在完成 basic system 过程中,安装 ncurses 过程中会破坏原有交叉编译版本,安装 ncurses 过程中会调用 /bin/sh,动态编译的 bash 就会在安装过程中失效,使系统失去响应,所以这里要临时安装一份静态编译的 bash.static。
如果不介意交叉编译版本的存在,则可以跳过已经交叉编译的软件包,直接安装剩余的其它软件包,完成 basic system。同时也不必安装静态编译的 bash.static。


这一部分分析有误,出现上面现象,与交叉编译动态连接生成的 bash 行为有关。

采用2008.4.24最初贴出的方法,不使用静态编译bash时,有上面现象。
采用2008.5.25修正后的方法,不需要静态编译bash,亦无上面现象。

早时的方法,交叉编译过程中,默认没有打开下面配置
  1. ac_cv_func_mmap_fixed_mapped=yes
复制代码


怀疑早时方法的动态连接bash,执行命令后,相关动态连接库加载到内存后没有映射,从而每次执行过程都要由文件系统读取。
怀疑新方法的动态连接bash,执行命令后,相关动态连接库加载到内存后进行映射,从而只有第一次执行命令时才由文件系统读取。
回复 支持 反对

使用道具 举报

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

本版积分规则

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