]> git.draconx.ca Git - dxcommon.git/commitdiff
Improve GLib probe against old GLib versions.
authorNick Bowler <nbowler@synopsys.com>
Fri, 7 Feb 2020 02:15:04 +0000 (21:15 -0500)
committerNick Bowler <nbowler@draconx.ca>
Fri, 7 Feb 2020 02:15:04 +0000 (21:15 -0500)
The glib_check_version function was not available in older versions
of glib2, so this is a bad choice for the link test.  Let's use
g_get_prgname instead, which is available at least as far back
as glib 2.0.0.

More importantly, with gcc these old glib versions use 'extern inline'
in header files and expect GNU inline semantics.  This generally does
not work with modern gcc, so add an additional configure test which
will detect this problem and work around it.

.gitignore
atlocal.in [new file with mode: 0644]
configure.ac
m4/glib.m4
t/libdummy.c
tests/libs.at
testsuite.at

index ae53a6932b6f18311bcd844cf3a20c4c7445ee05..88555f82920b37a78af4f30eb53c58365d70acfe 100644 (file)
@@ -1,21 +1,22 @@
-/config.*
-/configure
+*.a
+*.lo
+*.o
+.deps
+.dirstamp
 /aclocal.m4
+/atconfig
+/atlocal
 /autom4te.cache
+/compile
+/config.*
+/configure
+/depcomp
 /install-sh
 /missing
-/depcomp
-/compile
+/package.m4
+/testsuite
+/testsuite.deps
 /testsuite.dir
 /testsuite.log
-/testsuite.deps
-/testsuite
-/package.m4
-/atconfig
-Makefile.in
 Makefile
-.dirstamp
-.deps
-*.lo
-*.o
-*.a
+Makefile.in
diff --git a/atlocal.in b/atlocal.in
new file mode 100644 (file)
index 0000000..d15e74d
--- /dev/null
@@ -0,0 +1 @@
+: "${CC=@CC@}"
index a74cd71500503f45bedc26dd3b866d5151411935..35014288f4c49c7446e66a58fea7a8fcc3cf8af4 100644 (file)
@@ -20,7 +20,5 @@ AC_CONFIG_TESTDIR([.])
 DX_PROG_AUTOTEST
 AM_CONDITIONAL([HAVE_AUTOTEST], [test x"$dx_cv_autotest_works" = x"yes"])
 
-AC_CONFIG_FILES([
-  Makefile
-])
+AC_CONFIG_FILES([Makefile atlocal])
 AC_OUTPUT
index 32d27848da5d2656480a197960557bf916f4c8ba..21676a41cd145ccd2a3650878e66d7314be93698 100644 (file)
@@ -1,4 +1,4 @@
-dnl Copyright © 2009, 2019 Nick Bowler
+dnl Copyright © 2009, 2019-2020 Nick Bowler
 dnl
 dnl License WTFPL2: Do What The Fuck You Want To Public License, version 2.
 dnl This is free software: you are free to do what the fuck you want to.
@@ -32,14 +32,15 @@ AC_DEFUN([DX_LIB_GLIB2],
 m4_define([_DX_LIB_GLIB2_TESTHEAD], [#include <glib.h>])dnl
 _DX_LIB_GLIB2_VERSION_TEST(m4_split([$1], [\.]))dnl
 m4_define([_DX_LIB_GLIB2_TESTMAIN],
-  [const char *v = glib_check_version(2,0,0);])dnl
+  [const char *v = g_get_prgname();])dnl
 m4_define([_DX_GLIB_MODULES], [glib])dnl
 m4_append_uniq_w([_DX_GLIB_MODULES], [$2])dnl
 
 m4_map_args_w(m4_defn([_DX_GLIB_MODULES]), [_DX_LIB_GLIB2_MODULE(], [)])
 AC_SUBST([GLIB_CFLAGS])dnl
 AC_SUBST([GLIB_LIBS])dnl
-AS_IF([$_dx_lib_glib_search_ok], [$3], [m4_default([$4], [AC_MSG_FAILURE(
+AS_IF([$_dx_lib_glib_search_ok], [DX_LIB_GLIB_BUSTED_GNU_INLINE
+$3], [m4_default([$4], [AC_MSG_FAILURE(
 [GLib[]m4_ifnblank([$1], [ version $1 or newer]) is required.  The latest
 version may be found at <https://www.gtk.org/>.
 m4_newline([DX_LIB_USERFLAG_BLURB([libglib], [GLib])])
@@ -117,3 +118,39 @@ AC_DEFUN([_DX_LIB_GLIB2_VERSION_TEST], [m4_append([_DX_LIB_GLIB2_TESTHEAD], [
 [0]))
 DX_LIB_COMPILE_ERROR([glib version insufficient])
 #endif])])
+
+dnl Old glib headers expect gcc to provide GNU inline semantics by default.
+dnl This is not the case with modern gcc if the language standard is set to
+dnl C99 or later.  This results is linker failures due to multiple definitions
+dnl when two source files include the GLib headers.
+dnl
+dnl Pre-#defining G_INLINE_FUNC to 'static inline' works to avoid this problem,
+dnl so we have configure first test to see if the problem occurs, then test
+dnl if this definition fixes it, then AC_DEFINE that if necessary.
+AC_DEFUN([DX_LIB_GLIB_BUSTED_GNU_INLINE],
+[AC_CACHE_CHECK([whether GLib needs obsolete GNU inline semantics],
+[dx_cv_glib_busted_gnu_inline],
+[save_CFLAGS=$CFLAGS save_LIBS=$LIBS CFLAGS="$LIBGLIB_CFLAGS $CFLAGS"
+LIBS="conftest_bar.$OBJEXT $LIBGLIB_LIBS $save_LIBS"
+dx_cv_glib_busted_gnu_inline=unknown
+for dx_attempt in no yes; do
+AS_CASE([$dx_attempt],
+[yes], [DEFTEST='#define G_INLINE_FUNC static inline'
+], [DEFTEST=
+])
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([$DEFTEST
+#include <glib.h>
+int bar(void) { return 0; }])],
+[mv -f conftest.$OBJEXT conftest_bar.$OBJEXT],
+[continue])
+AC_LINK_IFELSE([AC_LANG_PROGRAM([$DEFTEST
+#include <glib.h>
+extern int bar(void);], [return bar();])],
+[dx_cv_glib_busted_gnu_inline=$dx_attempt; break])
+rm -f conftest_bar.$OBJEXT
+done
+CFLAGS=$save_CFLAGS LIBS=$save_LIBS])
+AS_CASE([$dx_cv_glib_busted_gnu_inline], [yes],
+[AC_DEFINE([G_INLINE_FUNC], [static inline],
+  [Define to static inline to work around multiple definitions in old GLib.])
+])])
index 5404a084eca7c05d46ab86a40e3a214819ec9cba..4b92f6f1975faf82f55838d089929f082325571d 100644 (file)
@@ -1,3 +1,5 @@
 /* Stub function definitions to satisfy link tests, as required. */
 void discid_new(void) {}
 void discid_free(void) {}
+
+void g_get_prgname(void) {}
index ab348ded7bbb3d95650c8ebc6852c10d68b3c6ee..cc09cead3a26e280d9d9ee97e09ac5cdbe08127d 100644 (file)
@@ -85,3 +85,60 @@ AT_CHECK_UNQUOTED([cat test], [0], [no
 ])
 
 AT_CLEANUP
+
+AT_SETUP([GLib GNU inline workaround])
+
+TEST_DUMMY_PKGCONFIG([-I.], [$builddir/t/libdummy.a])
+
+# This test will only work if we have a version of GCC that implements
+# C99 inline semantics by default.
+AT_DATA([a.c],
+[[#if __GNUC__
+extern inline void my_dup_fn(void) { }
+#endif
+int main(void) { return 0; }
+]])
+AT_DATA([b.c],
+[[#if __GNUC__
+extern inline void my_dup_fn(void) { }
+#endif
+]])
+
+AT_DATA([test.sh.in],
+[[#!/bin/sh
+@CC@ @CPPFLAGS@ @CFLAGS@ -c a.c || exit 77
+@CC@ @CPPFLAGS@ @CFLAGS@ -c b.c || exit 77
+@CC@ @CFLAGS@ @LDFLAGS@ a.o b.o || exit 0
+exit 77
+]])
+
+AT_DATA([glib.h],
+[[#define GLIB_CHECK_VERSION(x, y, z) 1
+const char *g_get_prgname(void);
+]])
+
+TEST_CONFIGURE_AC([[AC_CONFIG_HEADERS([config.h])
+DX_LIB_GLIB2
+AC_CONFIG_FILES([test.sh], [chmod +x test.sh])
+]])
+TEST_AUTORECONF
+TEST_CONFIGURE([PKG_CONFIG=$PWD/pkg-config])
+AT_CHECK([./test.sh], [0], [ignore], [ignore])
+
+AT_CHECK([grep G_INLINE_FUNC config.h], [0],
+[/* #undef G_INLINE_FUNC */
+])
+
+cat >>glib.h <<'EOF'
+#ifndef G_INLINE_FUNC
+#  define G_INLINE_FUNC extern inline
+#endif
+G_INLINE_FUNC void break_things(void) { }
+EOF
+
+TEST_CONFIGURE([PKG_CONFIG=$PWD/pkg-config])
+AT_CHECK([grep G_INLINE_FUNC config.h], [0],
+[#define G_INLINE_FUNC static inline
+])
+
+AT_CLEANUP
index 3c5fdacefd5e4952838e769e10cb3dce305b4399..eff4408aab14ef39f3ee06ab8b9c7fb31bbb53d3 100644 (file)
@@ -24,7 +24,7 @@ m4_define([TEST_AUTORECONF], [AT_KEYWORDS([autoconf])dnl
 AT_CHECK([autoreconf -I "$srcdir/m4"], [0], [], [stderr])])
 
 m4_define([TEST_CONFIGURE], [AT_KEYWORDS([configure])dnl
-AT_CHECK([./configure $1], [0], [ignore])])
+AT_CHECK([export CC; ./configure $1], [0], [ignore])])
 
 m4_include([tests/macros.at])
 m4_include([tests/functions.at])