Friday, 7 October 2011

A little problem with gprbuild

I was configuring AWS (from the git repository), and make setup failed disastrously.

$ make -w setup
make: Entering directory `/Users/simon/tmp/aws-git'
make[1]: Entering directory `/Users/simon/tmp/aws-git/config'
gcc -c check_config.c
ar cr libsetup.a …
ranlib -c libsetup.a
gcc check_config.o -o check_config
ld: duplicate symbol _P in libsetup.a(check_config.o) and check_config.o for architecture x86_64
collect2: ld returned 1 exit status
gprbuild: link of check_config.c failed
Setup OS specific definitions
make[1]: ../.build/native/release/../setup/check_config: No such file or directory
make[1]: *** [../.build/native/release/../setup/src/aws-os_lib.ads] Error 1
make[1]: Leaving directory `/Users/simon/tmp/aws-git/config'
make: *** [config_setup] Error 2
make: Leaving directory `/Users/simon/tmp/aws-git'
This reminded me of GCC bug 42554, caused by the inappropriate use of the -c flag to ranlib.

But why wasn't this problem found before?

It turns out that Apple's GCC (Xcode 4.1), GCC 4.6 and GCC 4.7 generate uninitialized file-level data (like, in this case, FILE *fd) as common data (.comm _fd,8,3). GNAT GPL 2011 generates as a global. ranlib -c has an unfortunate interaction with common data, see bug 42554 and below.

GCC has now been fixed so that the -c flag to ranlib is not used for Mac OS X later than Leopard. I don't know whether it was ever actually needed for earlier versions; see below.

My suggested fix is to remove the line that calls this up -- in GPRBuild GPL 2011, that is
diff -r 524940a5ae16 share/gprconfig/linker.xml
--- a/share/gprconfig/linker.xml Sat Jul 09 17:46:29 2011 +0100
+++ b/share/gprconfig/linker.xml Fri Oct 07 15:54:51 2011 +0100
@@ -293,7 +293,6 @@

   for Shared_Library_Suffix use ".dylib";
   for Library_Auto_Init_Supported use "true";
-   for Archive_Indexer use project'Archive_Indexer & ("-c");
   for Shared_Library_Minimum_Switches use
         ("-dynamiclib", "-Wl,-flat_namespace", "-shared-libgcc");
The patch is here, use patch -p1 at the top level of the gprbuild tree or at $prefix (the base of the installed GNAT).

[1] ranlib -c is disapproved of by Apple, "This is seldom the intended behavior for linking from a library, as it forces the linking of a library member just because it uses an uninitialized global that is undefined at that point in the linking. This option is included only because this was the original behavior of ranlib. This option is not the default." After a bit of googling, it seems that the -c flag may have been introduced in the first place to support an Intel Fortran compiler!

1 comment:

  1. I was just bit by this again with FSF GCC 9.1.0 (gcc-9.1.0-x86_64-apple-darwin15-bin). I fixed by removing the -c argument as you did above.

    I could not reproduce it with a simple "hello" C app, even though both the generated "libhello.a" and "hello.o" files had the same symbol (at the same address). It occurred on a larger C program with several local functions and that used a static library (but the duplicate symbols came from the "main" module).

    ReplyDelete