NEWS: Fix misindented bullet point
[libvirt.git] / meson.build
blobe98ab0d5acd423335616f23963e14099e79c5c12
1 project(
2   'libvirt', 'c',
3   version: '10.4.0',
4   license: 'LGPLv2+',
5   meson_version: '>= 0.56.0',
6   default_options: [
7     'buildtype=debugoptimized',
8     'b_pie=true',
9     'c_std=gnu99',
10     'warning_level=2',
11   ],
14 if meson.version().version_compare('>=0.64.0')
15   fs = import('fs')
16 endif
18 # figure out if we are building from git
20 git = run_command('test', '-d', '.git', check: false).returncode() == 0
22 if git and not get_option('no_git')
23   run_command('git', 'submodule', 'update', '--init', check: true)
24 endif
27 # detect operating system
29 os_release = run_command('grep', '-E', '^ID(_LIKE)*=', '/etc/os-release', check: false).stdout()
32 # prepare build configuration data
34 conf = configuration_data()
36 conf.set('_GNU_SOURCE', 1)
37 conf.set_quoted('abs_top_builddir', meson.project_build_root())
38 conf.set_quoted('abs_top_srcdir', meson.project_source_root())
39 conf.set_quoted('PACKAGE', meson.project_name())
40 conf.set_quoted('PACKAGE_NAME', meson.project_name())
41 conf.set_quoted('PACKAGE_VERSION', meson.project_version())
42 conf.set_quoted('VERSION', meson.project_version())
44 if host_machine.system() == 'windows'
45   # For AI_ADDRCONFIG
46   conf.set('_WIN32_WINNT', '0x0600') # Win Vista / Server 2008
47   conf.set('WINVER', '0x0600') # Win Vista / Server 2008
48 endif
51 # set various paths
53 if get_option('system')
54   prefix = '/usr'
55   libdir = prefix / 'lib64'
56   if run_command('test', '-d', libdir, check: false).returncode() != 0
57     libdir = prefix / 'lib'
58   endif
59   localstatedir = '/var'
60   sysconfdir = '/etc'
61 else
62   prefix = get_option('prefix')
63   libdir = prefix / get_option('libdir')
64   localstatedir = prefix / get_option('localstatedir')
65   sysconfdir = prefix / get_option('sysconfdir')
66 endif
68 # if --prefix is /usr, don't use /usr/var for localstatedir or /usr/etc for
69 # sysconfdir as this makes a lot of things break in testing situations
70 if prefix == '/usr'
71   if localstatedir == '/usr/var'
72     localstatedir = '/var'
73   endif
74   if sysconfdir == '/usr/etc'
75     sysconfdir = '/etc'
76   endif
77 endif
79 runstatedir = get_option('runstatedir')
80 if runstatedir == ''
81   runstatedir = localstatedir / 'run'
82 endif
84 initconfdir = get_option('initconfdir')
85 if initconfdir == ''
86   if (os_release.contains('alpine') or
87       os_release.contains('arch') or
88       os_release.contains('gentoo'))
89     initconfdir = sysconfdir / 'conf.d'
90   # Ubuntu has ID_LIKE=debian
91   elif os_release.contains('debian')
92     initconfdir = sysconfdir / 'default'
93   else
94     initconfdir = sysconfdir / 'sysconfig'
95   endif
96 endif
98 bindir = prefix / get_option('bindir')
99 datadir = prefix / get_option('datadir')
100 includedir = prefix / get_option('includedir')
101 infodir = prefix / get_option('infodir')
102 libexecdir = prefix / get_option('libexecdir')
103 localedir = prefix / get_option('localedir')
104 mandir = prefix / get_option('mandir')
105 sbindir = prefix / get_option('sbindir')
106 sharedstatedir = prefix / get_option('sharedstatedir')
108 docdir = get_option('docdir')
109 if docdir == ''
110   docdir = datadir / 'doc' / meson.project_name()
111 endif
113 confdir = sysconfdir / meson.project_name()
114 pkgdatadir = datadir / meson.project_name()
116 sshconfdir = get_option('sshconfdir')
117 if sshconfdir == ''
118   sshconfdir = sysconfdir / 'ssh' / 'ssh_config.d'
119 endif
122 # generate configmake.h header
124 configmake_conf = configuration_data()
125 configmake_conf.set_quoted('BINDIR', bindir)
126 configmake_conf.set_quoted('DATADIR', datadir)
127 configmake_conf.set_quoted('LIBDIR', libdir)
128 configmake_conf.set_quoted('LIBEXECDIR', libexecdir)
129 configmake_conf.set_quoted('LOCALEDIR', localedir)
130 configmake_conf.set_quoted('LOCALSTATEDIR', localstatedir)
131 configmake_conf.set_quoted('MANDIR', mandir)
132 configmake_conf.set_quoted('PKGDATADIR', pkgdatadir)
133 configmake_conf.set_quoted('PREFIX', prefix)
134 configmake_conf.set_quoted('RUNSTATEDIR', runstatedir)
135 configmake_conf.set_quoted('SBINDIR', sbindir)
136 configmake_conf.set_quoted('SYSCONFDIR', sysconfdir)
138 configure_file(
139   input: 'configmake.h.in',
140   output: '@BASENAME@',
141   configuration: configmake_conf,
145 # packager options
147 packager = get_option('packager')
148 packager_version = get_option('packager_version')
150 if packager != ''
151   conf.set_quoted('PACKAGER', packager)
152 endif
154 if packager_version != ''
155   conf.set_quoted('PACKAGER_VERSION', packager_version)
156 endif
159 # Add RPATH information when building for a non-standard prefix, or
160 # when explicitly requested to do so
162 if prefix == '/usr' and not get_option('rpath').enabled()
163   libvirt_rpath = ''
164 else
165   libvirt_rpath = libdir
166 endif
169 # figure out libvirt version strings
171 arr_version = meson.project_version().split('.')
172 libvirt_version_number = 1000000 * arr_version[0].to_int() + 1000 * arr_version[1].to_int() + arr_version[2].to_int()
174 conf.set('LIBVIRT_VERSION_NUMBER', libvirt_version_number)
176 # In libtool terminology we need to figure out:
178 # CURRENT
179 #     The most recent interface number that this library implements.
181 # REVISION
182 #     The implementation number of the CURRENT interface.
184 # AGE
185 #     The difference between the newest and oldest interfaces that this
186 #     library implements.
188 # In other words, the library implements all the interface numbers
189 # in the range from number `CURRENT - AGE' to `CURRENT'.
191 # Libtool assigns the soname version from `CURRENT - AGE', and we
192 # don't want that to ever change in libvirt. ie it must always be
193 # zero, to produce libvirt.so.0.
195 # We would, however, like the libvirt version number reflected
196 # in the so version'd symlinks, and this is based on AGE.REVISION
197 # eg  libvirt.so.0.AGE.REVISION
199 # The following examples show what libtool will do
201 # Input: 0.9.14 ->   libvirt.so.0.9.14
202 # Input: 1.0.0  ->   libvirt.so.0.1000.0
203 # Input: 2.5.8  ->   libvirt.so.0.2005.8
205 # Assuming we do ever want to break soname version, this can
206 # toggled. But seriously, don't ever touch this.
208 libvirt_so_version = 0
209 libvirt_age = 1000 * arr_version[0].to_int() + arr_version[1].to_int()
210 libvirt_revision = arr_version[2].to_int()
211 libvirt_lib_version = '@0@.@1@.@2@'.format(libvirt_so_version, libvirt_age, libvirt_revision)
214 # check compile flags
216 cc = meson.get_compiler('c')
217 cc_flags = []
219 git_werror = get_option('git_werror')
220 if (git_werror.enabled() or git_werror.auto()) and git and not get_option('werror')
221   cc_flags += [ '-Werror' ]
222 endif
225 # gcc --help=warnings outputs
226 ptrdiff_max = cc.sizeof('ptrdiff_t', prefix: '#include <stddef.h>')
227 size_max = cc.sizeof('size_t', prefix: '#include <stdint.h>')
228 # Compute max safe object size by checking ptrdiff_t and size_t sizes.
229 # Ideally we would get PTRDIFF_MAX and SIZE_MAX values but it would
230 # give us (2147483647L) and we would have to remove the () and the suffix
231 # in order to convert it to numbers to be able to pick the smaller one.
232 alloc_max = run_command(
233   'python3', '-c',
234   'print(min(2**(@0@ * 8 - 1) - 1, 2**(@1@ * 8) - 1))'.format(ptrdiff_max, size_max),
235   check: true,
238 stack_frame_size = 2048
240 # clang without optimization enlarges stack frames in certain corner cases
241 if cc.get_id() == 'clang' and get_option('optimization') == '0'
242     stack_frame_size = 4096
243 endif
245 # sanitizer instrumentation may enlarge stack frames
246 if get_option('b_sanitize') != 'none'
247   stack_frame_size = 32768
248 endif
250 # array_bounds=2 check triggers false positive on some GCC
251 # versions when using sanitizers. Seen on Fedora 34 with
252 # GCC 11.1.1
253 array_bounds = get_option('b_sanitize') == 'none' ? 2 : 1
255 cc_flags += [
256   '-fasynchronous-unwind-tables',
257   '-fexceptions',
258   '-fipa-pure-const',
259   '-fno-common',
260   '-Wabsolute-value',
261   '-Waddress',
262   '-Waddress-of-packed-member',
263   '-Waggressive-loop-optimizations',
264   '-Walloc-size-larger-than=@0@'.format(alloc_max.stdout().strip()),
265   '-Walloca',
266   '-Warray-bounds=@0@'.format(array_bounds),
267   '-Wattribute-alias=2',
268   '-Wattribute-warning',
269   '-Wattributes',
270   '-Wbool-compare',
271   '-Wbool-operation',
272   '-Wbuiltin-declaration-mismatch',
273   '-Wbuiltin-macro-redefined',
274   '-Wcannot-profile',
275   '-Wcast-align',
276   '-Wcast-align=strict',
277   # We do "bad" function casts all the time for event callbacks
278   '-Wno-cast-function-type',
279   '-Wchar-subscripts',
280   '-Wclobbered',
281   '-Wcomment',
282   '-Wcomments',
283   '-Wcoverage-mismatch',
284   '-Wcpp',
285   '-Wdangling-else',
286   '-Wdate-time',
287   '-Wdeclaration-after-statement',
288   '-Wdeprecated-declarations',
289   '-Wdesignated-init',
290   '-Wdiscarded-array-qualifiers',
291   '-Wdiscarded-qualifiers',
292   '-Wdiv-by-zero',
293   '-Wduplicated-cond',
294   '-Wduplicate-decl-specifier',
295   '-Wempty-body',
296   '-Wendif-labels',
297   '-Wexpansion-to-defined',
298   '-Wformat-contains-nul',
299   '-Wformat-extra-args',
300   # -Wformat=2 implies -Wformat-nonliteral so we need to manually exclude it
301   '-Wno-format-nonliteral',
302   '-Wformat-overflow=2',
303   '-Wformat-security',
304   # -Wformat enables this by default, and we should keep it,
305   # but need to rewrite various areas of code first
306   '-Wno-format-truncation',
307   '-Wformat-y2k',
308   '-Wformat-zero-length',
309   '-Wframe-address',
310   '-Wframe-larger-than=@0@'.format(stack_frame_size),
311   '-Wfree-nonheap-object',
312   '-Whsa',
313   '-Wif-not-aligned',
314   '-Wignored-attributes',
315   '-Wignored-qualifiers',
316   '-Wimplicit',
317   '-Wimplicit-fallthrough=5',
318   '-Wimplicit-function-declaration',
319   '-Wimplicit-int',
320   '-Wincompatible-pointer-types',
321   '-Winit-self',
322   '-Winline',
323   '-Wint-conversion',
324   '-Wint-in-bool-context',
325   '-Wint-to-pointer-cast',
326   '-Winvalid-memory-model',
327   '-Winvalid-pch',
328   '-Wjump-misses-init',
329   '-Wlogical-not-parentheses',
330   '-Wlogical-op',
331   '-Wmain',
332   '-Wmaybe-uninitialized',
333   '-Wmemset-elt-size',
334   '-Wmemset-transposed-args',
335   '-Wmisleading-indentation',
336   '-Wmissing-attributes',
337   '-Wmissing-braces',
338   '-Wmissing-declarations',
339   '-Wmissing-field-initializers',
340   '-Wmissing-include-dirs',
341   '-Wmissing-parameter-type',
342   '-Wmissing-profile',
343   '-Wmissing-prototypes',
344   '-Wmultichar',
345   '-Wmultistatement-macros',
346   '-Wnarrowing',
347   '-Wnested-externs',
348   '-Wnonnull',
349   '-Wnonnull-compare',
350   '-Wnormalized=nfc',
351   '-Wnull-dereference',
352   '-Wodr',
353   '-Wold-style-declaration',
354   '-Wold-style-definition',
355   '-Wopenmp-simd',
356   '-Woverflow',
357   '-Woverride-init',
358   '-Wpacked-bitfield-compat',
359   '-Wpacked-not-aligned',
360   '-Wparentheses',
361   '-Wpointer-arith',
362   '-Wpointer-compare',
363   '-Wpointer-sign',
364   '-Wpointer-to-int-cast',
365   '-Wpragmas',
366   '-Wpsabi',
367   '-Wrestrict',
368   '-Wreturn-local-addr',
369   '-Wreturn-type',
370   '-Wscalar-storage-order',
371   '-Wsequence-point',
372   '-Wshadow',
373   '-Wshift-count-negative',
374   '-Wshift-count-overflow',
375   '-Wshift-negative-value',
376   '-Wshift-overflow=2',
377   # So we have -W enabled, and then have to explicitly turn off...
378   '-Wno-sign-compare',
379   '-Wsizeof-array-argument',
380   '-Wsizeof-pointer-div',
381   '-Wsizeof-pointer-memaccess',
382   '-Wstrict-aliasing',
383   '-Wstrict-prototypes',
384   '-Wstringop-overflow=2',
385   '-Wstringop-truncation',
386   '-Wsuggest-attribute=cold',
387   '-Wno-suggest-attribute=const',
388   '-Wsuggest-attribute=format',
389   '-Wsuggest-attribute=noreturn',
390   '-Wno-suggest-attribute=pure',
391   '-Wsuggest-final-methods',
392   '-Wsuggest-final-types',
393   '-Wswitch',
394   '-Wswitch-bool',
395   '-Wswitch-enum',
396   '-Wswitch-unreachable',
397   '-Wsync-nand',
398   '-Wtautological-compare',
399   '-Wtrampolines',
400   '-Wtrigraphs',
401   '-Wtype-limits',
402   # Clang incorrectly complains about dup typedefs win gnu99 mode
403   # so use this Clang-specific arg to keep it quiet
404   '-Wno-typedef-redefinition',
405   '-Wuninitialized',
406   '-Wunknown-pragmas',
407   '-Wunused',
408   '-Wunused-but-set-parameter',
409   '-Wunused-but-set-variable',
410   '-Wunused-const-variable=2',
411   '-Wunused-function',
412   '-Wunused-label',
413   '-Wunused-local-typedefs',
414   '-Wunused-parameter',
415   '-Wunused-result',
416   '-Wunused-value',
417   '-Wunused-variable',
418   '-Wvarargs',
419   '-Wvariadic-macros',
420   '-Wvector-operation-performance',
421   '-Wvla',
422   '-Wvolatile-register-var',
423   '-Wwrite-strings',
426 if cc.get_id() == 'clang'
427     # Stop CLang from doing inter-procedural analysis of calls
428     # between functions in the same compilation unit. Such an
429     # optimization has been know to break the test suite by
430     # making assumptions that a return value is a constant.
431     # This makes it impossible to mock certain functions with
432     # replacement definitions via LD_PRELOAD that have different
433     # semantics.
434     #
435     # This is a bit of a big hammer, but alternatives don't work:
436     #
437     #  - 'weak' attribute - weak symbols get dropped from
438     #    when the .a libs are combined into the .so
439     #    see commit 407a281a8e2b6c5078ba1148535663ea64fd9314
440     #
441     #  - 'noipa' attribute - only available with GCC currently
442     #    https://reviews.llvm.org/D101011
443     cc_flags += [ '-fsemantic-interposition' ]
444 endif
446 if get_option('b_sanitize') != 'none'
447   # This is needed because of xdrproc_t. It's declared as a pointer to a
448   # function with variable arguments. But for catching type related problems at
449   # compile time, our rpcgen generates functions with proper types, say:
450   #
451   #    bool_t xdr_TestEnum(XDR *, TestEnum *);
452   #
453   # But passing xdr_TestEnum as a callback where xdrproc_t type is expected is
454   # undefined behavior. Yet, we want the comfort of compile time checks, so
455   # just disable the sanitizer warning for now. It's a big hammer though.
456   cc_flags += [ '-fno-sanitize=function' ]
457 endif
459 supported_cc_flags = []
460 if get_option('warning_level') == '2'
461   supported_cc_flags = cc.get_supported_arguments(cc_flags)
463   # we prefer -fstack-protector-strong but fallback to -fstack-protector-all
464   fstack_cflags = cc.first_supported_argument([
465     '-fstack-protector-strong',
466     '-fstack-protector-all',
467   ])
468   supported_cc_flags += fstack_cflags
470   # When building with mingw using -fstack-protector requires libssp library
471   # which is included by using -fstack-protector with linker.
472   if fstack_cflags.length() == 1 and host_machine.system() == 'windows'
473     add_project_link_arguments(fstack_cflags, language: 'c')
474   endif
476   if supported_cc_flags.contains('-Wlogical-op')
477     # Broken in 6.0 and later
478     #     https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69602
479     w_logical_op_args = [ '-O2', '-Wlogical-op', '-Werror' ]
480     w_logical_op_code = '''
481       #define TEST1 1
482       #define TEST2 TEST1
484       int main(void) {
485         int test = 0;
486         return test == TEST1 || test == TEST2;
487       }
488     '''
489     if not cc.compiles(w_logical_op_code, args: w_logical_op_args)
490       conf.set('BROKEN_GCC_WLOGICALOP_EQUAL_EXPR', 1)
491     endif
492   endif
494   # Check whether clang gives bogus warning for -Wdouble-promotion.
495   w_double_promotion_args = [ '-O2', '-Wdouble-promotion', '-Werror' ]
496   w_double_promotion_code = '''
497     #include <math.h>
499     int main(void) {
500       float f = 0.0;
501       return isnan(f);
502     }
503   '''
504   if cc.compiles(w_double_promotion_code, args: w_double_promotion_args, name: '-Wdouble-promotion')
505     supported_cc_flags += [ '-Wdouble-promotion' ]
506   endif
508   # Clang complains about unused static inline functions which are common
509   # with G_DEFINE_AUTOPTR_CLEANUP_FUNC.
510   w_unused_function_args = [ '-Wunused-function', '-Werror' ]
511   w_unused_function_code = '''
512     static inline void foo(void) {}
514     int main(void) { return 0; }
515   '''
516   # -Wunused-function is implied by -Wall, we must turn it off explicitly.
517   if not cc.compiles(w_unused_function_code, args: w_unused_function_args)
518     supported_cc_flags += [ '-Wno-unused-function' ]
519   endif
521 endif
522 add_project_arguments(supported_cc_flags, language: 'c')
524 if cc.has_argument('-Wsuggest-attribute=format')
525   conf.set('WITH_SUGGEST_ATTRIBUTE_FORMAT', 1)
526 endif
528 # used in tests
529 cc_flags_relaxed_frame_limit = []
530 if cc.has_argument('-Wframe-larger-than=262144')
531   cc_flags_relaxed_frame_limit += [
532   '-Wframe-larger-than=262144',
533   ]
534 endif
536 # various linker checks
538 libvirt_relro = cc.get_supported_link_arguments([
539   '-Wl,-z,relro',
540   '-Wl,-z,now',
543 libvirt_nodelete = cc.get_supported_link_arguments([
544   '-Wl,-z,nodelete',
547 libvirt_no_undefined = []
548 if get_option('b_sanitize') == 'none'
549   libvirt_no_undefined += cc.get_supported_link_arguments([
550     '-Wl,-z,defs',
551   ])
552 endif
554 libvirt_no_indirect = cc.get_supported_link_arguments([
555   '-Wl,--no-copy-dt-needed-entries',
558 libvirt_no_warn_duplicate_libraries = cc.get_supported_link_arguments([
559   '-Wl,-no_warn_duplicate_libraries',
562 if host_machine.system() == 'windows'
563   version_script_flags = '-Wl,'
564 elif host_machine.system() == 'darwin'
565   # macOS libraries don't support symbol versioning
566   version_script_flags = ''
567 else
568   version_script_flags = '-Wl,--version-script='
569 endif
571 libvirt_flat_namespace = []
572 if host_machine.system() == 'darwin'
573   libvirt_flat_namespace = '-Wl,-flat_namespace'
574 endif
576 libvirt_export_dynamic = cc.first_supported_link_argument([
577   '-Wl,-export-dynamic',
578   '-Wl,-export_dynamic',
582 # check availability of various common functions (non-fatal if missing)
584 functions = [
585   'elf_aux_info',
586   'explicit_bzero',
587   'fallocate',
588   'getauxval',
589   'getegid',
590   'geteuid',
591   'getgid',
592   'getifaddrs',
593   'getmntent_r',
594   'getpwuid_r',
595   'getrlimit',
596   'getuid',
597   'getutxid',
598   'if_indextoname',
599   'mmap',
600   'newlocale',
601   'pipe2',
602   'posix_fallocate',
603   'posix_memalign',
604   'prlimit',
605   'sched_get_priority_min',
606   'sched_getaffinity',
607   'sched_setscheduler',
608   'setgroups',
609   'setrlimit',
610   'symlink',
611   'sysctlbyname',
614 stat_functions = [
615   '__lxstat',
616   '__lxstat64',
617   '__xstat',
618   '__xstat64',
619   'lstat',
620   'lstat64',
621   'stat',
622   'stat64',
625 functions += stat_functions
627 open_functions = [
628   '__open_2',
631 functions += open_functions
633 foreach function : functions
634   if cc.has_function(function)
635     conf.set('WITH_@0@'.format(function.to_upper()), 1)
636   endif
637 endforeach
640 foreach function : stat_functions
641   if cc.has_header_symbol('sys/stat.h', function)
642     conf.set('WITH_@0@_DECL'.format(function.to_upper()), 1)
643   endif
644 endforeach
647 foreach function : open_functions
648   if cc.has_header_symbol('fcntl.h', function)
649     conf.set('WITH_@0@_DECL'.format(function.to_upper()), 1)
650   endif
651 endforeach
654 # various header checks
656 headers = [
657   'asm/hwcap.h',
658   'ifaddrs.h',
659   'libtasn1.h',
660   'linux/kvm.h',
661   'mntent.h',
662   'net/ethernet.h',
663   'net/if.h',
664   'pty.h',
665   'pwd.h',
666   'sched.h',
667   'sys/auxv.h',
668   'sys/ioctl.h',
669   'sys/mount.h',
670   'sys/syscall.h',
671   'sys/ucred.h',
672   'syslog.h',
673   'util.h',
674   'xlocale.h',
677 if host_machine.system() == 'freebsd'
678   headers += 'libutil.h'
679 endif
681 foreach name : headers
682   if cc.check_header(name)
683     conf.set('WITH_@0@'.format(name.underscorify().to_upper()), 1)
684   endif
685 endforeach
687 # check for kernel header required by src/util/virnetdevbridge.c
688 if host_machine.system() == 'linux'
689   if not cc.check_header('linux/sockios.h')
690     error('You must install kernel-headers in order to compile libvirt with QEMU or LXC support')
691   endif
692 endif
695 # check various symbols
697 symbols = [
698   # Check whether endian provides handy macros.
699   [ 'endian.h', 'htole64' ],
701   [ 'unistd.h', 'SEEK_HOLE' ],
703   # Check for BSD approach for setting MAC addr
704   [ 'net/if_dl.h', 'link_addr', '#include <sys/types.h>\n#include <sys/socket.h>' ],
707 if host_machine.system() == 'linux'
708   symbols += [
709     # process management
710     [ 'sys/syscall.h', 'SYS_pidfd_open' ],
711     # vsock
712     [ 'linux/vm_sockets.h', 'struct sockaddr_vm', '#include <sys/socket.h>' ],
713   ]
714 endif
716 foreach symbol : symbols
717   if cc.has_header_symbol(symbol[0], symbol[1], args: '-D_GNU_SOURCE', prefix: symbol.get(2, ''))
718     conf.set('WITH_DECL_@0@'.format(symbol[1].underscorify().to_upper()), 1)
719   endif
720 endforeach
722 # Check for BSD approach for bridge management
723 brd_required_headers = '''#include <stdint.h>
724 #include <net/if.h>
725 #include <net/ethernet.h>'''
726 if (cc.has_header_symbol('net/if_bridgevar.h', 'BRDGSFD', prefix: brd_required_headers) and
727     cc.has_header_symbol('net/if_bridgevar.h', 'BRDGADD', prefix: brd_required_headers) and
728     cc.has_header_symbol('net/if_bridgevar.h', 'BRDGDEL', prefix: brd_required_headers))
729   conf.set('WITH_BSD_BRIDGE_MGMT', 1)
730 endif
732 # Check for BSD CPU affinity availability
733 if cc.has_header_symbol('sys/cpuset.h', 'cpuset_getaffinity', prefix: '#include <sys/param.h>')
734   conf.set('WITH_BSD_CPU_AFFINITY', 1)
735 endif
737 # whether Mach clock routines are available
738 if (cc.has_header_symbol('mach/clock.h', 'clock_serv_t') and
739     cc.has_header_symbol('mach/clock.h', 'host_get_clock_service') and
740     cc.has_header_symbol('mach/clock.h', 'clock_get_time'))
741   conf.set('WITH_MACH_CLOCK_ROUTINES', 1)
742 endif
745 # check various types
747 types = [
748   [ 'struct ifreq', '#include <sys/socket.h>\n#include <net/if.h>'] ,
749   [ 'struct sockpeercred', '#include <sys/socket.h' ],
752 foreach type : types
753   if cc.has_type(type[0], prefix: type[1])
754     name = type[0].underscorify().to_upper()
755     conf.set('WITH_@0@'.format(name), 1)
756   endif
757 endforeach
759 if host_machine.system() == 'windows'
760   uid_types = [
761     'uid_t',
762     'gid_t',
763   ]
764   foreach type : uid_types
765     if not cc.has_type(type, prefix: '#include <sys/types.h>')
766       conf.set(type, 'int')
767     endif
768   endforeach
769 endif
772 # check various members
774 members = [
775   # Check for Linux vs. BSD ifreq members
776   [ 'struct ifreq', 'ifr_newname', '#include <sys/socket.h>\n#include <net/if.h>' ],
777   [ 'struct ifreq', 'ifr_ifindex', '#include <sys/socket.h>\n#include <net/if.h>' ],
778   [ 'struct ifreq', 'ifr_index', '#include <sys/socket.h>\n#include <net/if.h>' ],
779   [ 'struct ifreq', 'ifr_hwaddr', '#include <sys/socket.h>\n#include <net/if.h>' ],
782 foreach member : members
783   if cc.has_member(member[0], member[1], prefix: member[2])
784     type = member[0].underscorify().to_upper()
785     member = member[1].underscorify().to_upper()
786     conf.set('WITH_@0@_@1@'.format(type, member), 1)
787   endif
788 endforeach
791 # check various types sizeof
793 conf.set('SIZEOF_LONG', cc.sizeof('long'))
796 # Where we look for daemons and admin binaries during configure
798 libvirt_sbin_path = []
800 if host_machine.system() != 'windows'
801   libvirt_sbin_path += [
802     '/sbin',
803     '/usr/sbin',
804     '/usr/local/sbin',
805   ]
806 endif
809 # required programs check
811 required_programs = [
812   'perl',
813   'python3',
814   'xmllint',
815   'xsltproc',
818 if host_machine.system() == 'freebsd'
819   required_programs += 'ifconfig'
820 endif
822 foreach name : required_programs
823   prog = find_program(name, dirs: libvirt_sbin_path)
824   varname = name.underscorify()
825   conf.set_quoted(varname.to_upper(), prog.full_path())
826   set_variable('@0@_prog'.format(varname), prog)
827 endforeach
829 # optional programs
831 optional_test_programs = [
832   'augparse',
833   'black',
834   'flake8',
835   'pdwtags',
836   'pytest',
839 optional_programs = [
840   'dmidecode',
841   'ip',
842   'iscsiadm',
843   'mdevctl',
844   'mm-ctl',
845   'modprobe',
846   'ovs-vsctl',
847   'rmmod',
848   'tc',
849 ] + optional_test_programs
851 missing_optional_programs = []
852 foreach name : optional_programs
853   prog = find_program(name, required: false, dirs: libvirt_sbin_path)
854   varname = name.underscorify()
855   if prog.found()
856     prog_path = prog.full_path()
857   else
858     prog_path = name
859     if name in optional_test_programs
860       missing_optional_programs += [ name ]
861     endif
862   endif
864   conf.set_quoted(varname.to_upper(), prog_path)
865   set_variable('@0@_prog'.format(varname), prog)
866 endforeach
869 # early checks where lot of other packages depend on the result
871 if not get_option('driver_remote').disabled()
872   # On MinGW portablexdr provides XDR functions, on linux they are
873   # provided by libtirpc and on FreeBSD/macOS there is no need to
874   # use extra library as it's provided by libc directly.
875   if host_machine.system() == 'windows'
876     xdr_dep = cc.find_library('portablexdr', required: get_option('driver_remote'))
877   elif host_machine.system() in [ 'linux', 'gnu' ]
878     xdr_dep = dependency('libtirpc', required: get_option('driver_remote'))
879   elif host_machine.system() in [ 'freebsd', 'darwin' ]
880     xdr_dep = cc.find_library('c', required: get_option('driver_remote'))
881   else
882     xdr_dep = dependency('', required: false)
883   endif
885   if xdr_dep.found()
886     conf.set('WITH_REMOTE', 1)
887   elif get_option('driver_remote').enabled()
888     error('XDR is required for remote driver')
889   endif
890 else
891   xdr_dep = dependency('', required: false)
892 endif
895 # generic build dependencies
897 acl_dep = dependency('libacl', required: false)
898 if acl_dep.found()
899   conf.set('WITH_LIBACL', 1)
900 endif
902 apparmor_dep = dependency('libapparmor', required: get_option('apparmor'))
903 if apparmor_dep.found()
904   conf.set('WITH_APPARMOR', 1)
905   if apparmor_dep.version().version_compare('>=3.0.0')
906     conf.set('WITH_APPARMOR_3', 1)
907   endif
908   conf.set_quoted('APPARMOR_DIR', sysconfdir / 'apparmor.d')
909   conf.set_quoted('APPARMOR_PROFILES_PATH', '/sys/kernel/security/apparmor/profiles')
910 endif
912 if not get_option('apparmor_profiles').disabled()
913   apparmor_profiles_enable = true
915   if not conf.has('WITH_APPARMOR')
916     apparmor_profiles_enable = false
917     if get_option('apparmor_profiles').enabled()
918       error('Cannot enable apparmor_profiles without apparmor')
919     endif
920   endif
922   if apparmor_profiles_enable
923     conf.set('WITH_APPARMOR_PROFILES', 1)
924   endif
925 endif
927 # FIXME rewrite to use dependency() once we can use 2.4.48
928 attr_dep = cc.find_library('attr', required: get_option('attr'))
929 if attr_dep.found()
930   conf.set('WITH_LIBATTR', 1)
931 endif
933 audit_dep = dependency('audit', required: get_option('audit'))
934 if audit_dep.found()
935   conf.set('WITH_AUDIT', 1)
936 endif
938 bash_completion_version = '2.0'
939 bash_completion_dep = dependency('bash-completion', version: '>=' + bash_completion_version, required: get_option('bash_completion'))
941 blkid_version = '2.17'
942 blkid_dep = dependency('blkid', version: '>=' + blkid_version, required: get_option('blkid'))
943 if blkid_dep.found()
944   conf.set('WITH_BLKID', 1)
945 endif
947 capng_dep = dependency('libcap-ng', required: get_option('capng'))
948 if capng_dep.found()
949   conf.set('WITH_CAPNG', 1)
950 endif
952 curl_version = '7.19.1'
953 curl_dep = dependency('libcurl', version: '>=' + curl_version, required: get_option('curl'))
954 if curl_dep.found()
955   conf.set('WITH_CURL', 1)
956 endif
958 devmapper_version = '1.0.0'
959 devmapper_dep = dependency('devmapper', version: '>=' + devmapper_version, required: false)
960 if devmapper_dep.found()
961   conf.set('WITH_DEVMAPPER', 1)
962 endif
964 dlopen_use = host_machine.system() != 'windows'
965 dlopen_dep = cc.find_library('dl', required: dlopen_use)
966 if dlopen_dep.found()
967   if not cc.check_header('dlfcn.h')
968     error('Unable to find dlfcn.h')
969   endif
970   conf.set('WITH_DLFCN_H', 1)
971 endif
973 fuse_version = '3.1.0'
974 fuse_dep = dependency('fuse3', version: '>=' + fuse_version, required: false)
975 if fuse_dep.found()
976   conf.set('WITH_FUSE', 3)
977 else
978   fuse_version = '2.8.6'
979   fuse_dep = dependency('fuse', version: '>=' + fuse_version, required: get_option('fuse'))
980   if fuse_dep.found()
981     conf.set('WITH_FUSE', 1)
982   endif
983 endif
985 glib_version = '2.58.0'
986 glib_dep = dependency('glib-2.0', version: '>=' + glib_version)
987 gobject_dep = dependency('gobject-2.0', version: '>=' + glib_version)
988 if host_machine.system() == 'windows'
989   gio_dep = dependency('gio-2.0', version: '>=' + glib_version)
990 else
991   gio_dep = dependency('gio-unix-2.0', version: '>=' + glib_version)
992 endif
993 glib_dep = declare_dependency(
994   dependencies: [ glib_dep, gobject_dep, gio_dep ],
996 glib_version_arr = glib_version.split('.')
997 glib_version_str = 'GLIB_VERSION_@0@_@1@'.format(glib_version_arr[0], glib_version_arr[1])
998 # Ask for warnings for anything that was marked deprecated in
999 # the defined version, or before. It is a candidate for rewrite.
1000 conf.set('GLIB_VERSION_MIN_REQUIRED', glib_version_str)
1001 # Ask for warnings if code tries to use function that did not
1002 # exist in the defined version. These risk breaking builds
1003 conf.set('GLIB_VERSION_MAX_ALLOWED', glib_version_str)
1005 glusterfs_version = '3.4.1'
1006 glusterfs_dep = dependency('glusterfs-api', version: '>=' + glusterfs_version, required: get_option('glusterfs'))
1008 gnutls_version = '3.6.0'
1009 gnutls_dep = dependency('gnutls', version: '>=' + gnutls_version)
1011 # Check for BSD kvm (kernel memory interface)
1012 if host_machine.system() == 'freebsd'
1013   libkvm_dep = cc.find_library('kvm')
1014 else
1015   libkvm_dep = dependency('', required: false)
1016 endif
1018 libiscsi_version = '1.18.0'
1019 libiscsi_dep = dependency('libiscsi', version: '>=' + libiscsi_version, required: get_option('libiscsi'))
1021 if not get_option('nbdkit').disabled()
1022   libnbd_version = '1.0'
1023   libnbd_dep = dependency('libnbd', version: '>=' + libnbd_version, required: false)
1025   nbdkit_requested = get_option('nbdkit').enabled()
1026   nbdkit_syscall_ok = conf.has('WITH_DECL_SYS_PIDFD_OPEN')
1027   nbdkit_libnbd_ok = libnbd_dep.found()
1029   if not nbdkit_syscall_ok and nbdkit_requested
1030     error('nbdkit support requires pidfd_open(2)')
1031   endif
1032   if not nbdkit_libnbd_ok and nbdkit_requested
1033     error('nbdkit support requires libnbd')
1034   endif
1036   if nbdkit_syscall_ok and nbdkit_libnbd_ok
1037     conf.set('WITH_NBDKIT', 1)
1038   endif
1039 endif
1040 if not conf.has('WITH_NBDKIT')
1041   libnbd_dep = dependency('', required: false)
1042 endif
1044 # default value for storage_use_nbdkit config option.
1045 # For now 'auto' just maps to disabled, but in the future it may depend on
1046 # which security drivers are enabled
1047 use_nbdkit_default = get_option('nbdkit_config_default').enabled()
1049 if use_nbdkit_default and not conf.has('WITH_NBDKIT')
1050   error('nbdkit_config_default requires nbdkit to be enabled')
1051 endif
1052 conf.set10('USE_NBDKIT_DEFAULT', use_nbdkit_default)
1054 libnl_version = '3.0'
1055 if not get_option('libnl').disabled() and host_machine.system() == 'linux'
1056   libnl_dep = dependency('libnl-3.0', version: '>=' + libnl_version, required: get_option('libnl'))
1057   libnl_route_dep = dependency('libnl-route-3.0', version: '>=' + libnl_version, required: get_option('libnl'))
1059   if libnl_dep.found() and libnl_route_dep.found()
1060     libnl_dep = declare_dependency(
1061       dependencies: [ libnl_dep, libnl_route_dep ],
1062     )
1063     conf.set('WITH_LIBNL', 1)
1064   endif
1065 elif get_option('libnl').enabled()
1066   error('libnl can be enabled only on linux')
1067 else
1068   libnl_dep = dependency('', required: false)
1069 endif
1071 libparted_version = '1.8.0'
1072 libparted_dep = dependency('libparted', version: '>=' + libparted_version, required: get_option('storage_disk'))
1074 libpcap_version = '1.5.0'
1075 if not get_option('libpcap').disabled()
1076   libpcap_dep = dependency('pcap', version: '>=' + libpcap_version, required: get_option('libpcap'))
1077   if libpcap_dep.found()
1078     conf.set('WITH_LIBPCAP', 1)
1079   endif
1080 else
1081   libpcap_dep = dependency('', required: false)
1082 endif
1084 libssh_version = '0.8.1'
1085 if conf.has('WITH_REMOTE')
1086   libssh_dep = dependency('libssh', version: '>=' + libssh_version, required: get_option('libssh'))
1087   if libssh_dep.found()
1088     conf.set('WITH_LIBSSH', 1)
1089   endif
1090 else
1091   libssh_dep = dependency('', required: false)
1092 endif
1094 libssh2_version = '1.3'
1095 if conf.has('WITH_REMOTE')
1096   libssh2_dep = dependency('libssh2', version: '>=' + libssh2_version, required: get_option('libssh2'))
1097   if libssh2_dep.found()
1098     conf.set('WITH_SSH2', 1)
1099   endif
1100 else
1101   libssh2_dep = dependency('', required: false)
1102 endif
1104 libxml_version = '2.9.1'
1105 libxml_dep = dependency('libxml-2.0', version: '>=' + libxml_version)
1107 libm_dep = cc.find_library('m')
1109 netcf_version = '0.1.8'
1110 if not get_option('netcf').disabled()
1111   netcf_dep = dependency('netcf', version: '>=' + netcf_version, required: get_option('netcf'))
1112   if netcf_dep.found()
1113     conf.set('WITH_NETCF', 1)
1114   endif
1115 else
1116   netcf_dep = dependency('', required: false)
1117 endif
1119 have_gnu_gettext_tools = false
1120 if not get_option('nls').disabled()
1121   have_gettext = cc.has_function('gettext')
1122   if not have_gettext
1123     intl_dep = cc.find_library('intl', required: false)
1124     have_gettext = intl_dep.found()
1125   else
1126     intl_dep = dependency('', required: false)
1127   endif
1128   if not have_gettext and get_option('nls').enabled()
1129     error('gettext() is required to build libvirt')
1130   endif
1132   if cc.check_header('libintl.h')
1133     conf.set('WITH_LIBINTL_H', 1)
1134   elif get_option('nls').enabled()
1135     error('libintl.h is required to build libvirt')
1136   endif
1138   gettext_progs = [
1139     'xgettext',
1140     'msgfmt',
1141     'msgmerge',
1142   ]
1143   foreach name : gettext_progs
1144     prog = find_program(name, required: false)
1145     set_variable('@0@_prog'.format(name), prog)
1146   endforeach
1148   if xgettext_prog.found() and msgfmt_prog.found() and msgmerge_prog.found()
1149     rc = run_command(msgfmt_prog, '--version', check: false)
1150     if rc.returncode() == 0 and rc.stdout().contains('GNU gettext')
1151       have_gnu_gettext_tools = true
1152     endif
1153   endif
1154 else
1155   intl_dep = dependency('', required: false)
1156 endif
1158 numactl_dep = dependency('numa', required: get_option('numactl'))
1159 if numactl_dep.found()
1160   conf.set('WITH_NUMACTL', 1)
1161   if cc.has_function('numa_set_preferred_many', dependencies: numactl_dep)
1162     conf.set('WITH_NUMACTL_SET_PREFERRED_MANY', 1)
1163   endif
1164 endif
1166 openwsman_version = '2.6.3'
1167 openwsman_dep = dependency('openwsman', version: '>=' + openwsman_version, required: get_option('openwsman'))
1169 parallels_sdk_version = '7.0.22'
1170 parallels_sdk_dep = dependency('parallels-sdk', version: '>=' + parallels_sdk_version, required: false)
1172 pciaccess_version = '0.10.0'
1173 pciaccess_dep = dependency('pciaccess', version: '>=' + pciaccess_version, required: get_option('pciaccess'))
1175 rbd_dep = cc.find_library('rbd', required: get_option('storage_rbd'))
1176 rados_dep = cc.find_library('rados', required: get_option('storage_rbd'))
1177 if rbd_dep.found() and not cc.has_function('rbd_get_features', dependencies: rbd_dep)
1178   rbd_dep = dependency('', required: false)
1179 endif
1180 if rbd_dep.found() and rados_dep.found()
1181   if cc.has_function('rbd_list2', dependencies: rbd_dep)
1182     conf.set('WITH_RBD_LIST2', 1)
1183   endif
1185   rbd_dep = declare_dependency(dependencies: [ rbd_dep, rados_dep ])
1186 else
1187   rbd_dep = dependency('', required: false)
1188 endif
1190 # readline 7.0 is the first version which includes pkg-config support
1191 readline_version = '7.0'
1192 if not get_option('readline').disabled()
1193   readline_dep = dependency('readline', version: '>=' + readline_version, required: false)
1194   if not readline_dep.found()
1195     readline_dep = cc.find_library('readline', required: get_option('readline'))
1197     if readline_dep.found()
1198       # This variable is present in all reasonable (5.0+) readline versions;
1199       # however, the macOS base system contains a library called libedit which
1200       # takes over the readline name despite lacking many of its features. We
1201       # want to make sure we only enable readline support when linking against
1202       # the actual readline library, and the availability of this specific
1203       # variable is as good a witness for that fact as any.
1204       correct_rl = cc.has_header_symbol('readline/readline.h', 'rl_completion_quote_character', prefix: '#include <stdio.h>')
1205       if not correct_rl
1206         if get_option('readline').enabled()
1207           error('readline is missing rl_completion_quote_character')
1208         else
1209           readline_dep = dependency('', required: false)
1210         endif
1211       endif
1212     endif
1213   endif
1214   if readline_dep.found()
1215     # We need this to avoid compilation issues with modern compilers.
1216     # See 9ea3424a178 for a more detailed explanation
1217     readline_dep = declare_dependency(
1218       compile_args: [ '-D_FUNCTION_DEF' ],
1219       dependencies: [ readline_dep ],
1220     )
1222     conf.set('WITH_READLINE', 1)
1223   endif
1224 else
1225   readline_dep = dependency('', required: false)
1226 endif
1228 if not get_option('sanlock').disabled()
1229   sanlock_dep = dependency('libsanlock_client', required: get_option('sanlock'))
1231   if sanlock_dep.found()
1232     conf.set('WITH_SANLOCK', 1)
1233     # check for sanlock_strerror introduced in sanlock-3.5.0
1234     if cc.has_function('sanlock_strerror', dependencies: sanlock_dep)
1235       conf.set('WITH_SANLOCK_STRERROR', 1)
1236     endif
1237   endif
1238 else
1239   sanlock_dep = dependency('', required: false)
1240 endif
1242 sasl_version = '2.1.26'
1243 if conf.has('WITH_REMOTE')
1244   sasl_dep = dependency('libsasl2', version: '>=' + sasl_version, required: get_option('sasl'))
1245   if sasl_dep.found()
1246     conf.set('WITH_SASL', 1)
1247   endif
1248 else
1249   sasl_dep = dependency('', required: false)
1250 endif
1252 selinux_dep = dependency('libselinux', required: get_option('selinux'))
1253 if selinux_dep.found()
1254   selinux_mount = get_option('selinux_mount')
1255   if selinux_mount == ''
1256     if run_command('test', '-d', '/sys/fs/selinux', check: false).returncode() == 0
1257       selinux_mount = '/sys/fs/selinux'
1258     else
1259       selinux_mount = '/selinux'
1260     endif
1261   endif
1262   conf.set_quoted('SELINUX_MOUNT', selinux_mount)
1263   conf.set('WITH_SELINUX', 1)
1264 endif
1266 thread_dep = dependency('threads')
1267 pthread_sigmask_code = '''
1268   #include <sys/types.h>
1269   #include <signal.h>
1271   int main() {
1272       #ifdef pthread_sigmask
1273       int (*foo)(int, const sigset_t *, sigset_t *) = &pthread_sigmask;
1274       return !foo;
1275       #endif
1277       return 0;
1278   }
1280 if not cc.compiles(pthread_sigmask_code)
1281   conf.set('FUNC_PTHREAD_SIGMASK_BROKEN', 1)
1282 endif
1284 udev_version = '219'
1285 udev_dep = dependency('libudev', version: '>=' + udev_version, required: get_option('udev'))
1286 if udev_dep.found()
1287   conf.set('WITH_UDEV', 1)
1288 endif
1290 libutil_dep = cc.find_library('util', required: false)
1292 if host_machine.system() == 'windows'
1293   ole32_dep = cc.find_library('ole32')
1294   oleaut32_dep = cc.find_library('oleaut32')
1295   winsock2_dep = cc.find_library('ws2_32')
1296   win32_dep = declare_dependency(
1297     dependencies: [
1298       ole32_dep,
1299       oleaut32_dep,
1300       winsock2_dep,
1301     ],
1302   )
1303   if get_option('default_library') == 'static'
1304     win32_flags = [ '-DLIBVIRT_STATIC' ]
1305   else
1306     win32_flags = []
1307   endif
1308   win32_link_flags = [ '-Wl,-no-undefined' ]
1309 else
1310   win32_dep = dependency('', required: false)
1311   win32_flags = []
1312   win32_link_flags = []
1313 endif
1315 wireshark_version = '2.6.0'
1316 wireshark_dep = dependency('wireshark', version: '>=' + wireshark_version, required: get_option('wireshark_dissector'))
1317 if wireshark_dep.found()
1318   if not xdr_dep.found()
1319     if get_option('wireshark_dissector').enabled()
1320       error('XDR is required for wireshark plugin')
1321     else
1322       wireshark_dep = dependency('', required: false)
1323     endif
1324   endif
1325 endif
1327 if wireshark_dep.found()
1328   wireshark_plugindir = get_option('wireshark_plugindir')
1329   if wireshark_plugindir == ''
1330     wireshark_plugindir = wireshark_dep.get_variable(pkgconfig : 'plugindir')
1331   endif
1333   wireshark_prefix = wireshark_dep.get_variable(pkgconfig : 'prefix')
1334   if wireshark_prefix == ''
1335     # If wireshark's prefix cannot be retrieved from pkg-config,
1336     # this is our best bet.
1337     wireshark_prefix = '/usr'
1338   endif
1339   # Replace wireshark's prefix with our own.
1340   # There is no replace method in meson so we have to workaround it.
1341   rc = run_command(
1342     'python3', '-c',
1343     'print("@0@".replace("@1@", "@2@"))'.format(
1344       wireshark_plugindir, wireshark_prefix, prefix,
1345     ),
1346     check: true,
1347   )
1348   wireshark_plugindir = rc.stdout().strip()
1350   # Since wireshark 2.5.0 plugins can't live in top level plugindir but have
1351   # to be under one of ["epan", "wiretap", "codecs"] subdir. The first one looks okay.
1352   wireshark_plugindir = wireshark_plugindir / 'epan'
1354   # Wireshark is installing ws_version.h since v2.9.0, but some distributions
1355   # are not shipping it.
1356   if cc.check_header('wireshark/ws_version.h')
1357     conf.set('WITH_WS_VERSION', 1)
1358   endif
1359 endif
1361 yajl_version = '2.0.3'
1362 yajl_dep = dependency('yajl', version: '>=' + yajl_version, required: get_option('yajl'))
1363 if yajl_dep.found()
1364   # Kludge for yajl include path on non-Linux
1365   #
1366   # As of 2.1.0, upstream yajl.pc has -I${includedir}/yajl among
1367   # its Cflags, which is clearly wrong. This does not affect Linux
1368   # because ${includedir} is already part of the default include path,
1369   # but on other platforms that's not the case and the result is that
1370   # <yajl/yajl.h> can't be located, causing the build to fail.
1371   #
1372   # Since upstream development for yajl has stopped years ago, there's
1373   # little hope of this issue getting fixed by a new upstream release.
1374   # Some non-Linux operating systems such as FreeBSD have elected to
1375   # carry a small downstream patch, but in the case of Homebrew on
1376   # macOS this approach has been rejected[1] and so we're left with no
1377   # choice but to work around the issue ourselves.
1378   #
1379   # [1] https://github.com/Homebrew/homebrew-core/pull/74516
1380   if host_machine.system() != 'linux'
1381     yajl_includedir = yajl_dep.get_variable(pkgconfig : 'includedir')
1382     if yajl_includedir.contains('include/yajl')
1383       rc = run_command(
1384         'python3', '-c',
1385         'print("@0@".replace("@1@", "@2@"))'.format(
1386           yajl_includedir, 'include/yajl', 'include',
1387         ),
1388         check: true,
1389       )
1390       yajl_includedir = rc.stdout().strip()
1391       yajl_dep = declare_dependency(
1392         compile_args: [ '-I' + yajl_includedir ],
1393         dependencies: [ yajl_dep ],
1394       )
1395     endif
1396   endif
1398   conf.set('WITH_YAJL', 1)
1399 endif
1402 # generic build dependencies checks
1404 if bash_completion_dep.found() and not readline_dep.found()
1405   if get_option('bash_completion').enabled()
1406     error('readline is required for bash completion support')
1407   else
1408     bash_completion_dep = dependency('', required: false)
1409   endif
1410 endif
1411 if bash_completion_dep.found()
1412   bash_completion_dir = get_option('bash_completion_dir')
1413   if bash_completion_dir == ''
1414     bash_completion_dir = bash_completion_dep.get_variable(pkgconfig : 'completionsdir')
1415     bash_completion_prefix = bash_completion_dep.get_variable(pkgconfig : 'prefix')
1416     rc = run_command(
1417       'python3', '-c',
1418       'print("@0@".replace("@1@", "@2@"))'.format(
1419         bash_completion_dir, bash_completion_prefix, prefix,
1420       ),
1421       check: true,
1422     )
1423     bash_completion_dir = rc.stdout().strip()
1424   endif
1425 endif
1427 if not get_option('firewalld').disabled()
1428   firewalld_enable = true
1430   if host_machine.system() != 'linux'
1431     firewalld_enable = false
1432     if get_option('firewalld').enabled()
1433       error('firewalld support can only be enabled on Linux')
1434     endif
1435   endif
1437   if firewalld_enable
1438     conf.set('WITH_FIREWALLD', 1)
1439   endif
1440 endif
1442 if not get_option('firewalld_zone').disabled() and conf.has('WITH_FIREWALLD')
1443   conf.set('WITH_FIREWALLD_ZONE', 1)
1444 elif get_option('firewalld_zone').enabled()
1445   error('You must have firewalld support enabled to enable firewalld_zone')
1446 endif
1448 if not get_option('polkit').disabled()
1449   polkit_enable = true
1451   if get_option('polkit').auto()
1452     pkcheck_prog = find_program('pkcheck', required: false, dirs: libvirt_sbin_path)
1453     polkit_enable = pkcheck_prog.found()
1454   endif
1456   if host_machine.system() == 'windows'
1457     polkit_enable = false
1458     if get_option('polkit').enabled()
1459       error('polkit support cannot be enabled on Windows')
1460     endif
1461   endif
1463   if polkit_enable
1464     conf.set('WITH_POLKIT', 1)
1465   endif
1466 endif
1468 if udev_dep.found() and not pciaccess_dep.found()
1469   error('You must install the pciaccess module to build with udev')
1470 endif
1473 # build driver options
1475 remote_default_mode = get_option('remote_default_mode')
1476 if remote_default_mode == 'direct'
1477   conf.set('REMOTE_DRIVER_AUTOSTART_DIRECT', '1')
1478 endif
1480 if not get_option('driver_libvirtd').disabled()
1481   use_libvirtd = true
1483   if host_machine.system() == 'windows'
1484     use_libvirtd = false
1485     if get_option('driver_libvirtd').enabled()
1486       error('libvirtd daemon is not supported on windows')
1487     endif
1488   endif
1490   if not conf.has('WITH_REMOTE')
1491     use_libvirtd = false
1492     if get_option('driver_libvirtd').enabled()
1493       error('remote driver is required for libvirtd daemon')
1494     endif
1495   endif
1497   if use_libvirtd
1498     conf.set('WITH_LIBVIRTD', 1)
1499   endif
1500 endif
1502 if not get_option('driver_bhyve').disabled() and host_machine.system() == 'freebsd'
1503   bhyve_prog = find_program('bhyve', required: get_option('driver_bhyve'))
1504   bhyvectl_prog = find_program('bhyvectl', required: get_option('driver_bhyve'))
1505   bhyveload_prog = find_program('bhyveload', required: get_option('driver_bhyve'))
1507   if bhyve_prog.found() and bhyvectl_prog.found() and bhyveload_prog.found()
1508     conf.set('WITH_BHYVE', 1)
1509     conf.set_quoted('BHYVE', bhyve_prog.full_path())
1510     conf.set_quoted('BHYVECTL', bhyvectl_prog.full_path())
1511     conf.set_quoted('BHYVELOAD', bhyveload_prog.full_path())
1512   endif
1513 elif get_option('driver_bhyve').enabled()
1514   error('The bhyve driver cannot be enabled')
1515 endif
1517 if not get_option('driver_esx').disabled() and curl_dep.found()
1518   conf.set('WITH_ESX', 1)
1519   conf.set('WITH_VMX', 1)
1520 elif get_option('driver_esx').enabled()
1521   error('Curl is required for the ESX driver')
1522 endif
1524 if not get_option('driver_hyperv').disabled() and openwsman_dep.found()
1525   conf.set('WITH_HYPERV', 1)
1526 elif get_option('driver_hyperv').enabled()
1527   error('openwsman is required for the Hyper-V driver')
1528 endif
1530 if not get_option('driver_interface').disabled() and conf.has('WITH_LIBVIRTD') and (udev_dep.found() or conf.has('WITH_NETCF'))
1531   conf.set('WITH_INTERFACE', 1)
1532 elif get_option('driver_interface').enabled()
1533   error('Requested the Interface driver without netcf or udev and libvirtd support')
1534 endif
1536 if not get_option('driver_libxl').disabled() and conf.has('WITH_LIBVIRTD')
1537   libxl_version = '4.9.0'
1538   libxl_dep = dependency('xenlight', version: '>=' + libxl_version, required: get_option('driver_libxl'))
1540   if libxl_dep.found()
1541     libxl_firmware_dir = libxl_dep.get_variable(pkgconfig : 'xenfirmwaredir', default_value: '')
1542     libxl_execbin = libxl_dep.get_variable(pkgconfig : 'libexec_bin', default_value: '')
1543     if libxl_firmware_dir != ''
1544       conf.set_quoted('LIBXL_FIRMWARE_DIR', libxl_firmware_dir)
1545     endif
1546     if libxl_execbin != ''
1547       conf.set_quoted('LIBXL_EXECBIN_DIR', libxl_execbin)
1548     endif
1550     # If building with libxl, use the libxl utility header and lib too
1551     if cc.check_header('libxlutil.h')
1552       conf.set('WITH_LIBXLUTIL_H', 1)
1553     endif
1554     xl_util_dep = dependency('xlutil')
1556     xen_store_dep = dependency('xenstore')
1557     xtl_link_dep = dependency('xentoollog')
1559     # Upstream Xen failed to advertise LIBXL_API_VERSION 0x040700 and
1560     # 0x040800 until the Xen 4.13 release. For Xen versions 4.9-4.12
1561     # we'll need to stick with version 0x040500.
1562     if libxl_dep.version().version_compare('>=4.13.0')
1563       LIBXL_API_VERSION='0x041300'
1564     else
1565       LIBXL_API_VERSION='0x040500'
1566     endif
1567     libxl_dep = declare_dependency(
1568       compile_args: '-DLIBXL_API_VERSION=' + LIBXL_API_VERSION,
1569       dependencies: [
1570         libxl_dep,
1571         xtl_link_dep,
1572         xl_util_dep,
1573         xen_store_dep,
1574       ],
1575     )
1577     # Check if Xen has support for PVH
1578     if cc.has_header_symbol('libxl.h', 'LIBXL_DOMAIN_TYPE_PVH')
1579       conf.set('WITH_XEN_PVH', 1)
1580     endif
1582     conf.set('WITH_LIBXL', 1)
1583   endif
1584 elif get_option('driver_libxl').enabled()
1585   error('libvirtd is required for libxenlight')
1586 endif
1588 if not get_option('driver_lxc').disabled() and host_machine.system() == 'linux' and conf.has('WITH_LIBVIRTD')
1589   conf.set('WITH_LXC', 1)
1590 elif get_option('driver_lxc').enabled()
1591   error('linux and remote_driver are required for LXC')
1592 endif
1594 if not get_option('driver_ch').disabled() and host_machine.system() == 'linux' and (host_machine.cpu_family() == 'x86_64' or host_machine.cpu_family() == 'aarch64')
1595   use_ch = true
1597   if not conf.has('WITH_LIBVIRTD')
1598     use_ch = false
1599     if get_option('driver_ch').enabled()
1600       error('libvirtd is required to build Cloud-Hypervisor driver')
1601     endif
1602   endif
1604   if not yajl_dep.found()
1605     use_ch = false
1606     if get_option('driver_ch').enabled()
1607       error('YAJL 2 is required to build Cloud-Hypervisor driver')
1608     endif
1609   endif
1611   if not curl_dep.found()
1612     use_ch = false
1613     if get_option('driver_ch').enabled()
1614       error('curl is required to build Cloud-Hypervisor driver')
1615     endif
1616   endif
1618   if use_ch
1619     conf.set('WITH_CH', 1)
1621     default_ch_user = 'root'
1622     default_ch_group = 'root'
1623     ch_user = get_option('ch_user')
1624     if ch_user == ''
1625       ch_user = default_ch_user
1626     endif
1627     ch_group = get_option('ch_group')
1628     if ch_group == ''
1629       ch_group = default_ch_group
1630     endif
1631     conf.set_quoted('CH_USER', ch_user)
1632     conf.set_quoted('CH_GROUP', ch_group)
1633   endif
1634 endif
1636 if not get_option('driver_network').disabled() and conf.has('WITH_LIBVIRTD')
1637   conf.set('WITH_NETWORK', 1)
1639   firewall_backend_priority = get_option('firewall_backend_priority')
1640   if (not firewall_backend_priority.contains('nftables') or
1641       not firewall_backend_priority.contains('iptables') or
1642       firewall_backend_priority.length() != 2)
1643     error('invalid value for firewall_backend_priority option')
1644   endif
1646   conf.set('FIREWALL_BACKEND_PRIORITY_0', 'VIR_FIREWALL_BACKEND_' + firewall_backend_priority[0].to_upper())
1647   conf.set('FIREWALL_BACKEND_PRIORITY_1', 'VIR_FIREWALL_BACKEND_' + firewall_backend_priority[1].to_upper())
1648   conf.set('FIREWALL_BACKEND_PRIORITY_NUM', firewall_backend_priority.length())
1649 elif get_option('driver_network').enabled()
1650   error('libvirtd must be enabled to build the network driver')
1651 endif
1653 if udev_dep.found() and conf.has('WITH_LIBVIRTD')
1654   conf.set('WITH_NODE_DEVICES', 1)
1655 endif
1657 if not get_option('driver_openvz').disabled() and host_machine.system() == 'linux'
1658   conf.set('WITH_OPENVZ', 1)
1659 elif get_option('driver_openvz').enabled()
1660   error('OpenVZ driver can be enabled on Linux only')
1661 endif
1663 if not get_option('driver_qemu').disabled()
1664   use_qemu = true
1666   if not yajl_dep.found()
1667     use_qemu = false
1668     if get_option('driver_qemu').enabled()
1669       error('YAJL 2 is required to build QEMU driver')
1670     endif
1671   endif
1673   if not conf.has('WITH_LIBVIRTD')
1674     use_qemu = false
1675     if get_option('driver_qemu').enabled()
1676       error('libvirtd is required to build QEMU driver')
1677     endif
1678   endif
1680   if use_qemu
1681     conf.set('WITH_QEMU', 1)
1683     qemu_moddir = get_option('qemu_moddir')
1684     if qemu_moddir == ''
1685       qemu_moddir = libdir / 'qemu'
1686     endif
1687     conf.set_quoted('QEMU_MODDIR', qemu_moddir)
1689     qemu_datadir = get_option('qemu_datadir')
1690     if qemu_datadir == ''
1691       qemu_datadir = datadir / 'qemu'
1692     endif
1693     conf.set_quoted('QEMU_DATADIR', qemu_datadir)
1695     qemu_user = get_option('qemu_user')
1696     qemu_group = get_option('qemu_group')
1697     if (qemu_user == '' and qemu_group != '') or (qemu_user != '' and qemu_group == '')
1698       error('Please specify both qemu_user and qemu_group or neither of them')
1699     endif
1700     if qemu_user == '' and qemu_group == ''
1701       if host_machine.system() in [ 'freebsd', 'darwin' ]
1702         qemu_user = 'root'
1703         qemu_group = 'wheel'
1704       else
1705         # RHEL and CentOS both have ID_LIKE=fedora, SLES has ID_LIKE=suse
1706         if (os_release.contains('fedora') or
1707             os_release.contains('gentoo') or
1708             os_release.contains('suse'))
1709           qemu_user = 'qemu'
1710           qemu_group = 'qemu'
1711         # Ubuntu has ID_LIKE=debian so we need to handle it first
1712         elif os_release.contains('ubuntu')
1713           qemu_user = 'libvirt-qemu'
1714           qemu_group = 'kvm'
1715         elif (os_release.contains('arch') or
1716               os_release.contains('debian'))
1717           qemu_user = 'libvirt-qemu'
1718           qemu_group = 'libvirt-qemu'
1719         else
1720           qemu_user = 'root'
1721           qemu_group = 'root'
1722         endif
1723       endif
1724     endif
1725     conf.set_quoted('QEMU_USER', qemu_user)
1726     conf.set_quoted('QEMU_GROUP', qemu_group)
1728     qemu_slirp_prog = find_program(
1729       'slirp-helper',
1730       dirs: [ '/usr/bin', '/usr/libexec' ],
1731       required: false
1732     )
1733     if qemu_slirp_prog.found()
1734       qemu_slirp_path = qemu_slirp_prog.full_path()
1735     else
1736       qemu_slirp_path = '/usr/bin/slirp-helper'
1737     endif
1738     conf.set_quoted('QEMU_SLIRP_HELPER', qemu_slirp_path)
1739   endif
1740 endif
1742 if not get_option('driver_secrets').disabled() and conf.has('WITH_LIBVIRTD')
1743   conf.set('WITH_SECRETS', 1)
1744 endif
1746 if not get_option('driver_test').disabled()
1747   conf.set('WITH_TEST', 1)
1748 endif
1750 if not get_option('driver_vbox').disabled() and conf.has('WITH_LIBVIRTD')
1751   conf.set('WITH_VBOX', 1)
1752   conf.set_quoted('VBOX_XPCOMC_DIR', get_option('vbox_xpcomc_dir'))
1753 endif
1755 if not get_option('driver_vmware').disabled()
1756   conf.set('WITH_VMWARE', 1)
1757   conf.set('WITH_VMX', 1)
1758 endif
1760 if not get_option('driver_vz').disabled() and parallels_sdk_dep.found()
1761   conf.set('WITH_VZ', 1)
1762 elif get_option('driver_vz').enabled()
1763   error('Parallels Virtualization SDK is needed to build the Virtuozzo driver.')
1764 endif
1766 if not get_option('secdriver_apparmor').disabled() and apparmor_dep.found()
1767   conf.set('WITH_SECDRIVER_APPARMOR', 1)
1768 elif get_option('secdriver_apparmor').enabled()
1769   error('You must install the AppArmor development package in order to compile libvirt.')
1770 endif
1772 if not get_option('secdriver_selinux').disabled() and selinux_dep.found()
1773   conf.set('WITH_SECDRIVER_SELINUX', 1)
1774 elif get_option('secdriver_selinux').enabled()
1775   error('You must install the libselinux development package in order to compile libvirt.')
1776 endif
1778 if conf.has('WITH_QEMU') or conf.has('WITH_LXC') or conf.has('WITH_NETWORK')
1779   conf.set('WITH_BRIDGE', 1)
1780 endif
1783 # check for storage drivers
1785 use_storage = false
1787 if conf.has('WITH_LIBVIRTD')
1788   if not get_option('storage_dir').disabled()
1789     use_storage = true
1790     conf.set('WITH_STORAGE_DIR', 1)
1791   endif
1793   if not get_option('storage_disk').disabled() and devmapper_dep.found() and libparted_dep.found()
1794     use_storage = true
1795     conf.set('WITH_STORAGE_DISK', 1)
1796   elif get_option('storage_disk').enabled()
1797     error('You must install libparted and libdevmapper to compile libvirt with disk storage driver')
1798   endif
1800   if not get_option('storage_fs').disabled()
1801     fs_enable = true
1803     # storage-fs does not work on macOS
1804     if host_machine.system() == 'darwin'
1805       fs_enable = false
1806     endif
1808     if fs_enable and not cc.check_header('mntent.h')
1809       if get_option('storage_fs').enabled()
1810         error('<mntent.h> is required for the FS storage driver')
1811       else
1812         fs_enable = false
1813       endif
1814     endif
1816     if fs_enable
1817       mount_prog = find_program('mount', required: get_option('storage_fs'), dirs: libvirt_sbin_path)
1818       umount_prog = find_program('umount', required: get_option('storage_fs'), dirs: libvirt_sbin_path)
1819       mkfs_prog = find_program('mkfs', required: get_option('storage_fs'), dirs: libvirt_sbin_path)
1821       if not mount_prog.found() or not umount_prog.found() or not mkfs_prog.found()
1822         fs_enable = false
1823       endif
1824     endif
1826     if fs_enable
1827       use_storage = true
1829       conf.set('WITH_STORAGE_FS', 1)
1830       conf.set_quoted('MOUNT', mount_prog.full_path())
1831       conf.set_quoted('UMOUNT', umount_prog.full_path())
1832       conf.set_quoted('MKFS', mkfs_prog.full_path())
1834       showmount_prog = find_program('showmount', required: false, dirs: libvirt_sbin_path)
1835       showmount_path = ''
1836       if showmount_prog.found()
1837         showmount_path = showmount_prog.full_path()
1838       endif
1839       conf.set_quoted('SHOWMOUNT', showmount_path)
1840     endif
1841   endif
1843   if not get_option('storage_gluster').disabled() and glusterfs_dep.found()
1844     use_storage = true
1845     conf.set('WITH_STORAGE_GLUSTER', 1)
1846   elif get_option('storage_gluster').enabled()
1847     error('Need glusterfs (libgfapi) for gluster storage driver')
1848   endif
1850   if not get_option('storage_iscsi').disabled() and iscsiadm_prog.found()
1851     use_storage = true
1852     conf.set('WITH_STORAGE_ISCSI', 1)
1853   elif get_option('storage_iscsi').enabled()
1854     error('We need iscsiadm for iSCSI storage driver')
1855   endif
1857   if not get_option('storage_iscsi_direct').disabled() and libiscsi_dep.found()
1858     use_storage = true
1859     conf.set('WITH_STORAGE_ISCSI_DIRECT', 1)
1860   elif get_option('storage_iscsi_direct').enabled()
1861     error('Need libiscsi for iscsi-direct storage driver')
1862   endif
1864   if not get_option('storage_lvm').disabled()
1865     lvm_enable = true
1866     lvm_progs = [
1867       'pvcreate', 'vgcreate', 'lvcreate',
1868       'pvremove', 'vgremove', 'lvremove',
1869       'lvchange', 'vgchange', 'vgscan',
1870       'pvs', 'vgs', 'lvs',
1871     ]
1872     foreach name : lvm_progs
1873       set_variable(
1874         '@0@_prog'.format(name),
1875         find_program(name, required: get_option('storage_lvm'), dirs: libvirt_sbin_path)
1876       )
1877       if not get_variable('@0@_prog'.format(name)).found()
1878         lvm_enable = false
1879       endif
1880     endforeach
1882     if lvm_enable
1883       use_storage = true
1884       conf.set('WITH_STORAGE_LVM', 1)
1886       foreach name : lvm_progs
1887         conf.set_quoted(name.to_upper(), get_variable('@0@_prog'.format(name)).full_path())
1888       endforeach
1889     endif
1890   endif
1892   if not get_option('storage_mpath').disabled() and host_machine.system() == 'linux' and devmapper_dep.found()
1893     use_storage = true
1894     conf.set('WITH_STORAGE_MPATH', 1)
1895   elif get_option('storage_mpath').enabled()
1896     error('mpath storage driver is supported only on Linux and you must install libdevmapper')
1897   endif
1899   if not get_option('storage_rbd').disabled() and rbd_dep.found()
1900     use_storage = true
1901     conf.set('WITH_STORAGE_RBD', 1)
1902   elif get_option('storage_rbd').enabled()
1903     error('You must install the librbd library & headers to compile libvirt')
1904   endif
1906   if not get_option('storage_scsi').disabled() and host_machine.system() == 'linux'
1907     use_storage = true
1908     conf.set('WITH_STORAGE_SCSI', 1)
1909   endif
1911   if not get_option('storage_vstorage').disabled()
1912     vstorage_enable = true
1913     if host_machine.system() != 'linux'
1914       vstorage_enable = false
1915       if get_option('storage_vstorage').enabled()
1916         error('Vstorage is supported only on Linux')
1917       endif
1918     endif
1920     if vstorage_enable
1921       use_storage = true
1922       conf.set('WITH_STORAGE_VSTORAGE', 1)
1923     endif
1924   endif
1926   if not get_option('storage_zfs').disabled()
1927     use_storage = true
1928     conf.set('WITH_STORAGE_ZFS', 1)
1929   endif
1930 endif
1932 if use_storage
1933   conf.set('WITH_STORAGE', 1)
1934 endif
1937 # build feature options
1939 chrdev_lock_files = get_option('chrdev_lock_files')
1940 if chrdev_lock_files == '' and host_machine.system() == 'linux'
1941   chrdev_lock_files = '/var/lock'
1942 endif
1943 if chrdev_lock_files != ''
1944   conf.set_quoted('VIR_CHRDEV_LOCK_FILE_PATH', chrdev_lock_files)
1945 endif
1947 driver_modules_flags = []
1948 if conf.has('WITH_LIBVIRTD')
1949   if not conf.has('WITH_DLFCN_H') or not dlopen_dep.found()
1950     error('You must have dlfcn.h / dlopen() support to build driver modules')
1951   endif
1952   driver_modules_flags = libvirt_export_dynamic
1953 endif
1955 if host_machine.system() == 'linux'
1956   dtrace_prog = find_program('dtrace', required: get_option('dtrace'), dirs: libvirt_sbin_path)
1957   if dtrace_prog.found()
1958     conf.set('WITH_DTRACE_PROBES', 1)
1959   endif
1960   dtrace_command = [ 'env', 'CC=' + ' '.join(meson.get_compiler('c').cmd_array()), dtrace_prog ]
1961 endif
1963 if not get_option('host_validate').disabled() and host_machine.system() != 'windows'
1964   conf.set('WITH_HOST_VALIDATE', 1)
1965 elif get_option('host_validate').enabled()
1966   error('virt-host-validate is not supported on Windows')
1967 endif
1969 if get_option('init_script') == 'check'
1970   if meson.is_cross_build()
1971     init_script = 'none'
1972   elif find_program('systemctl', required: false).found()
1973     init_script = 'systemd'
1974   elif find_program('openrc', required: false).found()
1975     init_script = 'openrc'
1976   else
1977     init_script = 'none'
1978   endif
1979 else
1980   init_script = get_option('init_script')
1981 endif
1983 loader_nvram = get_option('loader_nvram')
1984 if loader_nvram != ''
1985   if (loader_nvram.split(':').length() % 2) != 0
1986     error('Malformed loader_nvram option')
1987   endif
1988   conf.set_quoted('DEFAULT_LOADER_NVRAM', loader_nvram)
1989 endif
1991 if not get_option('login_shell').disabled() and host_machine.system() == 'linux'
1992   conf.set('WITH_LOGIN_SHELL', 1)
1993 elif get_option('login_shell').enabled()
1994   error('virt-login-shell is supported on Linux only')
1995 endif
1997 if not get_option('nss').disabled()
1998   use_nss = true
1999   if not yajl_dep.found()
2000     if get_option('nss').enabled()
2001       error('Can\'t build nss plugin without yajl')
2002     else
2003       use_nss = false
2004     endif
2005   endif
2007   if use_nss and not conf.has('WITH_NETWORK')
2008     if get_option('nss').enabled()
2009       error('Can\'t build nss plugin without network')
2010     else
2011       use_nss = false
2012     endif
2013   endif
2015   if use_nss and not cc.check_header('nss.h')
2016     if get_option('nss').enabled()
2017       error('Can\'t build nss plugin without nss.h')
2018     else
2019       use_nss = false
2020     endif
2021   endif
2023   if use_nss
2024     conf.set('WITH_NSS', 1)
2026     if cc.has_type('struct gaih_addrtuple', prefix: '#include <nss.h>')
2027       conf.set('WITH_STRUCT_GAIH_ADDRTUPLE', 1)
2028     endif
2030     if (cc.has_type('ns_mtab', prefix: '#include <nsswitch.h>') and
2031         cc.has_type('nss_module_unregister_fn', prefix: '#include <nsswitch.h>'))
2032       conf.set('WITH_BSD_NSS', 1)
2033     endif
2034   endif
2035 endif
2037 if not get_option('numad').disabled() and numactl_dep.found()
2038   numad_prog = find_program('numad', required: get_option('numad'), dirs: libvirt_sbin_path)
2039   if numad_prog.found()
2040     conf.set('WITH_NUMAD', 1)
2041     conf.set_quoted('NUMAD', numad_prog.full_path())
2042   endif
2043 elif get_option('numad').enabled()
2044   error('You must have numactl enabled for numad support.')
2045 endif
2047 # nwfilter should only be compiled for linux, and only if the
2048 # libvirt daemon is also being compiled
2049 if conf.has('WITH_LIBVIRTD') and host_machine.system() == 'linux'
2050   conf.set('WITH_NWFILTER', 1)
2051 endif
2053 if not get_option('pm_utils').disabled()
2054   use_pm_utils = true
2055   if init_script == 'systemd'
2056     use_pm_utils = false
2057   endif
2059   if use_pm_utils
2060     conf.set('WITH_PM_UTILS', 1)
2061   endif
2062 endif
2064 if not get_option('ssh_proxy').disabled() and conf.has('WITH_DECL_STRUCT_SOCKADDR_VM')
2065   conf.set('WITH_SSH_PROXY', 1)
2066 elif get_option('ssh_proxy').enabled()
2067   error('ssh proxy requires vm_sockets.h which wasn\'t found')
2068 endif
2070 if not get_option('sysctl_config').disabled() and host_machine.system() == 'linux'
2071   conf.set('WITH_SYSCTL', 1)
2072 elif get_option('sysctl_config').enabled()
2073   error('sysctl configuration is supported only on linux')
2074 endif
2076 if not get_option('userfaultfd_sysctl').disabled() and conf.has('WITH_SYSCTL')
2077   conf.set('WITH_USERFAULTFD_SYSCTL', 1)
2078 elif get_option('userfaultfd_sysctl').enabled()
2079   error('userfaultfd_sysctl option requires sysctl_config to be enabled')
2080 endif
2082 conf.set_quoted('TLS_PRIORITY', get_option('tls_priority'))
2085 # test options
2087 tests_enabled = [ not get_option('tests').disabled() ]
2088 if tests_enabled[0] and \
2089    cc.get_id() == 'clang' and \
2090    not supported_cc_flags.contains('-fsemantic-interposition') \
2091    and get_option('optimization') != '0'
2092    # If CLang doesn't support -fsemantic-interposition then our
2093    # mocking doesn't work. The best we can do is to not run the
2094    # test suite.
2095    msg = 'Forcibly disabling tests because CLang lacks -fsemantic-interposition. Update CLang or disable optimization'
2096    if get_option('tests').enabled()
2097      error(msg)
2098    endif
2099    tests_enabled = [ false, '!!! @0@ !!!'.format(msg) ]
2100 endif
2102 if get_option('expensive_tests').auto()
2103   use_expensive_tests = not git and tests_enabled[0]
2104 else
2105   use_expensive_tests = get_option('expensive_tests').enabled()
2106   if use_expensive_tests and not tests_enabled[0]
2107     error('cannot enable expensive tests when tests are disabled')
2108   endif
2109 endif
2111 coverage_flags = []
2112 if get_option('test_coverage')
2113   coverage_flags = [
2114     '-fprofile-arcs',
2115     '-ftest-coverage',
2116   ]
2117 endif
2120 # Various definitions
2122 # Python3 < 3.7 treats the C locale as 7-bit only. We must force env vars so
2123 # it treats it as UTF-8 regardless of the user's locale.
2124 runutf8 = [ 'LC_ALL=', 'LANG=C', 'LC_CTYPE=en_US.UTF-8' ]
2127 # define top include directory
2129 top_inc_dir = include_directories('.')
2131 keycodemapdb = subproject('keycodemapdb')
2133 # include remaining subdirs
2135 subdir('scripts')
2137 subdir('include')
2139 subdir('src')
2141 subdir('tools')
2143 if tests_enabled[0]
2144   subdir('tests')
2145 else
2146   # Ensure that 'meson test' fails when tests are disabled, as opposed to
2147   # misleadingly succeeding at doing absolutely nothing
2148   test(
2149     'tests-are-disabled',
2150     python3_prog, args: [ '-c', 'raise Exception("tests are disabled")' ],
2151   )
2152 endif
2154 subdir('examples')
2156 subdir('po')
2158 gen_docs = not get_option('docs').disabled()
2159 if gen_docs
2160   subdir('docs')
2161 endif
2163 subdir('build-aux')
2166 # install pkgconfig files
2167 pkgconfig_files = [
2168   'libvirt.pc.in',
2169   'libvirt-qemu.pc.in',
2170   'libvirt-lxc.pc.in',
2171   'libvirt-admin.pc.in',
2174 pkgconfig_conf = configuration_data({
2175   'VERSION': meson.project_version(),
2176   'datadir': datadir,
2177   'datarootdir': datadir,
2178   'exec_prefix': prefix,
2179   'includedir': includedir,
2180   'libdir': libdir,
2181   'prefix': prefix,
2184 pkgconfig_dir = libdir / 'pkgconfig'
2186 foreach file : pkgconfig_files
2187   configure_file(
2188     input: file,
2189     output: '@BASENAME@',
2190     configuration: pkgconfig_conf,
2191     install: true,
2192     install_dir: pkgconfig_dir,
2193   )
2194 endforeach
2197 # generate dist files
2199 if git
2200   spec_conf = configuration_data({
2201     'VERSION': meson.project_version(),
2202   })
2204   configure_file(
2205     input: 'libvirt.spec.in',
2206     output: '@BASENAME@',
2207     configuration: spec_conf,
2208   )
2210   authors = run_command(python3_prog, meson_gen_authors_prog.full_path(),
2211                         env: runutf8, check: true)
2212   authors_file = 'AUTHORS.rst.in'
2214   authors_conf = configuration_data({
2215     'contributorslist': authors.stdout(),
2216   })
2218   configure_file(
2219     input: authors_file,
2220     output: '@BASENAME@',
2221     configuration: authors_conf,
2222   )
2224   # Using return values from configure_file in add_dist_script is possible since 0.55.0
2225   dist_files = [
2226     'libvirt.spec',
2227     'AUTHORS.rst',
2228   ]
2230   foreach file : dist_files
2231     meson.add_dist_script(
2232       meson_python_prog.full_path(), python3_prog.full_path(),
2233       meson_dist_prog.full_path(), file
2234     )
2235   endforeach
2236 endif
2239 # generate meson-config.h file
2240 configure_file(output: 'meson-config.h', configuration: conf)
2243 # generate run helper
2244 run_conf = configuration_data({
2245   'abs_builddir': meson.project_build_root(),
2246   'abs_top_builddir': meson.project_build_root(),
2249 configure_file(
2250   input: 'run.in',
2251   output: '@BASENAME@',
2252   configuration: run_conf,
2254 run_command('chmod', 'a+x', meson.current_build_dir() / 'run', check: true)
2257 # print configuration summary
2259 driver_summary = {
2260   'QEMU': conf.has('WITH_QEMU'),
2261   'OpenVZ': conf.has('WITH_OPENVZ'),
2262   'VMware': conf.has('WITH_VMWARE'),
2263   'VBox': conf.has('WITH_VBOX'),
2264   'libxl': conf.has('WITH_LIBXL'),
2265   'LXC': conf.has('WITH_LXC'),
2266   'Cloud-Hypervisor': conf.has('WITH_CH'),
2267   'ESX': conf.has('WITH_ESX'),
2268   'Hyper-V': conf.has('WITH_HYPERV'),
2269   'vz': conf.has('WITH_VZ'),
2270   'Bhyve': conf.has('WITH_BHYVE'),
2271   'Test': conf.has('WITH_TEST'),
2272   'Remote': conf.has('WITH_REMOTE'),
2273   'Network': conf.has('WITH_NETWORK'),
2274   'Libvirtd': conf.has('WITH_LIBVIRTD'),
2275   'Interface': conf.has('WITH_INTERFACE'),
2277 summary(driver_summary, section: 'Drivers', bool_yn: true)
2279 storagedriver_summary = {
2280   'Dir': conf.has('WITH_STORAGE_DIR'),
2281   'FS': conf.has('WITH_STORAGE_FS'),
2282   'NetFS': conf.has('WITH_STORAGE_FS'),
2283   'LVM': conf.has('WITH_STORAGE_LVM'),
2284   'iSCSI': conf.has('WITH_STORAGE_ISCSI'),
2285   'iscsi-direct': conf.has('WITH_STORAGE_ISCSI_DIRECT'),
2286   'SCSI': conf.has('WITH_STORAGE_SCSI'),
2287   'mpath': conf.has('WITH_STORAGE_MPATH'),
2288   'Disk': conf.has('WITH_STORAGE_DISK'),
2289   'RBD': conf.has('WITH_STORAGE_RBD'),
2290   'Gluster': conf.has('WITH_STORAGE_GLUSTER'),
2291   'ZFS': conf.has('WITH_STORAGE_ZFS'),
2292   'Virtuozzo storage': conf.has('WITH_STORAGE_VSTORAGE'),
2294 summary(storagedriver_summary, section: 'Storage Drivers', bool_yn: true)
2296 secdriver_summary = {
2297   'SELinux': conf.has('WITH_SECDRIVER_SELINUX'),
2298   'AppArmor': conf.has('WITH_SECDRIVER_APPARMOR'),
2300 summary(secdriver_summary, section: 'Security Drivers', bool_yn: true)
2302 drivermod_summary = {
2303   'driver_modules': driver_modules_flags.length() > 0,
2305 summary(drivermod_summary, section: 'Driver Loadable Modules', bool_yn: true)
2307 libs_summary = {
2308   'acl': acl_dep.found(),
2309   'apparmor': apparmor_dep.found(),
2310   'attr': attr_dep.found(),
2311   'audit': audit_dep.found(),
2312   'bash_completion': bash_completion_dep.found(),
2313   'blkid': blkid_dep.found(),
2314   'capng': capng_dep.found(),
2315   'curl': curl_dep.found(),
2316   'devmapper': devmapper_dep.found(),
2317   'dlopen': dlopen_dep.found(),
2318   'fuse': fuse_dep.found(),
2319   'glusterfs': glusterfs_dep.found(),
2320   'libiscsi': libiscsi_dep.found(),
2321   'libkvm': libkvm_dep.found(),
2322   'libnbd': libnbd_dep.found(),
2323   'libnl': libnl_dep.found(),
2324   'libparted': libparted_dep.found(),
2325   'libpcap': libpcap_dep.found(),
2326   'libssh': libssh_dep.found(),
2327   'libssh2': libssh2_dep.found(),
2328   'libutil': libutil_dep.found(),
2329   'netcf': netcf_dep.found(),
2330   'NLS': have_gnu_gettext_tools,
2331   'numactl': numactl_dep.found(),
2332   'openwsman': openwsman_dep.found(),
2333   'parallels-sdk': parallels_sdk_dep.found(),
2334   'pciaccess': pciaccess_dep.found(),
2335   'polkit': conf.has('WITH_POLKIT'),
2336   'rbd': rbd_dep.found(),
2337   'readline': readline_dep.found(),
2338   'sanlock': sanlock_dep.found(),
2339   'sasl': sasl_dep.found(),
2340   'selinux': selinux_dep.found(),
2341   'udev': udev_dep.found(),
2342   'xdr': xdr_dep.found(),
2343   'yajl': yajl_dep.found(),
2345 summary(libs_summary, section: 'Libraries', bool_yn: true)
2347 win_summary = {
2348   'MinGW': host_machine.system() == 'windows',
2349   'windres': host_machine.system() == 'windows',
2351 summary(win_summary, section: 'Windows', bool_yn: true)
2353 test_summary = {
2354   'Expensive': use_expensive_tests,
2355   'Coverage': coverage_flags.length() > 0,
2357 summary(test_summary, section: 'Test suite', bool_yn: true)
2359 if conf.has('DEFAULT_LOADER_NVRAM')
2360   loader_res = '@0@ !!! Using this configure option is strongly discouraged !!!'.format(conf.get_unquoted('DEFAULT_LOADER_NVRAM'))
2361 else
2362   loader_res = ''
2363 endif
2364 misc_summary = {
2365   'Warning Flags': supported_cc_flags,
2366   'docs': gen_docs,
2367   'tests': tests_enabled,
2368   'DTrace': conf.has('WITH_DTRACE_PROBES'),
2369   'firewalld': conf.has('WITH_FIREWALLD'),
2370   'firewalld-zone': conf.has('WITH_FIREWALLD_ZONE'),
2371   'nss': conf.has('WITH_NSS'),
2372   'numad': conf.has('WITH_NUMAD'),
2373   'nbdkit': conf.has('WITH_NBDKIT'),
2374   'Init script': init_script,
2375   'Char device locks': chrdev_lock_files,
2376   'Loader/NVRAM': loader_res,
2377   'pm_utils': conf.has('WITH_PM_UTILS'),
2378   'virt-login-shell': conf.has('WITH_LOGIN_SHELL'),
2379   'virt-host-validate': conf.has('WITH_HOST_VALIDATE'),
2380   'TLS priority': conf.get_unquoted('TLS_PRIORITY'),
2381   'SSH proxy': conf.has('WITH_SSH_PROXY'),
2382   'sysctl config': conf.has('WITH_SYSCTL'),
2383   'userfaultfd sysctl': conf.has('WITH_USERFAULTFD_SYSCTL'),
2385 if conf.has('WITH_NETWORK')
2386   misc_summary += {
2387     'firewall backends': firewall_backend_priority,
2388   }
2389 endif
2390 summary(misc_summary, section: 'Miscellaneous', bool_yn: true, list_sep: ' ')
2392 devtools_summary = {
2393   'wireshark_dissector': wireshark_dep.found(),
2395 summary(devtools_summary, section: 'Developer Tools', bool_yn: true)
2397 if missing_optional_programs.length() > 0
2398   missing_list = ' '.join(missing_optional_programs)
2399   missing_warn = ' (some tests will be skipped!)'
2400   test_programs_summary = {
2401     'Missing': missing_list + missing_warn,
2402   }
2403   summary(test_programs_summary, section: 'Optional programs', bool_yn: true)
2404 endif
2406 if conf.has('WITH_QEMU')
2407   qemu_warn = ''
2408   if qemu_user == 'root'
2409     qemu_warn = ' !!! running QEMU as root is strongly discouraged !!!'
2410   endif
2411   priv_summary = {
2412     'QEMU': '@0@:@1@@2@'.format(qemu_user, qemu_group, qemu_warn),
2413   }
2414   summary(priv_summary, section: 'Privileges')
2415 endif