自动配置忽略 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。这似乎既方便(如果我只是注释掉适当的行,它就是一个字符的差异)又有效(它导致构建成功)。

我可能会将此作为错误报告给上游。