【问题标题】:GCC 4.9.4 Cross Compiler Build (limits.h issue)GCC 4.9.4 交叉编译器构建(limits.h 问题)
【发布时间】:2017-11-09 05:12:12
【问题描述】:

提出问题的基本步骤:

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 里面有 actual 的东西,我需要像 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} 的值是多少?请编辑问题以改进它。
  • 用一些附加信息更新了问题。希望有帮助!

标签: gcc cross-compiling toolchain


【解决方案1】:

经过更多的挖掘和反复试验,我匹配了一些我从 How to Build a GCC Cross-Compiler 开始的东西,以及关于配置 GCC 的明显不推荐使用的选项 --with-headers 的信息。 (--with-headers=${PREFIX}/${TARGET}/include/linux) 这行得通,但是当我构建编译器支持库时,它抱怨缺少bits/stdio_lim.h。我发现另一个帖子here 谈到了这个问题(你必须在线程中稍微上升一点)并在我提到的第一页中提到了感人的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 作为选项,但线程上的人不同意其中任何一个是正确的解决方案。

如果有人对此有更深入的了解,我肯定会感谢一个不那么老套、更官方的解决方案。

如果有人想知道,修复 Glibc 2.11.3 的补丁(有两个)是配置脚本与 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__

我从here 那里得到了最后一个补丁。

【讨论】:

  • 这似乎也不够。问题是 GCC 将在 sys-include 目录中包含一堆 Linux Kernel 头文件,并且 Linux Kernel 的 time.h 与 GCC/Glibc 的 time.h 冲突,并且您会重新定义(至少)struct timeval。所以,还没有完全解决问题。
  • 所以在与这个问题斗争了一段时间后,我最终删除了${PREFIX}/${TARGET}/sys-include 目录,现在一切似乎都可以编译了。 (至少就我的测试而言。)如果最终正常工作,我将对其进行编辑并更新为答案。
猜你喜欢
  • 2010-10-26
  • 1970-01-01
  • 1970-01-01
  • 2017-04-21
  • 1970-01-01
  • 2011-09-03
  • 1970-01-01
  • 2014-09-30
  • 1970-01-01
相关资源
最近更新 更多