Discussion:
[PATCH] Don’t use AC_EGREP_CPP if affected by CFLAGS
Paul Eggert
2017-11-06 04:30:53 UTC
Permalink
* m4/float_h.m4 (gl_FLOAT_H):
* m4/host-cpu-c-abi.m4 (gl_HOST_CPU_C_ABI):
* m4/lib-ld.m4 (AC_LIB_PROG_LD):
* m4/lib-prefix.m4 (AC_LIB_PREPARE_MULTILIB):
* m4/year2038.m4 (gl_YEAR2038):
Prefer AC_COMPILE_IFELSE to AC_EGREP_CPP when testing conditions
likely to be affected by the choice of CFLAGS, since CFLAGS are
not used by AC_EGREP_CPP. Without this patch, ‘./configure
CFLAGS="-m32"’ fails on gzip with GNU/Linux x86-64.
---
ChangeLog | 11 ++++
m4/float_h.m4 | 26 +++++----
m4/host-cpu-c-abi.m4 | 147 ++++++++++++++++++++++++++++++++++-----------------
m4/lib-ld.m4 | 27 ++++++----
m4/lib-prefix.m4 | 17 +++---
m4/year2038.m4 | 15 +++---
6 files changed, 163 insertions(+), 80 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 4bc28d981..53a2b8f7b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
2017-11-05 Paul Eggert <***@cs.ucla.edu>

+ Don’t use AC_EGREP_CPP if affected by CFLAGS
+ * m4/float_h.m4 (gl_FLOAT_H):
+ * m4/host-cpu-c-abi.m4 (gl_HOST_CPU_C_ABI):
+ * m4/lib-ld.m4 (AC_LIB_PROG_LD):
+ * m4/lib-prefix.m4 (AC_LIB_PREPARE_MULTILIB):
+ * m4/year2038.m4 (gl_YEAR2038):
+ Prefer AC_COMPILE_IFELSE to AC_EGREP_CPP when testing conditions
+ likely to be affected by the choice of CFLAGS, since CFLAGS are
+ not used by AC_EGREP_CPP. Without this patch, ‘./configure
+ CFLAGS="-m32"’ fails on gzip with GNU/Linux x86-64.
+
fstatat: pacify GCC on unusual platform
* lib/fstatat.c (orig_fstatat) [!HAVE_WORKING_FSTATAT_ZERO_FLAG]:
Omit, as it’s unused in this case.
diff --git a/m4/float_h.m4 b/m4/float_h.m4
index 4c42176b6..24bd06ecc 100644
--- a/m4/float_h.m4
+++ b/m4/float_h.m4
@@ -1,4 +1,4 @@
-# float_h.m4 serial 11
+# float_h.m4 serial 12
dnl Copyright (C) 2007, 2009-2017 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -24,10 +24,14 @@ changequote([,])dnl
x86_64 )
# On x86_64 systems, the C compiler may still be generating
# 32-bit code.
- AC_EGREP_CPP([yes],
- [#if defined __LP64__ || defined __x86_64__ || defined __amd64__
- yes
- #endif],
+ AC_COMPILE_IFELSE(
+ [AC_LANG_SOURCE(
+ [[#if defined __LP64__ || defined __x86_64__ || defined __amd64__
+ int ok;
+ #else
+ error fail
+ #endif
+ ]])],
[],
[FLOAT_H=float.h])
;;
@@ -69,10 +73,14 @@ int main ()
[gl_cv_func_itold_works=no],
[case "$host" in
sparc*-*-linux*)
- AC_EGREP_CPP([yes],
- [#if defined __LP64__ || defined __arch64__
- yes
- #endif],
+ AC_COMPILE_IFELSE(
+ [AC_LANG_SOURCE(
+ [[#if defined __LP64__ || defined __arch64__
+ int ok;
+ #else
+ error fail
+ #endif
+ ]])],
[gl_cv_func_itold_works="guessing no"],
[gl_cv_func_itold_works="guessing yes"])
;;
diff --git a/m4/host-cpu-c-abi.m4 b/m4/host-cpu-c-abi.m4
index 59b0ebf67..9370c3185 100644
--- a/m4/host-cpu-c-abi.m4
+++ b/m4/host-cpu-c-abi.m4
@@ -1,4 +1,4 @@
-# host-cpu-c-abi.m4 serial 7
+# host-cpu-c-abi.m4 serial 8
dnl Copyright (C) 2002-2017 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -68,14 +68,23 @@ changequote([,])dnl
# with native Windows (mingw, MSVC).
# - 64-bit instruction set, 32-bit pointers, 32-bit 'long': x86_64-x32.
# - 32-bit instruction set, 32-bit pointers, 32-bit 'long': i386.
- AC_EGREP_CPP([yes],
- [#if defined __x86_64__ || defined __amd64__ || defined _M_X64 || defined _M_AMD64
- yes
- #endif],
- [AC_EGREP_CPP([yes],
- [#if defined __ILP32__ || defined _ILP32
- yes
- #endif],
+ AC_COMPILE_IFELSE(
+ [AC_LANG_SOURCE(
+ [[#if (defined __x86_64__ || defined __amd64__ \
+ || defined _M_X64 || defined _M_AMD64)
+ int ok;
+ #else
+ error fail
+ #endif
+ ]])],
+ [AC_COMPILE_IFELSE(
+ [AC_LANG_SOURCE(
+ [[#if defined __ILP32__ || defined _ILP32
+ int ok;
+ #else
+ error fail
+ #endif
+ ]])],
[gl_cv_host_cpu_c_abi=x86_64-x32],
[gl_cv_host_cpu_c_abi=x86_64])],
[gl_cv_host_cpu_c_abi=i386])
@@ -94,14 +103,22 @@ changequote([,])dnl
# - aarch64 instruction set, 64-bit pointers, 64-bit 'long': arm64.
# - aarch64 instruction set, 32-bit pointers, 32-bit 'long': arm64-ilp32.
# - 32-bit instruction set, 32-bit pointers, 32-bit 'long': arm or armhf.
- AC_EGREP_CPP([yes],
- [#if defined __aarch64__
- yes
- #endif],
- [AC_EGREP_CPP([yes],
- [#if defined __ILP32__ || defined _ILP32
- yes
- #endif],
+ AC_COMPILE_IFELSE(
+ [AC_LANG_SOURCE(
+ [[#ifdef __aarch64__
+ int ok;
+ #else
+ error fail
+ #endif
+ ]])],
+ [AC_COMPILE_IFELSE(
+ [AC_LANG_SOURCE(
+ [[#if defined __ILP32__ || defined _ILP32
+ int ok;
+ #else
+ error fail
+ #endif
+ ]])],
[gl_cv_host_cpu_c_abi=arm64-ilp32],
[gl_cv_host_cpu_c_abi=arm64])],
[# Don't distinguish little-endian and big-endian arm, since they
@@ -130,10 +147,14 @@ changequote([,])dnl
hppa1.0 | hppa1.1 | hppa2.0* | hppa64 )
# On hppa, the C compiler may be generating 32-bit code or 64-bit
# code. In the latter case, it defines _LP64 and __LP64__.
- AC_EGREP_CPP([yes],
- [#if defined(__LP64__)
- yes
- #endif],
+ AC_COMPILE_IFELSE(
+ [AC_LANG_SOURCE(
+ [[#ifdef __LP64__
+ int ok;
+ #else
+ error fail
+ #endif
+ ]])],
[gl_cv_host_cpu_c_abi=hppa64],
[gl_cv_host_cpu_c_abi=hppa])
;;
@@ -141,10 +162,14 @@ changequote([,])dnl
ia64* )
# On ia64 on HP-UX, the C compiler may be generating 64-bit code or
# 32-bit code. In the latter case, it defines _ILP32.
- AC_EGREP_CPP([yes],
- [#if defined _ILP32
- yes
- #endif],
+ AC_COMPILE_IFELSE(
+ [AC_LANG_SOURCE(
+ [[#ifdef _ILP32
+ int ok;
+ #else
+ error fail
+ #endif
+ ]])],
[gl_cv_host_cpu_c_abi=ia64-ilp32],
[gl_cv_host_cpu_c_abi=ia64])
;;
@@ -152,19 +177,27 @@ changequote([,])dnl
mips* )
# We should also check for (_MIPS_SZPTR == 64), but gcc keeps this
# at 32.
- AC_EGREP_CPP([yes],
- [#if defined _MIPS_SZLONG && (_MIPS_SZLONG == 64)
- yes
- #endif],
+ AC_COMPILE_IFELSE(
+ [AC_LANG_SOURCE(
+ [[#if defined _MIPS_SZLONG && (_MIPS_SZLONG == 64)
+ int ok;
+ #else
+ error fail
+ #endif
+ ]])],
[gl_cv_host_cpu_c_abi=mips64],
[# In the n32 ABI, _ABIN32 is defined, _ABIO32 is not defined (but
# may later get defined by <sgidefs.h>), and _MIPS_SIM == _ABIN32.
# In the 32 ABI, _ABIO32 is defined, _ABIN32 is not defined (but
# may later get defined by <sgidefs.h>), and _MIPS_SIM == _ABIO32.
- AC_EGREP_CPP([yes],
- [#if (_MIPS_SIM == _ABIN32)
- yes
- #endif],
+ AC_COMPILE_IFELSE(
+ [AC_LANG_SOURCE(
+ [[#if (_MIPS_SIM == _ABIN32)
+ int ok;
+ #else
+ error fail
+ #endif
+ ]])],
[gl_cv_host_cpu_c_abi=mipsn32],
[gl_cv_host_cpu_c_abi=mips])])
;;
@@ -176,16 +209,24 @@ changequote([,])dnl
# On powerpc64 systems, the C compiler may still be generating
# 32-bit code. And on powerpc-ibm-aix systems, the C compiler may
# be generating 64-bit code.
- AC_EGREP_CPP([yes],
- [#if defined __powerpc64__ || defined _ARCH_PPC64
- yes
- #endif],
+ AC_COMPILE_IFELSE(
+ [AC_LANG_SOURCE(
+ [[#if defined __powerpc64__ || defined _ARCH_PPC64
+ int ok;
+ #else
+ error fail
+ #endif
+ ]])],
[# On powerpc64, there are two ABIs on Linux: The AIX compatible
# one and the ELFv2 one. The latter defines _CALL_ELF=2.
- AC_EGREP_CPP([yes],
- [#if defined _CALL_ELF && _CALL_ELF == 2
- yes
- #endif],
+ AC_COMPILE_IFELSE(
+ [AC_LANG_SOURCE(
+ [[#if defined _CALL_ELF && _CALL_ELF == 2
+ int ok;
+ #else
+ error fail
+ #endif
+ ]])],
[gl_cv_host_cpu_c_abi=powerpc64-elfv2],
[gl_cv_host_cpu_c_abi=powerpc64])
],
@@ -199,10 +240,14 @@ changequote([,])dnl
s390* )
# On s390x, the C compiler may be generating 64-bit (= s390x) code
# or 31-bit (= s390) code.
- AC_EGREP_CPP([yes],
- [#if defined(__LP64__) || defined(__s390x__)
- yes
- #endif],
+ AC_COMPILE_IFELSE(
+ [AC_LANG_SOURCE(
+ [[#if defined __LP64__ || defined __s390x__
+ int ok;
+ #else
+ error fail
+ #endif
+ ]])],
[gl_cv_host_cpu_c_abi=s390x],
[gl_cv_host_cpu_c_abi=s390])
;;
@@ -210,10 +255,14 @@ changequote([,])dnl
sparc | sparc64 )
# UltraSPARCs running Linux have `uname -m` = "sparc64", but the
# C compiler still generates 32-bit code.
- AC_EGREP_CPP([yes],
- [#if defined __sparcv9 || defined __arch64__
- yes
- #endif],
+ AC_COMPILE_IFELSE(
+ [AC_LANG_SOURCE(
+ [[#if defined __sparcv9 || defined __arch64__
+ int ok;
+ #else
+ error fail
+ #endif
+ ]])],
[gl_cv_host_cpu_c_abi=sparc64],
[gl_cv_host_cpu_c_abi=sparc])
;;
diff --git a/m4/lib-ld.m4 b/m4/lib-ld.m4
index cffa0ef91..0f0c599fb 100644
--- a/m4/lib-ld.m4
+++ b/m4/lib-ld.m4
@@ -1,4 +1,4 @@
-# lib-ld.m4 serial 8
+# lib-ld.m4 serial 9
dnl Copyright (C) 1996-2003, 2009-2017 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -120,11 +120,14 @@ else
fi
case $host in
*-*-aix*)
- AC_EGREP_CPP([yes],
- [#if defined __powerpc64__ || defined _ARCH_PPC64
- yes
- #endif
- ],
+ AC_COMPILE_IFELSE(
+ [AC_LANG_SOURCE(
+ [[#if defined __powerpc64__ || defined _ARCH_PPC64
+ int ok;
+ #else
+ error fail
+ #endif
+ ]])],
[# The compiler produces 64-bit code. Add option '-b64' so that the
# linker groks 64-bit object files.
case "$acl_cv_path_LD " in
@@ -134,10 +137,14 @@ else
], [])
;;
sparc64-*-netbsd*)
- AC_EGREP_CPP([yes],
- [#if defined __sparcv9 || defined __arch64__
- yes
- #endif],
+ AC_COMPILE_IFELSE(
+ [AC_LANG_SOURCE(
+ [[#if defined __sparcv9 || defined __arch64__
+ int ok;
+ #else
+ error fail
+ #endif
+ ]])],
[],
[# The compiler produces 32-bit code. Add option '-m elf32_sparc'
# so that the linker groks 32-bit object files.
diff --git a/m4/lib-prefix.m4 b/m4/lib-prefix.m4
index ea3b03a63..6699ca172 100644
--- a/m4/lib-prefix.m4
+++ b/m4/lib-prefix.m4
@@ -1,4 +1,4 @@
-# lib-prefix.m4 serial 9
+# lib-prefix.m4 serial 10
dnl Copyright (C) 2001-2005, 2008-2017 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -188,11 +188,16 @@ AC_DEFUN([AC_LIB_PREPARE_MULTILIB],
dnl But we want to recognize the sparcv9 or amd64 subdirectory also if the
dnl symlink is missing, so we set acl_libdirstem2 too.
AC_CACHE_CHECK([for 64-bit host], [gl_cv_solaris_64bit],
- [AC_EGREP_CPP([sixtyfour bits], [
-#ifdef _LP64
-sixtyfour bits
-#endif
- ], [gl_cv_solaris_64bit=yes], [gl_cv_solaris_64bit=no])
+ [AC_COMPILE_IFELSE([sixtyfour bits],
+ [AC_LANG_SOURCE(
+ [[#ifdef _LP64
+ int ok;
+ #else
+ error fail
+ #endif
+ ]])],
+ [gl_cv_solaris_64bit=yes],
+ [gl_cv_solaris_64bit=no])
])
if test $gl_cv_solaris_64bit = yes; then
acl_libdirstem=lib/64
diff --git a/m4/year2038.m4 b/m4/year2038.m4
index 6e21f631d..b9adc99bd 100644
--- a/m4/year2038.m4
+++ b/m4/year2038.m4
@@ -1,4 +1,4 @@
-# year2038.m4 serial 1
+# year2038.m4 serial 2
dnl Copyright (C) 2017 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -43,11 +43,14 @@ AC_DEFUN([gl_YEAR2038],
if test $gl_cv_type_time_t_64 = no; then
dnl Just bail out if 'time_t' is not 64-bit, and let the user fix the
dnl problem.
- AC_EGREP_CPP([booboo], [
- #ifdef _USE_32BIT_TIME_T
- booboo
- #endif
- ],
+ AC_COMPILE_IFELSE(
+ [AC_LANG_SOURCE(
+ [[#ifdef _USE_32BIT_TIME_T
+ int ok;
+ #else
+ error fail
+ #endif
+ ]])],
[AC_MSG_FAILURE([This package requires a 64-bit 'time_t' type. Remove _USE_32BIT_TIME_T from the compiler flags.])],
[AC_MSG_FAILURE([This package requires a 64-bit 'time_t' type. Your system include files surely provide a way to make 'time_t' an alias of '__time64_t'.])])
fi
--
2.13.6
Bruno Haible
2017-11-06 10:08:07 UTC
Permalink
Hi Paul,

This patch is not good, IMO.
Without this patch, ‘./configure CFLAGS="-m32"’ fails on gzip with GNU/Linux x86-64.
We have documented in
https://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.69/html_node/Preset-Output-Variables.html
that this is the wrong way to do a 32-bit build on 64-bit platforms. There are
two ways that work:
1) ./configure CC="gcc -m32"
2) ./configure CPPFLAGS="-m32" LDFLAGS="-m32"

This configuration issue comes up occasionally, therefore it is a documentation
problem that we should probably fix in the INSTALL file.

I'd would be in favour of reverting this change because
1) AC_COMPILE_IFELSE is slower than AC_EGREP_CPP, and there is common
consensus (discussion on gnu-prog-discuss in October 2016) that configure
scripts are already slower than it should be.
2) There are many more uses of AC_EGREP_CPP outside of gnulib.

Bruno
Paul Eggert
2017-11-06 18:50:46 UTC
Permalink
Post by Bruno Haible
This configuration issue comes up occasionally
It's more than "occasionally", I'm afraid. I just did a Google search
for 'configure CFLAGS "-m32"' and in the first ten hits, more people got
it wrong than right. When the error rate is this high, it's appropriate
to change the code to make errors less likely.
Post by Bruno Haible
1) AC_COMPILE_IFELSE is slower than AC_EGREP_CPP, and there is common
consensus (discussion on gnu-prog-discuss in October 2016) that configure
scripts are already slower than it should be.
Yes, and that's a real problem. However, these changes won't hurt
performance much, as they're only a small number of tests.
Post by Bruno Haible
2) There are many more uses of AC_EGREP_CPP outside of gnulib.
Yes, and there are many other uses of AC_EGREP_CPP even inside Gnulib.
The patch does not eliminate all uses of AC_EGREP_CPP, only the uses
where it's common for builders to use idioms like "./configure
CFLAGS='-m32'" where CFLAGS unexpectedly affects the behavior that the
AC_EGREP_CPP code is testing for. Many builders don't know that -m32
affects the preprocessor, and we can't really expect them to read some
obscure corner of the Gnulib manual to find this stuff out.
Bruno Haible
2017-11-06 19:23:47 UTC
Permalink
Hi Paul,
Post by Paul Eggert
Post by Bruno Haible
This configuration issue comes up occasionally
It's more than "occasionally", I'm afraid. I just did a Google search
for 'configure CFLAGS "-m32"' and in the first ten hits, more people got
it wrong than right. When the error rate is this high, it's appropriate
to change the code to make errors less likely.
I completely disagree. When the error rate is so high, we should
1) improve the documentation (this is mainly install.texi from Autoconf),
2) add a consistency check in AC_PROG_CC or AC_PROG_CPP.

Ad (1): I am frequently running configures on these kinds of systems.
Therefore I think I could come up with some practically usable text.

i386 Linux, CC="gcc -m32"
Solaris
Mac OS X
Hurd
FreeBSD
NetBSD
OpenBSD
Haiku
Cygwin
Windows
m68k Linux
mips IRIX: 32, CC="cc -32"
n32, CC="cc -n32"
CC="gcc -mabi=n32"
Linux: 32-bit
n32, CC="gcc -mabi=n32"
64-bit, CC="gcc -mabi=64"
sparc Solaris: 32-bit
64-bit
Linux: 32-bit, CC="gcc -m32"
64-bit, CC="gcc -m64"
NetBSD: 32-bit, CC="gcc -m32"
alpha Linux
hppa HP-UX
Linux
hppa64 HP-UX, CC="cc +DD64"
arm Linux
arm64 Linux: 64-bit
FreeBSD: 64-bit
powerpc AIX: 32-bit, CC="xlc", CC="gcc"
64-bit, CC="xlc -q64" AR="ar -X 64" NM="nm -X 64", CC="gcc -maix64" AR="ar -X 64" NM="nm -X 64"
Linux: 32-bit, CC="gcc -m32"
64-bit BE
64-bit LE ELFv2
Mac OS X
ia64 Linux
HP-UX: 32-bit, CC="cc"
64-bit, CC="cc +DD64"
x86_64 Linux
Solaris
Mac OS X, CC="gcc -m64"
Linux x32, CC="gcc -mx32"
GNU/kFreeBSD
FreeBSD
NetBSD
OpenBSD
Cygwin
Windows
s390 Linux, CC="gcc -m31"
s390x Linux

Ad (2): Before AC_PROG_CC included a check whether the compiler can actually
produce executables, people were frequently reporting odd issues (ranging from
nonexistent compiler commands, to LD_LIBRARY_PATH problems of cc1) to the mailing
lists. This check helped a lot.
Post by Paul Eggert
The patch does not eliminate all uses of AC_EGREP_CPP, only the uses
where it's common for builders to use idioms like "./configure
CFLAGS='-m32'" where CFLAGS unexpectedly affects the behavior that the
AC_EGREP_CPP code is testing for.
It is bad to have 3 ways of using configure - with the same intended result -,
when
- 2 out of the 3 produce a 100% valid result,
- 1 out of the 3 produces a 95% valid result.
People will then waste time to squash out the remaining 5% of bugs in the 3rd
way. It is much better to make it clear that the third way is unsupported.
Post by Paul Eggert
Many builders don't know that -m32
affects the preprocessor, and we can't really expect them to read some
obscure corner of the Gnulib manual to find this stuff out.
But we can expect them to try differently when they get an error message
"You invoked configure incorrectly. Try with CC="gcc -m32" instead."

Bruno
Paul Eggert
2017-11-07 00:08:37 UTC
Permalink
Post by Bruno Haible
When the error rate is so high, we should
1) improve the documentation (this is mainly install.texi from Autoconf),
2) add a consistency check in AC_PROG_CC or AC_PROG_CPP.
(2) would be better than what we have now, yes. But how could such a
check be implemented robustly? Wouldn't it require a comprehensive
knowledge of which compiler options affect which predefined macros on
which platforms?

The problem is not limited to flags like -m32 and -m64. Flags like
-fsanitize=address can also affect preprocessor behavior. A complete
list of such flags would be daunting to maintain.

In contrast, it's relatively simple to say "Don't use AC_EGREP_CPP
unless you know the result isn't likely to depend on compiler options."
Bruno Haible
2017-11-07 00:57:57 UTC
Permalink
Post by Paul Eggert
In contrast, it's relatively simple to say "Don't use AC_EGREP_CPP
unless you know the result isn't likely to depend on compiler options."
No one can reasonably assert that a certain test is not dependent on compiler
options.
1) because there are unexpected cases, such as #include <sys/procfs.h>
on Solaris, which does totally different things when _FILE_OFFSET_BITS=64
is defined.
2) because few developers try different compilation options. Most stick
with their "usual" environment variables.

Therefore, making such a requirement on the use of AC_EGREP_CPP is similar
to forbidding the use of AC_EGREP_CPP entirely. Which doesn't help in the
attempt of making configure scripts execute fast.
Post by Paul Eggert
Post by Bruno Haible
When the error rate is so high, we should
1) improve the documentation (this is mainly install.texi from Autoconf),
2) add a consistency check in AC_PROG_CC or AC_PROG_CPP.
(2) would be better than what we have now, yes. But how could such a
check be implemented robustly? Wouldn't it require a comprehensive
knowledge of which compiler options affect which predefined macros on
which platforms?
Yes. But this is solvable:
* The list of such macros is finite.
* I imagine a test that
1. runs through $CPP a file such as

#ifdef _LP64
HAVE_LP64
#endif
#ifdef _ILP32
HAVE_ILP32
#endif
...

then eliminates the redundant #line statements and whitespace.
2. Compiles and runs a file such as

#include <stdio.h>
int main () {
#ifdef _LP64
puts("HAVE_LP64");
#endif
#ifdef _ILP32
puts("HAVE_ILP32');
#endif
...
return 0;
}
3. Compares the two results.
This way, the test can catch differences in any number of macros in
1 $CPP run + 1 $CC run.
Post by Paul Eggert
The problem is not limited to flags like -m32 and -m64. Flags like
-fsanitize=address can also affect preprocessor behavior. A complete
list of such flags would be daunting to maintain.
I didn't know about the -fsanitize=address effect, but it is easy to determine:

$ diff <(:|gcc -E -dM -|LC_ALL=C sort) <(:|gcc -fsanitize=address -E -dM -|LC_ALL=C sort)
155a156
Post by Paul Eggert
#define __SANITIZE_ADDRESS__ 1
We can even do this automatically for all gcc options that appear in the
"gcc --help" output, like we did for the warning options.

Once we have determined this list, it will cover nearly all cases, with only
occasional updates.

Bruno
Bruno Haible
2017-11-07 01:24:57 UTC
Permalink
Post by Bruno Haible
Post by Paul Eggert
The problem is not limited to flags like -m32 and -m64. Flags like
-fsanitize=address can also affect preprocessor behavior. A complete
list of such flags would be daunting to maintain.
$ diff <(:|gcc -E -dM -|LC_ALL=C sort) <(:|gcc -fsanitize=address -E -dM -|LC_ALL=C sort)
155a156
Post by Paul Eggert
#define __SANITIZE_ADDRESS__ 1
It is not limited to -fsanitize=address. -O does it as well:

$ diff <(:|gcc -E -dM -|LC_ALL=C sort) <(:|gcc -O -E -dM -|LC_ALL=C sort)
0a1
Post by Bruno Haible
#define _FORTIFY_SOURCE 2
148c149
< #define __NO_INLINE__ 1
---
Post by Bruno Haible
#define __OPTIMIZE__ 1
But people do put options like -O and -fsanitize=address into $CFLAGS and not
into $CPPFLAGS. So, if our check considers __OPTIMIZE__ and __SANITIZE_ADDRESS__
as relevant macros, it will fail in even the most basic setting, namely
CC=gcc CFLAGS="-O2 -g"

Probably we need to draw a line between
- macros that often change the result of $CPP output
(e.g. -D and -I options, but also -m32/-m64)
- macros that rarely change the result of $CPP output because they are just
witness macros of optimization options (e.g. __OPTIMIZE__).

Bruno
Paul Eggert
2017-11-07 02:59:28 UTC
Permalink
The approach you suggest would not work with cross-compilation, right? So it
might be better to use the output of $CPP to generate a .c file that could be
compiled and not run, that would check that the compiler options were consistent
with the preprocessor options.
Post by Bruno Haible
Probably we need to draw a line between
- macros that often change the result of $CPP output
(e.g. -D and -I options, but also -m32/-m64)
- macros that rarely change the result of $CPP output because they are just
witness macros of optimization options (e.g. __OPTIMIZE__).
In that case, the issue boils down to: what is the safe set of options that
builders can put into CFLAGS instead of CPPFLAGS+LDFLAGS (or CC)? Clearly
options like -D and -I are unsafe, and it seems we agree that -O and
-fsanitize=address are safe. However, we disagree whether -m32 and -m64 are safe.

The list of safe options would be ad-hoc, whatever it is. For example, the
following GCC options can all affect the preprocessor; which should be
considered safe and why?

-pthread -ffast-math -fnext-runtime -fno-exceptions -fno-inline
-fno-math-errno -fstack-protector -funsigned-char -mbig-endian -melf -mwin32
-pedantic -std

My impression is that builders mentally put options like these into CFLAGS and
not CPPFLAGS because they think of them as compiler not preprocessor options. So
I would consider all these options to be safe (along with -m32 and -m64 and
-fsanitize). Presumably you would consider some to be safe and some unsafe, but
what rule would you suggest to distinguish safe from unsafe options? Whatever
the rule is, it should be simple and easy to remember.

The rule I am thinking of is, "If the option is clearly intended for the
preprocessor, it's unsafe. Otherwise it's safe." So, for example, -D, -U, and -I
are unsafe, whereas the options mentioned above are safe. This rule is simple
and easy to remember. I realize it can lead to slower 'configure' scripts, but
in practice they're not so much slower as to be worth the cost of error-prone
configuration.

Loading...