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

From: Assaf Gordon <[email-masked]>
Date: Sat, 19 Jan 2013 22:02:22 -0500

On 01/18/13 19:58, Paul Eggert wrote:
> I'm puzzled as to why stpncpy.c is being compiled at all.
> Doesn't OS X have stpncpy?  I would look in config.log
> and try to figure out why 'configure' thinks stpncpy is
> missing.

This seems like the relevant part from 'config.log' (but more info below):
===
configure:8522: result: no
configure:8522: checking for sigaction
configure:8522: clang -o conftest -g -O2   conftest.c  >&5
configure:8522: $? = 0
configure:8522: result: yes
configure:8522: checking for sigaltstack
configure:8522: clang -o conftest -g -O2   conftest.c  >&5
configure:8522: $? = 0
configure:8522: result: yes
configure:8522: checking for siginterrupt
configure:8522: clang -o conftest -g -O2   conftest.c  >&5
configure:8522: $? = 0
configure:8522: result: yes
configure:8522: checking for snprintf
configure:8522: clang -o conftest -g -O2   conftest.c  >&5
conftest.c:144:6: warning: incompatible redeclaration of library function 'snprintf'
char snprintf ();
      ^
conftest.c:144:6: note: 'snprintf' is a builtin with type 'int (char *, unsigned long, const char *, ...)'
1 warning generated.
configure:8522: $? = 0
configure:8522: result: yes
configure:8522: checking for stpncpy
configure:8522: clang -o conftest -g -O2   conftest.c  >&5
conftest.c:145:6: warning: incompatible redeclaration of library function 'stpncpy'
char stpncpy ();
      ^
conftest.c:145:6: note: 'stpncpy' is a builtin with type 'char *(char *, const char *, unsigned long)'
1 warning generated.
Undefined symbols for architecture x86_64:
   "_stpncpy", referenced from:
       _main in conftest-eAtTGu.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
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
configure:8522: checking for strdup
configure:8522: clang -o conftest -g -O2   conftest.c  >&5
conftest.c:145:6: warning: incompatible redeclaration of library function 'strdup'
char strdup ();
      ^
conftest.c:145:6: note: 'strdup' is a builtin with type 'char *(const char *)'
===

I tried compiling a simple test program:
===
$ cat test.c
#include <string.h>
int main ()
{
  char a[10];
  stpncpy (a,"a",10);
  return 0;
}
$ clang -o test test.c
Undefined symbols for architecture x86_64:
   "___stpncpy_chk", referenced from:
       _main in test-GyRBLi.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
===

And it might be related to the following:
http://gcc.gnu.org/ml/gcc-patches/2011-11/msg02470.html

Trying macro expansion gives:
===
$ clang -E test.c | grep -A 4 -B 4 stpncpy
char *strdup(const char *);
void *memccpy(void *, const void *, int, size_t);
# 140 "/usr/include/string.h" 3 4
char *stpcpy(char *, const char *);
char *stpncpy(char *, const char *, size_t) __attribute__((availability(macosx,introduced=10.7)));
char *strndup(const char *, size_t) __attribute__((availability(macosx,introduced=10.7)));
size_t strnlen(const char *, size_t) __attribute__((availability(macosx,introduced=10.7)));
char *strsignal(int sig);
# 155 "/usr/include/string.h" 3 4
--
static __inline char *
__inline_stpncpy_chk (char *restrict __dest, const char *restrict __src,
         size_t __len)
{
   return __builtin___stpncpy_chk (__dest, __src, __len, __builtin_object_size (__dest, 2 > 1));
}
--
# 2 "test.c" 2
int main ()
{
  char a[10];
  ((__builtin_object_size (a, 0) != (size_t) -1) ? __builtin___stpncpy_chk (a, "a", 10, __builtin_object_size (a, 2 > 1)) : __inline_stpncpy_chk (a, "a", 10));
  return 0;
}
===

So if I understand correctly, this is the cause:
1. string.h does have "stpncpy", as a macro/inline
2. linking programs with stpncpy fails, leading "configure" to think there's no "stpncpy"
3. 'string.h' is #include'd, but so is gnulib's stpncpy.c
4.the GNULIB definition of 'stpncpy' conflicts with the 'string.h' definition.