]> git.draconx.ca Git - dxcommon.git/blob - m4/glib.m4
Improve GLib probe against old GLib versions.
[dxcommon.git] / m4 / glib.m4
1 dnl Copyright © 2009, 2019-2020 Nick Bowler
2 dnl
3 dnl License WTFPL2: Do What The Fuck You Want To Public License, version 2.
4 dnl This is free software: you are free to do what the fuck you want to.
5 dnl There is NO WARRANTY, to the extent permitted by law.
6
7 dnl DX_LIB_GLIB2([min-version], [modules], [action-if-ok], [action-if-fail])
8 dnl
9 dnl Search for GLib-2 libraries, with the given minimum version.  The modules
10 dnl argument specifies which additional GLib libraries are required, which is
11 dnl a space-separated list of zero or more of the following values:
12 dnl
13 dnl   gthread
14 dnl   gobject
15 dnl   gio
16 dnl   gio-unix
17 dnl   gmodule
18 dnl
19 dnl Each detected module's flags are set in LIBxxx_CFLAGS and LIBxxx_LIBS,
20 dnl where xxx is the module's name in all capital letters and with hyphens
21 dnl converted to underscores (cf. AS_TR_SH).  The core GLib flags are set
22 dnl in LIBGLIB_CFLAGS and LIBGLIB_LIBS.  The combination of all selected
23 dnl and detected modules is set in GLIB_CFLAGS and GLIB_LIBS.  All of
24 dnl these variables are substituted as normal.
25 dnl
26 dnl If GLib and all selected modules are successfully found, action-if-ok
27 dnl is run.  Otherwise, action-if-fail is run.  If necessary, use the
28 dnl dx_cv_libxxx_lib_found cache variables to determine exactly which
29 dnl modules are not available.
30 AC_DEFUN([DX_LIB_GLIB2],
31 [GLIB_CFLAGS= GLIB_LIBS= _dx_lib_glib_search_ok=true
32 m4_define([_DX_LIB_GLIB2_TESTHEAD], [#include <glib.h>])dnl
33 _DX_LIB_GLIB2_VERSION_TEST(m4_split([$1], [\.]))dnl
34 m4_define([_DX_LIB_GLIB2_TESTMAIN],
35   [const char *v = g_get_prgname();])dnl
36 m4_define([_DX_GLIB_MODULES], [glib])dnl
37 m4_append_uniq_w([_DX_GLIB_MODULES], [$2])dnl
38
39 m4_map_args_w(m4_defn([_DX_GLIB_MODULES]), [_DX_LIB_GLIB2_MODULE(], [)])
40 AC_SUBST([GLIB_CFLAGS])dnl
41 AC_SUBST([GLIB_LIBS])dnl
42 AS_IF([$_dx_lib_glib_search_ok], [DX_LIB_GLIB_BUSTED_GNU_INLINE
43 $3], [m4_default([$4], [AC_MSG_FAILURE(
44 [GLib[]m4_ifnblank([$1], [ version $1 or newer]) is required.  The latest
45 version may be found at <https://www.gtk.org/>.
46 m4_newline([DX_LIB_USERFLAG_BLURB([libglib], [GLib])])
47 m4_newline([DX_LIB_PKGCONFIG_BLURB([glib], [GLib])])
48 ])])])])
49
50 AC_DEFUN([_DX_LIB_GLIB2_MODULE],
51 [DX_LIB_SETUP([lib$1],
52 [m4_if([$1], [glib],     [GLib],
53        [$1], [gio],      [GIO],
54        [$1], [gio-unix], [GIO-Unix],
55        [$1], [gthread],  [GThread],
56        [$1], [gobject],  [GObject],
57        [$1], [gmodule],  [GModule])])dnl
58 DX_LIB_PKGCONFIG_FLAGS([lib$1],
59   [m4_if([$1], [gmodule], [gmodule-no-export-2.0], [$1-2.0])])
60 AC_MSG_CHECKING([for lib$1])
61 DX_LIB_SEARCH_LINK([lib$1],
62   [AC_LANG_PROGRAM([_DX_LIB_GLIB2_TESTHEAD
63 m4_n(m4_if([$1], [gobject], [[#include <glib-object.h>]]))dnl
64 m4_n(m4_if([$1], [gio], [[#include <gio/gio.h>]]))dnl
65 m4_n(m4_if([$1], [gio-unix], [[#include <gio/gunixmounts.h>]]))dnl
66 m4_n(m4_if([$1], [gmodule], [[#include <gmodule.h>]]))],
67     [_DX_LIB_GLIB2_TESTMAIN
68 m4_if([$1], [glib], [],
69       [$1], [gobject], [g_type_init();
70 { GObject *obj = g_object_new(G_TYPE_OBJECT, NULL); }],
71       [$1], [gthread], [g_thread_init(NULL);
72 { GThread *thr = g_thread_self(); }],
73       [$1], [gio], [{ GFile *f = g_file_new_for_path("/"); }],
74       [$1], [gio-unix], [{ GUnixMountEntry *m = g_unix_mount_at("/", NULL); }],
75       [$1], [gmodule], [{ GModule *m = g_module_open(NULL, 0); }],
76       [DX_LIB_COMPILE_ERROR([unsupported module])])])],
77   [ [[$LIBGLIB_CFLAGS m4_if([$1], [glib], [], [m4_toupper([$lib$1_cflags])])],
78      [$LIBGLIB_LIBS m4_if([$1], [glib], [], [m4_toupper([$lib$1_libs])])]],
79     [[$AS_TR_SH([dx_cv_lib$1_pkg_cflags])],
80      [$AS_TR_SH([dx_cv_lib$1_pkg_libs])],
81      [test x"$AS_TR_SH([dx_cv_lib$1_pkg_found])" = x"yes"]],
82     m4_if([$1], [gthread], [[[$LIBGLIB_CFLAGS -pthread],
83           [-pthread -lgthread-2.0 -lglib-2.0]],])
84     [[$LIBGLIB_CFLAGS], [m4_if([$1], [glib], [], [-l$1-2.0]) -lglib-2.0]],
85   ])
86 AS_IF([test x"$AS_TR_SH([dx_cv_lib$1_lib_found])" = x"yes"],
87 [set -f
88 set x $AS_TR_SH([m4_toupper([lib$1_cflags])]); shift
89 for _dx_i
90 do
91   for _dx_j in $GLIB_CFLAGS; do
92     if test x"$_dx_i" = x"$_dx_j"; then
93       shift; continue 2
94     fi
95   done
96   set x ${1+"$[]@"} "$[]1"; shift; shift
97 done
98 GLIB_CFLAGS=${GLIB_CFLAGS:+"$GLIB_CFLAGS "}$[]*
99 set x $AS_TR_SH([m4_toupper([lib$1_libs])]); shift
100 for _dx_i
101 do
102   for _dx_j in $GLIB_LIBS; do
103     if test x"$_dx_i" = x"$_dx_j"; then
104       shift; continue 2
105     fi
106   done
107   set x ${1+"$[]@"} "$[]1"; shift; shift
108 done
109 GLIB_LIBS=$[]*${GLIB_LIBS:+" $GLIB_LIBS"}
110 set +f],
111   [_dx_lib_glib_search_ok=false])
112 ])
113
114 AC_DEFUN([_DX_LIB_GLIB2_VERSION_TEST], [m4_append([_DX_LIB_GLIB2_TESTHEAD], [
115 [#if !GLIB_CHECK_VERSION(]m4_default([$1],
116 [0]), m4_default([$2],
117 [0]), m4_default([$3],
118 [0]))
119 DX_LIB_COMPILE_ERROR([glib version insufficient])
120 #endif])])
121
122 dnl Old glib headers expect gcc to provide GNU inline semantics by default.
123 dnl This is not the case with modern gcc if the language standard is set to
124 dnl C99 or later.  This results is linker failures due to multiple definitions
125 dnl when two source files include the GLib headers.
126 dnl
127 dnl Pre-#defining G_INLINE_FUNC to 'static inline' works to avoid this problem,
128 dnl so we have configure first test to see if the problem occurs, then test
129 dnl if this definition fixes it, then AC_DEFINE that if necessary.
130 AC_DEFUN([DX_LIB_GLIB_BUSTED_GNU_INLINE],
131 [AC_CACHE_CHECK([whether GLib needs obsolete GNU inline semantics],
132 [dx_cv_glib_busted_gnu_inline],
133 [save_CFLAGS=$CFLAGS save_LIBS=$LIBS CFLAGS="$LIBGLIB_CFLAGS $CFLAGS"
134 LIBS="conftest_bar.$OBJEXT $LIBGLIB_LIBS $save_LIBS"
135 dx_cv_glib_busted_gnu_inline=unknown
136 for dx_attempt in no yes; do
137 AS_CASE([$dx_attempt],
138 [yes], [DEFTEST='#define G_INLINE_FUNC static inline'
139 ], [DEFTEST=
140 ])
141 AC_COMPILE_IFELSE([AC_LANG_SOURCE([$DEFTEST
142 #include <glib.h>
143 int bar(void) { return 0; }])],
144 [mv -f conftest.$OBJEXT conftest_bar.$OBJEXT],
145 [continue])
146 AC_LINK_IFELSE([AC_LANG_PROGRAM([$DEFTEST
147 #include <glib.h>
148 extern int bar(void);], [return bar();])],
149 [dx_cv_glib_busted_gnu_inline=$dx_attempt; break])
150 rm -f conftest_bar.$OBJEXT
151 done
152 CFLAGS=$save_CFLAGS LIBS=$save_LIBS])
153 AS_CASE([$dx_cv_glib_busted_gnu_inline], [yes],
154 [AC_DEFINE([G_INLINE_FUNC], [static inline],
155   [Define to static inline to work around multiple definitions in old GLib.])
156 ])])