Imported Upstream version 2.62.3
[platform/upstream/glib.git] / meson.build
1 project('glib', 'c', 'cpp',
2   version : '2.62.3',
3   # NOTE: We keep this pinned at 0.49 because that's what Debian 10 ships
4   meson_version : '>= 0.49.2',
5   default_options : [
6     'buildtype=debugoptimized',
7     'warning_level=1',
8     'c_std=gnu89'
9   ]
10 )
11
12 cc = meson.get_compiler('c')
13 cxx = meson.get_compiler('cpp')
14
15 cc_can_run = not meson.is_cross_build() or meson.has_exe_wrapper()
16
17 if cc.get_id() == 'msvc'
18   # Ignore several spurious warnings for things glib does very commonly
19   # If a warning is completely useless and spammy, use '/wdXXXX' to suppress it
20   # If a warning is harmless but hard to fix, use '/woXXXX' so it's shown once
21   # NOTE: Only add warnings here if you are sure they're spurious
22   add_project_arguments('/wd4035', '/wd4715', '/wd4116',
23     '/wd4046', '/wd4068', '/wo4090', '/FImsvc_recommended_pragmas.h',language : 'c')
24   # Disable SAFESEH with MSVC for plugins and libs that use external deps that
25   # are built with MinGW
26   noseh_link_args = ['/SAFESEH:NO']
27   # Set the input and exec encoding to utf-8, like is the default with GCC
28   add_project_arguments(cc.get_supported_arguments(['/utf-8']), language: 'c')
29 else
30   noseh_link_args = []
31   # -mms-bitfields vs -fnative-struct ?
32 endif
33
34 host_system = host_machine.system()
35
36 glib_version = meson.project_version()
37 glib_api_version = '2.0'
38 version_arr = glib_version.split('.')
39 major_version = version_arr[0].to_int()
40 minor_version = version_arr[1].to_int()
41 micro_version = version_arr[2].to_int()
42
43 interface_age = minor_version.is_odd() ? 0 : micro_version
44 binary_age = 100 * minor_version + micro_version
45
46 soversion = 0
47 # Maintain compatibility with previous libtool versioning
48 # current = minor * 100 + micro
49 current = binary_age - interface_age
50 library_version = '@0@.@1@.@2@'.format(soversion, current, interface_age)
51 darwin_versions = [current + 1, '@0@.@1@'.format(current + 1, interface_age)]
52
53 configinc = include_directories('.')
54 glibinc = include_directories('glib')
55 gobjectinc = include_directories('gobject')
56 gmoduleinc = include_directories('gmodule')
57 gioinc = include_directories('gio')
58
59 glib_prefix = get_option('prefix')
60 glib_bindir = join_paths(glib_prefix, get_option('bindir'))
61 glib_libdir = join_paths(glib_prefix, get_option('libdir'))
62 glib_libexecdir = join_paths(glib_prefix, get_option('libexecdir'))
63 glib_datadir = join_paths(glib_prefix, get_option('datadir'))
64 glib_pkgdatadir = join_paths(glib_datadir, 'glib-2.0')
65 glib_includedir = join_paths(glib_prefix, get_option('includedir'))
66 glib_giomodulesdir = get_option('gio_module_dir')
67 if glib_giomodulesdir == ''
68   glib_giomodulesdir = join_paths(glib_libdir, 'gio', 'modules')
69 endif
70
71 glib_pkgconfigreldir = join_paths(glib_libdir, 'pkgconfig')
72
73 installed_tests_metadir = join_paths(glib_datadir, 'installed-tests', meson.project_name())
74 installed_tests_execdir = join_paths(glib_libexecdir, 'installed-tests', meson.project_name())
75 installed_tests_enabled = get_option('installed_tests')
76 installed_tests_template = files('template.test.in')
77 installed_tests_template_tap = files('template-tap.test.in')
78
79 # Don’t build the tests unless we can run them (either natively, in an exe wrapper, or by installing them for later use)
80 build_tests = not meson.is_cross_build() or (meson.is_cross_build() and meson.has_exe_wrapper()) or installed_tests_enabled
81
82 add_project_arguments('-D_GNU_SOURCE', language: 'c')
83
84 # Disable strict aliasing;
85 # see https://bugzilla.gnome.org/show_bug.cgi?id=791622
86 if cc.has_argument('-fno-strict-aliasing')
87   add_project_arguments('-fno-strict-aliasing', language: 'c')
88 endif
89
90 ########################
91 # Configuration begins #
92 ########################
93 glib_conf = configuration_data()
94 glibconfig_conf = configuration_data()
95
96 # accumulated list of defines as we check for them, so we can easily
97 # use them later in test programs (autoconf does this automatically)
98 glib_conf_prefix = ''
99
100 glib_conf.set('GLIB_MAJOR_VERSION', major_version)
101 glib_conf.set('GLIB_MINOR_VERSION', minor_version)
102 glib_conf.set('GLIB_MICRO_VERSION', micro_version)
103 glib_conf.set('GLIB_INTERFACE_AGE', interface_age)
104 glib_conf.set('GLIB_BINARY_AGE', binary_age)
105 glib_conf.set_quoted('GETTEXT_PACKAGE', 'glib20')
106 glib_conf.set_quoted('PACKAGE_BUGREPORT', 'https://gitlab.gnome.org/GNOME/glib/issues/new')
107 glib_conf.set_quoted('PACKAGE_NAME', 'glib')
108 glib_conf.set_quoted('PACKAGE_STRING', 'glib @0@'.format(meson.project_version()))
109 glib_conf.set_quoted('PACKAGE_TARNAME', 'glib')
110 glib_conf.set_quoted('PACKAGE_URL', '')
111 glib_conf.set_quoted('PACKAGE_VERSION', meson.project_version())
112 glib_conf.set('ENABLE_NLS', 1)
113
114 # used by the .rc.in files
115 glibconfig_conf.set('LT_CURRENT_MINUS_AGE', soversion)
116
117 glib_conf.set('_GNU_SOURCE', 1)
118
119 if host_system == 'windows'
120   # Poll doesn't work on devices on Windows
121   glib_conf.set('BROKEN_POLL', true)
122 endif
123
124 if host_system == 'windows' and cc.get_id() != 'msvc' and cc.get_id() != 'clang-cl'
125   # FIXME: Ideally we shouldn't depend on this on Windows and should use
126   # 64 bit capable Windows API that also works with MSVC.
127   # The autotools build did set this for mingw and while meson sets it
128   # for gcc/clang by default, it doesn't do so on Windows.
129   glib_conf.set('_FILE_OFFSET_BITS', 64)
130 endif
131
132 # Check for GNU visibility attributes
133 g_have_gnuc_visibility = cc.compiles('''
134   void
135   __attribute__ ((visibility ("hidden")))
136        f_hidden (void)
137   {
138   }
139   void
140   __attribute__ ((visibility ("internal")))
141        f_internal (void)
142   {
143   }
144   void
145   __attribute__ ((visibility ("protected")))
146        f_protected (void)
147   {
148   }
149   void
150   __attribute__ ((visibility ("default")))
151        f_default (void)
152   {
153   }
154   int main (void)
155   {
156     f_hidden();
157     f_internal();
158     f_protected();
159     f_default();
160     return 0;
161   }
162   ''',
163   # Not supported by MSVC, but MSVC also won't support visibility,
164   # so it's OK to pass -Werror explicitly. Replace with
165   # override_options : 'werror=true' once that is supported
166   args: ['-Werror'],
167   name : 'GNU C visibility attributes test')
168
169 if g_have_gnuc_visibility
170   glibconfig_conf.set('G_HAVE_GNUC_VISIBILITY', '1')
171 endif
172
173 # Detect and set symbol visibility
174 glib_hidden_visibility_args = []
175 if get_option('default_library') != 'static'
176   if host_system == 'windows' or host_system == 'cygwin'
177     glib_conf.set('DLL_EXPORT', true)
178     if cc.get_id() == 'msvc' or cc.get_id() == 'clang-cl'
179       glib_conf.set('_GLIB_EXTERN', '__declspec(dllexport) extern')
180     elif cc.has_argument('-fvisibility=hidden')
181       glib_conf.set('_GLIB_EXTERN', '__attribute__((visibility("default"))) __declspec(dllexport) extern')
182       glib_hidden_visibility_args = ['-fvisibility=hidden']
183     endif
184   elif cc.has_argument('-fvisibility=hidden')
185     glib_conf.set('_GLIB_EXTERN', '__attribute__((visibility("default"))) extern')
186     glib_hidden_visibility_args = ['-fvisibility=hidden']
187   endif
188 endif
189
190 if get_option('default_library') == 'static'
191     glibconfig_conf.set('GLIB_STATIC_COMPILATION', '1')
192     glibconfig_conf.set('GOBJECT_STATIC_COMPILATION', '1')
193 endif
194
195 # Cygwin glib port maintainers made it clear
196 # (via the patches they apply) that they want no
197 # part of glib W32 code, therefore we do not define
198 # G_PLATFORM_WIN32 for host_system == 'cygwin'.
199 # This makes G_PLATFORM_WIN32 a synonym for
200 # G_OS_WIN32.
201 if host_system == 'windows'
202   glib_os = '''#define G_OS_WIN32
203 #define G_PLATFORM_WIN32'''
204 elif host_system == 'cygwin'
205   glib_os = '''#define G_OS_UNIX
206 #define G_WITH_CYGWIN'''
207 else
208   glib_os = '#define G_OS_UNIX'
209 endif
210 glibconfig_conf.set('glib_os', glib_os)
211
212 # We need to know the build type to determine what .lib files we need on Visual Studio
213 # for dependencies that don't normally come with pkg-config files for Visual Studio builds
214 buildtype = get_option('buildtype')
215
216 glib_debug_cflags = []
217 if buildtype.startswith('debug')
218   glib_debug_cflags += ['-DG_ENABLE_DEBUG']
219 elif buildtype == 'release'
220   glib_debug_cflags += ['-DG_DISABLE_CAST_CHECKS']
221 endif
222
223 add_project_arguments(glib_debug_cflags, language: 'c')
224
225 # check for header files
226
227 headers = [
228   'alloca.h',
229   'crt_externs.h',
230   'dirent.h', # MSC does not come with this by default
231   'float.h',
232   'fstab.h',
233   'grp.h',
234   'inttypes.h',
235   'limits.h',
236   'linux/magic.h',
237   'locale.h',
238   'mach/mach_time.h',
239   'memory.h',
240   'mntent.h',
241   'poll.h',
242   'pwd.h',
243   'sched.h',
244   'spawn.h',
245   'stdint.h',
246   'stdlib.h',
247   'string.h',
248   'strings.h',
249   'sys/auxv.h',
250   'sys/event.h',
251   'sys/filio.h',
252   'sys/inotify.h',
253   'sys/mkdev.h',
254   'sys/mntctl.h',
255   'sys/mnttab.h',
256   'sys/mount.h',
257   'sys/param.h',
258   'sys/resource.h',
259   'sys/select.h',
260   'sys/statfs.h',
261   'sys/stat.h',
262   'sys/statvfs.h',
263   'sys/sysctl.h',
264   'sys/time.h', # MSC does not come with this by default
265   'sys/times.h',
266   'sys/types.h',
267   'sys/uio.h',
268   'sys/vfs.h',
269   'sys/vfstab.h',
270   'sys/vmount.h',
271   'sys/wait.h',
272   'termios.h',
273   'unistd.h',
274   'values.h',
275   'wchar.h',
276   'xlocale.h',
277 ]
278
279 foreach h : headers
280   if cc.has_header(h)
281     define = 'HAVE_' + h.underscorify().to_upper()
282     glib_conf.set(define, 1)
283     glib_conf_prefix = glib_conf_prefix + '#define @0@ 1\n'.format(define)
284   endif
285 endforeach
286
287 # FIXME: Use cc.check_header from Meson 0.47.
288 # FreeBSD includes a malloc.h which always throw compilation error.
289 if cc.compiles('#include <malloc.h>', name : 'malloc.h')
290   glib_conf.set('HAVE_MALLOC_H', 1)
291   glib_conf_prefix = glib_conf_prefix + '#define HAVE_MALLOC_H 1\n'
292 endif
293
294 if cc.has_header('linux/netlink.h')
295   glib_conf.set('HAVE_NETLINK', 1)
296 endif
297
298 if glib_conf.has('HAVE_LOCALE_H')
299   if cc.has_header_symbol('locale.h', 'LC_MESSAGES')
300     glib_conf.set('HAVE_LC_MESSAGES', 1)
301   endif
302 endif
303
304 struct_stat_blkprefix = '''
305 #include <sys/types.h>
306 #include <sys/stat.h>
307 #ifdef HAVE_UNISTD_H
308 #include <unistd.h>
309 #endif
310 #ifdef HAVE_SYS_STATFS_H
311 #include <sys/statfs.h>
312 #endif
313 #ifdef HAVE_SYS_PARAM_H
314 #include <sys/param.h>
315 #endif
316 #ifdef HAVE_SYS_MOUNT_H
317 #include <sys/mount.h>
318 #endif
319 '''
320
321 struct_members = [
322   [ 'stat', 'st_mtimensec' ],
323   [ 'stat', 'st_mtim.tv_nsec' ],
324   [ 'stat', 'st_atimensec' ],
325   [ 'stat', 'st_atim.tv_nsec' ],
326   [ 'stat', 'st_ctimensec' ],
327   [ 'stat', 'st_ctim.tv_nsec' ],
328   [ 'stat', 'st_birthtime' ],
329   [ 'stat', 'st_birthtimensec' ],
330   [ 'stat', 'st_birthtim' ],
331   [ 'stat', 'st_birthtim.tv_nsec' ],
332   [ 'stat', 'st_blksize', struct_stat_blkprefix ],
333   [ 'stat', 'st_blocks', struct_stat_blkprefix ],
334   [ 'statfs', 'f_fstypename', struct_stat_blkprefix ],
335   [ 'statfs', 'f_bavail', struct_stat_blkprefix ],
336   [ 'dirent', 'd_type', '''#include <sys/types.h>
337                            #include <dirent.h>''' ],
338   [ 'statvfs', 'f_basetype', '#include <sys/statvfs.h>' ],
339   [ 'statvfs', 'f_fstypename', '#include <sys/statvfs.h>' ],
340   [ 'tm', 'tm_gmtoff', '#include <time.h>' ],
341   [ 'tm', '__tm_gmtoff', '#include <time.h>' ],
342 ]
343
344 foreach m : struct_members
345   header_check_prefix = glib_conf_prefix
346   if m.length() == 3
347     header_check_prefix = header_check_prefix + m[2]
348   else
349     header_check_prefix = header_check_prefix + '#include <sys/stat.h>'
350   endif
351   if cc.has_member('struct ' + m[0], m[1], prefix : header_check_prefix)
352     define = 'HAVE_STRUCT_@0@_@1@'.format(m[0].to_upper(), m[1].underscorify().to_upper())
353     glib_conf.set(define, 1)
354     glib_conf_prefix = glib_conf_prefix + '#define @0@ 1\n'.format(define)
355   else
356   endif
357 endforeach
358
359 # Compiler flags
360 if cc.get_id() == 'gcc' or cc.get_id() == 'clang'
361   warning_c_args = [
362     '-Wall',
363     '-Wduplicated-branches',
364     '-Wimplicit-fallthrough',
365     '-Wmisleading-indentation',
366     '-Wstrict-prototypes',
367     '-Wunused',
368     # Due to maintained deprecated code, we do not want to see unused parameters
369     '-Wno-unused-parameter',
370     # Due to pervasive use of things like GPOINTER_TO_UINT(), we do not support
371     # building with -Wbad-function-cast.
372     '-Wno-bad-function-cast',
373     '-Wno-cast-function-type',
374     # Due to function casts through (void*) we cannot support -Wpedantic:
375     # https://wiki.gnome.org/Projects/GLib/CompilerRequirements#Function_pointer_conversions.
376     '-Wno-pedantic',
377     '-Werror=declaration-after-statement',
378     '-Werror=format=2',
379     '-Werror=implicit-function-declaration',
380     '-Werror=init-self',
381     '-Werror=missing-include-dirs',
382     '-Werror=missing-prototypes',
383     '-Werror=pointer-arith',
384   ]
385   warning_c_link_args = [
386     '-Wl,-z,nodelete',
387   ]
388   if get_option('bsymbolic_functions')
389     warning_c_link_args += ['-Wl,-Bsymbolic-functions']
390   endif
391 else
392   warning_c_args = []
393   warning_c_link_args = []
394 endif
395
396 add_project_arguments(cc.get_supported_arguments(warning_c_args), language: 'c')
397
398 # FIXME: We cannot build some of the GResource tests with -z nodelete, which
399 # means we cannot use that flag in add_project_link_arguments(), and must add
400 # it to the relevant targets manually. We do the same with -Bsymbolic-functions
401 # because that is what the autotools build did.
402 # See https://github.com/mesonbuild/meson/pull/3520 for a way to eventually
403 # improve this.
404 glib_link_flags = cc.get_supported_link_arguments(warning_c_link_args)
405
406 # Windows SDK requirements and checks
407 if host_system == 'windows'
408   # Check whether we're building for UWP apps
409   code = '''
410   #include <windows.h>
411   #if !(WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP))
412   #error "Not building for UWP"
413   #endif'''
414   if cc.compiles(code, name : 'building for UWP')
415     glib_conf.set('G_WINAPI_ONLY_APP', true)
416     # We require Windows 10+ on WinRT
417     glib_conf.set('_WIN32_WINNT', '0x0A00')
418   else
419     # We require Windows 7+ on Win32
420     glib_conf.set('_WIN32_WINNT', '0x0601')
421   endif
422 endif
423
424 functions = [
425   'endmntent',
426   'endservent',
427   'fallocate',
428   'fchmod',
429   'fchown',
430   'fdwalk',
431   'fsync',
432   'getauxval',
433   'getc_unlocked',
434   'getfsstat',
435   'getgrgid_r',
436   'getmntent_r',
437   'getpwuid_r',
438   'getresuid',
439   'getvfsstat',
440   'gmtime_r',
441   'hasmntopt',
442   'inotify_init1',
443   'issetugid',
444   'kevent',
445   'kqueue',
446   'lchmod',
447   'lchown',
448   'link',
449   'localtime_r',
450   'lstat',
451   'mbrtowc',
452   'memalign',
453   'mmap',
454   'newlocale',
455   'pipe2',
456   'poll',
457   'prlimit',
458   'readlink',
459   'recvmmsg',
460   'sendmmsg',
461   'setenv',
462   'setmntent',
463   'strerror_r',
464   'strnlen',
465   'strsignal',
466   'strtod_l',
467   'strtoll_l',
468   'strtoull_l',
469   'symlink',
470   'timegm',
471   'unsetenv',
472   'uselocale',
473   'utimes',
474   'valloc',
475   'vasprintf',
476   'vsnprintf',
477   'wcrtomb',
478   'wcslen',
479   'wcsnlen',
480   'sysctlbyname',
481   '_NSGetEnviron',
482 ]
483
484 if glib_conf.has('HAVE_SYS_STATVFS_H')
485   functions += ['statvfs']
486 else
487   have_func_statvfs = false
488 endif
489 if glib_conf.has('HAVE_SYS_STATFS_H') or glib_conf.has('HAVE_SYS_MOUNT_H')
490   functions += ['statfs']
491 else
492   have_func_statfs = false
493 endif
494
495 if host_system == 'windows'
496   iphlpapi_dep = cc.find_library('iphlpapi')
497   iphlpapi_funcs = ['if_nametoindex', 'if_indextoname']
498   foreach ifunc : iphlpapi_funcs
499     iphl_prefix =  '''#define _WIN32_WINNT @0@
500       #include <winsock2.h>
501       #include <iphlpapi.h>'''.format(glib_conf.get('_WIN32_WINNT'))
502     if cc.has_function(ifunc,
503                        prefix : iphl_prefix,
504                        dependencies : iphlpapi_dep)
505       idefine = 'HAVE_' + ifunc.underscorify().to_upper()
506       glib_conf.set(idefine, 1)
507       glib_conf_prefix = glib_conf_prefix + '#define @0@ 1\n'.format(idefine)
508       set_variable('have_func_' + ifunc, true)
509     else
510       set_variable('have_func_' + ifunc, false)
511     endif
512   endforeach
513 else
514   functions += ['if_indextoname', 'if_nametoindex']
515 endif
516
517 # AIX splice is something else
518 if host_system != 'aix'
519   functions += ['splice']
520 endif
521
522 foreach f : functions
523   if cc.has_function(f)
524     define = 'HAVE_' + f.underscorify().to_upper()
525     glib_conf.set(define, 1)
526     glib_conf_prefix = glib_conf_prefix + '#define @0@ 1\n'.format(define)
527     set_variable('have_func_' + f, true)
528   else
529     set_variable('have_func_' + f, false)
530   endif
531 endforeach
532
533 # Check that stpcpy() is usable; must use header
534 if cc.has_function('stpcpy', prefix : '#include <string.h>')
535   glib_conf.set('HAVE_STPCPY', 1)
536 endif
537
538 # Check that posix_memalign() is usable; must use header
539 if cc.has_function('posix_memalign', prefix : '#include <stdlib.h>')
540   glib_conf.set('HAVE_POSIX_MEMALIGN', 1)
541 endif
542
543 # Check that posix_spawn() is usable; must use header
544 if cc.has_function('posix_spawn', prefix : '#include <spawn.h>')
545   glib_conf.set('HAVE_POSIX_SPAWN', 1)
546 endif
547
548 # Check whether strerror_r returns char *
549 if have_func_strerror_r
550   if cc.compiles('''#define _GNU_SOURCE
551                     #include <string.h>
552                     int func (void) {
553                       char error_string[256];
554                       char *ptr = strerror_r (-2, error_string, 256);
555                       char c = *strerror_r (-2, error_string, 256);
556                       return c != 0 && ptr != (void*) 0L;
557                     }
558                  ''',
559                  name : 'strerror_r() returns char *')
560     glib_conf.set('STRERROR_R_CHAR_P', 1,
561                   description: 'Defined if strerror_r returns char *')
562   endif
563 endif
564
565 # Special-case these functions that have alternative names on Windows/MSVC
566 if cc.has_function('snprintf') or cc.has_header_symbol('stdio.h', 'snprintf')
567   glib_conf.set('HAVE_SNPRINTF', 1)
568   glib_conf_prefix = glib_conf_prefix + '#define HAVE_SNPRINTF 1\n'
569 elif cc.has_function('_snprintf') or cc.has_header_symbol('stdio.h', '_snprintf')
570   hack_define = '1\n#define snprintf _snprintf'
571   glib_conf.set('HAVE_SNPRINTF', hack_define)
572   glib_conf_prefix = glib_conf_prefix + '#define HAVE_SNPRINTF ' + hack_define
573 endif
574
575 if cc.has_function('strcasecmp')
576   glib_conf.set('HAVE_STRCASECMP', 1)
577   glib_conf_prefix = glib_conf_prefix + '#define HAVE_STRCASECMP 1\n'
578 elif cc.has_function('_stricmp')
579   hack_define = '1\n#define strcasecmp _stricmp'
580   glib_conf.set('HAVE_STRCASECMP', hack_define)
581   glib_conf_prefix = glib_conf_prefix + '#define HAVE_STRCASECMP ' + hack_define
582 endif
583
584 if cc.has_function('strncasecmp')
585   glib_conf.set('HAVE_STRNCASECMP', 1)
586   glib_conf_prefix = glib_conf_prefix + '#define HAVE_STRNCASECMP 1\n'
587 elif cc.has_function('_strnicmp')
588   hack_define = '1\n#define strncasecmp _strnicmp'
589   glib_conf.set('HAVE_STRNCASECMP', hack_define)
590   glib_conf_prefix = glib_conf_prefix + '#define HAVE_STRNCASECMP ' + hack_define
591 endif
592
593 if cc.has_header_symbol('sys/sysmacros.h', 'major')
594   glib_conf.set('MAJOR_IN_SYSMACROS', 1)
595 elif cc.has_header_symbol('sys/mkdev.h', 'major')
596   glib_conf.set('MAJOR_IN_MKDEV', 1)
597 elif cc.has_header_symbol('sys/types.h', 'major')
598   glib_conf.set('MAJOR_IN_TYPES', 1)
599 endif
600
601 if cc.has_header_symbol('dlfcn.h', 'RTLD_LAZY')
602   glib_conf.set('HAVE_RTLD_LAZY', 1)
603 endif
604
605 if cc.has_header_symbol('dlfcn.h', 'RTLD_NOW')
606   glib_conf.set('HAVE_RTLD_NOW', 1)
607 endif
608
609 if cc.has_header_symbol('dlfcn.h', 'RTLD_GLOBAL')
610   glib_conf.set('HAVE_RTLD_GLOBAL', 1)
611 endif
612
613 have_rtld_next = false
614 if cc.has_header_symbol('dlfcn.h', 'RTLD_NEXT', args: '-D_GNU_SOURCE')
615   have_rtld_next = true
616   glib_conf.set('HAVE_RTLD_NEXT', 1)
617 endif
618
619 # Check whether to use statfs or statvfs
620 # Some systems have both statfs and statvfs, pick the most "native" for these
621 if have_func_statfs and have_func_statvfs
622   # on solaris and irix, statfs doesn't even have the f_bavail field
623   if not glib_conf.has('HAVE_STRUCT_STATFS_F_BAVAIL')
624     have_func_statfs = false
625   else
626     # at least on linux, statfs is the actual syscall
627     have_func_statvfs = false
628   endif
629 endif
630 if have_func_statfs
631   glib_conf.set('USE_STATFS', 1)
632   stat_func_to_use = 'statfs'
633 elif have_func_statvfs
634   glib_conf.set('USE_STATVFS', 1)
635   stat_func_to_use = 'statvfs'
636 else
637   stat_func_to_use = 'neither'
638 endif
639 message('Checking whether to use statfs or statvfs .. ' + stat_func_to_use)
640
641 if host_system == 'linux'
642   if cc.has_function('mkostemp',
643                      prefix: '''#define _GNU_SOURCE
644                                 #include <stdlib.h>''')
645     glib_conf.set('HAVE_MKOSTEMP', 1)
646   endif
647 endif
648
649 osx_ldflags = []
650 glib_have_os_x_9_or_later = false
651 glib_have_carbon = false
652 glib_have_cocoa = false
653 if host_system == 'darwin'
654   add_languages('objc')
655   objcc = meson.get_compiler('objc')
656
657   osx_ldflags += ['-Wl,-framework,CoreFoundation']
658
659   # Mac OS X Carbon support
660   glib_have_carbon = objcc.compiles('''#include <Carbon/Carbon.h>
661                                        #include <CoreServices/CoreServices.h>''',
662                                     name : 'Mac OS X Carbon support')
663
664   if glib_have_carbon
665     glib_conf.set('HAVE_CARBON', true)
666     osx_ldflags += '-Wl,-framework,Carbon'
667     glib_have_os_x_9_or_later = objcc.compiles('''#include <AvailabilityMacros.h>
668                                                   #if MAC_OS_X_VERSION_MIN_REQUIRED < 1090
669                                                   #error Compiling for minimum OS X version before 10.9
670                                                   #endif''',
671                                                name : 'OS X 9 or later')
672   endif
673
674   # Mac OS X Cocoa support
675   glib_have_cocoa = objcc.compiles('''#include <Cocoa/Cocoa.h>
676                                       #ifdef GNUSTEP_BASE_VERSION
677                                       #error "Detected GNUstep, not Cocoa"
678                                       #endif''',
679                                    name : 'Mac OS X Cocoa support')
680
681   if glib_have_cocoa
682     glib_conf.set('HAVE_COCOA', true)
683     osx_ldflags += ['-Wl,-framework,Foundation', '-Wl,-framework,AppKit']
684   endif
685
686   # FIXME: libgio mix C and objC source files and there is no way to reliably
687   # know which language flags it's going to use to link. Add to both languages
688   # for now. See https://github.com/mesonbuild/meson/issues/3585.
689   add_project_link_arguments(osx_ldflags, language : ['objc', 'c'])
690 endif
691
692 # Check for futex(2)
693 if cc.links('''#include <linux/futex.h>
694                #include <sys/syscall.h>
695                #include <unistd.h>
696                int main (int argc, char ** argv) {
697                  syscall (__NR_futex, NULL, FUTEX_WAKE, FUTEX_WAIT);
698                  return 0;
699                }''', name : 'futex(2) system call')
700   glib_conf.set('HAVE_FUTEX', 1)
701 endif
702
703 # Check for eventfd(2)
704 if cc.links('''#include <sys/eventfd.h>
705                #include <unistd.h>
706                int main (int argc, char ** argv) {
707                  eventfd (0, EFD_CLOEXEC);
708                  return 0;
709                }''', name : 'eventfd(2) system call')
710   glib_conf.set('HAVE_EVENTFD', 1)
711 endif
712
713 clock_gettime_test_code = '''
714   #include <time.h>
715   struct timespec t;
716   int main (int argc, char ** argv) {
717     return clock_gettime(CLOCK_REALTIME, &t);
718   }'''
719 librt = []
720 if cc.links(clock_gettime_test_code, name : 'clock_gettime')
721   glib_conf.set('HAVE_CLOCK_GETTIME', 1)
722 elif cc.links(clock_gettime_test_code, args : '-lrt', name : 'clock_gettime in librt')
723   glib_conf.set('HAVE_CLOCK_GETTIME', 1)
724   librt = cc.find_library('rt')
725 endif
726
727 dlopen_dlsym_test_code = '''
728 #include <dlfcn.h>
729 int glib_underscore_test (void) { return 42; }
730 int main (int argc, char ** argv) {
731   void *f1 = (void*)0, *f2 = (void*)0, *handle;
732   handle = dlopen ((void*)0, 0);
733   if (handle) {
734     f1 = dlsym (handle, "glib_underscore_test");
735     f2 = dlsym (handle, "_glib_underscore_test");
736   }
737   return (!f2 || f1);
738 }'''
739 libdl_dep = []
740 if cc.links(dlopen_dlsym_test_code, name : 'dlopen() and dlsym() in system libraries')
741   have_dlopen_dlsym = true
742 elif cc.links(dlopen_dlsym_test_code, args : '-ldl', name : 'dlopen() and dlsym() in libdl')
743   have_dlopen_dlsym = true
744   libdl_dep = cc.find_library('dl')
745 else
746   have_dlopen_dlsym = false
747 endif
748
749 # if statfs() takes 2 arguments (Posix) or 4 (Solaris)
750 if have_func_statfs
751   if cc.compiles(glib_conf_prefix + '''
752                  #include <unistd.h>
753                         #ifdef HAVE_SYS_PARAM_H
754                         #include <sys/param.h>
755                         #endif
756                         #ifdef HAVE_SYS_VFS_H
757                         #include <sys/vfs.h>
758                         #endif
759                         #ifdef HAVE_SYS_MOUNT_H
760                         #include <sys/mount.h>
761                         #endif
762                         #ifdef HAVE_SYS_STATFS_H
763                         #include <sys/statfs.h>
764                         #endif
765                         void some_func (void) {
766                           struct statfs st;
767                           statfs("/", &st);
768                         }''', name : 'number of arguments to statfs() (n=2)')
769     glib_conf.set('STATFS_ARGS', 2)
770   elif cc.compiles(glib_conf_prefix + '''
771                    #include <unistd.h>
772                           #ifdef HAVE_SYS_PARAM_H
773                           #include <sys/param.h>
774                           #endif
775                           #ifdef HAVE_SYS_VFS_H
776                           #include <sys/vfs.h>
777                           #endif
778                           #ifdef HAVE_SYS_MOUNT_H
779                           #include <sys/mount.h>
780                           #endif
781                           #ifdef HAVE_SYS_STATFS_H
782                           #include <sys/statfs.h>
783                           #endif
784                           void some_func (void) {
785                             struct statfs st;
786                             statfs("/", &st, sizeof (st), 0);
787                           }''', name : 'number of arguments to statfs() (n=4)')
788     glib_conf.set('STATFS_ARGS', 4)
789   else
790     error('Unable to determine number of arguments to statfs()')
791   endif
792 endif
793
794 # open takes O_DIRECTORY as an option
795 #AC_MSG_CHECKING([])
796 if cc.compiles('''#include <fcntl.h>
797                   #include <sys/types.h>
798                   #include <sys/stat.h>],
799                   void some_func (void) {
800                     open(0, O_DIRECTORY, 0);
801                   }''', name : 'open() option O_DIRECTORY')
802   glib_conf.set('HAVE_OPEN_O_DIRECTORY', 1)
803 endif
804
805 # Check whether there is a vsnprintf() function with C99 semantics installed.
806 # (similar tests to AC_FUNC_VSNPRINTF_C99)
807 # Check whether there is a snprintf() function with C99 semantics installed.
808 # (similar tests to AC_FUNC_SNPRINTF_C99)
809 # Check whether there is a printf() function with Unix98 semantics installed.
810 # (similar tests to AC_FUNC_PRINTF_UNIX98)
811 have_good_vsnprintf = false
812 have_good_snprintf = false
813 have_good_printf = false
814
815 if host_system == 'windows' and (cc.get_id() == 'msvc' or cc.get_id() == 'clang-cl')
816   # Unfortunately the Visual Studio 2015+ implementations of C99-style
817   # snprintf and vsnprintf don't seem to be quite good enough.
818   # (Sorry, I don't know exactly what is the problem,
819   # but it is related to floating point formatting and decimal point vs. comma.)
820   # The simple tests in AC_FUNC_VSNPRINTF_C99 and AC_FUNC_SNPRINTF_C99 aren't
821   # rigorous enough to notice, though.
822   glib_conf.set('HAVE_C99_SNPRINTF', false)
823   glib_conf.set('HAVE_C99_VSNPRINTF', false)
824   glib_conf.set('HAVE_UNIX98_PRINTF', false)
825 else
826   vsnprintf_c99_test_code = '''
827 #include <stdio.h>
828 #include <stdarg.h>
829
830 int
831 doit(char * s, ...)
832 {
833   char buffer[32];
834   va_list args;
835   int r;
836
837   va_start(args, s);
838   r = vsnprintf(buffer, 5, s, args);
839   va_end(args);
840
841   if (r != 7)
842     exit(1);
843
844   /* AIX 5.1 and Solaris seems to have a half-baked vsnprintf()
845      implementation. The above will return 7 but if you replace
846      the size of the buffer with 0, it borks! */
847   va_start(args, s);
848   r = vsnprintf(buffer, 0, s, args);
849   va_end(args);
850
851   if (r != 7)
852     exit(1);
853
854   exit(0);
855 }
856
857 int
858 main(void)
859 {
860   doit("1234567");
861   exit(1);
862 }'''
863
864   if cc_can_run
865     rres = cc.run(vsnprintf_c99_test_code, name : 'C99 vsnprintf')
866     if rres.compiled() and rres.returncode() == 0
867       glib_conf.set('HAVE_C99_VSNPRINTF', 1)
868       have_good_vsnprintf = true
869     endif
870   else
871       have_good_vsnprintf = meson.get_cross_property('have_c99_vsnprintf', false)
872       glib_conf.set('HAVE_C99_VSNPRINTF', have_good_vsnprintf)
873   endif
874
875   snprintf_c99_test_code = '''
876 #include <stdio.h>
877 #include <stdarg.h>
878
879 int
880 doit()
881 {
882   char buffer[32];
883   va_list args;
884   int r;
885
886   r = snprintf(buffer, 5, "1234567");
887
888   if (r != 7)
889     exit(1);
890
891   r = snprintf(buffer, 0, "1234567");
892
893   if (r != 7)
894     exit(1);
895
896   r = snprintf(NULL, 0, "1234567");
897
898   if (r != 7)
899     exit(1);
900
901   exit(0);
902 }
903
904 int
905 main(void)
906 {
907   doit();
908   exit(1);
909 }'''
910
911   if cc_can_run
912     rres = cc.run(snprintf_c99_test_code, name : 'C99 snprintf')
913     if rres.compiled() and rres.returncode() == 0
914       glib_conf.set('HAVE_C99_SNPRINTF', 1)
915       have_good_snprintf = true
916     endif
917   else
918       have_good_snprintf = meson.get_cross_property('have_c99_snprintf', false)
919       glib_conf.set('HAVE_C99_SNPRINTF', have_good_snprintf)
920   endif
921
922   printf_unix98_test_code = '''
923 #include <stdio.h>
924
925 int
926 main (void)
927 {
928   char buffer[128];
929
930   sprintf (buffer, "%2\$d %3\$d %1\$d", 1, 2, 3);
931   if (strcmp ("2 3 1", buffer) == 0)
932     exit (0);
933   exit (1);
934 }'''
935
936   if cc_can_run
937     rres = cc.run(printf_unix98_test_code, name : 'Unix98 printf positional parameters')
938     if rres.compiled() and rres.returncode() == 0
939       glib_conf.set('HAVE_UNIX98_PRINTF', 1)
940       have_good_printf = true
941     endif
942   else
943       have_good_printf = meson.get_cross_property('have_unix98_printf', false)
944       glib_conf.set('HAVE_UNIX98_PRINTF', have_good_printf)
945   endif
946 endif
947
948 if host_system == 'windows'
949   glib_conf.set_quoted('EXEEXT', '.exe')
950 else
951   glib_conf.set('EXEEXT', '')
952 endif
953
954 # Our printf is 'good' only if vsnpintf()/snprintf()/printf() supports C99 well enough
955 use_system_printf = have_good_vsnprintf and have_good_snprintf and have_good_printf
956 glib_conf.set('USE_SYSTEM_PRINTF', use_system_printf)
957 glibconfig_conf.set('GLIB_USING_SYSTEM_PRINTF', use_system_printf)
958
959 if not use_system_printf
960   # gnulib has vasprintf so override the previous check
961   glib_conf.set('HAVE_VASPRINTF', 1)
962 endif
963
964 # Check for nl_langinfo and CODESET
965 if cc.links('''#include <langinfo.h>
966                int main (int argc, char ** argv) {
967                  char *codeset = nl_langinfo (CODESET);
968                  return 0;
969                }''', name : 'nl_langinfo and CODESET')
970   glib_conf.set('HAVE_LANGINFO_CODESET', 1)
971   glib_conf.set('HAVE_CODESET', 1)
972 endif
973
974 # Check for nl_langinfo and LC_TIME parts that are needed in gdatetime.c
975 if cc.links('''#include <langinfo.h>
976                int main (int argc, char ** argv) {
977                  char *str;
978                  str = nl_langinfo (PM_STR);
979                  str = nl_langinfo (D_T_FMT);
980                  str = nl_langinfo (D_FMT);
981                  str = nl_langinfo (T_FMT);
982                  str = nl_langinfo (T_FMT_AMPM);
983                  str = nl_langinfo (MON_1);
984                  str = nl_langinfo (ABMON_12);
985                  str = nl_langinfo (DAY_1);
986                  str = nl_langinfo (ABDAY_7);
987                  return 0;
988                }''', name : 'nl_langinfo (PM_STR)')
989   glib_conf.set('HAVE_LANGINFO_TIME', 1)
990 endif
991 if cc.links('''#include <langinfo.h>
992                int main (int argc, char ** argv) {
993                  char *str;
994                  str = nl_langinfo (_NL_CTYPE_OUTDIGIT0_MB);
995                  str = nl_langinfo (_NL_CTYPE_OUTDIGIT1_MB);
996                  str = nl_langinfo (_NL_CTYPE_OUTDIGIT2_MB);
997                  str = nl_langinfo (_NL_CTYPE_OUTDIGIT3_MB);
998                  str = nl_langinfo (_NL_CTYPE_OUTDIGIT4_MB);
999                  str = nl_langinfo (_NL_CTYPE_OUTDIGIT5_MB);
1000                  str = nl_langinfo (_NL_CTYPE_OUTDIGIT6_MB);
1001                  str = nl_langinfo (_NL_CTYPE_OUTDIGIT7_MB);
1002                  str = nl_langinfo (_NL_CTYPE_OUTDIGIT8_MB);
1003                  str = nl_langinfo (_NL_CTYPE_OUTDIGIT9_MB);
1004                  return 0;
1005                }''', name : 'nl_langinfo (_NL_CTYPE_OUTDIGITn_MB)')
1006   glib_conf.set('HAVE_LANGINFO_OUTDIGIT', 1)
1007 endif
1008
1009 # Check for nl_langinfo and alternative month names
1010 if cc.links('''#ifndef _GNU_SOURCE
1011               # define _GNU_SOURCE
1012               #endif
1013               #include <langinfo.h>
1014                int main (int argc, char ** argv) {
1015                  char *str;
1016                  str = nl_langinfo (ALTMON_1);
1017                  str = nl_langinfo (ALTMON_2);
1018                  str = nl_langinfo (ALTMON_3);
1019                  str = nl_langinfo (ALTMON_4);
1020                  str = nl_langinfo (ALTMON_5);
1021                  str = nl_langinfo (ALTMON_6);
1022                  str = nl_langinfo (ALTMON_7);
1023                  str = nl_langinfo (ALTMON_8);
1024                  str = nl_langinfo (ALTMON_9);
1025                  str = nl_langinfo (ALTMON_10);
1026                  str = nl_langinfo (ALTMON_11);
1027                  str = nl_langinfo (ALTMON_12);
1028                  return 0;
1029                }''', name : 'nl_langinfo (ALTMON_n)')
1030   glib_conf.set('HAVE_LANGINFO_ALTMON', 1)
1031 endif
1032
1033 # Check for nl_langinfo and abbreviated alternative month names
1034 if cc.links('''#ifndef _GNU_SOURCE
1035               # define _GNU_SOURCE
1036               #endif
1037               #include <langinfo.h>
1038                int main (int argc, char ** argv) {
1039                  char *str;
1040                  str = nl_langinfo (_NL_ABALTMON_1);
1041                  str = nl_langinfo (_NL_ABALTMON_2);
1042                  str = nl_langinfo (_NL_ABALTMON_3);
1043                  str = nl_langinfo (_NL_ABALTMON_4);
1044                  str = nl_langinfo (_NL_ABALTMON_5);
1045                  str = nl_langinfo (_NL_ABALTMON_6);
1046                  str = nl_langinfo (_NL_ABALTMON_7);
1047                  str = nl_langinfo (_NL_ABALTMON_8);
1048                  str = nl_langinfo (_NL_ABALTMON_9);
1049                  str = nl_langinfo (_NL_ABALTMON_10);
1050                  str = nl_langinfo (_NL_ABALTMON_11);
1051                  str = nl_langinfo (_NL_ABALTMON_12);
1052                  return 0;
1053                }''', name : 'nl_langinfo (_NL_ABALTMON_n)')
1054   glib_conf.set('HAVE_LANGINFO_ABALTMON', 1)
1055 endif
1056
1057 # Check if C compiler supports the 'signed' keyword
1058 if not cc.compiles('''signed char x;''', name : 'signed')
1059   glib_conf.set('signed', '/* NOOP */')
1060 endif
1061
1062 # Check if the ptrdiff_t type exists
1063 if cc.has_header_symbol('stddef.h', 'ptrdiff_t')
1064   glib_conf.set('HAVE_PTRDIFF_T', 1)
1065 endif
1066
1067 # Check for sig_atomic_t type
1068 if cc.links('''#include <signal.h>
1069                #include <sys/types.h>
1070                sig_atomic_t val = 42;
1071                int main (int argc, char ** argv) {
1072                  return val == 42 ? 0 : 1;
1073                }''', name : 'sig_atomic_t')
1074   glib_conf.set('HAVE_SIG_ATOMIC_T', 1)
1075 endif
1076
1077 # Check if 'long long' works
1078 # jm_AC_TYPE_LONG_LONG
1079 if cc.compiles('''long long ll = 1LL;
1080                   int i = 63;
1081                   int some_func (void) {
1082                     long long llmax = (long long) -1;
1083                     return ll << i | ll >> i | llmax / ll | llmax % ll;
1084                   }''', name : 'long long')
1085   glib_conf.set('HAVE_LONG_LONG', 1)
1086   have_long_long = true
1087 else
1088   have_long_long = false
1089 endif
1090
1091 # Test whether the compiler supports the 'long double' type.
1092 if cc.compiles('''/* The Stardent Vistra knows sizeof(long double), but does not support it.  */
1093                   long double foo = 0.0;
1094                   /* On Ultrix 4.3 cc, long double is 4 and double is 8.  */
1095                   int array [2*(sizeof(long double) >= sizeof(double)) - 1];''',
1096                name : 'long double')
1097   glib_conf.set('HAVE_LONG_DOUBLE', 1)
1098 endif
1099
1100 # Test whether <stddef.h> has the 'wchar_t' type.
1101 if cc.has_header_symbol('stddef.h', 'wchar_t')
1102   glib_conf.set('HAVE_WCHAR_T', 1)
1103 endif
1104
1105 # Test whether <wchar.h> has the 'wint_t' type.
1106 if cc.has_header_symbol('wchar.h', 'wint_t')
1107   glib_conf.set('HAVE_WINT_T', 1)
1108 endif
1109
1110 found_uintmax_t = false
1111
1112 # Define HAVE_INTTYPES_H_WITH_UINTMAX if <inttypes.h> exists,
1113 # doesn't clash with <sys/types.h>, and declares uintmax_t.
1114 # jm_AC_HEADER_INTTYPES_H
1115 if cc.compiles('''#include <sys/types.h>
1116                   #include <inttypes.h>
1117                   void some_func (void) {
1118                     uintmax_t i = (uintmax_t) -1;
1119                   }''', name : 'uintmax_t in inttypes.h')
1120   glib_conf.set('HAVE_INTTYPES_H_WITH_UINTMAX', 1)
1121   found_uintmax_t = true
1122 endif
1123
1124 # Define HAVE_STDINT_H_WITH_UINTMAX if <stdint.h> exists,
1125 # doesn't clash with <sys/types.h>, and declares uintmax_t.
1126 # jm_AC_HEADER_STDINT_H
1127 if cc.compiles('''#include <sys/types.h>
1128                   #include <stdint.h>
1129                   void some_func (void) {
1130                     uintmax_t i = (uintmax_t) -1;
1131                   }''', name : 'uintmax_t in stdint.h')
1132   glib_conf.set('HAVE_STDINT_H_WITH_UINTMAX', 1)
1133   found_uintmax_t = true
1134 endif
1135
1136 # Define intmax_t to 'long' or 'long long'
1137 # if it is not already defined in <stdint.h> or <inttypes.h>.
1138 # For simplicity, we assume that a header file defines 'intmax_t' if and
1139 # only if it defines 'uintmax_t'.
1140 if found_uintmax_t
1141   glib_conf.set('HAVE_INTMAX_T', 1)
1142 elif have_long_long
1143   glib_conf.set('intmax_t', 'long long')
1144 else
1145   glib_conf.set('intmax_t', 'long')
1146 endif
1147
1148 char_size = cc.sizeof('char')
1149 short_size = cc.sizeof('short')
1150 int_size = cc.sizeof('int')
1151 voidp_size = cc.sizeof('void*')
1152 long_size = cc.sizeof('long')
1153 if have_long_long
1154   long_long_size = cc.sizeof('long long')
1155 else
1156   long_long_size = 0
1157 endif
1158 sizet_size = cc.sizeof('size_t')
1159 if cc.get_id() == 'msvc' or cc.get_id() == 'clang-cl'
1160   ssizet_size = cc.sizeof('SSIZE_T', prefix : '#include <BaseTsd.h>')
1161 else
1162   ssizet_size = cc.sizeof('ssize_t')
1163 endif
1164
1165 # Some platforms (Apple) hard-code int64_t to long long instead of
1166 # using long on 64-bit architectures. This can cause type mismatch
1167 # warnings when trying to interface with code using the standard
1168 # library type. Test for the warnings and set gint64 to whichever
1169 # works.
1170 if long_long_size == long_size
1171   if cc.compiles('''#if defined(_AIX) && !defined(__GNUC__)
1172                     #pragma options langlvl=stdc99
1173                     #endif
1174                     #pragma GCC diagnostic error "-Wincompatible-pointer-types"
1175                     #include <stdint.h>
1176                     #include <stdio.h>
1177                     int main () {
1178                       int64_t i1 = 1;
1179                       long *i2 = &i1;
1180                       return 1;
1181                     }''', name : 'int64_t is long')
1182     int64_t_typedef = 'long'
1183   elif cc.compiles('''#if defined(_AIX) && !defined(__GNUC__)
1184                       #pragma options langlvl=stdc99
1185                       #endif
1186                       #pragma GCC diagnostic error "-Wincompatible-pointer-types"
1187                       #include <stdint.h>
1188                       #include <stdio.h>
1189                       int main () {
1190                         int64_t i1 = 1;
1191                         long long *i2 = &i1;
1192                         return 1;
1193                       }''', name : 'int64_t is long long')
1194     int64_t_typedef = 'long long'
1195   endif
1196 endif
1197
1198 int64_m = 'll'
1199 char_align = cc.alignment('char')
1200 short_align = cc.alignment('short')
1201 int_align = cc.alignment('int')
1202 voidp_align = cc.alignment('void*')
1203 long_align = cc.alignment('long')
1204 long_long_align = cc.alignment('long long')
1205 # NOTE: We don't check for size of __int64 because long long is guaranteed to
1206 # be 64-bit in C99, and it is available on all supported compilers
1207 sizet_align = cc.alignment('size_t')
1208
1209 glib_conf.set('ALIGNOF_UNSIGNED_LONG', long_align)
1210
1211 glib_conf.set('SIZEOF_CHAR', char_size)
1212 glib_conf.set('SIZEOF_INT', int_size)
1213 glib_conf.set('SIZEOF_SHORT', short_size)
1214 glib_conf.set('SIZEOF_LONG', long_size)
1215 glib_conf.set('SIZEOF_LONG_LONG', long_long_size)
1216 glib_conf.set('SIZEOF_SIZE_T', sizet_size)
1217 glib_conf.set('SIZEOF_SSIZE_T', ssizet_size)
1218 glib_conf.set('SIZEOF_VOID_P', voidp_size)
1219 glib_conf.set('SIZEOF_WCHAR_T', cc.sizeof('wchar_t', prefix: '#include <stddef.h>'))
1220
1221 if short_size == 2
1222   gint16 = 'short'
1223   gint16_modifier='h'
1224   gint16_format='hi'
1225   guint16_format='hu'
1226 elif int_size == 2
1227   gint16 = 'int'
1228   gint16_modifier=''
1229   gint16_format='i'
1230   guint16_format='u'
1231 else
1232   error('Compiler provides no native 16-bit integer type')
1233 endif
1234 glibconfig_conf.set('gint16', gint16)
1235 glibconfig_conf.set_quoted('gint16_modifier', gint16_modifier)
1236 glibconfig_conf.set_quoted('gint16_format', gint16_format)
1237 glibconfig_conf.set_quoted('guint16_format', guint16_format)
1238
1239 if short_size == 4
1240   gint32 = 'short'
1241   gint32_modifier='h'
1242   gint32_format='hi'
1243   guint32_format='hu'
1244   guint32_align = short_align
1245 elif int_size == 4
1246   gint32 = 'int'
1247   gint32_modifier=''
1248   gint32_format='i'
1249   guint32_format='u'
1250   guint32_align = int_align
1251 elif long_size == 4
1252   gint32 = 'long'
1253   gint32_modifier='l'
1254   gint32_format='li'
1255   guint32_format='lu'
1256   guint32_align = long_align
1257 else
1258   error('Compiler provides no native 32-bit integer type')
1259 endif
1260 glibconfig_conf.set('gint32', gint32)
1261 glibconfig_conf.set_quoted('gint32_modifier', gint32_modifier)
1262 glibconfig_conf.set_quoted('gint32_format', gint32_format)
1263 glibconfig_conf.set_quoted('guint32_format', guint32_format)
1264 glib_conf.set('ALIGNOF_GUINT32', guint32_align)
1265
1266 if int_size == 8
1267   gint64 = 'int'
1268   gint64_modifier=''
1269   gint64_format='i'
1270   guint64_format='u'
1271   glib_extension=''
1272   gint64_constant='(val)'
1273   guint64_constant='(val)'
1274   guint64_align = int_align
1275 elif long_size == 8 and (long_long_size != long_size or int64_t_typedef == 'long')
1276   gint64 = 'long'
1277   glib_extension=''
1278   gint64_modifier='l'
1279   gint64_format='li'
1280   guint64_format='lu'
1281   gint64_constant='(val##L)'
1282   guint64_constant='(val##UL)'
1283   guint64_align = long_align
1284 elif long_long_size == 8 and (long_long_size != long_size or int64_t_typedef == 'long long')
1285   gint64 = 'long long'
1286   glib_extension='G_GNUC_EXTENSION '
1287   gint64_modifier=int64_m
1288   gint64_format=int64_m + 'i'
1289   guint64_format=int64_m + 'u'
1290   gint64_constant='(G_GNUC_EXTENSION (val##LL))'
1291   guint64_constant='(G_GNUC_EXTENSION (val##ULL))'
1292   guint64_align = long_long_align
1293 else
1294   error('Compiler provides no native 64-bit integer type')
1295 endif
1296 glibconfig_conf.set('glib_extension', glib_extension)
1297 glibconfig_conf.set('gint64', gint64)
1298 glibconfig_conf.set_quoted('gint64_modifier', gint64_modifier)
1299 glibconfig_conf.set_quoted('gint64_format', gint64_format)
1300 glibconfig_conf.set_quoted('guint64_format', guint64_format)
1301 glibconfig_conf.set('gint64_constant', gint64_constant)
1302 glibconfig_conf.set('guint64_constant', guint64_constant)
1303 glib_conf.set('ALIGNOF_GUINT64', guint64_align)
1304
1305 if host_system == 'windows'
1306   glibconfig_conf.set('g_pid_type', 'void*')
1307   glibconfig_conf.set_quoted('g_pid_format', 'p')
1308   if host_machine.cpu_family() == 'x86_64'
1309     glibconfig_conf.set_quoted('g_pollfd_format', '%#' + int64_m + 'x')
1310   else
1311     glibconfig_conf.set_quoted('g_pollfd_format', '%#x')
1312   endif
1313   glibconfig_conf.set('g_dir_separator', '\\\\')
1314   glibconfig_conf.set('g_searchpath_separator', ';')
1315 else
1316   glibconfig_conf.set('g_pid_type', 'int')
1317   glibconfig_conf.set_quoted('g_pid_format', 'i')
1318   glibconfig_conf.set_quoted('g_pollfd_format', '%d')
1319   glibconfig_conf.set('g_dir_separator', '/')
1320   glibconfig_conf.set('g_searchpath_separator', ':')
1321 endif
1322
1323 if sizet_size == short_size
1324   glibconfig_conf.set('glib_size_type_define', 'short')
1325   glibconfig_conf.set_quoted('gsize_modifier', 'h')
1326   glibconfig_conf.set_quoted('gssize_modifier', 'h')
1327   glibconfig_conf.set_quoted('gsize_format', 'hu')
1328   glibconfig_conf.set_quoted('gssize_format', 'hi')
1329   glibconfig_conf.set('glib_msize_type', 'SHRT')
1330 elif sizet_size == int_size
1331   glibconfig_conf.set('glib_size_type_define', 'int')
1332   glibconfig_conf.set_quoted('gsize_modifier', '')
1333   glibconfig_conf.set_quoted('gssize_modifier', '')
1334   glibconfig_conf.set_quoted('gsize_format', 'u')
1335   glibconfig_conf.set_quoted('gssize_format', 'i')
1336   glibconfig_conf.set('glib_msize_type', 'INT')
1337 elif sizet_size == long_size
1338   glibconfig_conf.set('glib_size_type_define', 'long')
1339   glibconfig_conf.set_quoted('gsize_modifier', 'l')
1340   glibconfig_conf.set_quoted('gssize_modifier', 'l')
1341   glibconfig_conf.set_quoted('gsize_format', 'lu')
1342   glibconfig_conf.set_quoted('gssize_format', 'li')
1343   glibconfig_conf.set('glib_msize_type', 'LONG')
1344 elif sizet_size == long_long_size
1345   glibconfig_conf.set('glib_size_type_define', 'long long')
1346   glibconfig_conf.set_quoted('gsize_modifier', int64_m)
1347   glibconfig_conf.set_quoted('gssize_modifier', int64_m)
1348   glibconfig_conf.set_quoted('gsize_format', int64_m + 'u')
1349   glibconfig_conf.set_quoted('gssize_format', int64_m + 'i')
1350   glibconfig_conf.set('glib_msize_type', 'INT64')
1351 else
1352   error('Could not determine size of size_t.')
1353 endif
1354
1355 if voidp_size == int_size
1356   glibconfig_conf.set('glib_intptr_type_define', 'int')
1357   glibconfig_conf.set_quoted('gintptr_modifier', '')
1358   glibconfig_conf.set_quoted('gintptr_format', 'i')
1359   glibconfig_conf.set_quoted('guintptr_format', 'u')
1360   glibconfig_conf.set('glib_gpi_cast', '(gint)')
1361   glibconfig_conf.set('glib_gpui_cast', '(guint)')
1362 elif voidp_size == long_size
1363   glibconfig_conf.set('glib_intptr_type_define', 'long')
1364   glibconfig_conf.set_quoted('gintptr_modifier', 'l')
1365   glibconfig_conf.set_quoted('gintptr_format', 'li')
1366   glibconfig_conf.set_quoted('guintptr_format', 'lu')
1367   glibconfig_conf.set('glib_gpi_cast', '(glong)')
1368   glibconfig_conf.set('glib_gpui_cast', '(gulong)')
1369 elif voidp_size == long_long_size
1370   glibconfig_conf.set('glib_intptr_type_define', 'long long')
1371   glibconfig_conf.set_quoted('gintptr_modifier', int64_m)
1372   glibconfig_conf.set_quoted('gintptr_format', int64_m + 'i')
1373   glibconfig_conf.set_quoted('guintptr_format', int64_m + 'u')
1374   glibconfig_conf.set('glib_gpi_cast', '(gint64)')
1375   glibconfig_conf.set('glib_gpui_cast', '(guint64)')
1376 else
1377   error('Could not determine size of void *')
1378 endif
1379
1380 if long_size != 8 and long_long_size != 8 and int_size != 8
1381   error('GLib requires a 64-bit type. You might want to consider using the GNU C compiler.')
1382 endif
1383
1384 glibconfig_conf.set('gintbits', int_size * 8)
1385 glibconfig_conf.set('glongbits', long_size * 8)
1386 glibconfig_conf.set('gsizebits', sizet_size * 8)
1387 glibconfig_conf.set('gssizebits', ssizet_size * 8)
1388
1389 # XXX: https://gitlab.gnome.org/GNOME/glib/issues/1413
1390 if host_system == 'windows'
1391   g_module_suffix = 'dll'
1392 else
1393   g_module_suffix = 'so'
1394 endif
1395 glibconfig_conf.set('g_module_suffix', g_module_suffix)
1396
1397 glibconfig_conf.set('GLIB_MAJOR_VERSION', major_version)
1398 glibconfig_conf.set('GLIB_MINOR_VERSION', minor_version)
1399 glibconfig_conf.set('GLIB_MICRO_VERSION', micro_version)
1400 glibconfig_conf.set('GLIB_VERSION', glib_version)
1401
1402 glibconfig_conf.set('glib_void_p', voidp_size)
1403 glibconfig_conf.set('glib_long', long_size)
1404 glibconfig_conf.set('glib_size_t', sizet_size)
1405 glibconfig_conf.set('glib_ssize_t', ssizet_size)
1406 if host_machine.endian() == 'big'
1407   glibconfig_conf.set('g_byte_order', 'G_BIG_ENDIAN')
1408   glibconfig_conf.set('g_bs_native', 'BE')
1409   glibconfig_conf.set('g_bs_alien', 'LE')
1410 else
1411   glibconfig_conf.set('g_byte_order', 'G_LITTLE_ENDIAN')
1412   glibconfig_conf.set('g_bs_native', 'LE')
1413   glibconfig_conf.set('g_bs_alien', 'BE')
1414 endif
1415
1416 # === va_copy checks ===
1417 # we currently check for all three va_copy possibilities, so we get
1418 # all results in config.log for bug reports.
1419
1420 va_copy_func = ''
1421 foreach try_func : [ '__va_copy', 'va_copy' ]
1422   if cc.compiles('''#include <stdarg.h>
1423                     #include <stdlib.h>
1424                     #ifdef _MSC_VER
1425                     # include "msvc_recommended_pragmas.h"
1426                     #endif
1427                     void f (int i, ...) {
1428                     va_list args1, args2;
1429                     va_start (args1, i);
1430                     @0@ (args2, args1);
1431                     if (va_arg (args2, int) != 42 || va_arg (args1, int) != 42)
1432                       exit (1);
1433                     va_end (args1); va_end (args2);
1434                     }
1435                     int main() {
1436                       f (0, 42);
1437                       return 0;
1438                     }'''.format(try_func),
1439                     name : try_func + ' check')
1440     va_copy_func = try_func
1441   endif
1442 endforeach
1443 if va_copy_func != ''
1444   glib_conf.set('G_VA_COPY', va_copy_func)
1445   glib_vacopy = '#define G_VA_COPY ' + va_copy_func
1446 else
1447   glib_vacopy = '/* #undef G_VA_COPY */'
1448 endif
1449
1450 va_list_val_copy_prog = '''
1451   #include <stdarg.h>
1452   #include <stdlib.h>
1453   void f (int i, ...) {
1454     va_list args1, args2;
1455     va_start (args1, i);
1456     args2 = args1;
1457     if (va_arg (args2, int) != 42 || va_arg (args1, int) != 42)
1458       exit (1);
1459     va_end (args1); va_end (args2);
1460   }
1461   int main() {
1462     f (0, 42);
1463     return 0;
1464   }'''
1465
1466 if cc_can_run
1467   rres = cc.run(va_list_val_copy_prog, name : 'va_lists can be copied as values')
1468   glib_va_val_copy = rres.returncode() == 0
1469 else
1470   glib_va_val_copy = meson.get_cross_property('va_val_copy', true)
1471 endif
1472 if not glib_va_val_copy
1473   glib_vacopy = glib_vacopy + '\n#define G_VA_COPY_AS_ARRAY 1'
1474   glib_conf.set('G_VA_COPY_AS_ARRAY', 1)
1475 endif
1476 glibconfig_conf.set('glib_vacopy', glib_vacopy)
1477
1478 # check for flavours of varargs macros
1479 g_have_iso_c_varargs = cc.compiles('''
1480   void some_func (void) {
1481     int a(int p1, int p2, int p3);
1482     #define call_a(...) a(1,__VA_ARGS__)
1483     call_a(2,3);
1484   }''', name : 'ISO C99 varargs macros in C')
1485
1486 if g_have_iso_c_varargs
1487   glibconfig_conf.set('g_have_iso_c_varargs', '''
1488 #ifndef __cplusplus
1489 # define G_HAVE_ISO_VARARGS 1
1490 #endif''')
1491 endif
1492
1493 g_have_iso_cxx_varargs = cxx.compiles('''
1494   void some_func (void) {
1495     int a(int p1, int p2, int p3);
1496     #define call_a(...) a(1,__VA_ARGS__)
1497     call_a(2,3);
1498   }''', name : 'ISO C99 varargs macros in C++')
1499
1500 if g_have_iso_cxx_varargs
1501   glibconfig_conf.set('g_have_iso_cxx_varargs', '''
1502 #ifdef __cplusplus
1503 # define G_HAVE_ISO_VARARGS 1
1504 #endif''')
1505 endif
1506
1507 g_have_gnuc_varargs = cc.compiles('''
1508   void some_func (void) {
1509     int a(int p1, int p2, int p3);
1510     #define call_a(params...) a(1,params)
1511     call_a(2,3);
1512   }''', name : 'GNUC varargs macros')
1513
1514 if cc.has_header('alloca.h')
1515   glibconfig_conf.set('GLIB_HAVE_ALLOCA_H', true)
1516 endif
1517 has_syspoll = cc.has_header('sys/poll.h')
1518 has_systypes = cc.has_header('sys/types.h')
1519 if has_syspoll
1520   glibconfig_conf.set('GLIB_HAVE_SYS_POLL_H', true)
1521 endif
1522 has_winsock2 = cc.has_header('winsock2.h')
1523
1524 if has_syspoll and has_systypes
1525   poll_includes = '''
1526       #include<sys/poll.h>
1527       #include<sys/types.h>'''
1528 elif has_winsock2
1529   poll_includes = '''
1530       #define _WIN32_WINNT @0@
1531       #include <winsock2.h>'''.format(glib_conf.get('_WIN32_WINNT'))
1532 else
1533   # FIXME?
1534   error('FIX POLL* defines')
1535 endif
1536
1537 poll_defines = [
1538   [ 'POLLIN', 'g_pollin', 1 ],
1539   [ 'POLLOUT', 'g_pollout', 4 ],
1540   [ 'POLLPRI', 'g_pollpri', 2 ],
1541   [ 'POLLERR', 'g_pollerr', 8 ],
1542   [ 'POLLHUP', 'g_pollhup', 16 ],
1543   [ 'POLLNVAL', 'g_pollnval', 32 ],
1544 ]
1545
1546 if has_syspoll and has_systypes
1547   foreach d : poll_defines
1548     val = cc.compute_int(d[0], prefix: poll_includes)
1549     glibconfig_conf.set(d[1], val)
1550   endforeach
1551 elif has_winsock2
1552   # Due to a missed bug in configure.ac the poll test
1553   # never succeeded on Windows and used some pre-defined
1554   # values as a fallback. Keep using them to maintain
1555   # ABI compatibility with autotools builds of glibs
1556   # and with *any* glib-using code compiled against them,
1557   # since these values end up in a public header glibconfig.h.
1558   foreach d : poll_defines
1559     glibconfig_conf.set(d[1], d[2])
1560   endforeach
1561 endif
1562
1563 # Internet address families
1564 # FIXME: what about Cygwin (G_WITH_CYGWIN)
1565 if host_system == 'windows'
1566   inet_includes = '''
1567       #include <winsock2.h>'''
1568 else
1569   inet_includes = '''
1570       #include <sys/types.h>
1571       #include <sys/socket.h>'''
1572 endif
1573
1574 inet_defines = [
1575   [ 'AF_UNIX', 'g_af_unix' ],
1576   [ 'AF_INET', 'g_af_inet' ],
1577   [ 'AF_INET6', 'g_af_inet6' ],
1578   [ 'MSG_OOB', 'g_msg_oob' ],
1579   [ 'MSG_PEEK', 'g_msg_peek' ],
1580   [ 'MSG_DONTROUTE', 'g_msg_dontroute' ],
1581 ]
1582 foreach d : inet_defines
1583   val = cc.compute_int(d[0], prefix: inet_includes)
1584   glibconfig_conf.set(d[1], val)
1585 endforeach
1586
1587 # We need a more robust approach here...
1588 host_cpu_family = host_machine.cpu_family()
1589 if host_cpu_family == 'x86' or host_cpu_family == 'x86_64' or host_cpu_family == 's390' or host_cpu_family == 's390x' or host_cpu_family.startswith('arm') or host_cpu_family == 'aarch64' or host_cpu_family.startswith('crisv32') or host_cpu_family.startswith('etrax')
1590   glib_memory_barrier_needed = false
1591 elif host_cpu_family.startswith('sparc') or host_cpu_family.startswith('alpha') or host_cpu_family.startswith('powerpc') or host_cpu_family == 'ia64'
1592   glib_memory_barrier_needed = true
1593 else
1594   warning('Unknown host cpu: ' + host_cpu_family)
1595   glib_memory_barrier_needed = true
1596 endif
1597 glibconfig_conf.set('G_ATOMIC_OP_MEMORY_BARRIER_NEEDED', glib_memory_barrier_needed)
1598
1599 # We need to decide at configure time if GLib will use real atomic
1600 # operations ("lock free") or emulated ones with a mutex.  This is
1601 # because we must put this information in glibconfig.h so we know if
1602 # it is safe or not to inline using compiler intrinsics directly from
1603 # the header.
1604 #
1605 # We also publish the information via G_ATOMIC_LOCK_FREE in case the
1606 # user is interested in knowing if they can use the atomic ops across
1607 # processes.
1608 #
1609 # We can currently support the atomic ops natively when building GLib
1610 # with recent versions of GCC or MSVC.
1611 #
1612 # Note that the atomic ops are only available with GCC on x86 when
1613 # using -march=i486 or higher.  If we detect that the atomic ops are
1614 # not available but would be available given the right flags, we want
1615 # to abort and advise the user to fix their CFLAGS.  It's better to do
1616 # that then to silently fall back on emulated atomic ops just because
1617 # the user had the wrong build environment.
1618 atomictest = '''int main() {
1619   volatile int atomic = 2;
1620   __sync_bool_compare_and_swap (&atomic, 2, 3);
1621   return 0;
1622 }
1623 '''
1624
1625 atomicdefine = '''
1626 #ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
1627 #error "compiler has atomic ops, but doesn't define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"
1628 #endif
1629 '''
1630
1631 # We know that we can always use real ("lock free") atomic operations with MSVC
1632 if cc.get_id() == 'msvc' or cc.get_id() == 'clang-cl' or cc.links(atomictest, name : 'atomic ops')
1633   have_atomic_lock_free = true
1634   if cc.get_id() == 'gcc' and not cc.compiles(atomicdefine, name : 'atomic ops define')
1635     # Old gcc release may provide
1636     # __sync_bool_compare_and_swap but doesn't define
1637     # __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
1638     glib_conf.set('__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4', true)
1639   endif
1640 else
1641   have_atomic_lock_free = false
1642   if host_machine.cpu_family() == 'x86' and cc.links(atomictest, args : '-march=i486')
1643     error('GLib must be built with -march=i486 or later.')
1644   endif
1645 endif
1646 glibconfig_conf.set('G_ATOMIC_LOCK_FREE', have_atomic_lock_free)
1647
1648 # === Threads ===
1649
1650 # Determination of thread implementation
1651 if host_system == 'windows' and not get_option('force_posix_threads')
1652   thread_dep = []
1653   threads_implementation = 'win32'
1654   glibconfig_conf.set('g_threads_impl_def', 'WIN32')
1655   glib_conf.set('THREADS_WIN32', 1)
1656 else
1657   thread_dep = dependency('threads')
1658   threads_implementation = 'posix'
1659   pthread_prefix = '''
1660       #ifndef _GNU_SOURCE
1661       # define _GNU_SOURCE
1662       #endif
1663       #include <pthread.h>'''
1664   glibconfig_conf.set('g_threads_impl_def', 'POSIX')
1665   glib_conf.set('THREADS_POSIX', 1)
1666   if cc.has_header_symbol('pthread.h', 'pthread_attr_setstacksize')
1667     glib_conf.set('HAVE_PTHREAD_ATTR_SETSTACKSIZE', 1)
1668   endif
1669   if cc.has_header_symbol('pthread.h', 'pthread_condattr_setclock')
1670     glib_conf.set('HAVE_PTHREAD_CONDATTR_SETCLOCK', 1)
1671   endif
1672   if cc.has_header_symbol('pthread.h', 'pthread_cond_timedwait_relative_np')
1673     glib_conf.set('HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP', 1)
1674   endif
1675   if cc.has_header_symbol('pthread.h', 'pthread_getname_np', prefix : pthread_prefix)
1676     glib_conf.set('HAVE_PTHREAD_GETNAME_NP', 1)
1677   endif
1678   # Assume that pthread_setname_np is available in some form; same as configure
1679   if cc.links(pthread_prefix + '''
1680               int main() {
1681                 pthread_setname_np("example");
1682                 return 0;
1683               }''',
1684               name : 'pthread_setname_np(const char*)',
1685               dependencies : thread_dep)
1686     # macOS and iOS
1687     glib_conf.set('HAVE_PTHREAD_SETNAME_NP_WITHOUT_TID', 1)
1688   elif cc.links(pthread_prefix + '''
1689                 int main() {
1690                   pthread_setname_np(pthread_self(), "example");
1691                   return 0;
1692                 }''',
1693                 name : 'pthread_setname_np(pthread_t, const char*)',
1694                 dependencies : thread_dep)
1695     # Linux, Solaris, etc.
1696     glib_conf.set('HAVE_PTHREAD_SETNAME_NP_WITH_TID', 1)
1697   elif cc.links(pthread_prefix + '''
1698                 int main() {
1699                   pthread_setname_np(pthread_self(), "%s", "example");
1700                   return 0;
1701                 }''',
1702                 name : 'pthread_setname_np(pthread_t, const char*, void*)',
1703                 dependencies : thread_dep)
1704     # NetBSD
1705     glib_conf.set('HAVE_PTHREAD_SETNAME_NP_WITH_TID_AND_ARG', 1)
1706   elif cc.links(pthread_prefix + '''
1707                 #include <pthread_np.h>
1708                 int main() {
1709                   pthread_set_name_np(pthread_self(), "example");
1710                   return 0;
1711                 }''',
1712                 name : 'pthread_set_name_np(pthread_t, const char*)',
1713                 dependencies : thread_dep)
1714     # FreeBSD, DragonFlyBSD, OpenBSD, etc.
1715     glib_conf.set('HAVE_PTHREAD_SET_NAME_NP', 1)
1716   endif
1717 endif
1718
1719 # FIXME: we should make it print the result and always return 0, so that
1720 # the output in meson shows up as green
1721 stack_grows_check_prog = '''
1722   volatile int *a = 0, *b = 0;
1723   void f (int i) {
1724     volatile int x = 5;
1725     if (i == 0)
1726       b = &x;
1727     else
1728       f (i - 1);
1729   }
1730   int main () {
1731     volatile int y = 7;
1732     a = &y;
1733     f (100);
1734     return b > a ? 0 : 1;
1735   }'''
1736
1737 if cc_can_run
1738   rres = cc.run(stack_grows_check_prog, name : 'stack grows check')
1739   growing_stack = rres.returncode() == 0
1740 else
1741   growing_stack = meson.get_cross_property('growing_stack', false)
1742 endif
1743
1744 glibconfig_conf.set10('G_HAVE_GROWING_STACK', growing_stack)
1745
1746 # Tests for iconv
1747 #
1748 # We should never use the MinGW C library's iconv because it may not be
1749 # available in the actual runtime environment. On Windows, we always use
1750 # the built-in implementation
1751 iconv_opt = get_option('iconv')
1752 if host_system == 'windows'
1753   libiconv = []
1754   # We have a #include "win_iconv.c" in gconvert.c on Windows, so we don't need
1755   # any external library for it
1756   if iconv_opt != 'auto'
1757     warning('-Diconv was set to @0@, which was ignored')
1758   endif
1759 else
1760   found_iconv = false
1761   if ['auto', 'libc'].contains(iconv_opt) and cc.has_function('iconv_open')
1762     libiconv = []
1763     found_iconv = true
1764   endif
1765   if not found_iconv and ['auto', 'external'].contains(iconv_opt) and cc.has_header_symbol('iconv.h', 'iconv_open')
1766     libiconv = [cc.find_library('iconv')]
1767     found_iconv = true
1768   endif
1769
1770   if not found_iconv
1771     error('iconv implementation "@0@" not found'.format(iconv_opt))
1772   endif
1773 endif
1774
1775 if get_option('internal_pcre')
1776   pcre = []
1777   use_system_pcre = false
1778 else
1779   pcre = dependency('libpcre', version: '>= 8.31', required : false) # Should check for Unicode support, too. FIXME
1780   if not pcre.found()
1781     if cc.get_id() == 'msvc' or cc.get_id() == 'clang-cl'
1782     # MSVC: Search for the PCRE library by the configuration, which corresponds
1783     # to the output of CMake builds of PCRE.  Note that debugoptimized
1784     # is really a Release build with .PDB files.
1785       if buildtype == 'debug'
1786         pcre = cc.find_library('pcred', required : false)
1787       else
1788         pcre = cc.find_library('pcre', required : false)
1789       endif
1790     endif
1791   endif
1792   use_system_pcre = pcre.found()
1793 endif
1794 glib_conf.set('USE_SYSTEM_PCRE', use_system_pcre)
1795
1796 use_pcre_static_flag = false
1797
1798 if host_system == 'windows'
1799   if not use_system_pcre
1800     use_pcre_static_flag = true
1801   else
1802     pcre_static = cc.links('''#define PCRE_STATIC
1803                               #include <pcre.h>
1804                               int main() {
1805                                 void *p = NULL;
1806                                 pcre_free(p);
1807                                 return 0;
1808                               }''',
1809                            dependencies: pcre,
1810                            name : 'Windows system PCRE is a static build')
1811     if pcre_static
1812       use_pcre_static_flag = true
1813     endif
1814   endif
1815 endif
1816
1817 libm = cc.find_library('m', required : false)
1818 libffi_dep = dependency('libffi', version : '>= 3.0.0', fallback : ['libffi', 'ffi_dep'])
1819
1820 # Don't use the bundled ZLib sources until we are sure that we can't find it on
1821 # the system
1822 libz_dep = dependency('zlib', required : false)
1823 if not libz_dep.found()
1824   if cc.get_id() != 'msvc' and cc.get_id() != 'clang-cl'
1825     libz_dep = cc.find_library('z', required : false)
1826   else
1827     libz_dep = cc.find_library('zlib1', required : false)
1828     if not libz_dep.found()
1829       libz_dep = cc.find_library('zlib', required : false)
1830     endif
1831   endif
1832   if not libz_dep.found() or not cc.has_header('zlib.h')
1833     libz_dep = subproject('zlib').get_variable('zlib_dep')
1834   endif
1835 endif
1836
1837 # First check in libc, fallback to libintl, and as last chance build
1838 # proxy-libintl subproject.
1839 # FIXME: glib-gettext.m4 has much more checks to detect broken/uncompatible
1840 # implementations. This could be extended if issues are found in some platforms.
1841 if cc.has_function('ngettext')
1842   libintl = []
1843   have_bind_textdomain_codeset = cc.has_function('bind_textdomain_codeset')
1844 else
1845   libintl = cc.find_library('intl', required : false)
1846   if not libintl.found()
1847     libintl = subproject('proxy-libintl').get_variable('intl_dep')
1848     have_bind_textdomain_codeset = true  # proxy-libintl supports it
1849   else
1850     have_bind_textdomain_codeset = cc.has_function('bind_textdomain_codeset',
1851                                                    dependencies : libintl)
1852   endif
1853 endif
1854
1855 glib_conf.set('HAVE_BIND_TEXTDOMAIN_CODESET', have_bind_textdomain_codeset)
1856
1857 # We require gettext to always be present
1858 glib_conf.set('HAVE_DCGETTEXT', 1)
1859 glib_conf.set('HAVE_GETTEXT', 1)
1860
1861 glib_conf.set_quoted('GLIB_LOCALE_DIR', join_paths(glib_datadir, 'locale'))
1862
1863 # libmount is only used by gio, but we need to fetch the libs to generate the
1864 # pkg-config file below
1865 libmount_dep = []
1866 if host_system == 'linux' and get_option('libmount')
1867   libmount_dep = [dependency('mount', version : '>=2.23', required : true)]
1868   glib_conf.set('HAVE_LIBMOUNT', 1)
1869 endif
1870
1871 if host_system == 'windows'
1872   winsock2 = cc.find_library('ws2_32')
1873 endif
1874
1875 selinux_dep = []
1876 if host_system == 'linux'
1877   selinux_dep = dependency('libselinux', required: get_option('selinux'))
1878
1879   glib_conf.set('HAVE_SELINUX', selinux_dep.found())
1880 endif
1881
1882 xattr_dep = []
1883 if host_system != 'windows' and get_option('xattr')
1884   # either glibc or libattr can provide xattr support
1885   # for both of them, we check for getxattr being in
1886   # the library and a valid xattr header.
1887
1888   # try glibc
1889   if cc.has_function('getxattr') and cc.has_header('sys/xattr.h')
1890     glib_conf.set('HAVE_SYS_XATTR_H', 1)
1891     glib_conf_prefix = glib_conf_prefix + '#define @0@ 1\n'.format('HAVE_SYS_XATTR_H')
1892   #failure. try libattr
1893   elif cc.has_header_symbol('attr/xattr.h', 'getxattr')
1894     glib_conf.set('HAVE_ATTR_XATTR_H', 1)
1895     glib_conf_prefix = glib_conf_prefix + '#define @0@ 1\n'.format('HAVE_ATTR_XATTR_H')
1896     xattr_dep = [cc.find_library('xattr')]
1897   else
1898     error('No getxattr implementation found in C library or libxattr')
1899   endif
1900
1901   glib_conf.set('HAVE_XATTR', 1)
1902   if cc.compiles(glib_conf_prefix + '''
1903                  #include <stdio.h>
1904                  #ifdef HAVE_SYS_TYPES_H
1905                  #include <sys/types.h>
1906                  #endif
1907                  #ifdef HAVE_SYS_XATTR_H
1908                  #include <sys/xattr.h>
1909                  #elif HAVE_ATTR_XATTR_H
1910                  #include <attr/xattr.h>
1911                  #endif
1912
1913                  int main (void) {
1914                    ssize_t len = getxattr("", "", NULL, 0, 0, XATTR_NOFOLLOW);
1915                    return len;
1916                  }''',
1917                  name : 'XATTR_NOFOLLOW')
1918     glib_conf.set('HAVE_XATTR_NOFOLLOW', 1)
1919   endif
1920 endif
1921
1922 # If strlcpy is present (BSD and similar), check that it conforms to the BSD
1923 # specification. Specifically Solaris 8's strlcpy() does not, see
1924 # https://bugzilla.gnome.org/show_bug.cgi?id=53933 for further context.
1925 if cc.has_function('strlcpy')
1926   if cc_can_run
1927     rres = cc.run('''#include <stdlib.h>
1928                     #include <string.h>
1929                     int main() {
1930                       char p[10];
1931                       (void) strlcpy (p, "hi", 10);
1932                       if (strlcat (p, "bye", 0) != 3)
1933                         return 1;
1934                       return 0;
1935                     }''',
1936                   name : 'OpenBSD strlcpy/strlcat')
1937     if rres.compiled() and rres.returncode() == 0
1938       glib_conf.set('HAVE_STRLCPY', 1)
1939     endif
1940   elif meson.get_cross_property('have_strlcpy', false)
1941     glib_conf.set('HAVE_STRLCPY', 1)
1942   endif
1943 endif
1944
1945 cmdline_test_code = '''
1946 #include <fcntl.h>
1947 #include <sys/stat.h>
1948 #include <stdio.h>
1949 #include <stdlib.h>
1950 #undef NDEBUG
1951 #include <assert.h>
1952
1953 static int
1954 __getcmdline (void)
1955 {
1956 /* This code is a dumbed-down version of g_file_get_contents() */
1957 #ifndef O_BINARY
1958 #define O_BINARY 0
1959 #endif
1960 #define BUFSIZE 1024
1961   char result[BUFSIZE];
1962   struct stat stat_buf;
1963
1964   int fd = open ("/proc/self/cmdline", O_RDONLY|O_BINARY);
1965   assert (fd >= 0);
1966   assert (fstat (fd, &stat_buf) == 0);
1967
1968   if (stat_buf.st_size > 0 && S_ISREG (stat_buf.st_mode))
1969     assert (read (fd, result, BUFSIZE) > 0);
1970   else
1971     {
1972       FILE *f = fdopen (fd, "r");
1973       assert (f != NULL);
1974       assert (fread (result, 1, BUFSIZE, f) > 0);
1975     }
1976
1977   return 0;
1978 }
1979
1980 int
1981 main (void)
1982 {
1983   exit (__getcmdline ());
1984 }'''
1985
1986 if cc_can_run
1987   rres = cc.run(cmdline_test_code, name : '/proc/self/cmdline')
1988   have_proc_self_cmdline = rres.compiled() and rres.returncode() == 0
1989 else
1990   have_proc_self_cmdline = meson.get_cross_property('have_proc_self_cmdline', false)
1991 endif
1992
1993 glib_conf.set('HAVE_PROC_SELF_CMDLINE', have_proc_self_cmdline)
1994
1995 python = import('python').find_installation('python3')
1996 # used for '#!/usr/bin/env <name>'
1997 python_name = 'python3'
1998
1999 python_version = python.language_version()
2000 python_version_req = '>=3.4'
2001 if not python_version.version_compare(python_version_req)
2002   error('Requires Python @0@, @1@ found.'.format(python_version_req, python_version))
2003 endif
2004
2005 # Determine which user environment-dependent files that we want to install
2006 have_bash = find_program('bash', required : false).found() # For completion scripts
2007 have_sh = find_program('sh', required : false).found() # For glib-gettextize
2008
2009 # Some installed tests require a custom environment
2010 env_program = find_program('env', required: installed_tests_enabled)
2011
2012 # FIXME: How to detect Solaris? https://github.com/mesonbuild/meson/issues/1578
2013 if host_system == 'sunos'
2014   glib_conf.set('_XOPEN_SOURCE_EXTENDED', 1)
2015   glib_conf.set('_XOPEN_SOURCE', 2)
2016   glib_conf.set('__EXTENSIONS__',1)
2017 endif
2018
2019 # Sadly Meson does not expose this value:
2020 # https://github.com/mesonbuild/meson/pull/3460
2021 if host_system == 'windows'
2022   # Autotools explicitly removed --Wl,--export-all-symbols from windows builds,
2023   # with no explanation. Do the same here for now but this could be revisited if
2024   # if causes issues.
2025   export_dynamic_ldflags = []
2026 elif host_system == 'cygwin'
2027   export_dynamic_ldflags = ['-Wl,--export-all-symbols']
2028 elif host_system == 'darwin'
2029   export_dynamic_ldflags = []
2030 elif host_system == 'sunos'
2031   export_dynamic_ldflags = []
2032 else
2033   export_dynamic_ldflags = ['-Wl,--export-dynamic']
2034 endif
2035
2036 win32_cflags = []
2037 win32_ldflags = []
2038 if host_system == 'windows' and cc.get_id() != 'msvc' and cc.get_id() != 'clang-cl'
2039   # Ensure MSVC-compatible struct packing convention is used when
2040   # compiling for Win32 with gcc. It is used for the whole project and exposed
2041   # in glib-2.0.pc.
2042   win32_cflags = ['-mms-bitfields']
2043   add_project_arguments(win32_cflags, language : 'c')
2044
2045   # Win32 API libs, used only by libglib and exposed in glib-2.0.pc
2046   win32_ldflags = ['-lws2_32', '-lole32', '-lwinmm', '-lshlwapi']
2047 elif host_system == 'cygwin'
2048   win32_ldflags = ['-luser32', '-lkernel32']
2049 endif
2050
2051 # Tracing: dtrace
2052 want_dtrace = get_option('dtrace')
2053 enable_dtrace = false
2054
2055 # Since dtrace support is opt-in we just error out if it was requested but
2056 # is not available. We don't bother with autodetection yet.
2057 if want_dtrace
2058   if glib_have_carbon
2059     error('GLib dtrace support not yet compatible with macOS dtrace')
2060   endif
2061   dtrace = find_program('dtrace', required : true) # error out if not found
2062   if not cc.has_header('sys/sdt.h')
2063     error('dtrace support needs sys/sdt.h header')
2064   endif
2065   # FIXME: autotools build also passes -fPIC -DPIC but is it needed in this case?
2066   dtrace_obj_gen = generator(dtrace,
2067     output : '@BASENAME@.o',
2068     arguments : ['-G', '-s', '@INPUT@', '-o', '@OUTPUT@'])
2069   # FIXME: $(SED) -e "s,define STAP_HAS_SEMAPHORES 1,undef STAP_HAS_SEMAPHORES,"
2070   #               -e "s,define _SDT_HAS_SEMAPHORES 1,undef _SDT_HAS_SEMAPHORES,"
2071   dtrace_hdr_gen = generator(dtrace,
2072     output : '@BASENAME@.h',
2073     arguments : ['-h', '-s', '@INPUT@', '-o', '@OUTPUT@'])
2074   glib_conf.set('HAVE_DTRACE', 1)
2075   enable_dtrace = true
2076 endif
2077
2078 # systemtap
2079 want_systemtap = get_option('systemtap')
2080 enable_systemtap = false
2081
2082 if want_systemtap and enable_dtrace
2083   tapset_install_dir = get_option('tapset_install_dir')
2084   if tapset_install_dir == ''
2085     tapset_install_dir = join_paths(get_option('datadir'), 'systemtap/tapset', host_machine.cpu_family())
2086   endif
2087   stp_cdata = configuration_data()
2088   stp_cdata.set('ABS_GLIB_RUNTIME_LIBDIR', glib_libdir)
2089   stp_cdata.set('LT_CURRENT', minor_version * 100)
2090   stp_cdata.set('LT_REVISION', micro_version)
2091   enable_systemtap = true
2092 endif
2093
2094 test_timeout = 60
2095 test_timeout_slow = 180
2096
2097 pkg = import('pkgconfig')
2098 windows = import('windows')
2099 subdir('glib')
2100 subdir('gobject')
2101 subdir('gthread')
2102 subdir('gmodule')
2103 subdir('gio')
2104 subdir('fuzzing')
2105 if build_tests
2106   subdir('tests')
2107 endif
2108
2109 # xgettext is optional (on Windows for instance)
2110 if find_program('xgettext', required : get_option('nls')).found()
2111   subdir('po')
2112 endif
2113
2114 # Install glib-gettextize executable, if a UNIX-style shell is found
2115 if have_sh
2116   # These should not contain " quotes around the values
2117   gettextize_conf = configuration_data()
2118   gettextize_conf.set('PACKAGE', 'glib')
2119   gettextize_conf.set('VERSION', meson.project_version())
2120   gettextize_conf.set('prefix', glib_prefix)
2121   gettextize_conf.set('datarootdir', glib_datadir)
2122   gettextize_conf.set('datadir', glib_datadir)
2123   configure_file(input : 'glib-gettextize.in',
2124     install_dir : glib_bindir,
2125     output : 'glib-gettextize',
2126     configuration : gettextize_conf)
2127 endif
2128
2129 # Install m4 macros that other projects use
2130 install_data('m4macros/glib-2.0.m4', 'm4macros/glib-gettext.m4', 'm4macros/gsettings.m4',
2131   install_dir : join_paths(get_option('datadir'), 'aclocal'))
2132
2133 if host_system != 'windows'
2134   # Install Valgrind suppression file (except on Windows,
2135   # as Valgrind is currently not supported on Windows)
2136   install_data('glib.supp',
2137     install_dir : join_paths(get_option('datadir'), 'glib-2.0', 'valgrind'))
2138 endif
2139
2140 configure_file(output : 'config.h', configuration : glib_conf)
2141
2142 if host_system == 'windows'
2143   install_headers([ 'msvc_recommended_pragmas.h' ], subdir : 'glib-2.0')
2144 endif
2145
2146 if get_option('man')
2147   xsltproc = find_program('xsltproc', required : true)
2148   xsltproc_command = [
2149     xsltproc,
2150     '--nonet',
2151     '--stringparam', 'man.output.quietly', '1',
2152     '--stringparam', 'funcsynopsis.style', 'ansi',
2153     '--stringparam', 'man.th.extra1.suppress', '1',
2154     '--stringparam', 'man.authors.section.enabled', '0',
2155     '--stringparam', 'man.copyright.section.enabled', '0',
2156     '-o', '@OUTPUT@',
2157     'http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl',
2158     '@INPUT@',
2159   ]
2160   man1_dir = get_option('mandir') + '/man1'
2161 endif
2162
2163 gnome = import('gnome')
2164 subdir('docs/reference')