Versioned library symbols from Nicolas Boullis. Much appreciated.

This commit is contained in:
rocky
2004-02-10 01:38:54 +00:00
parent ebe70e9ba0
commit b712f599c6

View File

@@ -1,4 +1,4 @@
# $Id: Makefile.am,v 1.19 2004/02/09 10:32:35 rocky Exp $
# $Id: Makefile.am,v 1.20 2004/02/10 01:38:54 rocky Exp $
#
# Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com>
#
@@ -29,7 +29,7 @@
# faster.
#
# 3. If the library source code has changed at all since the last
# update, then increment REVISION (`C:R:A' becomes `C:r+1:A').
# update, then increment REVISION (`C:R:A' becomes `C:R+1:A').
#
# 4. If any interfaces have been added, removed, or changed since the
# last update, increment CURRENT, and set REVISION to 0.
@@ -83,7 +83,7 @@ libcdio_sources = \
lib_LTLIBRARIES = libcdio.la libiso9660.la
libcdio_la_SOURCES = $(libcdio_sources)
libcdio_la_LDFLAGS = -version-info $(libcdio_la_CURRENT):$(libcdio_la_REVISION):$(libcdio_la_AGE)
libcdio_la_LDFLAGS = -version-info $(libcdio_la_CURRENT):$(libcdio_la_REVISION):$(libcdio_la_AGE) -Wl,--version-script=libcdio.la.ver
libiso9660_la_SOURCES = \
iso9660.c \
@@ -92,6 +92,80 @@ libiso9660_la_SOURCES = \
xa.c
libiso9660_la_LIBADD = $(LIBCDIO_LIBS)
libiso9660_la_LDFLAGS = -version-info $(libiso9660_la_CURRENT):$(libiso9660_la_REVISION):$(libiso9660_la_AGE)
libiso9660_la_LDFLAGS = -version-info $(libiso9660_la_CURRENT):$(libiso9660_la_REVISION):$(libiso9660_la_AGE) -Wl,--version-script=libiso9660.la.ver
# An explanation of the versioning problem from Nicolas Boullis and
# the versioned symbol solution he uses below...
#
# Currently, libvcdinfo uses the cdio_open function from libcdio.
# Let's imagine a program foobar that uses both the vcdinfo_open
# function from libvcdinfo and the cdio_open function from libcdio.
# Currently, libcdio has SONAME libcdio.so.0, libvcdinfo has SONAME
# libvcdinfo.so.0 and requires libcdio.so.0, and foobar requires both
# libvcdinfo.so.0 and libcdio.so.0. Everything looks fine.
#
# Now, for some reason, you decide to change the cdio_open function.
# That's your right, but you have to bump the CURRENT version and (if I
# understand it correctly, athough this is not that clear in libtool's
# documentation) set the AGE to 0. Anyway, this bumps the SONAME, which is
# sane since the interface changes incompatibly.
# Now, you have a new libcdio with SONAME libcdio.so.1. But libvcdinfo and
# foobar still require libcdio.so.0. Everything is still fine.
# Now, after some minor changes, the author of foobar recompiles foobar.
# Then, foobar now requires libvcdinfo.so.0 and libcdio.so.1. And foobar
# now segfaults...
# What is happening? When you run foobar, if brings both libvcdinfo.so.0
# and libcdio.so.1, but libvcdinfo.so.0 also brings libcdio.so.0. So you
# have both libcdio.so.0 and libcdio.so.1 that bring their symbols to the
# global namespace. Hence, you have to incompatible versions of the
# cdio_open function in the name space. When foobar calls cdio_open, it
# may choose the wrong function, and segfaults...
# With versioned symbols, the cdio_open function from libcdio.so.0 may be
# known as (something that looks like) cdio_open@@CDIO_0. An the cdio_open
# function from libcdio.so.1 as cdio_open@@CDIO_1. Both versions of
# libcdio would still be brought in by the most recent foobar, but foobar
# (and libvcdinfo) know which versioned function to use and then use the
# good one.
# This is some simple versioning where every symbol is versioned with
# something that looks like the SONAME of the library. More complex (and
# better) versioning is possible; it is for example what is used by glibc.
# But good complex versioning is something that requires much more
# work...
# The below is a impliments symbol versioning. First of all, I
# compute MAJOR as CURENT - AGE; that is what is used within libtool
# (at least on GNU/Linux systems) for the number in the SONAME. The
# nm command gives the list of symbols known in each of the object
# files that will be part of the shared library. And the sed command
# extracts from this list those symbols that will be shared. (This sed
# command comes from libtool.)
libcdio_la_MAJOR := $(shell expr $(libcdio_la_CURRENT) - $(libcdio_la_AGE))
libcdio_la_DEPENDENCIES = libcdio.la.ver
libcdio.la.ver: $(libcdio_la_OBJECTS)
echo 'CDIO_$(libcdio_la_MAJOR) { ' > $@
echo " global:" >> $@
nm $(patsubst %lo,%o,$(libcdio_la_OBJECTS)) | sed -n -e 's/^.*[ ][ABCDGIRSTW][ABCDGIRSTW]*[ ][ ]*\([_A-Za-z][_A-Za-z0-9]*\)$$/ \1;/p' | sort | uniq >> $@
echo '};' >> $@
libiso9660_la_MAJOR := $(shell expr $(libiso9660_la_CURRENT) - $(libiso9660_la_AGE))
libiso9660_la_DEPENDENCIES = $(LIBCDIO_LIBS) libiso9660.la.ver
libiso9660.la.ver: $(libiso9660_la_OBJECTS)
echo 'ISO9660_$(libiso9660_la_MAJOR) {' > $@
echo " global:" >> $@
nm $(patsubst %lo,%o,$(libiso9660_la_OBJECTS)) | sed -n -e 's/^.*[ ][ABCDGIRSTW][ABCDGIRSTW]*[ ][ ]*\([_A-Za-z][_A-Za-z0-9]*\)$$/ \1;/p' | sort | uniq >> $@
echo '};' >> $@
MOSTLYCLEANFILES = libcdio.la.ver libiso9660.la.ver
INCLUDES = -I$(LIBCDIO_CFLAGS)