1project(
2  'libvirt-glib', 'c',
3  version: '4.0.0',
4  license: 'LGPLv2+',
5  meson_version: '>= 0.50.0',
6  default_options: [
7    'buildtype=debugoptimized',
8    'c_std=gnu99',
9  ],
10)
11
12python3 = find_program('python3', required: true)
13# Python3 < 3.7 treats the C locale as 7-bit only. We must force env vars so
14# it treats it as UTF-8 regardless of the user's locale.
15runutf8 = [ 'LC_ALL=', 'LANG=C', 'LC_CTYPE=en_US.UTF-8' ]
16
17cc = meson.get_compiler('c')
18git = run_command('test', '-d', '.git').returncode() == 0
19
20version_info = meson.project_version().split('.')
21version_major = version_info[0].to_int()
22version_minor = version_info[1].to_int()
23version_micro = version_info[2].to_int()
24
25libvirt_glib_interface_age = 0
26libvirt_glib_binary_age = 1000 * version_major + version_minor
27
28# Maintain version scheme with libtool
29libvirt_glib_soversion = 0
30libvirt_glib_version = '@0@.@1@.@2@'.format(
31    libvirt_glib_soversion,
32    (libvirt_glib_binary_age - libvirt_glib_interface_age),
33    libvirt_glib_interface_age)
34osx_current = libvirt_glib_binary_age - libvirt_glib_interface_age + 1
35libvirt_glib_darwin_versions = [
36  osx_current,
37  '@0@.@1@.0'.format(osx_current, libvirt_glib_interface_age)
38]
39
40# Keep these two definitions in agreement.
41glib_version = '2.48.0'
42glib_min_version_symbol='GLIB_VERSION_2_48'
43glib_dep = dependency('glib-2.0', version: '>=' + glib_version)
44gobject_dep = dependency('gobject-2.0', version: '>=' + glib_version)
45gio_dep = dependency('gio-2.0', version: '>=' + glib_version)
46
47libvirt_version = '1.2.8'
48libvirt_dep = dependency('libvirt', version: '>=' + libvirt_version)
49
50libxml_min_version='>=2.9.1'
51libxml_dep = dependency('libxml-2.0', version: libxml_min_version)
52
53add_global_arguments('-DGLIB_VERSION_MIN_REQUIRED=@0@'.format(glib_min_version_symbol), language: 'c')
54add_global_arguments('-DGLIB_VERSION_MAX_ALLOWED=@0@'.format(glib_min_version_symbol), language: 'c')
55
56prefix = get_option('prefix')
57localedir = join_paths(prefix, get_option('localedir'))
58datadir = join_paths(prefix, get_option('datadir'))
59libdir = join_paths(prefix, get_option('libdir'))
60includedir = join_paths(prefix, get_option('includedir'))
61
62# gobject introspection
63gir = find_program('g-ir-scanner', required: get_option('introspection'))
64enable_introspection = gir.found() and not meson.is_cross_build()
65
66# vala
67vapi_opt = get_option('vapi')
68enable_vapi = add_languages('vala', required: vapi_opt)
69if enable_vapi and not enable_introspection
70    enable_vapi = false
71    if vapi_opt.enabled()
72        error('vala support was requested, but introspection support is mandatory.')
73    endif
74endif
75
76# gtk-doc
77if not get_option('docs').disabled()
78  gtk_doc = find_program('gtkdoc-scan', required: get_option('docs'))
79  enable_doc = gtk_doc.found() and not meson.is_cross_build()
80else
81  enable_doc = false
82endif
83
84# Add RPATH information when building for a non-standard prefix, or
85# when explicitly requested to do so
86
87if prefix == '/usr' and not get_option('rpath').enabled()
88  rpathdir = ''
89else
90  rpathdir = libdir
91endif
92
93common_link_args = []
94if meson.get_compiler('c').has_link_argument('-Wl,--no-undefined')
95  common_link_args += ['-Wl,--no-undefined']
96endif
97
98
99build_tests = not get_option('tests').disabled()
100
101girdir = join_paths(datadir, 'gir-1.0')
102typelibdir = join_paths(libdir, 'girepository-1.0')
103pkgconfdir = join_paths(libdir, 'pkgconfig')
104
105conf_data = configuration_data()
106conf_data.set('VERSION', meson.project_version())
107conf_data.set('prefix', prefix)
108conf_data.set('includedir', includedir)
109conf_data.set('exec_prefix', prefix)
110conf_data.set('libdir', libdir)
111
112configure_file(
113  input: 'meson-config.h.in',
114  output: 'config.h',
115  configuration: conf_data
116)
117
118if git
119  configure_file(
120    input: 'libvirt-glib.spec.in',
121    output: 'libvirt-glib.spec',
122    configuration: conf_data
123  )
124
125  configure_file(
126    input: 'mingw-libvirt-glib.spec.in',
127    output: 'mingw-libvirt-glib.spec',
128    configuration: conf_data
129  )
130endif
131
132configure_file(
133  input: 'libvirt-glib-1.0.pc.in',
134  output: 'libvirt-glib-1.0.pc',
135  configuration: conf_data,
136  install: true,
137  install_dir: pkgconfdir
138)
139
140configure_file(
141  input: 'libvirt-gconfig-1.0.pc.in',
142  output: 'libvirt-gconfig-1.0.pc',
143  configuration: conf_data,
144  install: true,
145  install_dir: pkgconfdir
146)
147
148configure_file(
149  input: 'libvirt-gobject-1.0.pc.in',
150  output: 'libvirt-gobject-1.0.pc',
151  configuration: conf_data,
152  install: true,
153  install_dir: pkgconfdir
154)
155
156cc_flags = []
157
158git_werror = get_option('git_werror')
159if git_werror.enabled() or git_werror.auto() and git
160  cc_flags += [ '-Werror' ]
161endif
162
163cc_flags += [
164  '-fno-common',
165  '-W',
166  '-Wabsolute-value',
167  '-Waddress',
168  '-Waddress-of-packed-member',
169  '-Waggressive-loop-optimizations',
170  '-Wall',
171  '-Wattribute-warning',
172  '-Wattributes',
173  '-Wbool-compare',
174  '-Wbool-operation',
175  '-Wbuiltin-declaration-mismatch',
176  '-Wbuiltin-macro-redefined',
177  '-Wcannot-profile',
178  '-Wcast-align',
179  '-Wcast-align=strict',
180  '-Wcast-function-type',
181  '-Wchar-subscripts',
182  '-Wclobbered',
183  '-Wcomment',
184  '-Wcomments',
185  '-Wcoverage-mismatch',
186  '-Wcpp',
187  '-Wdangling-else',
188  '-Wdate-time',
189  '-Wdeprecated-declarations',
190  '-Wdesignated-init',
191  '-Wdiscarded-array-qualifiers',
192  '-Wdiscarded-qualifiers',
193  '-Wdiv-by-zero',
194  '-Wduplicated-cond',
195  '-Wduplicate-decl-specifier',
196  '-Wempty-body',
197  '-Wendif-labels',
198  '-Wexpansion-to-defined',
199  '-Wextra',
200  '-Wformat-contains-nul',
201  '-Wformat-extra-args',
202  '-Wformat-nonliteral',
203  '-Wformat-security',
204  '-Wformat-y2k',
205  '-Wformat-zero-length',
206  '-Wframe-address',
207  '-Wfree-nonheap-object',
208  '-Whsa',
209  '-Wif-not-aligned',
210  '-Wignored-attributes',
211  '-Wignored-qualifiers',
212  '-Wimplicit',
213  '-Wimplicit-function-declaration',
214  '-Wimplicit-int',
215  '-Wincompatible-pointer-types',
216  '-Winit-self',
217  '-Winline',
218  '-Wint-conversion',
219  '-Wint-in-bool-context',
220  '-Wint-to-pointer-cast',
221  '-Winvalid-memory-model',
222  '-Winvalid-pch',
223  '-Wlogical-not-parentheses',
224  '-Wlogical-op',
225  '-Wmain',
226  '-Wmaybe-uninitialized',
227  '-Wmemset-elt-size',
228  '-Wmemset-transposed-args',
229  '-Wmisleading-indentation',
230  '-Wmissing-attributes',
231  '-Wmissing-braces',
232  '-Wmissing-declarations',
233  '-Wmissing-field-initializers',
234  '-Wmissing-include-dirs',
235  '-Wmissing-parameter-type',
236  '-Wmissing-profile',
237  '-Wmissing-prototypes',
238  '-Wmultichar',
239  '-Wmultistatement-macros',
240  '-Wnarrowing',
241  '-Wnested-externs',
242  '-Wnonnull',
243  '-Wnonnull-compare',
244  '-Wnull-dereference',
245  '-Wodr',
246  '-Wold-style-declaration',
247  '-Wold-style-definition',
248  '-Wopenmp-simd',
249  '-Woverflow',
250  '-Woverride-init',
251  '-Wpacked-bitfield-compat',
252  '-Wpacked-not-aligned',
253  '-Wparentheses',
254  '-Wpointer-arith',
255  '-Wpointer-compare',
256  '-Wpointer-sign',
257  '-Wpointer-to-int-cast',
258  '-Wpragmas',
259  '-Wpsabi',
260  '-Wrestrict',
261  '-Wreturn-local-addr',
262  '-Wreturn-type',
263  '-Wscalar-storage-order',
264  '-Wsequence-point',
265  '-Wshadow',
266  '-Wshift-count-negative',
267  '-Wshift-count-overflow',
268  '-Wshift-negative-value',
269  '-Wsizeof-array-argument',
270  '-Wsizeof-pointer-div',
271  '-Wsizeof-pointer-memaccess',
272  '-Wstrict-aliasing',
273  '-Wstrict-prototypes',
274  '-Wstringop-truncation',
275  '-Wsuggest-attribute=cold',
276  '-Wsuggest-attribute=const',
277  '-Wsuggest-attribute=format',
278  '-Wsuggest-attribute=noreturn',
279  '-Wsuggest-attribute=pure',
280  '-Wsuggest-final-methods',
281  '-Wsuggest-final-types',
282  '-Wswitch',
283  '-Wswitch-bool',
284  '-Wswitch-unreachable',
285  '-Wsync-nand',
286  '-Wtautological-compare',
287  '-Wtrampolines',
288  '-Wtrigraphs',
289  '-Wtype-limits',
290  '-Wuninitialized',
291  '-Wunknown-pragmas',
292  '-Wunused',
293  '-Wunused-but-set-parameter',
294  '-Wunused-but-set-variable',
295  '-Wunused-function',
296  '-Wunused-label',
297  '-Wunused-local-typedefs',
298  '-Wunused-result',
299  '-Wunused-value',
300  '-Wunused-variable',
301  '-Wvarargs',
302  '-Wvariadic-macros',
303  '-Wvector-operation-performance',
304  '-Wvla',
305  '-Wvolatile-register-var',
306  '-Wwrite-strings',
307]
308
309# gcc --help=warnings outputs
310ptrdiff_max = cc.sizeof('ptrdiff_t', prefix: '#include <stddef.h>')
311size_max = cc.sizeof('size_t', prefix: '#include <stdint.h>')
312# Compute max safe object size by checking ptrdiff_t and size_t sizes.
313# Ideally we would get PTRDIFF_MAX and SIZE_MAX values but it would
314# give us (2147483647L) and we would have to remove the () and the suffix
315# in order to convert it to numbers to be able to pick the smaller one.
316alloc_max = run_command(
317  python3.path(), '-c',
318  'print(min(2**(@0@ * 8 - 1) - 1, 2**(@1@ * 8) - 1))'.format(ptrdiff_max, size_max),
319)
320cc_flags += [
321  '-Walloc-size-larger-than=@0@'.format(alloc_max.stdout().strip()),
322  '-Warray-bounds=2',
323  '-Wattribute-alias=2',
324  '-Wformat-overflow=2',
325  '-Wformat-truncation=2',
326  '-Wimplicit-fallthrough=5',
327  '-Wnormalized=nfc',
328  '-Wshift-overflow=2',
329  '-Wstringop-overflow=2',
330  '-Wunused-const-variable=2',
331  '-Wvla-larger-then=4031',
332]
333
334cc_flags += [
335  # So we have -W enabled, and then have to explicitly turn off...
336  '-Wno-sign-compare',
337
338  # We do "bad" function casts all the time for event callbacks
339  '-Wno-cast-function-type',
340
341  # Clang incorrectly complains about dup typedefs win gnu99 mode
342  # so use this Clang-specific arg to keep it quiet
343  '-Wno-typedef-redefinition',
344
345  # We don't use -Wc++-compat so we have to enable it explicitly
346  '-Wjump-misses-init',
347
348  # -Wswitch is enabled but that doesn't report missing enums if a default:
349  # is present
350  '-Wswitch-enum',
351
352  # -Wformat=2 implies -Wformat-nonliteral so we need to manually exclude it
353  '-Wno-format-nonliteral',
354
355  # -Wformat enables this by default, and we should keep it,
356  # but need to rewrite various areas of code first
357  '-Wno-format-truncation',
358
359  # This should be < 256 really. Currently we're down to 4096,
360  # but using 1024 bytes sized buffers (mostly for virStrerror)
361  # stops us from going down further
362  '-Wframe-larger-than=4096',
363
364  # extra special flags
365  '-fexceptions',
366  '-fasynchronous-unwind-tables',
367
368  # Need -fipa-pure-const in order to make -Wsuggest-attribute=pure
369  # fire even without -O.
370  '-fipa-pure-const',
371
372  # We should eventually enable this, but right now there are at
373  # least 75 functions triggering warnings.
374  '-Wno-suggest-attribute=pure',
375  '-Wno-suggest-attribute=const',
376
377  # gtk-doc-scangobj causes failures. We should do a
378  # more targetted workaround for this really.
379  '-Wno-unused-parameter',
380]
381
382# on aarch64 error: -fstack-protector not supported for this target
383if host_machine.cpu_family() != 'aarch64'
384  if host_machine.system() in [ 'linux', 'freebsd', 'windows' ]
385    # we prefer -fstack-protector-strong but fallback to -fstack-protector-all
386    fstack_cflags = cc.first_supported_argument([
387      '-fstack-protector-strong',
388      '-fstack-protector-all',
389    ])
390    cc_flags += fstack_cflags
391
392    # When building with mingw using -fstack-protector requires libssp library
393    # which is included by using -fstack-protector with linker.
394    if fstack_cflags.length() == 1 and host_machine.system() == 'windows'
395      add_project_link_arguments(fstack_cflags, language: 'c')
396    endif
397  endif
398endif
399
400# Clang complains about unused static inline functions which are common
401# with G_DEFINE_AUTOPTR_CLEANUP_FUNC.
402w_unused_function_args = ['-Wunused-function', '-Werror']
403w_unused_function_code = '''
404  static inline void foo(void) {}
405
406  int main(void) { return 0; }
407'''
408# -Wunused-function is implied by -Wall, we must turn it off explicitly.
409if not cc.compiles(w_unused_function_code, args: w_unused_function_args)
410  cc_flags += ['-Wno-unused-function']
411endif
412
413cc_flags_disabled = [
414  # In meson this is specified using 'c_std=gnu99' in project() function.
415  '-std=gnu99',
416
417  # don't care about C++ compiler compat
418  '-Wc++-compat',
419  '-Wabi',
420  '-Wdeprecated',
421
422  # Don't care about ancient C standard compat
423  '-Wtraditional',
424  '-Wtraditional-conversion',
425
426  # Ignore warnings in /usr/include
427  '-Wsystem-headers',
428
429  # Happy for compiler to add struct padding
430  '-Wpadded',
431
432  # GCC very confused with -O2
433  '-Wunreachable-code',
434
435  # Too many to deal with
436  '-Wconversion',
437  '-Wsign-conversion',
438
439  # Need to allow bad cast for execve()
440  '-Wcast-qual',
441
442  # We need to use long long in many places
443  '-Wlong-long',
444
445  # We allow manual list of all enum cases without default
446  '-Wswitch-default',
447
448  # Not a problem since we don't use -fstrict-overflow
449  '-Wstrict-overflow',
450
451  # Not a problem since we don't use -funsafe-loop-optimizations
452  '-Wunsafe-loop-optimizations',
453
454  # gcc 4.4.6 complains this is C++ only; gcc 4.7.0 implies this from -Wall
455  '-Wenum-compare',
456
457  # gcc 5.1 -Wformat-signedness mishandles enums, not ready for prime time
458  '-Wformat-signedness',
459
460  # Several conditionals expand the same on both branches depending on the
461  # particular platform/architecture
462  '-Wduplicated-branches',
463
464  # > This warning does not generally indicate that there is anything wrong
465  # > with your code; it merely indicates that GCC's optimizers are unable
466  # > to handle the code effectively.
467  # Source: https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
468  '-Wdisabled-optimization',
469
470  # Various valid glib APIs/macros trigger this warning
471  '-Wbad-function-cast',
472
473  # We might fundamentally need some of these disabled forever, but
474  # ideally we'd turn many of them on
475  '-Wfloat-equal',
476  '-Wpacked',
477  '-Wunused-macros',
478  '-Woverlength-strings',
479  '-Wstack-protector',
480  '-Wsuggest-attribute=malloc',
481
482  # g_return_val_if_fail usage violates this often
483  '-Wdeclaration-after-statement',
484
485  # older gtk-doc fails - re-enable this in future
486  '-Wdouble-promotion',
487]
488
489foreach flag : cc_flags_disabled
490  if cc_flags.contains(flag)
491    error('@0@ is disabled but listed in cc_flags'.format(flag))
492  endif
493endforeach
494
495supported_cc_flags = cc.get_supported_arguments(cc_flags)
496add_project_arguments(supported_cc_flags, language: 'c')
497
498if git
499  authors_helper = join_paths(meson.source_root(), 'build-aux', 'gen-authors.py')
500  authors = run_command(python3.path(), authors_helper, env: runutf8)
501  authors_file = 'AUTHORS.in'
502
503  authors_conf = configuration_data()
504  authors_conf.set('authorslist', authors.stdout())
505
506  configure_file(
507    input: authors_file,
508    output: '@BASENAME@',
509    configuration: authors_conf,
510  )
511
512  dist_helper = join_paths(meson.source_root(), 'build-aux', 'dist.py')
513  meson.add_dist_script(python3.path(), dist_helper, meson.build_root(), 'AUTHORS')
514  meson.add_dist_script(python3.path(), dist_helper, meson.build_root(), 'libvirt-glib.spec')
515endif
516
517common_cflags = [
518  '-DLOCALEDIR="@0@"'.format(localedir),
519  '-DDATADIR="@0@"'.format(datadir),
520  '-DLIBVIRT_GLIB_BUILD',
521]
522
523gnome = import('gnome')
524i18n = import('i18n')
525
526top_include_dir = [include_directories('.')]
527
528check_symfile = join_paths(meson.source_root(), 'build-aux', 'check-symfile.py')
529check_symsorting = join_paths(meson.source_root(), 'build-aux', 'check-symsorting.py')
530
531
532subdir('libvirt-glib')
533subdir('libvirt-gconfig')
534subdir('libvirt-gobject')
535subdir('po')
536subdir('examples')
537subdir('docs')
538if build_tests
539  subdir('tests')
540endif
541subdir('build-aux')
542