diff mbox

[RFC] Filename based shared library versioning on AIX

Message ID 5098011F.8020807@salomon.at
State New
Headers show

Commit Message

Michael Haubenwallner Nov. 5, 2012, 6:10 p.m. UTC
On 11/02/2012 12:16 AM, David Edelsohn wrote:
> I would like to introduce filename-based shared library versioning (known as
> the "soname" in ELF world) for AIX, activated by the '--enable-aix-soname'
> configure flag.

> As discussed in the Bugzilla, I think this is a good feature and a
> nice trick to support SVR4-like shared object naming on AIX (I think
> this really is Linux/SVR4 convention, not ELF file format convention).

Thank you!

> As you mention, this scheme is not compatible with the current shared
> object naming scheme of GCC/libtool on AIX and not backward compatible,

Well, as long as the old sharedlibs were not created as standalone shared
objects (lib.so), this is similar to a normal "soname"-bump on AIX, in that
it is still possible for the package manager to transfer the old shared
objects (with F_LOADONLY flag set) into the new archives.

As far as I can see, gcc does not provide this libtool-option (environment
variable LDFLAGS=-brtl) at all for its libraries (for good reason).

> so it definitely should not be the default.

Yes, of course.

> As Joseph mentioned, these options needs to be documented, but
> otherwise they are a good feature to add.

Here's the updated patch.

Thank you!
/haubi/

Comments

David Edelsohn Nov. 5, 2012, 6:31 p.m. UTC | #1
On Mon, Nov 5, 2012 at 1:10 PM, Michael Haubenwallner
<michael.haubenwallner@salomon.at> wrote:

> Well, as long as the old sharedlibs were not created as standalone shared
> objects (lib.so), this is similar to a normal "soname"-bump on AIX, in that
> it is still possible for the package manager to transfer the old shared
> objects (with F_LOADONLY flag set) into the new archives.

Yes, the old shared objects can be placed in the new archive, but one
also needs to ensure that the archive has the correct name, e.g.
libfoo.a not libfoo.so.x.y ad libfoo.so.

> As far as I can see, gcc does not provide this libtool-option (environment
> variable LDFLAGS=-brtl) at all for its libraries (for good reason).

I do not understand what you mean by gcc does not provide this libtool
option.  GCC does link libstdc++ with -G option, for use with -brtl,
but does not automatically link applications with -brtl.

Thanks, David
Michael Haubenwallner Nov. 6, 2012, 9:02 a.m. UTC | #2
On 11/05/2012 07:31 PM, David Edelsohn wrote:
> On Mon, Nov 5, 2012 at 1:10 PM, Michael Haubenwallner
> <michael.haubenwallner@salomon.at> wrote:
> 
>> Well, as long as the old sharedlibs were not created as standalone shared
>> objects (lib.so), this is similar to a normal "soname"-bump on AIX, in that
>> it is still possible for the package manager to transfer the old shared
>> objects (with F_LOADONLY flag set) into the new archives.
> 
> Yes, the old shared objects can be placed in the new archive, but one
> also needs to ensure that the archive has the correct name, e.g.
> libfoo.a not libfoo.so.x.y ad libfoo.so.

Actually, AIX does symlink some of its system libraries (including libc), so
it seems to be fine when libfoo.a is a symlink to libfoo.so.x.y containing
the correct shared objects.

>> As far as I can see, gcc does not provide this libtool-option (environment
>> variable LDFLAGS=-brtl) at all for its libraries (for good reason).
> 
> I do not understand what you mean by gcc does not provide this libtool
> option.  GCC does link libstdc++ with -G option, for use with -brtl,
> but does not automatically link applications with -brtl.

When vanilla libtool detects "-brtl" in LDFLAGS, it does:
  * Link the Shared Object with -G flag.
  * The Shared Object's filename is libNAME.so.1.2.3
  * Create symlink libNAME.so.1 -> libNAME.so.1.2.3
  * Create symlink libNAME.so -> libNAME.so.1.2.3
  * Create libNAME.a from static objects.

When "-brtl" is not in LDFLAGS, it does it the traditional way:
  * Link the Shared Object with -bM:SRE flag.
  * The Shared Object's filename is libNAME.so.1
  * Put the Shared Object into libNAME.a

The former is what is incompatible with this "aix-soname" proposal, but I've never
seen any gcc library (libstdc++) being created that way as standalone Shared Object.

Instead, libstdc++ is created the traditional way, but with -G flag - not
listening to -brtl in LDFLAGS as vanilla libtool does.

/haubi/
diff mbox

Patch

From 3c9141f9df666ad972688b31e1cfecfbfd6ef6b6 Mon Sep 17 00:00:00 2001
From: Michael Haubenwallner <michael.haubenwallner@salomon.at>
Date: Fri, 16 Mar 2012 14:49:20 +0100
Subject: [PATCH] AIX: Filename-based shlib versioning for libgcc_s

2012-11-05  Michael Haubenwallner  <michael.haubenwallner@salomon.at>

	(libgcc_s) Optional filename-based shared library versioning on AIX.
	* gcc/doc/install.texi: Add --enable-aix-soname option.
	* Makefile.in (enable_aix_soname): Define.
	* config/rs6000/t-slibgcc-aix: Implement filename-based versioning.
	* configure.in: Accept --enable-aix-soname option.
	* configure: Recreate.
---
 gcc/doc/install.texi               |   29 +++++++++++++
 libgcc/Makefile.in                 |    1 +
 libgcc/config/rs6000/t-slibgcc-aix |   79 +++++++++++++++++++++++++++++++-----
 libgcc/configure                   |   26 ++++++++++++
 libgcc/configure.ac                |   17 ++++++++
 5 files changed, 141 insertions(+), 11 deletions(-)

diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index 7b2441a..8f9425d 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -1336,6 +1336,30 @@  particularly useful if you intend to use several versions of GCC in
 parallel.  This is currently supported by @samp{libgfortran},
 @samp{libjava}, @samp{libmudflap}, @samp{libstdc++}, and @samp{libobjc}.
 
+@item @anchor{enable-aix-soname}--enable-aix-soname
+Traditional AIX shared library versioning (versioned @code{Shared Objects} as
+members of unversioned @code{Archive Library} files named @samp{lib.a}) causes
+numerous headaches for package managers.  However, @code{Import Files} as
+members of @code{Archive Library} files allow for @emph{filename-based} shared
+library versioning known on Linux/SVR4, where this is called the "SONAME".
+But as they prevent static linking, @code{Import Files} may be used with
+@code{Runtime Linking} only, where the linker does search for @samp{lib.so}
+library filenames first.
+
+When enabled, a shared library supporting @option{--enable-aix-soname} is
+created as @code{Shared Archive Library} using the @samp{lib.so} filename, for
+use @emph{with} @code{Runtime Linking} @emph{only}, while the @samp{lib.a}
+filename is created as the plain static @code{Archive Library} - @emph{except}
+for @samp{libgcc_s}, which is not used in static linking, so @file{libgcc_s.a}
+is the symlink referring to the versioned @samp{lib.so} filename.
+
+Package managers can still
+@uref{./specific.html#transfer-aix-shobj,,transfer} the old @code{Shared
+Objects} to the static @code{Archive Library} file (pointed to by the symlink)
+@samp{lib.a} when merging into the live filesystem.
+
+@option{--enable-aix-soname} is currently supported by @samp{libgcc_s}.
+
 @item --enable-languages=@var{lang1},@var{lang2},@dots{}
 Specify that only a particular subset of compilers and
 their runtime libraries should be built.  For a list of valid values for
@@ -3690,6 +3714,7 @@  APAR IY26685 (AIX 4.3) or APAR IY25528 (AIX 5.1).  It also requires a
 fix for another AIX Assembler bug and a co-dependent AIX Archiver fix
 referenced as APAR IY53606 (AIX 5.2) or as APAR IY54774 (AIX 5.1)
 
+@anchor{transfer-aix-shobj}
 @samp{libstdc++} in GCC 3.4 increments the major version number of the
 shared object and GCC installation places the @file{libstdc++.a}
 shared library in a common location which will overwrite the and GCC
@@ -3720,6 +3745,10 @@  Archive the runtime-only shared object in the GCC 3.4
 % ar -q libstdc++.a libstdc++.so.4 libstdc++.so.5
 @end smallexample
 
+You may also need this procedure when you start using the
+@uref{./configure.html#enable-aix-soname,,@option{--enable-aix-soname}}
+configure option.
+
 Linking executables and shared libraries may produce warnings of
 duplicate symbols.  The assembly files generated by GCC for AIX always
 have included multiple symbol definitions for certain global variable
diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in
index 43b14a0..b22e82b 100644
--- a/libgcc/Makefile.in
+++ b/libgcc/Makefile.in
@@ -41,6 +41,7 @@  long_double_type_size = @long_double_type_size@
 decimal_float = @decimal_float@
 enable_decimal_float = @enable_decimal_float@
 fixed_point = @fixed_point@
+enable_aix_soname = @enable_aix_soname@
 
 host_noncanonical = @host_noncanonical@
 target_noncanonical = @target_noncanonical@
diff --git a/libgcc/config/rs6000/t-slibgcc-aix b/libgcc/config/rs6000/t-slibgcc-aix
index a0fdd13..79a6f1f 100644
--- a/libgcc/config/rs6000/t-slibgcc-aix
+++ b/libgcc/config/rs6000/t-slibgcc-aix
@@ -17,24 +17,81 @@ 
 # along with GCC; see the file COPYING3.  If not see
 # <http://www.gnu.org/licenses/>.
 
-# Build a shared libgcc library.
+# Build a shared libgcc library, with optional filename-based versioning:
+#
+# To get a different *filename* used at runtime than at linktime, instead of
+# the Shared Object we need to give an Import File to the linker, which allows
+# to define a different filename for runtime.
+#
+# Packing both the Import File and the Shared Object into one archive file
+# allows for a file layout similar to what is known on SVR4/Linux platforms -
+# having the unversioned library name as symlink to the versioned one, while
+# still keeping the AIX specific multilib variant of having both 32bit and
+# 64bit Shared Objects within one archive file possible, even if we do not
+# create such libraries (yet?).
+#
+# However, static linking of Shared Objects via an Import File does not work.
+# So as long as a library needs to be statically linkable, we want to use .so
+# as extension for the unversioned symlink, even if that will be used with
+# runtime-linking enabled (-brtl or -G linker flag) only.
+#
+# But as libgcc_s never is statically linked anyway, we can create libgcc_s.a
+# as symlink to libgcc_s.so.1 too (rendering the use of the .so extension as
+# best-practice template here).
+#
+# Use these configure arguments to control the filename-based versioning:
+#
+#   --disable-aix-soname
+#       Do not provide filename-based versioning for shared libgcc (default).
+#
+#   --enable-aix-soname
+#       Create shared libgcc with filename-based versioning, for both linking
+#       with and without AIX runtime-linking enabled.
+#
+# For the symbols listed in the Import File:
+# It would be important to specify their 'weak' attribute, but it turns out
+# that libgcc_s doesn't have weak symbols at all. So there is no need for
+# extra effort to identify weak symbols here.
 SHLIB_EXT = .a
-SHLIB_LINK = $(CC) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \
-	-Wl,-bE:@shlib_map_file@ -o @multilib_dir@/shr.o \
+SHLIB_SOVERSION = 1
+SHLIB_SONAME = `test no != $(enable_aix_soname) && echo '@shlib_base_name@.so.$(SHLIB_SOVERSION)' || echo '@shlib_base_name@$(SHLIB_EXT)'`
+SHLIB_MEMBER = `case $(enable_aix_soname):@multilib_dir@ in no:*) echo 'shr' ;; *64*) echo 'shr_64' ;; *) echo 'shr' ;; esac`
+SHLIB_BITS   = `case @multilib_dir@ in *64*) echo '64' ;; *) echo '32' ;; esac`
+SHLIB_LINK = soname=$(SHLIB_SONAME) ; shr=$(SHLIB_MEMBER) ; imp= ; \
+	$(CC) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \
+	-Wl,-bE:@shlib_map_file@ -o @multilib_dir@/$$shr.o \
 	@multilib_flags@ @shlib_objs@ -lc \
 	`case @multilib_dir@ in \
 	*pthread*) echo -L$(TARGET_SYSTEM_ROOT)/usr/lib/threads -lpthreads -lc_r $(TARGET_SYSTEM_ROOT)/usr/lib/libc.a ;; \
 	*) echo -lc ;; esac` ; \
-	rm -f @multilib_dir@/tmp-@shlib_base_name@.a ; \
-	$(AR_CREATE_FOR_TARGET) @multilib_dir@/tmp-@shlib_base_name@.a \
-	@multilib_dir@/shr.o ; \
-	mv @multilib_dir@/tmp-@shlib_base_name@.a \
-	   @multilib_dir@/@shlib_base_name@.a ; \
-	rm -f @multilib_dir@/shr.o
+	if test no != $(enable_aix_soname); then \
+	  imp=@multilib_dir@/$$shr.imp ; \
+	  $(STRIP_FOR_TARGET) -X32_64 -e @multilib_dir@/$$shr.o ; \
+	  { echo "\#! $$soname($$shr.o)" ; \
+	    echo "\# $(SHLIB_BITS)" ; \
+	    cat @shlib_map_file@ ; \
+	  } > $$imp ; \
+	fi ; \
+	rm -f @multilib_dir@/tmp-$$soname ; \
+	$(AR_CREATE_FOR_TARGET) @multilib_dir@/tmp-$$soname \
+	  $$imp @multilib_dir@/$$shr.o ; \
+	mv @multilib_dir@/tmp-$$soname \
+	   @multilib_dir@/$$soname ; \
+	rm -f $$imp @multilib_dir@/$$shr.o ; \
+	if test no != $(enable_aix_soname); then \
+	  rm -f @multilib_dir@/@shlib_base_name@$(SHLIB_EXT) ; \
+	  $(LN_S) $$soname @multilib_dir@/@shlib_base_name@$(SHLIB_EXT) ; \
+	fi
 SHLIB_INSTALL = \
 	$(mkinstalldirs) $(DESTDIR)$(slibdir)@shlib_slibdir_qual@; \
-	$(INSTALL_DATA) @multilib_dir@/@shlib_base_name@.a \
-		$(DESTDIR)$(slibdir)@shlib_slibdir_qual@/
+	soname=$(SHLIB_SONAME) ; \
+	$(INSTALL_DATA) @multilib_dir@/$$soname \
+		$(DESTDIR)$(slibdir)@shlib_slibdir_qual@/ ; \
+	if test no != $(enable_aix_soname) ; then \
+	  rm -f $(DESTDIR)$(slibdir)@shlib_slibdir_qual@/@shlib_base_name@$(SHLIB_EXT) ; \
+	  $(LN_S) $$soname \
+		  $(DESTDIR)$(slibdir)@shlib_slibdir_qual@/@shlib_base_name@$(SHLIB_EXT) ; \
+	fi
 SHLIB_LIBS = -lc `case @multilib_dir@ in *pthread*) echo -lpthread ;; esac`
 SHLIB_MKMAP = $(srcdir)/mkmap-flat.awk
 SHLIB_MAPFILES = libgcc-std.ver
diff --git a/libgcc/configure b/libgcc/configure
index 1425df6..13d063d 100644
--- a/libgcc/configure
+++ b/libgcc/configure
@@ -608,6 +608,7 @@  build_os
 build_vendor
 build_cpu
 build
+enable_aix_soname
 enable_shared
 libgcc_topdir
 target_alias
@@ -655,6 +656,7 @@  with_target_subdir
 with_cross_host
 with_ld
 enable_shared
+enable_aix_soname
 enable_version_specific_runtime_libs
 with_slibdir
 enable_maintainer_mode
@@ -1288,6 +1290,7 @@  Optional Features:
   --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
   --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
   --disable-shared        don't provide a shared libgcc
+  --enable-aix-soname     on AIX, do filename-based versioning for the shared libgcc
   --enable-version-specific-runtime-libs    Specify that runtime libraries should be installed in a compiler-specific directory
   --enable-maintainer-mode
                           enable make rules and dependencies not useful (and
@@ -2140,6 +2143,29 @@  fi
 
 
 
+# Check whether --enable-aix-soname was given.
+if test "${enable_aix_soname+set}" = set; then :
+  enableval=$enable_aix_soname;
+  case "${host}:${enable_shared}" in
+  powerpc*-*-aix[5-9]*:yes)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to do filename-based versioning for shared libgcc" >&5
+$as_echo_n "checking whether to do filename-based versioning for shared libgcc... " >&6; }
+    case ${enable_aix_soname} in
+    no) ;;
+    *) enable_aix_soname=yes ;;
+    esac
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_aix_soname" >&5
+$as_echo "$enable_aix_soname" >&6; }
+    ;;
+  *) enable_aix_soname=no ;;
+  esac
+
+else
+  enable_aix_soname=no
+fi
+
+
+
 # Make sure we can run config.sub.
 $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
   as_fn_error "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
diff --git a/libgcc/configure.ac b/libgcc/configure.ac
index 8b7aba5..32b3e70 100644
--- a/libgcc/configure.ac
+++ b/libgcc/configure.ac
@@ -66,6 +66,23 @@  AC_ARG_ENABLE(shared,
 ], [enable_shared=yes])
 AC_SUBST(enable_shared)
 
+AC_ARG_ENABLE(aix-soname,
+[  --enable-aix-soname     on AIX, do filename-based versioning for the shared libgcc],
+[
+  case "${host}:${enable_shared}" in
+  powerpc*-*-aix[[5-9]]*:yes)
+    AC_MSG_CHECKING([whether to do filename-based versioning for shared libgcc])
+    case ${enable_aix_soname} in
+    no) ;;
+    *) enable_aix_soname=yes ;;
+    esac
+    AC_MSG_RESULT($enable_aix_soname)
+    ;;
+  *) enable_aix_soname=no ;;
+  esac
+], [enable_aix_soname=no])
+AC_SUBST(enable_aix_soname)
+
 GCC_PICFLAG
 AC_SUBST(PICFLAG)
 
-- 
1.7.3.4