GCC的交叉编译autotools应该是灵活的,但我已经隔离了一个错误,它已经破坏了应该工作的交叉编译器构建。
注意:有些系统会“毒害”#34;默认编译器工具名称,以防止使用错误的工具。在我的系统上,x86_64-pc-gnu-linux-ar将执行,但是" ar"找不到。
我需要使用自定义名称构建交叉编译器工具链。 gcc的configure脚本支持--program-prefix或--program-transform-name。但是,使用自定义名称时,必须在配置行上显式命名所有编译时工具。 gcc configure不够智能,无法找到刚刚使用名称更改构建的工具。 (太愚蠢了)。
GCC手册说明了如何明确命名工具:
configure AR=x86_foo_b_ar AR_FOR_TARGET=ARMv6m_foo_b_ar ...
但是,它不能正常工作。 Autoools有时会忽略提供的名称,并且构建失败。特别是,它忽略了AR' AR'和' OBJDUMP'变量
显然,顶级gcc配置是在较低级别配置之后创建的。
Makefile.in without Makefile.am in GCC?
Makefile.am在某些子目录中不存在,但 存在于较新的子目录中。
这会导致从顶级makefile传递的变量不一致。
在内部,顶级"配置"脚本具有变量AR_FOR_HOST(AR的别名),AR_FOR_BUILD和AR_FOR_TARGET。这些变量用于重新定义" AR"进入子目录时强制通用make脚本为特定目标编译。
我甚至已经正确地定义了内部变量以及" AR"和" OBJDUMP"在configure命令行上。 (不应该需要)。
gcc-7.3.0/configure --host=x86_64-pc-linux-gnu --program-prefix=armv6m-softfloat-eabi-newlib- AR_FOR_BUILD=/usr/bin/x86_64-pc-linux-gnu-ar AR=/usr/bin/x86_64-pc-linux-gnu-ar AR_FOR_HOST=/usr/bin/x86_64-pc-linux-gnu-ar AR_FOR_TARGET=/usr/libexec/gcc/armv6m-softfloat-eabi-newlib/ar AS_FOR_BUILD=/usr/bin/x86_64-pc-linux-gnu-as AS=/usr/bin/x86_64-pc-linux-gnu-as AS_FOR_HOST=/usr/bin/x86_64-pc-linux-gnu-as AS_FOR_TARGET=/usr/libexec/gcc/armv6m-softfloat-eabi-newlib/as DLLTOOL_FOR_TARGET=/usr/libexec/gcc/armv6m-softfloat-eabi-newlib/dlltool LD_FOR_BUILD=/usr/bin/x86_64-pc-linux-gnu-ld LD=/usr/bin/x86_64-pc-linux-gnu-ld LD_FOR_HOST=/usr/bin/x86_64-pc-linux-gnu-ld LD_FOR_TARGET=/usr/libexec/gcc/armv6m-softfloat-eabi-newlib/ld LIPO_FOR_TARGET=/usr/libexec/gcc/armv6m-softfloat-eabi-newlib/lipo NM_FOR_BUILD=/usr/bin/x86_64-pc-linux-gnu-nm NM=/usr/bin/x86_64-pc-linux-gnu-nm NM_FOR_HOST=/usr/bin/x86_64-pc-linux-gnu-nm NM_FOR_TARGET=/usr/libexec/gcc/armv6m-softfloat-eabi-newlib/nm OBJCOPY_FOR_BUILD=/usr/bin/x86_64-pc-linux-gnu-objcopy OBJCOPY=/usr/bin/x86_64-pc-linux-gnu-objcopy OBJCOPY_FOR_HOST=/usr/bin/x86_64-pc-linux-gnu-objcopy OBJCOPY_FOR_TARGET=/usr/libexec/gcc/armv6m-softfloat-eabi-newlib/objcopy OBJDUMP_FOR_BUILD=/usr/bin/x86_64-pc-linux-gnu-objdump OBJDUMP=/usr/bin/x86_64-pc-linux-gnu-objdump OBJDUMP_FOR_HOST=/usr/bin/x86_64-pc-linux-gnu-objdump OBJDUMP_FOR_TARGET=/usr/libexec/gcc/armv6m-softfloat-eabi-newlib/objdump RANLIB_FOR_BUILD=/usr/bin/x86_64-pc-linux-gnu-ranlib RANLIB=/usr/bin/x86_64-pc-linux-gnu-ranlib RANLIB_FOR_HOST=/usr/bin/x86_64-pc-linux-gnu-ranlib RANLIB_FOR_TARGET=/usr/libexec/gcc/armv6m-softfloat-eabi-newlib/ranlib READELF_FOR_BUILD=/usr/bin/x86_64-pc-linux-gnu-readelf READELF=/usr/bin/x86_64-pc-linux-gnu-readelf READELF_FOR_HOST=/usr/bin/x86_64-pc-linux-gnu-readelf READELF_FOR_TARGET=/usr/libexec/gcc/armv6m-softfloat-eabi-newlib/readelf STRIP_FOR_BUILD=/usr/bin/x86_64-pc-linux-gnu-strip STRIP=/usr/bin/x86_64-pc-linux-gnu-strip STRIP_FOR_HOST=/usr/bin/x86_64-pc-linux-gnu-strip STRIP_FOR_TARGET=/usr/libexec/gcc/armv6m-softfloat-eabi-newlib/strip CC_FOR_TARGET=/usr/libexec/gcc/armv6m-softfloat-eabi-newlib/cc CXX_FOR_TARGET=/usr/libexec/gcc/armv6m-softfloat-eabi-newlib/cxx WINDRES_FOR_TARGET=/usr/libexec/gcc/armv6m-softfloat-eabi-newlib/windres WINDMC_FOR_TARGET=/usr/libexec/gcc/armv6m-softfloat-eabi-newlib/windmc --target=armv6m-softfloat-eabi --build=x86_64-pc-linux-gnu --prefix=/usr --bindir=/usr/x86_64-pc-linux-gnu/armv6m-softfloat-eabi-newlib/gcc-bin/7.3.0 --includedir=/usr/lib/gcc/armv6m-softfloat-eabi-newlib/7.3.0/include --datadir=/usr/share/gcc-data/armv6m-softfloat-eabi-newlib/7.3.0 --mandir=/usr/share/gcc-data/armv6m-softfloat-eabi-newlib/7.3.0/man --infodir=/usr/share/gcc-data/armv6m-softfloat-eabi-newlib/7.3.0/info --with-gxx-include-dir=/usr/lib/gcc/armv6m-softfloat-eabi-newlib/7.3.0/include/g++-v7 --with-python-dir=/share/gcc-data/armv6m-softfloat-eabi-newlib/7.3.0/python --enable-languages=c --enable-obsolete --enable-secureplt --disable-werror --with-system-zlib --enable-nls --without-included-gettext --enable-checking=release --with-bugurl=https://bugs.gentoo.org/ --with-pkgversion=Gentoo 7.3.0-r3 p1.4 --disable-esp --enable-poison-system-directories --disable-bootstrap --with-newlib --enable-multilib --disable-altivec --disable-fixed-point --with-float=soft --disable-libgcj --disable-libgomp --disable-libmudflap --disable-libssp --disable-libcilkrts --disable-libmpx --disable-vtable-verify --disable-libvtv --disable-libquadmath --enable-lto --without-isl --disable-libsanitizer --enable-default-pie --enable-default-ssp
我希望gcc同时制作和使用以前缀开头的工具:armv6m-softfloat-eabi-newlib- (Arm cortex m0芯片组是我正在使用的)
但" make"在尝试执行" ar"时仍然失败在... / libcpp目录中。原因是... / libcpp / Makefile.in没有被automake更新。它是手工制作的文件。在旧的... / libcpp / Makefile.in的第28行,它说" AR = ar"
因此,AR变量被硬编码为" ar"但是," ar"在我的系统上不存在。我已尝试使用" AR = dummyname"编辑... / libcpp / Makefile.in和#34的构建崩溃不能使用dummyname"而不是找不到" ar"。所以,这个错误就在第28行。
... / libcpp / Makefile.in中的所有其他变量的格式为:
CC = @CC@
INSTALL = @INSTALL@
等。 从积极的方面来说:... / libcpp使用的编译器是我给gcc-7.3.0 / configure的完全规范的名称。这个成功让我觉得我可以通过编辑makefile来解决这个问题:
AR = @AR@
但是构建失败了"无法找到AR @"
我对autotools不熟悉,不能手动编辑Makefile.in并修复bug。 @ variable @ name格式的作用是什么?
子目录中的configure.ac是否必须定义" AR"以某种方式将@ AR @链接到顶层目录中的值?
我在构建不同的gcc版本时尝试了一些其他测试。重新运行autoconfig,automake,是因为GCC使用AC_PREREQ()宏。
例如,我安装了自动工具2.69 ...但gcc 7.3.0失败并抱怨我必须使用autotools 2.64,仅限。例如:AC_PREREQ(2.64)
因此,通过autotools修复bug似乎并不实用。 我希望简单地修补... / libcpp / Makefile.in,因为在很多版本的gcc中该文件完全相同。
问题: 为什么" ar"硬编码?这是一个严重的遗留问题吗?什么是不会干扰GCC其他配置的最小补丁?
修改shell或Makefile是否更好;例如:像顶级配置shell脚本可以定义一个bash函数,该函数将由make作为"如果"这是一个程序。
if [ -z ${AR##*-*} ] ; then
ar() { $AR }
fi
编辑:gcc-7.3.0的快速修补补丁 这不是一个正确的"修复,但只是解决方法。
我找到了三个子目录忽略从toplevel配置传入的变量的地方。 第29行的... / libcpp / Makefile.in ... / gcc /在第29531行之前配置 ... / libcc1 /在14574之前配置
第二个和第三个错误来自configure.ac中的有缺陷的宏。我还没有追溯到它,因为无论如何我都无法运行自动配置。
我在configure中添加了一行,以查看是否传递默认的OBJDUMP覆盖变量将允许gcc进行编译。确实如此。我不确定我是否为gcc编译开关的所有情况选择了正确的覆盖变量,但至少它证明了bug的位置。
补丁文件如下:
--- gcc-old/libcpp/Makefile.in
+++ gcc-new/libcpp/Makefile.in
@@ -28,3 +28,3 @@
INSTALL = @INSTALL@
-AR = ar
+AR ?= ar
ARFLAGS = cru
--- gcc-old/gcc/configure
+++ gcc-new/gcc/configure
@@ -29531,4 +29531,6 @@
;;
esac
+ if [ -n $OBJDUMP ]; then export_sym_check="$OBJDUMP -T"; fi
+
if test x"$enable_plugin" = x"yes"; then
--- gcc-old/libcc1/configure
+++ gcc-new/libcc1/configure
@@ -14574,4 +14574,6 @@
;;
esac
+ if [ -n $OBJDUMP ]; then export_sym_check="$OBJDUMP -T"; fi
+
if test x"$enable_plugin" = x"yes"; then
答案 0 :(得分:2)
TL; DR :您可以尝试很多事情,但第一个是在运行AR
时在命令行上指定make
:
make AR=x86_foo_b_ar
当你已经为configure
指定了相同的时,
或者您正在查看的Makefile.in
更高级别。 make
命令行上指定的变量定义会覆盖makefile中的定义。
"使"在尝试执行" ar"时仍然失败来自... / libcpp目录。原因是... / libcpp / Makefile.in没有被automake更新。它是手工制作的文件。
要清楚,因为了解您尝试使用的系统对排除故障非常有帮助,automake
不会在配置或构建时运行。包维护者使用它来构建要包含在源分发中的一个或多个Makefile.in
文件,例如您获得的文件。当然,这不是创建Makefile.in
文件的唯一方法,而configure
脚本并不关心如何创建它们(或其他输入文件)。
我对autotools不熟悉,不能手动编辑Makefile.in并修复bug。 @ variable @ name格式的作用是什么?
子目录中的configure.ac是否必须定义" AR"以某种方式将@ AR @链接到顶层目录中的值?
@variable@
构造用于构建相应输出文件时预期由configure
脚本替换的值。要实现这一点,需要在AC_SUBST([variable])
(有时命名为configure.ac
)中至少有相应的configure.in
或其等价物。通常情况下,代码会在configure.ac
中的某个位置通过代码为shell变量variable
指定适当的值。
如果修改configure.ac
,则需要重建configure
脚本,在这种情况下,重建整个构建系统可能是最安全的,就像软件包维护者一样。包中可能有为此目的提供的脚本(autogen.sh
是此类脚本的通用名称),但默认机制是在顶级目录中运行Autotools程序autoreconf
。项目源树。
我在构建不同的gcc版本时尝试了一些其他测试。 重新运行autoconfig,automake,是因为GCC使用
AC_PREREQ()
宏。例如,我安装了自动工具2.69 ...但是gcc 7.3.0失败了 并抱怨我必须使用autotools 2.64,仅限。例如:
AC_PREREQ(2.64)
该描述与AC_PREREQ
的文档不一致,也与我对该宏的经验不一致。 AC_PREREQ
测试指定的Autoconf版本或更新。它不需要精确的Autoconf版本。构建系统中可能还有其他内容可以执行此操作,但它不是AC_PREREQ
。
在任何情况下,一种替代方案是获取并安装Autoconf 2.64。您甚至可以将其与现有版本一起安装。有些系统甚至可以提供预先构建的软件包。
因此,通过autotools修复bug似乎并不实用。我希望 只需修补... / libcpp / Makefile.in,因为该文件完全正确 在许多版本的gcc中也一样。
修补Makefile.in
后不需要重新运行autotools,所以至少可以想象它会起作用。即使是由Automake生成的Makefile.in
文件也是如此。你可以考虑一下如何在项目中的一些Automake生成的AR
文件中定义Makefile.in
(假设有任何文件),以了解它应该如何看待。
为什么" ar"硬编码?这是一个严重的遗留问题吗?
我只能推测。作为一个门槛问题,我倾向于认为在那个Makefile
中,构建系统的归档器是想要的(不是预期的主机系统的归档,也不是主机 - 目标的交叉)。 )。在这种情况下,AR = ar
作为默认值提供是合理的,因为可以通过在命令行上声明该变量来覆盖。
你实际上没有得到你指定给AR
的{{1}}看起来像是一个错误 - 可能是在构建的某些高级位时某些时候引入的回归系统更新了。我可以毫不费力地想象这样一个问题,因为像你这样的系统配置,系统自己的归档器只能以非标准名称发送,这种情况非常罕见。
什么是 最小的补丁不会干扰GCC的其他配置?
首先要尝试的是在顶级configure
命令行上传递AR
定义:
make
此类定义将传递给递归调用的子make AR=x86_foo_b_ar
,并且命令行上的定义(但默认情况下,不会从环境中定义)覆盖Makefile中的定义。
修改shell或Makefile是否更好;例如:像顶部一样 level configure shell脚本可以定义一个bash函数 如果"继承为make as"这是一个程序。
可以修改顶级make
脚本以定义shell函数并将其导出到子进程,但不到其父进程或兄弟进程。这与configure
无关; shell只是不这样做。无论您做出哪些更改(如果有),最好在configure
文件中进行更改,然后再运行Makefile.in
,或者之后生成的configure
。