Subject: Re: bug#13378: Cleaning up AC_PROG_CC_C_O semantics

From: Stefano Lattarini <[email-masked]>
Date: Sat, 19 Jan 2013 14:10:28 +0100

[-cc automake-patches]

On 01/16/2013 06:48 PM, Paul Eggert wrote:
> On 01/16/13 04:46, Stefano Lattarini wrote:
>> Makes sense.  Should I try to implement something along these lines (might
>> take a few days), or are you planning to do that yourself (in which case
>> I'll avoid the duplicated efforts)?
> 
> I wasn't planning on doing that, so please go ahead.
>
Here is my attempt.  OK to go in Autoconf 2.70?

Thanks,
  Stefano

---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ----

>From 6d20ebf0abd4e08f0c7793d36d57ac9037026e05 Mon Sep 17 00:00:00 2001
Message-Id: <6d20ebf0a[email-masked]>
From: Stefano Lattarini <[email-masked]>
Date: Sat, 19 Jan 2013 13:32:44 +0100
Subject: [PATCH] AC_PROG_CC_C_O: allow for improved semantics

The current semantics of AC_PROG_CC_C_O have two serious shortcomings,
that make the use of that macro in Automake problematic:

 1. It checks that *both* 'cc' and '$CC' (which might easily be 'gcc'
    or 'clang') supports "-c -o" together.  Why?  If the user has a
    broken base vendor compiler, but has installed a better one (say
    GCC), why should he still be penalized?  This behaviour is very
    likely only due to historical reasons, and has no good rationale
    today.

 2. The name of the cache variable used by this macro is based on the
    contents of the $CC expansion, rather than following the usual
    'ac_cv_cc_*' pattern.  This is fragile and confusing.  In addition,
    none of the other cache variables referring to check on the
    selected C compiler has this property -- so why should this one?
    Again, no good reasons come to mind (apart for "historical" ones).

For backward-compatibility reasons, we can't change these behaviours
abruptly; so, we implement a new saner behaviour, but don't make it
the default yet, instead allowing the user to explicitly request it
by defining the witness macro 'AC_PROG_CC_C_O_USE_MODERN_SEMANTICS'.
Future versions of Automake will thus define that macro to enable the
desired behaviour.

As a consequence of this change, we can drop the Automake-specific
private (and hacky) hook that has been added to AC_PROG_CC in past
commit 'v2.69-63-gce48964': Automake no longer plan to use it.

This change has been motivated by the on-going work on Automake and
its 'subdir-object' mode (see automake bug#13378).  See also:
<http://lists.gnu.org/archive/html/bug-autoconf/2013-01/msg00034.html>

* NEWS: Update.
* doc/autoconf.texi: Likewise.
* lib/autoconf/c.m4 (AC_PROG_CC_C_O): If the witness macro
'AC_PROG_CC_C_O_USE_MODERN_SEMANTICS' is defined:
  - check support for "-c -o" only for the currently selected C
    compiler '$CC', and not also the "system" one 'cc'
  - unconditionally use 'ac_cv_prog_cc_c_o' as the cache variable
    for this check, instead of a cache variable name based on the
    expansion of $CC.
(AC_PROG_CC): Drop Automake-specific hook enabled when the
witness macro '_AM_PROG_CC_C_O_HELPME' was defined.

Signed-off-by: Stefano Lattarini <[email-masked]>
---
 NEWS              |  5 +++++
 doc/autoconf.texi | 31 ++++++++++++++++++++++++-------
 lib/autoconf/c.m4 | 46 ++++++++++++++--------------------------------
 3 files changed, 43 insertions(+), 39 deletions(-)

diff --git a/NEWS b/NEWS
index a9b2226..9e18436 100644
--- a/NEWS
+++ b/NEWS
@@ -28,6 +28,11 @@ GNU Autoconf NEWS - User visible changes.
 - AC_PROG_CC_STDC, AC_PROG_CC_C89, AC_PROG_CC_C99 have been marked as obsolete.
   Applications should use AC_PROG_CC.

+- AC_PROG_CC_C_O implements saner semantics if the new witness macro
+  AC_PROG_CC_C_O_USE_MODERN_SEMANTICS is defined (see the documentation
+  for details).  Future versions of autoconf might make such new
+  semantics the default at some point.
+
 - AC_FUNC_VFORK now checks for the signal-handling bug in Solaris 2.4 'vfork'.
   Formerly, it ignored this bug, so that Emacs could use some tricky
   code on that platform.  Solaris 2.4 has not been supported since
diff --git a/doc/autoconf.texi b/doc/autoconf.texi
index bb83443..c1e89d7 100644
--- a/doc/autoconf.texi
+++ b/doc/autoconf.texi
@@ -7304,17 +7304,34 @@ needless reexpansion (@pxref{One-Shot Macros}).
 @acindex{PROG_CC_C_O}
 @cvindex NO_MINUS_C_MINUS_O
 @caindex prog_cc_@var{compiler}_c_o
+@caindex prog_cc_c_o
 If the C compiler does not accept the @option{-c} and @option{-o} options
-simultaneously, define @code{NO_MINUS_C_MINUS_O}.  This macro actually
-tests both the compiler found by @code{AC_PROG_CC}, and, if different,
-the first @code{cc} in the path.  The test fails if one fails.  This
-macro was created for GNU Make to choose the default C compilation
-rule.
+simultaneously, define @code{NO_MINUS_C_MINUS_O}.

-For the compiler @var{compiler}, this macro caches its result in the
+This macro has two modes of behavior, the historical one and a new
+sanest one, both described just below.  The historical mode is the
+default for the moment, but this might change in future autoconf
+versions.
+
+@itemize
+
+@item
+In the ``historical'' mode (originally created for GNU Make to choose
+the default C compilation rule), both the compiler @code{$CC} found by
+@code{AC_PROG_CC}, and, if different, the first @code{cc} in @env{PATH}
+are tested.  The test fails if one fails.  If @code{$CC} expands to
+@var{compiler}, the result of the check is cached in the
 @code{ac_cv_prog_cc_@var{compiler}_c_o} variable.
-@end defmac

+@item
+In the ``new'' mode (enabled whenever the witness macro
+@code{AC_PROG_CC_C_O_USE_MODERN_SEMANTICS} is defined), only the compiler
+@code{$CC} found by @code{AC_PROG_CC} is tested, and the result of this
+check is cached in the @code{ac_cv_prog_cc_c_o} variable.
+
+@end itemize
+
+@end defmac

 @defmac AC_PROG_CPP
 @acindex{PROG_CPP}
diff --git a/lib/autoconf/c.m4 b/lib/autoconf/c.m4
index affd765..90cd696 100644
--- a/lib/autoconf/c.m4
+++ b/lib/autoconf/c.m4
@@ -490,31 +490,6 @@ _AC_PROG_CC_C11([ac_prog_cc_stdc=c11
 		       ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89],
 		      [ac_prog_cc_stdc=no
 		       ac_cv_prog_cc_stdc=no])])])
-dnl This is a hook for Automake and its 'subdir-objects' mode, which
-dnl needs to know whether $CC supports "-c -o" together or not.  See
-dnl automake bug#13378, in particular <http://debbugs.gnu.org/13378#73>.
-dnl FIXME: there is some code duplication with AC_PROG_CC_C_O here.
-m4_ifdef([_AM_PROG_CC_C_O_HELPME],
-[set dummy $CC; ac_cc=`AS_ECHO(["$[2]"]) | \
-                       sed 's/[[^a-zA-Z0-9_]]/_/g;s/^[[0-9]]/_/'`
-AC_MSG_CHECKING([whether $CC understands -c and -o together])
-AC_CACHE_VAL([ac_cv_prog_cc_${ac_cc}_c_o],
-[AC_LANG_CONFTEST([AC_LANG_PROGRAM([])])
-# Make sure it works both with $CC and with simple cc.
-# We do the test twice because some compilers refuse to overwrite an
-# existing .o file with -o, though they will create one.
-ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&AS_MESSAGE_LOG_FD'
-rm -f conftest2.*
-if _AC_DO_VAR(ac_try) && test -f conftest2.$ac_objext
-then
-  AC_MSG_RESULT([yes])
-  eval ac_cv_prog_cc_${ac_cc}_c_o=yes
-else
-  AC_MSG_RESULT([no])
-  eval ac_cv_prog_cc_${ac_cc}_c_o=no
-fi
-rm -f core conftest*
-])])dnl
 AC_LANG_POP(C)dnl
 ])# AC_PROG_CC

@@ -589,14 +564,20 @@ fi
 # --------------
 AC_DEFUN([AC_PROG_CC_C_O],
 [AC_REQUIRE([AC_PROG_CC])dnl
-if test "x$CC" != xcc; then
+m4_ifdef([AC_PROG_CC_C_O_USE_MODERN_SEMANTICS],
+[AC_MSG_CHECKING([whether $CC understands -c and -o together])
+dnl Our cache variable will be simply named 'ac_cv_prog_cc_c_o',
+dnl but we keep this indirection to reduce code duplication, below.
+_ac_prog_cc_c_o_cache_var=ac_cv_prog_cc_c_o],
+[if test "x$CC" != xcc; then
   AC_MSG_CHECKING([whether $CC and cc understand -c and -o together])
 else
   AC_MSG_CHECKING([whether cc understands -c and -o together])
 fi
 set dummy $CC; ac_cc=`AS_ECHO(["$[2]"]) |
 		      sed 's/[[^a-zA-Z0-9_]]/_/g;s/^[[0-9]]/_/'`
-AC_CACHE_VAL(ac_cv_prog_cc_${ac_cc}_c_o,
+_ac_prog_cc_c_o_cache_var=ac_cv_prog_cc_${ac_cc}_c_o])
+AC_CACHE_VAL([$_ac_prog_cc_c_o_cache_var],
 [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])])
 # Make sure it works both with $CC and with simple cc.
 # We do the test twice because some compilers refuse to overwrite an
@@ -606,7 +587,8 @@ rm -f conftest2.*
 if _AC_DO_VAR(ac_try) &&
    test -f conftest2.$ac_objext && _AC_DO_VAR(ac_try);
 then
-  eval ac_cv_prog_cc_${ac_cc}_c_o=yes
+  eval $_ac_prog_cc_c_o_cache_var=yes
+  m4_ifndef([AC_PROG_CC_C_O_USE_MODERN_SEMANTICS], [
   if test "x$CC" != xcc; then
     # Test first that cc exists at all.
     if _AC_DO_TOKENS(cc -c conftest.$ac_ext >&AS_MESSAGE_LOG_FD); then
@@ -619,16 +601,16 @@ then
 	:
       else
 	# cc exists but doesn't like -o.
-	eval ac_cv_prog_cc_${ac_cc}_c_o=no
+	eval $_ac_prog_cc_c_o_cache_var=no
       fi
     fi
-  fi
+  fi])
 else
-  eval ac_cv_prog_cc_${ac_cc}_c_o=no
+  eval $_ac_prog_cc_c_o_cache_var=no
 fi
 rm -f core conftest*
 ])dnl
-if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; then
+if eval test \${$_ac_prog_cc_c_o_cache_var} = yes; then
   AC_MSG_RESULT([yes])
 else
   AC_MSG_RESULT([no])
-- 
1.8.1.rc3.192.g2d0029e