自动配置忽略 CFLAGS?
autoconf ignoring CFLAGS?
我正在构建一个使用 GNU autoconf 的包 (vice 3.4)。 运行 ./configure
失败并显示以下消息:
checking size of time_t... 0
configure: error: can not figure type of time_t
error: Bad exit status from /var/tmp/rpm-tmp.wIgnPw (%build)
正在检查 config.log
,这似乎由于以下错误而失败:
/usr/bin/ld: /tmp/ccMTSdtB.o: relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a PIE object; recompile with -fPIC
/usr/bin/ld: final link failed: nonrepresentable section on output
collect2: error: ld returned 1 exit status
我尝试通过将 -fPIC
添加到 CFLAGS
环境变量来解决此问题:
CFLAGS=-fPIC ./configure
但是虽然这显然在 ./configure
的其他阶段使用...
configure:3657: checking whether the C compiler works
configure:3679: gcc -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -D_GNU_SOURCE=1 -fPIC -Wl,-z,relro -Wl,--as-needed -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld conftest.c >&5
time_t
:
相关的特性测试中好像没有用到
configure:9684: checking for time_t in time.h
configure:9700: gcc -c -g -O3 -Wall -Wformat -Wformat-signedness -Wshadow -Wpointer-arith -Wstrict-prototypes -Wuninitialized -Wunreachable-code -Wno-unused-parameter -Werror=implicit-function-declaration -Wfatal-errors conftest.c >&5
[...]
configure:9753: checking size of time_t
configure:9758: gcc -o conftest -g -O3 -Wall -Wformat -Wformat-signedness -Wshadow -Wpointer-arith -Wstrict-prototypes -Wuninitialized -Wunreachable-code -Wno-unused-parameter -Werror=implicit-function-declaration -Wfatal-errors -Wl,-z,relro -Wl,--as-needed -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld conftest.c >&5
查看configure.ac
,以上代码生成自:
if test $bu_cv_decl_time_t_time_h = yes; then
AC_CHECK_SIZEOF([time_t],[],[#include <time.h>])
else
AC_CHECK_SIZEOF([time_t],[],[#include <sys/types.h>])
fi
我已经能够通过重新定义 CC
来解决这个问题:
CC="gcc -fPIC" ./configure
这行得通,但它很丑(如果有东西想调用 gcc
而没有 -fPIC
怎么办?)。 AC_CHECK_SIZEOF
忽略 CFLAGS
是有原因的吗?
看来我在评论中表达的怀疑得到了证实。 VICE 在执行某些检查时故意 substitutes its own choice of CFLAGS
for the user's specified ones 配置程序,包括与 time_t
相关的检查。因此,这不是 Autoconf 忽略您的标志的问题,而是 VICE 这样做的问题。
我重申,我认为首先配置对您来说不是开箱即用是一个更重要的问题。我建议将其作为针对该项目的问题提出。虽然我不喜欢 VICE 如此轻率地忽略用户的 CFLAGS
,但这是另一回事,我怀疑开发人员不会对它产生太大的兴趣。
John 正确地确定了问题,根据这些信息我做了一些挖掘,我已经弄清楚发生了什么。
我在 rpm
的控制下构建它,它调用这样的配置:
%configure --enable-native-gtk3ui $COMMON_FLAGS
%configure
扩展成一大块 shell 代码,如下所示:
CFLAGS="${CFLAGS:--O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection}" ; export CFLAGS ;
CXXFLAGS="${CXXFLAGS:--O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection}" ; export CXXFLAGS ;
FFLAGS="${FFLAGS:--O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -I/usr/lib64/gfortran/modules}" ; export FFLAGS ;
FCFLAGS="${FCFLAGS:--O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -I/usr/lib64/gfortran/modules}" ; export FCFLAGS ;
LDFLAGS="${LDFLAGS:--Wl,-z,relro -Wl,--as-needed -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld}" ; export LDFLAGS;
[ "1" = 1 ] && for i in $(find $(dirname ./configure) -name config.guess -o -name config.sub) ; do
[ -f /usr/lib/rpm/redhat/$(basename $i) ] && /usr/bin/rm -f $i && /usr/bin/cp -fv /usr/lib/rpm/redhat/$(basename $i) $i ;
done ;
[ "1" = 1 ] && [ x != "x-Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld" ] &&
for i in $(find . -name ltmain.sh) ; do
/usr/bin/sed -i.backup -e 's~compiler_flags=$~compiler_flags="-Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld"~' $i
done ;
./configure --build=x86_64-redhat-linux-gnu --host=x86_64-redhat-linux-gnu \
--program-prefix= \
--disable-dependency-tracking \
\
--prefix=/usr \
--exec-prefix=/usr \
--bindir=/usr/bin \
--sbindir=/usr/sbin \
--sysconfdir=/etc \
--datadir=/usr/share \
--includedir=/usr/include \
--libdir=/usr/lib64 \
--libexecdir=/usr/libexec \
--localstatedir=/var \
--sharedstatedir=/var/lib \
--mandir=/usr/share/man \
--infodir=/usr/share/info
特别有趣的是,这是设置 LDFLAGS
。失败的配置测试是:
gcc -o conftest -g -O3 -Wall -Wformat -Wformat-signedness -Wshadow \
-Wpointer-arith -Wstrict-prototypes -Wuninitialized -Wunreachable-code \
-Wno-unused-parameter -Werror=implicit-function-declaration \
-Wfatal-errors -Wl,-z,relro -Wl,--as-needed -Wl,-z,now \
-specs=/usr/lib/rpm/redhat/redhat-hardened-ld conftest.c
那 -specs
行指向一个 gcc 规范文件,如下所示:
*self_spec:
+ %{!static:%{!shared:%{!r:-pie}}}
这有效地将 -pie
选项添加到命令行。我们可以用一个简单的 hello.c
程序重现失败:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char **argv) {
printf("hello world\n");
return(0);
}
像这样:
$ gcc -o hello -pie hello.c
/usr/bin/ld: /tmp/ccXRAu6r.o: relocation R_X86_64_32 against `.rodata' can not be used when making a PIE object; recompile with -fPIC
/usr/bin/ld: final link failed: nonrepresentable section on output
collect2: error: ld returned 1 exit status
但事情是这样的:
一个成功 gcc
调用看起来像这样:
gcc -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 \
-Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong \
-grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 \
-specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic \
-fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection \
-D_GNU_SOURCE=1 -fPIC -Wl,-z,relro -Wl,--as-needed -Wl,-z,now \
-specs=/usr/lib/rpm/redhat/redhat-hardened-ld conftest.c
请注意,那里还有第二个 -specs
选项,它指向 /usr/lib/rpm/redhat/redhat-hardened-cc1
,看起来像:
*cc1_options:
+ %{!r:%{!fpie:%{!fPIE:%{!fpic:%{!fPIC:%{!fno-pic:-fPIE}}}}}}
这负责将 -fPIE
添加到命令行,从而导致编译成功:
$ gcc -o hello -pie -fPIE hello.c
$
我们遇到此故障是因为 configure
脚本在测试期间 替换 CFLAGS
,但 保留 LDFLAGS
。这会导致错误的命令行。
为了我自己的目的,我只是修补 configure
脚本,以便在 time_t
相关测试期间不替换 CFLAGS
。这似乎既方便(如果我只是注释掉适当的行,它就是一个字符的差异)又有效(它导致构建成功)。
我可能会将此作为错误报告给上游。
我正在构建一个使用 GNU autoconf 的包 (vice 3.4)。 运行 ./configure
失败并显示以下消息:
checking size of time_t... 0
configure: error: can not figure type of time_t
error: Bad exit status from /var/tmp/rpm-tmp.wIgnPw (%build)
正在检查 config.log
,这似乎由于以下错误而失败:
/usr/bin/ld: /tmp/ccMTSdtB.o: relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a PIE object; recompile with -fPIC
/usr/bin/ld: final link failed: nonrepresentable section on output
collect2: error: ld returned 1 exit status
我尝试通过将 -fPIC
添加到 CFLAGS
环境变量来解决此问题:
CFLAGS=-fPIC ./configure
但是虽然这显然在 ./configure
的其他阶段使用...
configure:3657: checking whether the C compiler works
configure:3679: gcc -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -D_GNU_SOURCE=1 -fPIC -Wl,-z,relro -Wl,--as-needed -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld conftest.c >&5
time_t
:
configure:9684: checking for time_t in time.h
configure:9700: gcc -c -g -O3 -Wall -Wformat -Wformat-signedness -Wshadow -Wpointer-arith -Wstrict-prototypes -Wuninitialized -Wunreachable-code -Wno-unused-parameter -Werror=implicit-function-declaration -Wfatal-errors conftest.c >&5
[...]
configure:9753: checking size of time_t
configure:9758: gcc -o conftest -g -O3 -Wall -Wformat -Wformat-signedness -Wshadow -Wpointer-arith -Wstrict-prototypes -Wuninitialized -Wunreachable-code -Wno-unused-parameter -Werror=implicit-function-declaration -Wfatal-errors -Wl,-z,relro -Wl,--as-needed -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld conftest.c >&5
查看configure.ac
,以上代码生成自:
if test $bu_cv_decl_time_t_time_h = yes; then
AC_CHECK_SIZEOF([time_t],[],[#include <time.h>])
else
AC_CHECK_SIZEOF([time_t],[],[#include <sys/types.h>])
fi
我已经能够通过重新定义 CC
来解决这个问题:
CC="gcc -fPIC" ./configure
这行得通,但它很丑(如果有东西想调用 gcc
而没有 -fPIC
怎么办?)。 AC_CHECK_SIZEOF
忽略 CFLAGS
是有原因的吗?
看来我在评论中表达的怀疑得到了证实。 VICE 在执行某些检查时故意 substitutes its own choice of CFLAGS
for the user's specified ones 配置程序,包括与 time_t
相关的检查。因此,这不是 Autoconf 忽略您的标志的问题,而是 VICE 这样做的问题。
我重申,我认为首先配置对您来说不是开箱即用是一个更重要的问题。我建议将其作为针对该项目的问题提出。虽然我不喜欢 VICE 如此轻率地忽略用户的 CFLAGS
,但这是另一回事,我怀疑开发人员不会对它产生太大的兴趣。
John 正确地确定了问题,根据这些信息我做了一些挖掘,我已经弄清楚发生了什么。
我在 rpm
的控制下构建它,它调用这样的配置:
%configure --enable-native-gtk3ui $COMMON_FLAGS
%configure
扩展成一大块 shell 代码,如下所示:
CFLAGS="${CFLAGS:--O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection}" ; export CFLAGS ;
CXXFLAGS="${CXXFLAGS:--O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection}" ; export CXXFLAGS ;
FFLAGS="${FFLAGS:--O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -I/usr/lib64/gfortran/modules}" ; export FFLAGS ;
FCFLAGS="${FCFLAGS:--O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -I/usr/lib64/gfortran/modules}" ; export FCFLAGS ;
LDFLAGS="${LDFLAGS:--Wl,-z,relro -Wl,--as-needed -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld}" ; export LDFLAGS;
[ "1" = 1 ] && for i in $(find $(dirname ./configure) -name config.guess -o -name config.sub) ; do
[ -f /usr/lib/rpm/redhat/$(basename $i) ] && /usr/bin/rm -f $i && /usr/bin/cp -fv /usr/lib/rpm/redhat/$(basename $i) $i ;
done ;
[ "1" = 1 ] && [ x != "x-Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld" ] &&
for i in $(find . -name ltmain.sh) ; do
/usr/bin/sed -i.backup -e 's~compiler_flags=$~compiler_flags="-Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld"~' $i
done ;
./configure --build=x86_64-redhat-linux-gnu --host=x86_64-redhat-linux-gnu \
--program-prefix= \
--disable-dependency-tracking \
\
--prefix=/usr \
--exec-prefix=/usr \
--bindir=/usr/bin \
--sbindir=/usr/sbin \
--sysconfdir=/etc \
--datadir=/usr/share \
--includedir=/usr/include \
--libdir=/usr/lib64 \
--libexecdir=/usr/libexec \
--localstatedir=/var \
--sharedstatedir=/var/lib \
--mandir=/usr/share/man \
--infodir=/usr/share/info
特别有趣的是,这是设置 LDFLAGS
。失败的配置测试是:
gcc -o conftest -g -O3 -Wall -Wformat -Wformat-signedness -Wshadow \
-Wpointer-arith -Wstrict-prototypes -Wuninitialized -Wunreachable-code \
-Wno-unused-parameter -Werror=implicit-function-declaration \
-Wfatal-errors -Wl,-z,relro -Wl,--as-needed -Wl,-z,now \
-specs=/usr/lib/rpm/redhat/redhat-hardened-ld conftest.c
那 -specs
行指向一个 gcc 规范文件,如下所示:
*self_spec:
+ %{!static:%{!shared:%{!r:-pie}}}
这有效地将 -pie
选项添加到命令行。我们可以用一个简单的 hello.c
程序重现失败:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char **argv) {
printf("hello world\n");
return(0);
}
像这样:
$ gcc -o hello -pie hello.c
/usr/bin/ld: /tmp/ccXRAu6r.o: relocation R_X86_64_32 against `.rodata' can not be used when making a PIE object; recompile with -fPIC
/usr/bin/ld: final link failed: nonrepresentable section on output
collect2: error: ld returned 1 exit status
但事情是这样的:
一个成功 gcc
调用看起来像这样:
gcc -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 \
-Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong \
-grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 \
-specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic \
-fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection \
-D_GNU_SOURCE=1 -fPIC -Wl,-z,relro -Wl,--as-needed -Wl,-z,now \
-specs=/usr/lib/rpm/redhat/redhat-hardened-ld conftest.c
请注意,那里还有第二个 -specs
选项,它指向 /usr/lib/rpm/redhat/redhat-hardened-cc1
,看起来像:
*cc1_options:
+ %{!r:%{!fpie:%{!fPIE:%{!fpic:%{!fPIC:%{!fno-pic:-fPIE}}}}}}
这负责将 -fPIE
添加到命令行,从而导致编译成功:
$ gcc -o hello -pie -fPIE hello.c
$
我们遇到此故障是因为 configure
脚本在测试期间 替换 CFLAGS
,但 保留 LDFLAGS
。这会导致错误的命令行。
为了我自己的目的,我只是修补 configure
脚本,以便在 time_t
相关测试期间不替换 CFLAGS
。这似乎既方便(如果我只是注释掉适当的行,它就是一个字符的差异)又有效(它导致构建成功)。
我可能会将此作为错误报告给上游。