Subject: Re: bug#13495: Compilation fails on Mac OS X 10.8.0

From: Assaf Gordon <[email-masked]>
Date: Fri, 25 Jan 2013 14:25:57 -0500

Paul Eggert wrote, On 01/24/2013 04:38 PM:
> On 01/24/13 13:07, Assaf Gordon wrote:
>>   $ CFLAGS="-g -O0" ./configure
> 
> Isn't it better to use this?
> 
>    ./configure CFLAGS="-g -O0"
> 
> If that works, it solves your problem.

No, doesn't work - same linking error.

> Otherwise:
> 
>>   $ make
>>   [ ... snip ... ]
>>     CCLD     src/dircolors
>>   Undefined symbols for architecture x86_64:
>>     "___stpncpy_chk", referenced from:
> 
> This is the broken stpncpy implementation on OS X.
> But why isn't 'configure' catching that?
> What is the value of HAVE_STPNCPY?  It should
> not be 1.  config.log should tell you why it has
> the wrong value.

I found the following:

1. "config.log" has one check for "stpncpy" the fails:
===
configure:8522: checking for stpncpy
configure:8522: gcc -std=gnu99 -o conftest -g -O0   conftest.c  >&5
conftest.c:145: warning: conflicting types for built-in function 'stpncpy'
Undefined symbols for architecture x86_64:
  "_stpncpy", referenced from:
      _main in ccBRWint.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
configure:8522: $? = 1
configure: failed program was:
| /* confdefs.h */
| #define PACKAGE_NAME "GNU coreutils"
| #define PACKAGE_TARNAME "coreutils"
| #define PACKAGE_VERSION "8.20.90-e27bfd"
| #define PACKAGE_STRING "GNU coreutils 8.20.90-e27bfd"
| #define PACKAGE_BUGREPORT "[email-masked]"
| #define PACKAGE_URL "http://www.gnu.org/software/coreutils/"
| #define PACKAGE "coreutils"
| #define VERSION "8.20.90-e27bfd"
| #define STDC_HEADERS 1
| #define HAVE_SYS_TYPES_H 1
| #define HAVE_SYS_STAT_H 1
| #define HAVE_STDLIB_H 1
| #define HAVE_STRING_H 1
| #define HAVE_MEMORY_H 1
| #define HAVE_STRINGS_H 1
| #define HAVE_INTTYPES_H 1
| #define HAVE_STDINT_H 1
| #define HAVE_UNISTD_H 1
| #define __EXTENSIONS__ 1
| #define _ALL_SOURCE 1
| #define _DARWIN_C_SOURCE 1
| #define _GNU_SOURCE 1
| #define _POSIX_PTHREAD_SEMANTICS 1
| #define _TANDEM_SOURCE 1
| #define HAVE_FSEEKO 1
| #define HAVE_ALLOCA_H 1
| #define HAVE_ALLOCA 1
| #define HAVE_ARPA_INET_H 1
| #define HAVE_UNISTD_H 1
| #define HAVE_SYS_PARAM_H 1
| #define HAVE_SYS_SOCKET_H 1
| #define HAVE_DIRENT_H 1
| #define HAVE_WCTYPE_H 1
| #define HAVE_SYS_STAT_H 1
| #define HAVE_NETDB_H 1
| #define HAVE_NETINET_IN_H 1
| #define HAVE_GETOPT_H 1
| #define HAVE_TERMIOS_H 1
| #define HAVE_SYS_TIME_H 1
| #define HAVE_GRP_H 1
| #define HAVE_ICONV_H 1
| #define HAVE_WCHAR_H 1
| #define HAVE_STDINT_H 1
| #define HAVE_INTTYPES_H 1
| #define HAVE_LANGINFO_H 1
| #define HAVE_XLOCALE_H 1
| #define HAVE_MATH_H 1
| #define HAVE_SYS_MMAN_H 1
| #define HAVE_SYS_STATVFS_H 1
| #define HAVE_SYS_SELECT_H 1
| #define HAVE_PTHREAD_H 1
| #define HAVE_UTMP_H 1
| #define HAVE_UTMPX_H 1
| #define HAVE_SCHED_H 1
| #define HAVE_SPAWN_H 1
| #define HAVE_SYS_IOCTL_H 1
| #define HAVE_SYS_RESOURCE_H 1
| #define HAVE_SYS_UIO_H 1
| #define HAVE_SYS_UTSNAME_H 1
| #define HAVE_SYS_WAIT_H 1
| #define HAVE_UTIME_H 1
| #define HAVE_PATHS_H 1
| #define HAVE_SYSLOG_H 1
| #define HAVE_PWD_H 1
| #define D_INO_IN_DIRENT 1
| #define HAVE_LONG_FILE_NAMES 1
| #define HAVE_PATHCONF 1
| #define HAVE_BTOWC 1
| #define HAVE_REALPATH 1
| #define HAVE_CHOWN 1
| #define HAVE_FCHOWN 1
| #define HAVE_FCHDIR 1
| #define HAVE_LCHMOD 1
| #define HAVE_FCNTL 1
| #define HAVE_SYMLINK 1
| #define HAVE_ISBLANK 1
| #define HAVE_ISWCTYPE 1
| #define HAVE_MBSRTOWCS 1
| #define HAVE_WMEMCHR 1
| #define HAVE_WMEMCPY 1
| #define HAVE_FPURGE 1
| #define HAVE_ALARM 1
| #define HAVE_FSYNC 1
| #define HAVE_STRTOF 1
| #define HAVE_FTRUNCATE 1
| #define HAVE_FSTATFS 1
| #define HAVE_GETDTABLESIZE 1
| #define HAVE_GETLOGIN 1
| #define HAVE_FLOCKFILE 1
| #define HAVE_FUNLOCKFILE 1
| #define HAVE_TCGETATTR 1
| #define HAVE_TCSETATTR 1
| #define HAVE_GETTIMEOFDAY 1
| #define HAVE_GETUSERSHELL 1
| #define HAVE_ISWCNTRL 1
| #define HAVE_ISWBLANK 1
| #define HAVE_LINK 1
| #define HAVE_READLINK 1
| #define HAVE_LSTAT 1
| #define HAVE_MBSINIT 1
| #define HAVE_MBRTOWC 1
| #define HAVE_MBRLEN 1
| #define HAVE_ISASCII 1
| #define HAVE_MPROTECT 1
| #define HAVE_GETGROUPLIST 1
| #define HAVE_FCHMOD 1
| #define HAVE_MKFIFO 1
| #define HAVE_MKNOD 1
| #define HAVE_MKSTEMP 1
| #define HAVE_NL_LANGINFO 1
| #define HAVE_POSIX_SPAWN 1
| #define HAVE_UTMPXNAME 1
| #define HAVE_WCSCOLL 1
| #define HAVE_SETENV 1
| #define HAVE_SETTIMEOFDAY 1
| #define HAVE_SIGACTION 1
| #define HAVE_SIGALTSTACK 1
| #define HAVE_SIGINTERRUPT 1
| #define HAVE_SNPRINTF 1
| /* end confdefs.h.  */
| /* Define stpncpy to an innocuous variant, in case <limits.h> declares stpncpy.
|    For example, HP-UX 11i <limits.h> declares gettimeofday.  */
| #define stpncpy innocuous_stpncpy
| 
| /* System header to define __stub macros and hopefully few prototypes,
|     which can conflict with char stpncpy (); below.
|     Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
|     <limits.h> exists even on freestanding compilers.  */
| 
| #ifdef __STDC__
| # include <limits.h>
| #else
| # include <assert.h>
| #endif
| 
| #undef stpncpy
| 
| /* Override any GCC internal prototype to avoid an error.
|    Use char because int might match the return type of a GCC
|    builtin and then its argument prototype would still apply.  */
| #ifdef __cplusplus
| extern "C"
| #endif
| char stpncpy ();
| /* The GNU C library defines this for functions which it implements
|     to always fail with ENOSYS.  Some functions are actually named
|     something starting with __ and the normal name is an alias.  */
| #if defined __stub_stpncpy || defined __stub___stpncpy
| choke me
| #endif
| 
| int
| main ()
| {
| return stpncpy ();
|   ;
|   return 0;
| }
configure:8522: result: no
===

2. "config.log" has another check for the declaration of "stpncpy" that succeeds:
===
configure:21404: checking whether stpncpy is declared
configure:21404: gcc -std=gnu99 -c -g -O0  conftest.c >&5
configure:21404: $? = 0
configure:21404: result: yes
===

3. "lib/config.h" then have the followings (after "configure"):
===
/* Define to 1 when the gnulib module stpncpy should be tested. */
#define GNULIB_TEST_STPNCPY 1

/* Define to 1 if you have the declaration of `stpncpy', and to 0 if you
   don't. */
#define HAVE_DECL_STPNCPY 1

/* Define if you have the stpncpy() function and it works. */
/* #undef HAVE_STPNCPY */
===

4. The declaration of "stpncpy" in /usr/include/secure/_string.h is messy:
===
#define stpncpy(dest, src, len)                                 \
  ((__darwin_obsz0 (dest) != (size_t) -1)                               \
   ? __builtin___stpncpy_chk (dest, src, len, __darwin_obsz (dest))     \
   : __inline_stpncpy_chk (dest, src, len))

static __inline char *
__inline_stpncpy_chk (char *__restrict __dest, const char *__restrict __src,
                      size_t __len)
{
  return __builtin___stpncpy_chk (__dest, __src, __len, __darwin_obsz(__dest));
}
===

So I'm guessing that even though gnulib's stpncpy code is used, because the MacOS's native declaration of stpncpy is included, it causes problems when the macro is expanded to use "__stpncpy_chk".