GCC 4.9.4 交叉编译器构建(limits.h 问题)

3

问题前的基本步骤:

cd linux-2.6.35.9/
make ARCH=x86 INSTALL_HDR_PATH=${PREFIX}/${TARGET} headers_install
cd ../

cd build-binutils/
sh ../binutils-2.28/configure --prefix=${PREFIX} --target=${TARGET}
make
make install
cd ../

cd build-gcc/
sh ../gcc-4.9.4/configure --prefix=${PREFIX} --target=${TARGET} --enable-languages=c,c++ --disable-multilib
make all-gcc
make install-gcc
cd ../

我遇到的问题是,安装到${PREFIX}/lib/gcc/${TARGET}/4.9.4/include-fixed/limits.h的内容似乎不正确。具体来说,在构建和安装GCC时,“fixincludes”位期望存在一个叫做“sys-include”的目录,但实际上从未放置,因此上述limits.h没有引用相关的syslimits.h(在同一目录中)。
如果我查看构建/安装序列的输出,会有一个关于使用limitx.h、limity.h和其他组件构建此文件的引用。这个测试失败了,它只安装了随GCC一起提供的“通用”limits.h(不包括对syslimits.h的引用,后者使用GCC的#include_next指令来引用${PREFIX}/${TARGET}/include/limits.h,其中包含了我需要的实际内容,如NAME_MAX和PATH_MAX)。
该文件缺失的内容是:
/* This administrivia gets added to the beginning of limits.h
   if the system has its own version of limits.h.  */

/* We use _GCC_LIMITS_H_ because we want this not to match
   any macros that the system's limits.h uses for its own purposes.  */
#ifndef _GCC_LIMITS_H_  /* Terminated in limity.h.  */
#define _GCC_LIMITS_H_

#ifndef _LIBC_LIMITS_H_
/* Use "..." so that we find syslimits.h only in this same directory.  */
#include "syslimits.h"
#endif

那么,我是否需要在GCC的配置脚本中添加选项或在此步骤之前传递给其他内容的选项,以正确创建sys-include目录?

[编辑]

TARGET=i686-redhat-linux(是从我们用于该项目的构建服务器上的"gcc -dumpmachine"获取的目标三元组)

可能更有帮助的信息:这些软件包只是从各自的存档中获取的"wget"。我是在最新版本的Ubuntu 16.04安装中构建的,其中我安装了libgmp-dev和libmpfr-dev,以避免使用编译器源代码进行编译。

${TARGET} 的值是多少?请编辑问题以改进它。 - Basile Starynkevitch
已更新问题并提供了一些额外的信息。希望这有所帮助! - Paul Braman
1个回答

0
经过更深入的挖掘和试错,我将一些东西与如何构建GCC交叉编译器的信息匹配起来,并发现了一个明显已弃用的选项--with-headers来配置GCC。(--with-headers=${PREFIX}/${TARGET}/include/linux)这个方法有效,但是当我构建编译器支持库时,它抱怨缺少bits/stdio_lim.h。我找到了另一篇文章在这里,讨论了这个问题(你必须在线程中向上滚动一点),并提到了我之前提到的第一页中有关触摸gnu/stubs.h的事情。
从我的下面的评论中添加说明,需要删除在make install-gcc步骤后构建的${PREFIX}/${TARGET}/sys-include目录,否则您的普通C头文件将与默认情况下包含在搜索路径中的Linux内核特定头文件发生冲突。

可以这么说,在对我使用的旧版Glibc(2.11.3)应用了一个补丁之后,整个序列最终变成了这样:

export TARGET=i686-redhat-linux
export PREFIX=$(pwd)/output
export PATH=${PATH}:${PREFIX}/bin

mkdir build-binutils
mkdir build-gcc
mkdir build-glibc

cd linux-2.6.35.9/
make ARCH=x86 INSTALL_HDR_PATH=${PREFIX}/${TARGET} headers_install
cd ../

cd build-binutils/
sh ../binutils-2.28/configure --prefix=${PREFIX} --target=${TARGET}
make
make install
cd ../

cd build-gcc/
sh ../gcc-4.9.4/configure --prefix=${PREFIX} --target=${TARGET} --enable-languages=c,c++ --disable-multilib --with-headers=${PREFIX}/${TARGET}/include/linux
make all-gcc
make install-gcc
cd ../
rm --recursive --force ${PREFIX}/${TARGET}/sys-include

cd build-glibc/
sh ../glibc-2.11.3/configure --prefix=${PREFIX}/${TARGET} --build=$(gcc -dumpmachine) --host=${TARGET} --target=${TARGET} --disable-multilib libc_cv_forced_unwind=yes libc_cv_c_cleanup=yes
make install-bootstrap-headers=yes install-headers
make csu/subdir_lib
install csu/crt1.o csu/crti.o csu/crtn.o ${PREFIX}/${TARGET}/lib
${TARGET}-gcc -nostdlib -nostartfiles -shared -x c /dev/null -o ${PREFIX}/${TARGET}/lib/libc.so
touch ${PREFIX}/${TARGET}/include/gnu/stubs.h ${PREFIX}/${TARGET}/include/bits/stdio_lim.h
cd ../

cd build-gcc/
make all-target-libgcc
make install-target-libgcc
cd ../

cd build-glibc/
make
make install
cd ../

我没有看到任何页面实际上深入到这个层面(也许 Preshing on Programming 页面并不完全正确?),但我将测试这个配置,并确保软件在目标上完全构建而没有问题。(我在一个文件中测试了 limits.h 中的 NAME_MAX,它似乎工作得非常好。)

我也不知道是否需要加入 --disable-multilib 这个东西,但其他页面似乎是这样做的。GCC 邮件列表中的那个链条谈到使用 --with-newlib--disable-shared 作为选项,但是线程上的人们都不能同意这些是否是正确的解决方案。

如果有人对此有更好的见解,我肯定会欣赏一个不那么 hacky、更正式的解决方案。

如果有人想知道,修复 Glibc 2.11.3 的补丁(有两个)是为了使 configure 脚本与 GNU Make 4+ 兼容的自定义修复程序:

sed -i 's/\(3.79\)/4.* | \1/' glibc-2.11.3/configure

...并提供了实际的补丁来修复库中两个文件的i686支持:

patch glibc-2.11.3/nptl/sysdeps/pthread/pt-initfini.c <<__EOF__
@@ -45,6 +45,11 @@
 /* Embed an #include to pull in the alignment and .end directives. */
 asm ("\n#include \"defs.h\"");

+asm ("\n#if defined __i686 && defined __ASSEMBLER__");
+asm ("\n#undef __i686");
+asm ("\n#define __i686 __i686");
+asm ("\n#endif");
+
 /* The initial common code ends here. */
 asm ("\n/*@HEADER_ENDS*/");

__EOF__
patch glibc-2.11.3/sysdeps/unix/sysv/linux/i386/sysdep.h <<__EOF__
@@ -29,6 +29,10 @@
 #include <dl-sysdep.h>
 #include <tls.h>

+#if defined __i686 && defined __ASSEMBLER__
+#undef __i686
+#define __i686 __i686
+#endif

 /* For Linux we can use the system call table in the header file
        /usr/include/asm/unistd.h
__EOF__

我从这里获得了最后的补丁。


似乎这也不足够。问题在于GCC将在sys-include目录中包含一堆Linux内核头文件,而Linux内核的time.h与GCC / Glibc的time.h冲突,您会得到(至少)struct timeval的重新定义。因此,仍未完全解决该问题。 - Paul Braman
所以在与此进行了一段时间的斗争后,我最终决定删除${PREFIX}/${TARGET}/sys-include目录,现在似乎一切都可以编译了。(至少在我测试的范围内是如此。)如果这样做能够正确地工作,我会将其编辑并更新为答案。 - Paul Braman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接