5 meson_version: '>= 0.56.0',
7 'buildtype=debugoptimized',
14 if meson.version().version_compare('>=0.64.0')
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)
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'
46 conf.set('_WIN32_WINNT', '0x0600') # Win Vista / Server 2008
47 conf.set('WINVER', '0x0600') # Win Vista / Server 2008
53 if get_option('system')
55 libdir = prefix / 'lib64'
56 if run_command('test', '-d', libdir, check: false).returncode() != 0
57 libdir = prefix / 'lib'
59 localstatedir = '/var'
62 prefix = get_option('prefix')
63 libdir = prefix / get_option('libdir')
64 localstatedir = prefix / get_option('localstatedir')
65 sysconfdir = prefix / get_option('sysconfdir')
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
71 if localstatedir == '/usr/var'
72 localstatedir = '/var'
74 if sysconfdir == '/usr/etc'
79 runstatedir = get_option('runstatedir')
81 runstatedir = localstatedir / 'run'
84 initconfdir = get_option('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'
94 initconfdir = sysconfdir / 'sysconfig'
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')
110 docdir = datadir / 'doc' / meson.project_name()
113 confdir = sysconfdir / meson.project_name()
114 pkgdatadir = datadir / meson.project_name()
116 sshconfdir = get_option('sshconfdir')
118 sshconfdir = sysconfdir / 'ssh' / 'ssh_config.d'
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)
139 input: 'configmake.h.in',
140 output: '@BASENAME@',
141 configuration: configmake_conf,
147 packager = get_option('packager')
148 packager_version = get_option('packager_version')
151 conf.set_quoted('PACKAGER', packager)
154 if packager_version != ''
155 conf.set_quoted('PACKAGER_VERSION', packager_version)
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()
165 libvirt_rpath = libdir
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:
179 # The most recent interface number that this library implements.
182 # The implementation number of the CURRENT interface.
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')
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' ]
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(
234 'print(min(2**(@0@ * 8 - 1) - 1, 2**(@1@ * 8) - 1))'.format(ptrdiff_max, size_max),
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
245 # sanitizer instrumentation may enlarge stack frames
246 if get_option('b_sanitize') != 'none'
247 stack_frame_size = 32768
250 # array_bounds=2 check triggers false positive on some GCC
251 # versions when using sanitizers. Seen on Fedora 34 with
253 array_bounds = get_option('b_sanitize') == 'none' ? 2 : 1
256 '-fasynchronous-unwind-tables',
262 '-Waddress-of-packed-member',
263 '-Waggressive-loop-optimizations',
264 '-Walloc-size-larger-than=@0@'.format(alloc_max.stdout().strip()),
266 '-Warray-bounds=@0@'.format(array_bounds),
267 '-Wattribute-alias=2',
268 '-Wattribute-warning',
272 '-Wbuiltin-declaration-mismatch',
273 '-Wbuiltin-macro-redefined',
276 '-Wcast-align=strict',
277 # We do "bad" function casts all the time for event callbacks
278 '-Wno-cast-function-type',
283 '-Wcoverage-mismatch',
287 '-Wdeclaration-after-statement',
288 '-Wdeprecated-declarations',
290 '-Wdiscarded-array-qualifiers',
291 '-Wdiscarded-qualifiers',
294 '-Wduplicate-decl-specifier',
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',
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',
308 '-Wformat-zero-length',
310 '-Wframe-larger-than=@0@'.format(stack_frame_size),
311 '-Wfree-nonheap-object',
314 '-Wignored-attributes',
315 '-Wignored-qualifiers',
317 '-Wimplicit-fallthrough=5',
318 '-Wimplicit-function-declaration',
320 '-Wincompatible-pointer-types',
324 '-Wint-in-bool-context',
325 '-Wint-to-pointer-cast',
326 '-Winvalid-memory-model',
328 '-Wjump-misses-init',
329 '-Wlogical-not-parentheses',
332 '-Wmaybe-uninitialized',
334 '-Wmemset-transposed-args',
335 '-Wmisleading-indentation',
336 '-Wmissing-attributes',
338 '-Wmissing-declarations',
339 '-Wmissing-field-initializers',
340 '-Wmissing-include-dirs',
341 '-Wmissing-parameter-type',
343 '-Wmissing-prototypes',
345 '-Wmultistatement-macros',
351 '-Wnull-dereference',
353 '-Wold-style-declaration',
354 '-Wold-style-definition',
358 '-Wpacked-bitfield-compat',
359 '-Wpacked-not-aligned',
364 '-Wpointer-to-int-cast',
368 '-Wreturn-local-addr',
370 '-Wscalar-storage-order',
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...
379 '-Wsizeof-array-argument',
380 '-Wsizeof-pointer-div',
381 '-Wsizeof-pointer-memaccess',
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',
396 '-Wswitch-unreachable',
398 '-Wtautological-compare',
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',
408 '-Wunused-but-set-parameter',
409 '-Wunused-but-set-variable',
410 '-Wunused-const-variable=2',
413 '-Wunused-local-typedefs',
414 '-Wunused-parameter',
420 '-Wvector-operation-performance',
422 '-Wvolatile-register-var',
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
435 # This is a bit of a big hammer, but alternatives don't work:
437 # - 'weak' attribute - weak symbols get dropped from
438 # when the .a libs are combined into the .so
439 # see commit 407a281a8e2b6c5078ba1148535663ea64fd9314
441 # - 'noipa' attribute - only available with GCC currently
442 # https://reviews.llvm.org/D101011
443 cc_flags += [ '-fsemantic-interposition' ]
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:
451 # bool_t xdr_TestEnum(XDR *, TestEnum *);
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' ]
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',
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')
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 = '''
486 return test == TEST1 || test == TEST2;
489 if not cc.compiles(w_logical_op_code, args: w_logical_op_args)
490 conf.set('BROKEN_GCC_WLOGICALOP_EQUAL_EXPR', 1)
494 # Check whether clang gives bogus warning for -Wdouble-promotion.
495 w_double_promotion_args = [ '-O2', '-Wdouble-promotion', '-Werror' ]
496 w_double_promotion_code = '''
504 if cc.compiles(w_double_promotion_code, args: w_double_promotion_args, name: '-Wdouble-promotion')
505 supported_cc_flags += [ '-Wdouble-promotion' ]
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; }
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' ]
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)
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',
536 # various linker checks
538 libvirt_relro = cc.get_supported_link_arguments([
543 libvirt_nodelete = cc.get_supported_link_arguments([
547 libvirt_no_undefined = []
548 if get_option('b_sanitize') == 'none'
549 libvirt_no_undefined += cc.get_supported_link_arguments([
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 = ''
568 version_script_flags = '-Wl,--version-script='
571 libvirt_flat_namespace = []
572 if host_machine.system() == 'darwin'
573 libvirt_flat_namespace = '-Wl,-flat_namespace'
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)
605 'sched_get_priority_min',
607 'sched_setscheduler',
625 functions += stat_functions
631 functions += open_functions
633 foreach function : functions
634 if cc.has_function(function)
635 conf.set('WITH_@0@'.format(function.to_upper()), 1)
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)
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)
654 # various header checks
677 if host_machine.system() == 'freebsd'
678 headers += 'libutil.h'
681 foreach name : headers
682 if cc.check_header(name)
683 conf.set('WITH_@0@'.format(name.underscorify().to_upper()), 1)
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')
695 # check various 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'
710 [ 'sys/syscall.h', 'SYS_pidfd_open' ],
712 [ 'linux/vm_sockets.h', 'struct sockaddr_vm', '#include <sys/socket.h>' ],
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)
722 # Check for BSD approach for bridge management
723 brd_required_headers = '''#include <stdint.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)
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)
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)
745 # check various types
748 [ 'struct ifreq', '#include <sys/socket.h>\n#include <net/if.h>'] ,
749 [ 'struct sockpeercred', '#include <sys/socket.h' ],
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)
759 if host_machine.system() == 'windows'
764 foreach type : uid_types
765 if not cc.has_type(type, prefix: '#include <sys/types.h>')
766 conf.set(type, 'int')
772 # check various 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)
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 += [
809 # required programs check
811 required_programs = [
818 if host_machine.system() == 'freebsd'
819 required_programs += 'ifconfig'
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)
831 optional_test_programs = [
839 optional_programs = [
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()
856 prog_path = prog.full_path()
859 if name in optional_test_programs
860 missing_optional_programs += [ name ]
864 conf.set_quoted(varname.to_upper(), prog_path)
865 set_variable('@0@_prog'.format(varname), prog)
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'))
882 xdr_dep = dependency('', required: false)
886 conf.set('WITH_REMOTE', 1)
887 elif get_option('driver_remote').enabled()
888 error('XDR is required for remote driver')
891 xdr_dep = dependency('', required: false)
895 # generic build dependencies
897 acl_dep = dependency('libacl', required: false)
899 conf.set('WITH_LIBACL', 1)
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)
908 conf.set_quoted('APPARMOR_DIR', sysconfdir / 'apparmor.d')
909 conf.set_quoted('APPARMOR_PROFILES_PATH', '/sys/kernel/security/apparmor/profiles')
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')
922 if apparmor_profiles_enable
923 conf.set('WITH_APPARMOR_PROFILES', 1)
927 # FIXME rewrite to use dependency() once we can use 2.4.48
928 attr_dep = cc.find_library('attr', required: get_option('attr'))
930 conf.set('WITH_LIBATTR', 1)
933 audit_dep = dependency('audit', required: get_option('audit'))
935 conf.set('WITH_AUDIT', 1)
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'))
944 conf.set('WITH_BLKID', 1)
947 capng_dep = dependency('libcap-ng', required: get_option('capng'))
949 conf.set('WITH_CAPNG', 1)
952 curl_version = '7.19.1'
953 curl_dep = dependency('libcurl', version: '>=' + curl_version, required: get_option('curl'))
955 conf.set('WITH_CURL', 1)
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)
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')
970 conf.set('WITH_DLFCN_H', 1)
973 fuse_version = '3.1.0'
974 fuse_dep = dependency('fuse3', version: '>=' + fuse_version, required: false)
976 conf.set('WITH_FUSE', 3)
978 fuse_version = '2.8.6'
979 fuse_dep = dependency('fuse', version: '>=' + fuse_version, required: get_option('fuse'))
981 conf.set('WITH_FUSE', 1)
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)
991 gio_dep = dependency('gio-unix-2.0', version: '>=' + glib_version)
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')
1015 libkvm_dep = dependency('', required: false)
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)')
1032 if not nbdkit_libnbd_ok and nbdkit_requested
1033 error('nbdkit support requires libnbd')
1036 if nbdkit_syscall_ok and nbdkit_libnbd_ok
1037 conf.set('WITH_NBDKIT', 1)
1040 if not conf.has('WITH_NBDKIT')
1041 libnbd_dep = dependency('', required: false)
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')
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 ],
1063 conf.set('WITH_LIBNL', 1)
1065 elif get_option('libnl').enabled()
1066 error('libnl can be enabled only on linux')
1068 libnl_dep = dependency('', required: false)
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)
1081 libpcap_dep = dependency('', required: false)
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)
1091 libssh_dep = dependency('', required: false)
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)
1101 libssh2_dep = dependency('', required: false)
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)
1116 netcf_dep = dependency('', required: false)
1119 have_gnu_gettext_tools = false
1120 if not get_option('nls').disabled()
1121 have_gettext = cc.has_function('gettext')
1123 intl_dep = cc.find_library('intl', required: false)
1124 have_gettext = intl_dep.found()
1126 intl_dep = dependency('', required: false)
1128 if not have_gettext and get_option('nls').enabled()
1129 error('gettext() is required to build libvirt')
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')
1143 foreach name : gettext_progs
1144 prog = find_program(name, required: false)
1145 set_variable('@0@_prog'.format(name), prog)
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
1155 intl_dep = dependency('', required: false)
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)
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)
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)
1185 rbd_dep = declare_dependency(dependencies: [ rbd_dep, rados_dep ])
1187 rbd_dep = dependency('', required: false)
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>')
1206 if get_option('readline').enabled()
1207 error('readline is missing rl_completion_quote_character')
1209 readline_dep = dependency('', required: false)
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 ],
1222 conf.set('WITH_READLINE', 1)
1225 readline_dep = dependency('', required: false)
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)
1239 sanlock_dep = dependency('', required: false)
1242 sasl_version = '2.1.26'
1243 if conf.has('WITH_REMOTE')
1244 sasl_dep = dependency('libsasl2', version: '>=' + sasl_version, required: get_option('sasl'))
1246 conf.set('WITH_SASL', 1)
1249 sasl_dep = dependency('', required: false)
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'
1259 selinux_mount = '/selinux'
1262 conf.set_quoted('SELINUX_MOUNT', selinux_mount)
1263 conf.set('WITH_SELINUX', 1)
1266 thread_dep = dependency('threads')
1267 pthread_sigmask_code = '''
1268 #include <sys/types.h>
1272 #ifdef pthread_sigmask
1273 int (*foo)(int, const sigset_t *, sigset_t *) = &pthread_sigmask;
1280 if not cc.compiles(pthread_sigmask_code)
1281 conf.set('FUNC_PTHREAD_SIGMASK_BROKEN', 1)
1284 udev_version = '219'
1285 udev_dep = dependency('libudev', version: '>=' + udev_version, required: get_option('udev'))
1287 conf.set('WITH_UDEV', 1)
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(
1303 if get_option('default_library') == 'static'
1304 win32_flags = [ '-DLIBVIRT_STATIC' ]
1308 win32_link_flags = [ '-Wl,-no-undefined' ]
1310 win32_dep = dependency('', required: false)
1312 win32_link_flags = []
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')
1322 wireshark_dep = dependency('', required: false)
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')
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'
1339 # Replace wireshark's prefix with our own.
1340 # There is no replace method in meson so we have to workaround it.
1343 'print("@0@".replace("@1@", "@2@"))'.format(
1344 wireshark_plugindir, wireshark_prefix, prefix,
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)
1361 yajl_version = '2.0.3'
1362 yajl_dep = dependency('yajl', version: '>=' + yajl_version, required: get_option('yajl'))
1364 # Kludge for yajl include path on non-Linux
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.
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.
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')
1385 'print("@0@".replace("@1@", "@2@"))'.format(
1386 yajl_includedir, 'include/yajl', 'include',
1390 yajl_includedir = rc.stdout().strip()
1391 yajl_dep = declare_dependency(
1392 compile_args: [ '-I' + yajl_includedir ],
1393 dependencies: [ yajl_dep ],
1398 conf.set('WITH_YAJL', 1)
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')
1408 bash_completion_dep = dependency('', required: false)
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')
1418 'print("@0@".replace("@1@", "@2@"))'.format(
1419 bash_completion_dir, bash_completion_prefix, prefix,
1423 bash_completion_dir = rc.stdout().strip()
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')
1438 conf.set('WITH_FIREWALLD', 1)
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')
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()
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')
1464 conf.set('WITH_POLKIT', 1)
1468 if udev_dep.found() and not pciaccess_dep.found()
1469 error('You must install the pciaccess module to build with udev')
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')
1480 if not get_option('driver_libvirtd').disabled()
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')
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')
1498 conf.set('WITH_LIBVIRTD', 1)
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())
1513 elif get_option('driver_bhyve').enabled()
1514 error('The bhyve driver cannot be enabled')
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')
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')
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')
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)
1546 if libxl_execbin != ''
1547 conf.set_quoted('LIBXL_EXECBIN_DIR', libxl_execbin)
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)
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'
1565 LIBXL_API_VERSION='0x040500'
1567 libxl_dep = declare_dependency(
1568 compile_args: '-DLIBXL_API_VERSION=' + LIBXL_API_VERSION,
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)
1582 conf.set('WITH_LIBXL', 1)
1584 elif get_option('driver_libxl').enabled()
1585 error('libvirtd is required for libxenlight')
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')
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')
1597 if not conf.has('WITH_LIBVIRTD')
1599 if get_option('driver_ch').enabled()
1600 error('libvirtd is required to build Cloud-Hypervisor driver')
1604 if not yajl_dep.found()
1606 if get_option('driver_ch').enabled()
1607 error('YAJL 2 is required to build Cloud-Hypervisor driver')
1611 if not curl_dep.found()
1613 if get_option('driver_ch').enabled()
1614 error('curl is required to build Cloud-Hypervisor driver')
1619 conf.set('WITH_CH', 1)
1621 default_ch_user = 'root'
1622 default_ch_group = 'root'
1623 ch_user = get_option('ch_user')
1625 ch_user = default_ch_user
1627 ch_group = get_option('ch_group')
1629 ch_group = default_ch_group
1631 conf.set_quoted('CH_USER', ch_user)
1632 conf.set_quoted('CH_GROUP', ch_group)
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')
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')
1653 if udev_dep.found() and conf.has('WITH_LIBVIRTD')
1654 conf.set('WITH_NODE_DEVICES', 1)
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')
1663 if not get_option('driver_qemu').disabled()
1666 if not yajl_dep.found()
1668 if get_option('driver_qemu').enabled()
1669 error('YAJL 2 is required to build QEMU driver')
1673 if not conf.has('WITH_LIBVIRTD')
1675 if get_option('driver_qemu').enabled()
1676 error('libvirtd is required to build QEMU driver')
1681 conf.set('WITH_QEMU', 1)
1683 qemu_moddir = get_option('qemu_moddir')
1684 if qemu_moddir == ''
1685 qemu_moddir = libdir / 'qemu'
1687 conf.set_quoted('QEMU_MODDIR', qemu_moddir)
1689 qemu_datadir = get_option('qemu_datadir')
1690 if qemu_datadir == ''
1691 qemu_datadir = datadir / 'qemu'
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')
1700 if qemu_user == '' and qemu_group == ''
1701 if host_machine.system() in [ 'freebsd', 'darwin' ]
1703 qemu_group = 'wheel'
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'))
1711 # Ubuntu has ID_LIKE=debian so we need to handle it first
1712 elif os_release.contains('ubuntu')
1713 qemu_user = 'libvirt-qemu'
1715 elif (os_release.contains('arch') or
1716 os_release.contains('debian'))
1717 qemu_user = 'libvirt-qemu'
1718 qemu_group = 'libvirt-qemu'
1725 conf.set_quoted('QEMU_USER', qemu_user)
1726 conf.set_quoted('QEMU_GROUP', qemu_group)
1728 qemu_slirp_prog = find_program(
1730 dirs: [ '/usr/bin', '/usr/libexec' ],
1733 if qemu_slirp_prog.found()
1734 qemu_slirp_path = qemu_slirp_prog.full_path()
1736 qemu_slirp_path = '/usr/bin/slirp-helper'
1738 conf.set_quoted('QEMU_SLIRP_HELPER', qemu_slirp_path)
1742 if not get_option('driver_secrets').disabled() and conf.has('WITH_LIBVIRTD')
1743 conf.set('WITH_SECRETS', 1)
1746 if not get_option('driver_test').disabled()
1747 conf.set('WITH_TEST', 1)
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'))
1755 if not get_option('driver_vmware').disabled()
1756 conf.set('WITH_VMWARE', 1)
1757 conf.set('WITH_VMX', 1)
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.')
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.')
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.')
1778 if conf.has('WITH_QEMU') or conf.has('WITH_LXC') or conf.has('WITH_NETWORK')
1779 conf.set('WITH_BRIDGE', 1)
1783 # check for storage drivers
1787 if conf.has('WITH_LIBVIRTD')
1788 if not get_option('storage_dir').disabled()
1790 conf.set('WITH_STORAGE_DIR', 1)
1793 if not get_option('storage_disk').disabled() and devmapper_dep.found() and libparted_dep.found()
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')
1800 if not get_option('storage_fs').disabled()
1803 # storage-fs does not work on macOS
1804 if host_machine.system() == 'darwin'
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')
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()
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)
1836 if showmount_prog.found()
1837 showmount_path = showmount_prog.full_path()
1839 conf.set_quoted('SHOWMOUNT', showmount_path)
1843 if not get_option('storage_gluster').disabled() and glusterfs_dep.found()
1845 conf.set('WITH_STORAGE_GLUSTER', 1)
1846 elif get_option('storage_gluster').enabled()
1847 error('Need glusterfs (libgfapi) for gluster storage driver')
1850 if not get_option('storage_iscsi').disabled() and iscsiadm_prog.found()
1852 conf.set('WITH_STORAGE_ISCSI', 1)
1853 elif get_option('storage_iscsi').enabled()
1854 error('We need iscsiadm for iSCSI storage driver')
1857 if not get_option('storage_iscsi_direct').disabled() and libiscsi_dep.found()
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')
1864 if not get_option('storage_lvm').disabled()
1867 'pvcreate', 'vgcreate', 'lvcreate',
1868 'pvremove', 'vgremove', 'lvremove',
1869 'lvchange', 'vgchange', 'vgscan',
1870 'pvs', 'vgs', 'lvs',
1872 foreach name : lvm_progs
1874 '@0@_prog'.format(name),
1875 find_program(name, required: get_option('storage_lvm'), dirs: libvirt_sbin_path)
1877 if not get_variable('@0@_prog'.format(name)).found()
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())
1892 if not get_option('storage_mpath').disabled() and host_machine.system() == 'linux' and devmapper_dep.found()
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')
1899 if not get_option('storage_rbd').disabled() and rbd_dep.found()
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')
1906 if not get_option('storage_scsi').disabled() and host_machine.system() == 'linux'
1908 conf.set('WITH_STORAGE_SCSI', 1)
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')
1922 conf.set('WITH_STORAGE_VSTORAGE', 1)
1926 if not get_option('storage_zfs').disabled()
1928 conf.set('WITH_STORAGE_ZFS', 1)
1933 conf.set('WITH_STORAGE', 1)
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'
1943 if chrdev_lock_files != ''
1944 conf.set_quoted('VIR_CHRDEV_LOCK_FILE_PATH', chrdev_lock_files)
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')
1952 driver_modules_flags = libvirt_export_dynamic
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)
1960 dtrace_command = [ 'env', 'CC=' + ' '.join(meson.get_compiler('c').cmd_array()), dtrace_prog ]
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')
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'
1977 init_script = 'none'
1980 init_script = get_option('init_script')
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')
1988 conf.set_quoted('DEFAULT_LOADER_NVRAM', loader_nvram)
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')
1997 if not get_option('nss').disabled()
1999 if not yajl_dep.found()
2000 if get_option('nss').enabled()
2001 error('Can\'t build nss plugin without yajl')
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')
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')
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)
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)
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())
2043 elif get_option('numad').enabled()
2044 error('You must have numactl enabled for numad support.')
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)
2053 if not get_option('pm_utils').disabled()
2055 if init_script == 'systemd'
2056 use_pm_utils = false
2060 conf.set('WITH_PM_UTILS', 1)
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')
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')
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')
2082 conf.set_quoted('TLS_PRIORITY', get_option('tls_priority'))
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
2095 msg = 'Forcibly disabling tests because CLang lacks -fsemantic-interposition. Update CLang or disable optimization'
2096 if get_option('tests').enabled()
2099 tests_enabled = [ false, '!!! @0@ !!!'.format(msg) ]
2102 if get_option('expensive_tests').auto()
2103 use_expensive_tests = not git and tests_enabled[0]
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')
2112 if get_option('test_coverage')
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
2146 # Ensure that 'meson test' fails when tests are disabled, as opposed to
2147 # misleadingly succeeding at doing absolutely nothing
2149 'tests-are-disabled',
2150 python3_prog, args: [ '-c', 'raise Exception("tests are disabled")' ],
2158 gen_docs = not get_option('docs').disabled()
2166 # install pkgconfig files
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(),
2177 'datarootdir': datadir,
2178 'exec_prefix': prefix,
2179 'includedir': includedir,
2184 pkgconfig_dir = libdir / 'pkgconfig'
2186 foreach file : pkgconfig_files
2189 output: '@BASENAME@',
2190 configuration: pkgconfig_conf,
2192 install_dir: pkgconfig_dir,
2197 # generate dist files
2200 spec_conf = configuration_data({
2201 'VERSION': meson.project_version(),
2205 input: 'libvirt.spec.in',
2206 output: '@BASENAME@',
2207 configuration: spec_conf,
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(),
2219 input: authors_file,
2220 output: '@BASENAME@',
2221 configuration: authors_conf,
2224 # Using return values from configure_file in add_dist_script is possible since 0.55.0
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
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(),
2251 output: '@BASENAME@',
2252 configuration: run_conf,
2254 run_command('chmod', 'a+x', meson.current_build_dir() / 'run', check: true)
2257 # print configuration 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)
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)
2348 'MinGW': host_machine.system() == 'windows',
2349 'windres': host_machine.system() == 'windows',
2351 summary(win_summary, section: 'Windows', bool_yn: true)
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'))
2365 'Warning Flags': supported_cc_flags,
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')
2387 'firewall backends': firewall_backend_priority,
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,
2403 summary(test_programs_summary, section: 'Optional programs', bool_yn: true)
2406 if conf.has('WITH_QEMU')
2408 if qemu_user == 'root'
2409 qemu_warn = ' !!! running QEMU as root is strongly discouraged !!!'
2412 'QEMU': '@0@:@1@@2@'.format(qemu_user, qemu_group, qemu_warn),
2414 summary(priv_summary, section: 'Privileges')