]> git.draconx.ca Git - dxcommon.git/commitdiff
Rewrite Gnulib symbols to be in libcdecl's namespace.
authorNick Bowler <nbowler@draconx.ca>
Wed, 21 Sep 2011 04:51:17 +0000 (00:51 -0400)
committerNick Bowler <nbowler@draconx.ca>
Thu, 22 Sep 2011 01:02:07 +0000 (21:02 -0400)
The gnulib symbols are not properly prefixed for libcdecl internal
symbols (e.g. cdecl__blah).  This *will* cause problems when statically
linking against both libcdecl and another library that uses the same
gnulib modules.

Unfortunately, there's no simple way to determine what symbols need
prefixing without compiling all the gnulib objects.  The results can't
be distributed either, because they depend on the configuration.  So,
limited to simple tools and portable make rules, we hack together a
"new" config.h at build time that defines object-like macros to rewrite
the symbols, carefully ensuring that header dependencies are correct.

scripts/fix-gnulib.pl
snippet/glconfig.mk [new file with mode: 0644]

index 17163c7e24cc15d436bd5dd593c7629212bc5963..b8185fa642107538128023f844d76eb03191f286 100755 (executable)
@@ -174,9 +174,21 @@ if (defined $m4output) {
 
        open(M4OUT, '>', $m4output) or die "$m4output: $!\n";
 
-       print M4OUT "dnl This file was generated by fix-gnulib.pl\n";
-       print M4OUT "AC_DEFUN([$m4macro], [dnl\n";
+       print M4OUT <<EOF;
+dnl This file was generated by fix-gnulib.pl
+dnl
+dnl Usage: DX_FIX_GNULIB([symbol-prefix])
+dnl   where symbol-prefix is the application-specific symbol prefix to apply
+dnl   to Gnulib's symbols.  Defaults to \${PACKAGE}__.
+dnl   top-level source directory; e.g. lib.
+AC_DEFUN([$m4macro], [dnl
+EOF
        print M4OUT <<'EOF';
+GLSRC=lib
+GLSYM_PREFIX='ifelse([$1], [], [${PACKAGE}__], [$1])'
+AC_SUBST([GLSRC])
+AC_SUBST([GLSYM_PREFIX])
+
 m4_foreach([gl_objvar], [[gl_LIBOBJS], [gl_LTLIBOBJS]], [dnl
 set x $gl_objvar; shift
 gl_objvar=
@@ -185,7 +197,6 @@ while test ${#} -gt 0; do
 done
 ])
 EOF
-
        foreach (@vars) {
                print M4OUT "$_=\${$_:+lib/\$$_}\n";
        }
diff --git a/snippet/glconfig.mk b/snippet/glconfig.mk
new file mode 100644 (file)
index 0000000..0673817
--- /dev/null
@@ -0,0 +1,82 @@
+# Copyright © 2011 Nick Bowler
+#
+# Automake fragment to generate a Gnulib config header to rewrite exported
+# symbols.  This fragment relies on the Gnulib makefile enhancements done by
+# fix-gnulib.pl.  Furthermore, the following additional changes may be
+# required:
+#
+#   * Add AUTOMAKE_OPTIONS = nostdinc to Makefile.am (or equivalent).
+#   * Ensure that -I$(top_builddir)/@GLSRC@ and -I$(top_builddir) are
+#     listed in AM_CPPFLAGS (in that order).
+#   * Pass the desired symbol prefix to DX_FIX_GNULIB in configure.ac.
+#
+# License WTFPL2: Do What The Fuck You Want To Public License, version 2.
+# This is free software: you are free to do what the fuck you want to.
+# There is NO WARRANTY, to the extent permitted by law.
+
+GLCONFIG = @GLSRC@/config.h
+GLCAT    = cat /dev/null
+
+GLSYM_V   = $(GLSYM_V_$(V))
+GLSYM_V_  = $(GLSYM_V_$(AM_DEFAULT_VERBOSITY))
+GLSYM_V_0 = @echo "  GLSYM " $<;
+
+gnulib_symfiles = $(gnulib_lt_objects:.lo=.glsym)
+gnulib_src_headers += $(GLCONFIG)
+
+# This suffix rule triggers symbol generation only on demand.  Dependencies are
+# not tracked directly, so it must remain phony and thus not create the target.
+.c.glsym:
+       $(GLSYM_V) $(MKDIR_P) $(@D)/.syms
+       $(AM_V_at) depfile=$(@D)/.syms/$(*F).deps \
+               source=$< object=$(GLCONFIG) $(CCDEPMODE) \
+               $(depcomp) $(COMPILE) -c -o $(@D)/.syms/$(*F).o $<
+       $(AM_V_at) $(SHELL) $(top_builddir)/exported.sh \
+               $(@D)/.syms/$(*F).o > $(@D)/.syms/$(*F).sym
+$(gnulib_symfiles): $(gnulib_core_headers)
+
+clean-local: clean-glconfig
+clean-glconfig:
+       @for sym in $(libgnu_la_SOURCES) $(EXTRA_libgnu_la_SOURCES); do \
+               symdir=`expr "$$sym" : '\(.*/\)'`.syms; \
+               if test -d "$$symdir"; then \
+                       echo "rm -rf $$symdir"; rm -rf "$$symdir"; \
+               fi; \
+       done
+.PHONY: clean-glconfig
+
+# The config header requires compilation of all gnulib object files via the
+# .glsym rule above.  However, it cannot depend on those build products
+# directly because those compilations will include this header if it exists,
+# which is (by definition) out of date when this rule gets triggered.
+#
+# Thus, we delete the header, then perform a recursive make call to regenerate
+# the header, which can in turn parallelize the required compilation.
+#
+# Also delete the phony symbol files so the build doesn't fail badly if they
+# got created somehow (for instance by make -t).
+$(GLCONFIG): $(top_builddir)/config.h $(gnulib_core_headers)
+       -$(AM_V_at) rm -f $(gnulib_symfiles) $@.tmp $@
+       $(AM_V_at) $(MAKE) $(AM_MAKEFLAGS) glconfig-gen
+       $(AM_V_GEN) cat $(top_builddir)/config.h >> $@.tmp
+       $(AM_V_at) mv -f $@.tmp $@
+CLEANFILES += $(GLCONFIG)
+
+# The glconfig-gen target is intended only for use in recursive make
+# invocations.
+glconfig-gen: $(gnulib_symfiles)
+       $(AM_V_at) depfiles=; symfiles=; \
+       for sym in $(gnulib_symfiles); do \
+               symdir=`expr "$$sym" : '\(.*/\)'`; \
+               symfile=`expr "$$sym" : '.*/\(.*\)' || printf '%s\n' "$$sym"`; \
+               symbase=$$symdir.syms/`expr "$$symfile" : '\(.*\)\..*'`; \
+               test -f "$$symbase.deps" && \
+                       depfiles="$$depfiles $$symbase.deps"; \
+               symfiles="$$symfiles $$symbase.sym"; \
+       done; \
+               $(GLCAT) $$depfiles > @GLSRC@/$(DEPDIR)/glconfig.Ph && \
+               $(GLCAT) $$symfiles | sed 's/.*/#define & $(GLSYM_PREFIX)&/' \
+                       > $(GLCONFIG).tmp
+.PHONY: glconfig-gen
+
+@AMDEP_TRUE@@am__include@ @am__quote@@GLSRC@/$(DEPDIR)/glconfig.Ph@am__quote@