On Wed, 2007-11-07 at 16:31 -0500, Behdad Esfahbod wrote: > On Wed, 2007-11-07 at 21:46 +0100, Alexander Larsson wrote: > > > > This leads me to belive it should be possible to create a configure > > option for glib such that libglib, libgmodule, libgobject are in the > > same libglib.so file, and with symlinks for gmodule and gobject. This > > setup should allow all old binaries to work as they used to, plus apps > > linked against this setup will continue to work in systems using the old > > setup.
After talking to jakub I came up with a better approach for this. Consider the case of merging libglib and libgobject. We make libglib.so and libgobject.so small libraries that only contain the symbols from the respective real library. These libraries are what are picked by the linker (ld) when you specify -lglib and -lgobject, and the symbols in them are verified against what the app uses (so you get errors if you reference symbols that are not in the libs). However, in the resulting binary the DT_NEEDED is encoded based on the DT_SONAME of these libraries. In our case the sonames of these libraries is libglib.so.0 and libgobject.so.0. These are the things looked up by the runtime linker (ld.so) when finding the library to load for the app. However, we make both libglib.so.0 and libgobject.so.0 symlinks to the same file, libglib_combined.so.0, which contains all the object files from glib and gobjects in one shared object. So, the result is: a) binaries have the same dependencies as before (i.e on both libs) b) however, we only load one library, meaning less linker overhead c) and that library is actually smaller than the two separate ones as in-library calls can now be optimized There is a slight problem with ldconfig. It goes throught the $prefix/lib directory and "fixes" up all symlinks based on the actual soname in the files. This means it will change the libglib.so.0 symlink to point to libglib.so, totally breaking things. I've worked around this by having the dummy library be in another directory ($libdir/glib-2.0/dummy/) which causes ldconfig not to change anything. I've attached a patch that gives a --enable-combined feature which combines glib, gobject and gmodule. (Not gthread, because linking in libpthreads causes slowdown since e.g. all mallocs etc suddenly become threadsafe with locking.) I tested this patch by just starting gedit and then looking at /proc/pid/smaps. The total combined rss/vmsize before combination was 712kb/984kb, and afterwards it was 688kb/964kb. In addition each of the three libraries had 4k private dirty memory, which was reduced to only one in the combined case. So, 24kb less RSS, 20k less vmsize and 8k less private dirty memory (this is per process using glib). For some reason the combined version also uses 8k less RSS in libgtk. I'm not sure why that is. Maybe just random fluctuations. Anyway, I can't think of any negative aspects about this, appart from the additional dependency on libdl.so for apps linking to glib. Sounds like a good idea to me.
Index: combined/Makefile.am =================================================================== --- combined/Makefile.am (revision 0) +++ combined/Makefile.am (revision 0) @@ -0,0 +1,36 @@ +## Process this file with automake to produce Makefile.in + +lib_LTLIBRARIES = libglib_combined-2.0.la + +export_symbols = $(LIBTOOL_EXPORT_OPTIONS) + +libglib_combined_2_0_la_SOURCES = +libglib_combined_2_0_la_LIBADD = ../glib/libglib-noin-2.0.la ../gobject/libgobject-noin-2.0.la ../gmodule/libgmodule-noin-2.0.la +libglib_combined_2_0_la_DEPENDENCIES = ../glib/libglib-noin-2.0.la ../gobject/libgobject-noin-2.0.la ../gmodule/libgmodule-noin-2.0.la +libglib_combined_2_0_la_LDFLAGS = \ + -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ + -export-dynamic $(export_symbols) + +install-exec-local: + rm -f $(DESTDIR)$(libdir)/libglib-2.0.so + ln -s glib-2.0/dummy/libglib-2.0.so $(DESTDIR)$(libdir)/libglib-2.0.so + rm -f $(DESTDIR)$(libdir)/libglib-2.0.so.0 + rm -f $(DESTDIR)$(libdir)/libglib-2.0.so.0.$(LT_CURRENT).$(LT_REVISION) + ln -s libglib_combined-2.0.so.0.$(LT_CURRENT).$(LT_REVISION) $(DESTDIR)$(libdir)/libglib-2.0.so.0.$(LT_CURRENT).$(LT_REVISION) + ln -s libglib-2.0.so.0.$(LT_CURRENT).$(LT_REVISION) $(DESTDIR)$(libdir)/libglib-2.0.so.0 + + rm -f $(DESTDIR)$(libdir)/libgobject-2.0.so + ln -s glib-2.0/dummy/libgobject-2.0.so $(DESTDIR)$(libdir)/libgobject-2.0.so + rm -f $(DESTDIR)$(libdir)/libgobject-2.0.so.0 + rm -f $(DESTDIR)$(libdir)/libgobject-2.0.so.0.$(LT_CURRENT).$(LT_REVISION) + ln -s libglib_combined-2.0.so.0.$(LT_CURRENT).$(LT_REVISION) $(DESTDIR)$(libdir)/libgobject-2.0.so.0.$(LT_CURRENT).$(LT_REVISION) + ln -s libgobject-2.0.so.0.$(LT_CURRENT).$(LT_REVISION) $(DESTDIR)$(libdir)/libgobject-2.0.so.0 + ls -l /gnome/head/INSTALL/lib/libglib* + + rm -f $(DESTDIR)$(libdir)/libgmodule-2.0.so + ln -s glib-2.0/dummy/libgmodule-2.0.so $(DESTDIR)$(libdir)/libgmodule-2.0.so + rm -f $(DESTDIR)$(libdir)/libgmodule-2.0.so.0 + rm -f $(DESTDIR)$(libdir)/libgmodule-2.0.so.0.$(LT_CURRENT).$(LT_REVISION) + ln -s libglib_combined-2.0.so.0.$(LT_CURRENT).$(LT_REVISION) $(DESTDIR)$(libdir)/libgmodule-2.0.so.0.$(LT_CURRENT).$(LT_REVISION) + ln -s libgmodule-2.0.so.0.$(LT_CURRENT).$(LT_REVISION) $(DESTDIR)$(libdir)/libgmodule-2.0.so.0 + ls -l /gnome/head/INSTALL/lib/libglib* Index: dummylib.sh =================================================================== --- dummylib.sh (revision 0) +++ dummylib.sh (revision 0) @@ -0,0 +1,41 @@ +#!/bin/sh +F=`file -L $1` +C= +S=8 +case "$F" in + *ELF\ 64-bit*shared\ object*x86-64*) C=-m64;; + *ELF\ 32-bit*shared\ object*80?86*) C=-m32; S=4;; + *ELF\ 64-bit*shared\ object*PowerPC*) C=-m64;; + *ELF\ 32-bit*shared\ object*PowerPC*) C=-m32; S=4;; + *ELF\ 64-bit*shared\ object*cisco*) C=-m64;; + *ELF\ 32-bit*shared\ object*cisco*) C=-m32; S=4;; + *ELF\ 64-bit*shared\ object*IA-64*) C=;; + *ELF\ 64-bit*shared\ object*Alpha*) C=;; + *ELF\ 64-bit*shared\ object*390*) C=-m64;; + *ELF\ 32-bit*shared\ object*390*) C=-m31; S=4;; + *ELF\ 64-bit*shared\ object*SPARC*) C=-m64;; + *ELF\ 32-bit*shared\ object*SPARC*) C=-m32; S=4;; + *ELF\ 64-bit*shared\ object*Alpha*) C=;; +esac +readelf -Ws $1 | awk ' +/\.dynsym.* contains/ { start=3 } +/^$/ { start=0 } +/ UND / { next } + { + if (start > 1) + start = start - 1; + else if (start == 1) { + fn=$8 + if ($4 ~ /FUNC/) { print ".text"; size=16; print ".type " fn ",@function" } + else if ($4 ~ /OBJECT/) { print ".data"; size=$3; print ".type " fn ",@object" } + else if ($4 ~ /NOTYPE/) { print ".data"; size=$3 } + else exit(1); + print ".globl " fn + if ($5 ~ /WEAK/) { print ".weak " fn } + else if ($5 !~ /GLOBAL/) exit(1); + print fn ": .skip " size + print ".size " fn "," size +} } +' > lib.s || exit +gcc $C -shared -Wl,-soname,$3 -o $2 lib.s -nostdlib +strip $2 Property changes on: dummylib.sh ___________________________________________________________________ Name: svn:executable + * Index: gmodule/Makefile.am =================================================================== --- gmodule/Makefile.am (revision 5790) +++ gmodule/Makefile.am (working copy) @@ -69,17 +69,20 @@ gmodule_win32_res_ldflag = -Wl,$(gmodule_win32_res) endif -libgmodule_2_0_la_SOURCES = gmodule.c +libgmodule_noin_2_0_la_SOURCES = gmodule.c +libgmodule_noin_2_0_la_LIBADD = $(G_MODULE_LIBS_EXTRA) $(G_MODULE_LIBS) $(libglib) +libgmodule_noin_2_0_la_DEPENDENCIES = $(gmodule_win32_res) $(GMODULE_DEF) + + +libgmodule_2_0_la_SOURCES = libgmodule_2_0_la_LDFLAGS = \ $(gmodule_win32_res_ldflag) \ $(G_MODULE_LDFLAGS) \ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ -export-dynamic $(no_undefined) $(export_symbols) -libgmodule_2_0_la_LIBADD = $(G_MODULE_LIBS_EXTRA) $(G_MODULE_LIBS) $(libglib) +libgmodule_2_0_la_LIBADD = libgmodule-noin-2.0.la -libgmodule_2_0_la_DEPENDENCIES = $(gmodule_win32_res) $(GMODULE_DEF) - if OS_WIN32 gmodule-win32-res.o: gmodule.rc $(WINDRES) gmodule.rc $@ @@ -108,3 +111,26 @@ install-data-local: install-ms-lib install-def-file uninstall-local: uninstall-ms-lib uninstall-def-file + +if ENABLE_COMBINED +noinst_LTLIBRARIES = libgmodule-noin-2.0.la + +libgmodule-dummy-2.0.la: + $(LINK) -rpath `pwd` \ + -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ + -export-dynamic $(no_undefined) $(export_symbols) \ + libgmodule-noin-2.0.la + +libgmodule-dummy-2.0.so: libgmodule-dummy-2.0.la + ../dummylib.sh .libs/libgmodule-dummy-2.0.so.0 libgmodule-dummy-2.0.so libgmodule-2.0.so.$(LT_CURRENT_MINUS_AGE) + +install-dummy-lib: libgmodule-dummy-2.0.so + mkdir -p $(DESTDIR)$(libdir)/glib-2.0/dummy/ + $(INSTALL) $(INSTALL_STRIP_FLAG) libgmodule-dummy-2.0.so $(DESTDIR)$(libdir)/glib-2.0/dummy/libgmodule-2.0.so + +install-exec-local: install-ms-lib install-dummy-lib + + +# Make sure to not actually install libmodule-2.0.so +install-libLTLIBRARIES: +endif Index: gobject/Makefile.am =================================================================== --- gobject/Makefile.am (revision 5790) +++ gobject/Makefile.am (working copy) @@ -77,10 +77,12 @@ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ -export-dynamic $(no_undefined) $(export_symbols) -libgobject_2_0_la_LIBADD = $(libglib) +libgobject_2_0_la_LIBADD = libgobject-noin-2.0.la -libgobject_2_0_la_DEPENDENCIES = $(gobject_win32_res) $(GOBJECT_DEF) +libgobject_noin_2_0_la_LIBADD = $(libglib) +libgobject_noin_2_0_la_DEPENDENCIES = $(gobject_win32_res) $(GOBJECT_DEF) + # # setup source file variables # @@ -197,7 +199,8 @@ # target platform: libgobjectinclude_HEADERS = $(gobject_target_headers) -libgobject_2_0_la_SOURCES = $(gobject_target_sources) +libgobject_2_0_la_SOURCES = +libgobject_noin_2_0_la_SOURCES = $(gobject_target_sources) # # programs to compile and install @@ -259,3 +262,26 @@ if test $(srcdir) = .; then :; else \ rm -f $(BUILT_EXTRA_DIST); \ fi + +if ENABLE_COMBINED +noinst_LTLIBRARIES = libgobject-noin-2.0.la + +libgobject-dummy-2.0.la: + $(LINK) -rpath `pwd` \ + -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ + -export-dynamic $(no_undefined) $(export_symbols) \ + libgobject-noin-2.0.la + +libgobject-dummy-2.0.so: libgobject-dummy-2.0.la + ../dummylib.sh .libs/libgobject-dummy-2.0.so.0 libgobject-dummy-2.0.so libgobject-2.0.so.$(LT_CURRENT_MINUS_AGE) + +install-dummy-lib: libgobject-dummy-2.0.so + mkdir -p $(DESTDIR)$(libdir)/glib-2.0/dummy/ + $(INSTALL) $(INSTALL_STRIP_FLAG) libgobject-dummy-2.0.so $(DESTDIR)$(libdir)/glib-2.0/dummy/libgobject-2.0.so + +install-exec-local: install-ms-lib install-dummy-lib + +# Make sure to not actually install libgobject-2.0.so +install-libLTLIBRARIES: + +endif Index: glib/Makefile.am =================================================================== --- glib/Makefile.am (revision 5790) +++ glib/Makefile.am (working copy) @@ -86,7 +86,7 @@ uninstall-ms-lib: endif -libglib_2_0_la_SOURCES = \ +libglib_noin_2_0_la_SOURCES = \ garray.c \ gasyncqueue.c \ gatomic.c \ @@ -153,7 +153,7 @@ gprintf.c \ gprintfint.h -EXTRA_libglib_2_0_la_SOURCES = \ +EXTRA_libglib_noin_2_0_la_SOURCES = \ giounix.c \ giowin32.c \ gspawn.c \ @@ -271,9 +271,11 @@ pcre_inc = endif -libglib_2_0_la_LIBADD = libcharset/libcharset.la $(printf_la) @GIO@ @GSPAWN@ @PLATFORMDEP@ @ICONV_LIBS@ @G_LIBS_EXTRA@ $(pcre_lib) -libglib_2_0_la_DEPENDENCIES = libcharset/libcharset.la $(printf_la) @GIO@ @GSPAWN@ @PLATFORMDEP@ $(glib_win32_res) @GLIB_DEF@ +libglib_noin_2_0_la_LIBADD = libcharset/libcharset.la $(printf_la) @GIO@ @GSPAWN@ @PLATFORMDEP@ @ICONV_LIBS@ @G_LIBS_EXTRA@ $(pcre_lib) +libglib_noin_2_0_la_DEPENDENCIES = libcharset/libcharset.la $(printf_la) @GIO@ @GSPAWN@ @PLATFORMDEP@ $(glib_win32_res) @GLIB_DEF@ +libglib_2_0_la_SOURCES = +libglib_2_0_la_LIBADD = libglib-noin-2.0.la libglib_2_0_la_LDFLAGS = \ $(glib_win32_res_ldflag) \ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ @@ -300,3 +302,27 @@ for f in $$files; do \ if test -f $$f; then d=.; else d=$(srcdir); fi; \ cp $$d/$$f $(distdir) || exit 1; done + + +if ENABLE_COMBINED +noinst_LTLIBRARIES = libglib-noin-2.0.la + +libglib-dummy-2.0.la: + $(LINK) -rpath `pwd` \ + -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ + -export-dynamic $(no_undefined) $(export_symbols) \ + libglib-noin-2.0.la + +libglib-dummy-2.0.so: libglib-dummy-2.0.la + ../dummylib.sh .libs/libglib-dummy-2.0.so.0 libglib-dummy-2.0.so libglib-2.0.so.$(LT_CURRENT_MINUS_AGE) + +install-dummy-lib: libglib-dummy-2.0.so + mkdir -p $(DESTDIR)$(libdir)/glib-2.0/dummy/ + $(INSTALL) $(INSTALL_STRIP_FLAG) libglib-dummy-2.0.so $(DESTDIR)$(libdir)/glib-2.0/dummy/libglib-2.0.so + +install-exec-local: install-ms-lib install-dummy-lib + +# Make sure to not actually install libglib-2.0.so +install-libLTLIBRARIES: + +endif Index: configure.in =================================================================== --- configure.in (revision 5790) +++ configure.in (working copy) @@ -223,6 +223,10 @@ [AC_HELP_STRING([--disable-visibility], [don't use ELF visibility attributes])],, [enable_visibility=yes]) +AC_ARG_ENABLE(combined, + [AC_HELP_STRING([--enable-combined], + [turn on garbage collector friendliness [default=no]])],, + [enable_combined=no]) if test "x$enable_threads" != "xyes"; then enable_threads=no @@ -245,6 +249,14 @@ AC_MSG_RESULT([yes]) fi +AC_MSG_CHECKING([whether to enable combined glib]) +if test "x$enable_combined" = "xyes"; then + AC_MSG_RESULT([yes]) +else + AC_MSG_RESULT([no]) +fi +AM_CONDITIONAL(ENABLE_COMBINED, [test x$enable_combined = xyes]) + if test "$glib_native_win32" = "yes"; then if test x$enable_static = xyes -o x$enable_static = x; then AC_MSG_WARN([Disabling static library build, must build as DLL on Windows.]) @@ -2971,6 +2983,7 @@ gobject/Makefile gobject/glib-mkenums gthread/Makefile +combined/Makefile po/Makefile.in docs/Makefile docs/reference/Makefile Index: Makefile.am =================================================================== --- Makefile.am (revision 5790) +++ Makefile.am (working copy) @@ -2,8 +2,14 @@ AUTOMAKE_OPTIONS = 1.7 -SUBDIRS = . m4macros glib gobject gmodule gthread tests build po docs +if ENABLE_COMBINED +COMBINE_DIR=combined +else +COMBINE_DIR= +endif +SUBDIRS = . m4macros glib gobject gmodule gthread $(COMBINE_DIR) tests build po docs + bin_SCRIPTS = glib-gettextize INCLUDES = -DG_LOG_DOMAIN=g_log_domain_glib @GLIB_DEBUG_FLAGS@ \
_______________________________________________ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list