LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
楼主: 地球发动机

用GCC 4.3-20040810构造SYSROOT工具链

[复制链接]
发表于 2008-4-14 00:16:27 | 显示全部楼层
发动机发动了~
---
不错~等我放假了,就一口气把LFS来次~
现在是老板月经期~上班不敢乱动~
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-4-14 11:54:37 | 显示全部楼层
Post by 1987a;1837856
首先,lz 已经修改cc这个部分,表扬一下。但c++还留着,还是不妥。

按个人理解:
gcc已经是非常成熟的软件包,在host系统各相关软件版本满足该版本gcc配置编译要求的情况下,制作toolchain过程中,配置编译该版本gcc时,应当仅给出--build --host --target参数以及相应binutils工具变量就可以顺利完成编译才是正常的,不应当依赖其它不相关变量设置或连接(如lz 给出的cc/c++软连接);
否则,就是什么地方出了问题,可能是该版本gcc的bug,可能是编译者hacking引起的,可能是host系统并不真正满足要求……



lz这么讲正说明自己相关概念不清晰,有点逻辑混乱。没别的意思,只是讨论讨论,有不对的地方,尽管使板砖。

没错,你的gcc是cross gcc,是toolchain中使用的cross gcc。
我只是说"你这么做相当于为host升级了 native gcc"。
可能是我没讲清楚,lz正文中cc c++两个软连接给我的直接印象是toolchain中gcc的编译依赖host系统的gcc-4.3,而lz的host系统使用的是低版本的gcc。
我认为对host系统的基本要求应当加入gcc-4.3,相应的GMP MPFR也加入基本要求,这样制作toolchain的过程应当只需要正常的2次编译gcc而不是lz的3次,同时也不需要cc c++两个软连接。这个现在只是猜测,需要实际验证。


没必要这么偏执,必要时,还是需要的,过河是目的,之后拆桥都成,host系统随你处置。
如你把GMP MPFR安装在host系统/usr下,不是更简单么,制作toolchain时不再需要--with-gmp --with-mpfr参数。


按个人标准,这是hacking,可能会带来不可预测的后果,应优先使用通用方法,除非这种行为能带来可以接受的优势,或不得不这样做。


我不否认你这个是cross gcc。但根据你的正文,你有定义这么两个变量CLFS_HOST=x86_64-cross-linux-gnu CLFS_TARGET=x86_64-unknown-linux-gnu,所以你的cross gcc事实上是一个变相的native gcc,只是它的sysroot路径指向/mnt/clfs。不出意外的话,你host系统和toolchain使用的是同版本glibc-2.7。用你的toolchain交叉编译一份for x86_64的程序,只要host系统有同版本必须的lib,可以在host系统上运行的几率接近1。
另,你连接为cc的第一次编译的gcc-4.3,是一个静态的裸编译器。在你用它完成第一遍gcc-4.3后半部分时,等同于native gcc-4.3。
请注意到此为止,我从没说过你的gcc是native gcc。


对以上评论的答复如下:
1. GCC 4.3本次作出的重大改变是将Libgcc等独立为单独的build-target。这样的方式,其优点是独立性更强了,缺点是需要对构建系统做较大修改。在Native build的情况下,它能自动将新编译的gcc用于构建相应的libgcc。我承认,使用符号连接的方法是一种hacking,但至于你说的“不相关变量”,我不同意。CC_FOR_TARGET和CXX_FOR_TARGET从名字上就可以看出来,是专门用来设置生成TARGET代码所需的CC和CXX用的。所以这并不是“不相关变量”

2.事实上,我们看到GCC4.3 cross不需要在GCC 4.3 host上编译。从GCC官方网站我们看到的是GCC 4.3对宿主native GCC的最低要求是2.95。
那么我们为什么会面临libgcc不能编译的问题呢?根本的原因是libgcc应该在刚编译的gcc下编译出来,不管是cross build还是native build。
如果说,有了native gcc 4.3之后能够顺利编译cross build,那是侥幸!因为你刚好有一个native libgcc for CLFS_TARGET,所以你编译当然是没有问题。但如果你进行真正的cross build(例如,for 龙芯),就会碰壁了。原因很简单,你的native gcc里面不会有libgcc for 龙芯,因此编译必然失败。

3.编译3次绝对不正常。是因为编译系统出了毛病造成的。本来,动态库的构建应当依赖于已经编译完成的静态库,但现在静态库还没编译出来,gcc的Makefile就已经试图编译动态库了。这应该是一个bug。目前的方案只是绕开了问题,并没有解决问题。尽管看上去,如果有一个native build似乎就解决了这个问题,但那是虚假的。因为编译target库必须使用新编译的编译器,这是保证系统运作良好的基本要求。
回复 支持 反对

使用道具 举报

发表于 2008-4-14 21:00:05 | 显示全部楼层
验证进展:

我参照自己使用的 CLFS-SYSROOT x86_64 pure64 Builds 和 lz 的方法,进行的验证表明,用 lz 方法得到的 toolchain 纯>度有缺陷。

1. x86_64 -> x86_64 伪交叉编译toolchain
host系统x86_64-unknown-linux-gnu
完成相当于 lz 方法8小节后,尝试直接完成 final gcc 失败,提示找不到libgcc_s,怀疑受到 host 系统影响,决定放弃伪>交叉编译。

值得指出的是,进行gcc静态编译时,仿照 lz 方法的结果与
  1. make && make install
复制代码
一样,我使用fakeroot的方式比较了两种方法的结果。

2. i686 -> x86_64 交叉编译toolchain
host系统i686-pc-linux-gnu
进行gcc静态编译时出错,make all-gcc 结果如下
  1. x86_64-unknown-linux-gnu-gcc  -dumpspecs > tmp-specs
  2. [font color="red"][strong]/bin/sh: x86_64-unknown-linux-gnu-gcc: command not found[/strong][/font]
  3. make[1]: *** [specs] Error 127
  4. make[1]: Leaving directory `/x86_64-linux-gnu/source/gcc-build/gcc'
  5. make: *** [all-gcc] Error 2
复制代码

[font color="red"]对照方法1,我们可以确认方法1引入host系统 gcc specs 到toolchain,所以说 lz 方法得到的 toolchain 纯度有缺陷。
同时我们也应注意,使用伪交叉编译方式建立 toolchain 不安全,有可能在自己不清楚的情况下引入 host系统的东西。
当然,如果该方法经过真正的交叉编译方式验证后,应该是可以放心使用的。如用官方CLFS-sysroot进行伪交叉编译。

我暂时的解决方案是,
  1. make all-gcc
  2. make -C gcc
  3. make all-gcc &&
  4. make install-gcc &&
  5. make all-target-libgcc &&
  6. make install-target-libgcc
复制代码

完成相当于 lz 方法8小节后,尝试直接完成 final gcc 失败,make结果如下
  1. checking for x86_64-unknown-linux-gnu-gcc... x86_64-unknown-linux-gnu-gcc
  2. checking for C compiler default output file name... configure: error: C compiler cannot create executables
  3. See `config.log' for more details.
  4. make[1]: *** [configure-target-libgomp] Error 1
  5. make[1]: Leaving directory `/x86_64-linux-gnu/source/gcc-build'
  6. make: *** [all] Error 2
复制代码
恢复备份到完成相当于 lz 方法8小节后状态,仿照 lz 方法9、10小节,完成 toolchain。
回复 支持 反对

使用道具 举报

发表于 2008-4-14 21:11:54 | 显示全部楼层
刚刚交叉编译一份64bit sed,可以正常运行于x86_64环境,初步验证表明,toolchain可用。
回复 支持 反对

使用道具 举报

发表于 2008-4-14 21:56:28 | 显示全部楼层
1. 但至于你说的“不相关变量”,我不同意。CC_FOR_TARGET和CXX_FOR_TARGET

我提到“不相关变量”时,你使用的还是软连接cc c++。这个只是说明,不是指CC_FOR_TARGET和CXX_FOR_TARGET。
我自己的验证表明,根据编译错误,确实需要设置这两个变量。伪交叉编译静态gcc时执行make && make install,在不设置CC_FOR_TARGET时,有类似CC_FOR_TARGET=x86_64-unknown-linux-gnu-cc的错误提示。很自然就联想到需要设置这个变量。

2.事实上,我们看到GCC4.3 cross不需要在GCC 4.3 host上编译。从GCC官方网站我们看到的是GCC 4.3对宿主native GCC的最低要求是2.95。
那么我们为什么会面临libgcc不能编译的问题呢?根本的原因是libgcc应该在刚编译的gcc下编译出来,不管是cross build还是native build。
如果说,有了native gcc 4.3之后能够顺利编译cross build,那是侥幸!因为你刚好有一个native libgcc for CLFS_TARGET,所以你编译当然是没有问题。但如果你进行真正的cross build(例如,for 龙芯),就会碰壁了。原因很简单,你的native gcc里面不会有libgcc for 龙芯,因此编译必然失败。

我的验证表明,你的伪交叉编译方式确实侥幸。
这里有逻辑错误,toolchain实际是运行于host的,是host系统上的程序,libgcc是目标系统库,是需要交叉编译器来编译的,编译用于toolchain 的 gcc时不会受host系统gcc影响。
我的验证表明,编译用于toolchain 的 gcc 时没有cc c++出现,但有类似CC_FOR_TARGET=x86_64-unknown-linux-gnu-cc的错误提示。

3.编译3次绝对不正常。是因为编译系统出了毛病造成的。本来,动态库的构建应当依赖于已经编译完成的静态库,但现在静态库还没编译出来,gcc的 Makefile就已经试图编译动态库了。这应该是一个bug。目前的方案只是绕开了问题,并没有解决问题。尽管看上去,如果有一个native build似乎就解决了这个问题,但那是虚假的。因为编译target库必须使用新编译的编译器,这是保证系统运作良好的基本要求。

进行伪交叉编译时,我发现,完成你方法中的第8小节后,直接进行 final gcc 时失败,提示找不到libgcc_s.so。进入gcc-build/libgcc下查看是有需要的文件的,也就是说如果可以中途安装这些库的话,应该是可以2编完成的。
但结合我交叉编译的验证结果,伪交叉编译在验证前不可靠。
回复 支持 反对

使用道具 举报

发表于 2008-4-14 22:06:35 | 显示全部楼层
建议lz把glibc系统搜索路径调整部分
cp configure{,.orig}
sed -e "/ccheaders=/s/\`\(\$CC.*include\)\`/\"& -isystem \`\1-fixed\`\"/" configure.orig > configure
修改为
sed -i -e '/SYSINCLUDES=/s@-isystem $ccheaders @&-isystem $ccheaders-fixed @'  configure
更简单明了。
回复 支持 反对

使用道具 举报

发表于 2008-4-14 22:19:43 | 显示全部楼层
之前我们说过,默认情况下静态库的生成不包括libgcc_eh.a,尽管我们加了个补丁,make install-target-libgcc仍然不会把生成的文件拷贝过去。没关系,我们手工来做:
cp $CLFS_TARGET/libgcc/libgcc_eh.a $CLFS/cross-tools/lib/gcc/$CLFS_TARGET/4.3.1
cp $CLFS_TARGET/32/libgcc/libgcc_eh.a $CLFS/cross-tools/lib/gcc/$CLFS_TARGET/4.3.1/32
${CLFS_TARGET}-ranlib $CLFS/cross-tools/lib/gcc/$CLFS_TARGET/4.3.1/libgcc_eh.a
${CLFS_TARGET}-ranlib $CLFS/cross-tools/lib/gcc/$CLFS_TARGET/4.3.1/32/libgcc_eh.a

这部分没必要,画蛇添足。
glibc-2.7-libgcc_eh-1.patch就是用来解决循环依赖问题的。
不爽的话,可以最后再多编译一遍glibc。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-4-15 10:17:17 | 显示全部楼层
Post by 1987a;1838227
1. 但至于你说的“不相关变量”,我不同意。CC_FOR_TARGET和CXX_FOR_TARGET

我提到“不相关变量”时,你使用的还是软连接cc c++。这个只是说明,不是指CC_FOR_TARGET和CXX_FOR_TARGET。
我自己的验证表明,根据编译错误,确实需要设置这两个变量。伪交叉编译静态gcc时执行make && make install,在不设置CC_FOR_TARGET时,有类似CC_FOR_TARGET=x86_64-unknown-linux-gnu-cc的错误提示。很自然就联想到需要设置这个变量。

2.事实上,我们看到GCC4.3 cross不需要在GCC 4.3 host上编译。从GCC官方网站我们看到的是GCC 4.3对宿主native GCC的最低要求是2.95。
那么我们为什么会面临libgcc不能编译的问题呢?根本的原因是libgcc应该在刚编译的gcc下编译出来,不管是cross build还是native build。
如果说,有了native gcc 4.3之后能够顺利编译cross build,那是侥幸!因为你刚好有一个native libgcc for CLFS_TARGET,所以你编译当然是没有问题。但如果你进行真正的cross build(例如,for 龙芯),就会碰壁了。原因很简单,你的native gcc里面不会有libgcc for 龙芯,因此编译必然失败。

我的验证表明,你的伪交叉编译方式确实侥幸。
这里有逻辑错误,toolchain实际是运行于host的,是host系统上的程序,libgcc是目标系统库,是需要交叉编译器来编译的,编译用于toolchain 的 gcc时不会受host系统gcc影响。
我的验证表明,编译用于toolchain 的 gcc 时没有cc c++出现,但有类似CC_FOR_TARGET=x86_64-unknown-linux-gnu-cc的错误提示。

3.编译3次绝对不正常。是因为编译系统出了毛病造成的。本来,动态库的构建应当依赖于已经编译完成的静态库,但现在静态库还没编译出来,gcc的 Makefile就已经试图编译动态库了。这应该是一个bug。目前的方案只是绕开了问题,并没有解决问题。尽管看上去,如果有一个native build似乎就解决了这个问题,但那是虚假的。因为编译target库必须使用新编译的编译器,这是保证系统运作良好的基本要求。

进行伪交叉编译时,我发现,完成你方法中的第8小节后,直接进行 final gcc 时失败,提示找不到libgcc_s.so。进入gcc-build/libgcc下查看是有需要的文件的,也就是说如果可以中途安装这些库的话,应该是可以2编完成的。
但结合我交叉编译的验证结果,伪交叉编译在验证前不可靠。


对于第三个问题,我想原因可能是,gcc一些组件需要被随后的步骤访问,但现在gcc编译系统没能把之前的步骤所产生的文件关联到后面的步骤上去。因此你需要做一次make all-target-libgcc && make install-target-libgcc,然后再make。试试看?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-4-15 10:30:40 | 显示全部楼层
Post by 1987a;1838231
建议lz把glibc系统搜索路径调整部分
cp configure{,.orig}
sed -e "/ccheaders=/s/\`\(\$CC.*include\)\`/\"& -isystem \`\1-fixed\`\"/" configure.orig > configure
修改为
sed -i -e '/SYSINCLUDES=/s@-isystem $ccheaders @&-isystem $ccheaders-fixed @'  configure
更简单明了。

我觉的你的是简单些。不过有一点我觉得 sed -i 的方式不太好,特别对初学者不利。先做cp备份的方式有一个好处,就是完成后可以很容易检验:
diff configure{,.orig}
要是没有任何输出,或者输出超过3行,肯定是有问题。而这时候原始文件没有被破坏,可以随时修改命令后继续。

此外,我之前不是没有想过去修改SYSINCLUDES这一行,但从程序设计的角度看,这两者的作用虽然一样,但语义是不一样的。原来的设计,是让ccheaders自动调用CC来找到头文件的目录。我的修改是让它调用两次,也就是说两次都是从CC生成的。而你的修改则去改动引用ccheaders的地方,这暗中假定了include和include-fixed两个目录是放在同一个地方的。虽然目前两者都可以达到目的,但是显然降低了灵活性。鉴于这些情况,我会坚持使用原来的补丁。
回复 支持 反对

使用道具 举报

发表于 2008-4-18 00:36:01 | 显示全部楼层
Post by 地球发动机;1838385
我觉的你的是简单些。不过有一点我觉得 sed -i 的方式不太好,特别对初学者不利。先做cp备份的方式有一个好处,就是完成后可以很容易检验:
diff configure{,.orig}
要是没有任何输出,或者输出超过3行,肯定是有问题。而这时候原始文件没有被破坏,可以随时修改命令后继续。

此外,我之前不是没有想过去修改SYSINCLUDES这一行,但从程序设计的角度看,这两者的作用虽然一样,但语义是不一样的。原来的设计,是让ccheaders自动调用CC来找到头文件的目录。我的修改是让它调用两次,也就是说两次都是从CC生成的。而你的修改则去改动引用ccheaders的地方,这暗中假定了include和include-fixed两个目录是放在同一个地方的。虽然目前两者都可以达到目的,但是显然降低了灵活性。鉴于这些情况,我会坚持使用原来的补丁。


有些道理。
不过应用你的补丁,ccheaders这一行会多出一个 -isystem ,感觉怪怪的。

这里有些奇怪,完成第一编 gcc 后,运行tools 下 x86_64-unknown-linux-cpp -v ,可以清楚的看到 include-fixed 在系统头文件搜索路径下,但编译 glibc 居然要要用 -isystem 指明。
回复 支持 反对

使用道具 举报

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

本版积分规则

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