x86: add support for KVM_CAP_XSAVE2 and AMX state migration
[qemu.git] / meson.build
blobad4327888f86cdbec93b59cabdbd37308001108e
1 project('qemu', ['c'], meson_version: '>=0.59.3',
2         default_options: ['warning_level=1', 'c_std=gnu11', 'cpp_std=gnu++11', 'b_colorout=auto',
3                           'b_staticpic=false', 'stdsplit=false'],
4         version: files('VERSION'))
6 add_test_setup('quick', exclude_suites: ['block', 'slow', 'thorough'], is_default: true)
7 add_test_setup('slow', exclude_suites: ['block', 'thorough'], env: ['G_TEST_SLOW=1', 'SPEED=slow'])
8 add_test_setup('thorough', exclude_suites: ['block'], env: ['G_TEST_SLOW=1', 'SPEED=thorough'])
10 not_found = dependency('', required: false)
11 keyval = import('keyval')
12 ss = import('sourceset')
13 fs = import('fs')
15 sh = find_program('sh')
16 cc = meson.get_compiler('c')
17 config_host = keyval.load(meson.current_build_dir() / 'config-host.mak')
18 enable_modules = 'CONFIG_MODULES' in config_host
19 enable_static = 'CONFIG_STATIC' in config_host
21 # Allow both shared and static libraries unless --enable-static
22 static_kwargs = enable_static ? {'static': true} : {}
24 # Temporary directory used for files created while
25 # configure runs. Since it is in the build directory
26 # we can safely blow away any previous version of it
27 # (and we need not jump through hoops to try to delete
28 # it when configure exits.)
29 tmpdir = meson.current_build_dir() / 'meson-private/temp'
31 if get_option('qemu_suffix').startswith('/')
32   error('qemu_suffix cannot start with a /')
33 endif
35 qemu_confdir = get_option('sysconfdir') / get_option('qemu_suffix')
36 qemu_datadir = get_option('datadir') / get_option('qemu_suffix')
37 qemu_docdir = get_option('docdir') / get_option('qemu_suffix')
38 qemu_moddir = get_option('libdir') / get_option('qemu_suffix')
40 qemu_desktopdir = get_option('datadir') / 'applications'
41 qemu_icondir = get_option('datadir') / 'icons'
43 config_host_data = configuration_data()
44 genh = []
45 qapi_trace_events = []
47 bsd_oses = ['gnu/kfreebsd', 'freebsd', 'netbsd', 'openbsd', 'dragonfly', 'darwin']
48 supported_oses = ['windows', 'freebsd', 'netbsd', 'openbsd', 'darwin', 'sunos', 'linux']
49 supported_cpus = ['ppc', 'ppc64', 's390x', 'riscv', 'x86', 'x86_64',
50   'arm', 'aarch64', 'loongarch64', 'mips', 'mips64', 'sparc', 'sparc64']
52 cpu = host_machine.cpu_family()
54 # Unify riscv* to a single family.
55 if cpu in ['riscv32', 'riscv64']
56   cpu = 'riscv'
57 endif
59 targetos = host_machine.system()
61 target_dirs = config_host['TARGET_DIRS'].split()
62 have_linux_user = false
63 have_bsd_user = false
64 have_system = false
65 foreach target : target_dirs
66   have_linux_user = have_linux_user or target.endswith('linux-user')
67   have_bsd_user = have_bsd_user or target.endswith('bsd-user')
68   have_system = have_system or target.endswith('-softmmu')
69 endforeach
70 have_user = have_linux_user or have_bsd_user
71 have_tools = get_option('tools') \
72   .disable_auto_if(not have_system) \
73   .allowed()
74 have_ga = get_option('guest_agent') \
75   .disable_auto_if(not have_system and not have_tools) \
76   .require(targetos in ['sunos', 'linux', 'windows'],
77            error_message: 'unsupported OS for QEMU guest agent') \
78   .allowed()
79 have_block = have_system or have_tools
81 python = import('python').find_installation()
83 if cpu not in supported_cpus
84   host_arch = 'unknown'
85 elif cpu == 'x86'
86   host_arch = 'i386'
87 elif cpu == 'mips64'
88   host_arch = 'mips'
89 else
90   host_arch = cpu
91 endif
93 if cpu in ['x86', 'x86_64']
94   kvm_targets = ['i386-softmmu', 'x86_64-softmmu']
95 elif cpu == 'aarch64'
96   kvm_targets = ['aarch64-softmmu']
97 elif cpu == 's390x'
98   kvm_targets = ['s390x-softmmu']
99 elif cpu in ['ppc', 'ppc64']
100   kvm_targets = ['ppc-softmmu', 'ppc64-softmmu']
101 elif cpu in ['mips', 'mips64']
102   kvm_targets = ['mips-softmmu', 'mipsel-softmmu', 'mips64-softmmu', 'mips64el-softmmu']
103 elif cpu in ['riscv']
104   kvm_targets = ['riscv32-softmmu', 'riscv64-softmmu']
105 else
106   kvm_targets = []
107 endif
109 kvm_targets_c = '""'
110 if get_option('kvm').allowed() and targetos == 'linux'
111   kvm_targets_c = '"' + '" ,"'.join(kvm_targets) + '"'
112 endif
113 config_host_data.set('CONFIG_KVM_TARGETS', kvm_targets_c)
115 accelerator_targets = { 'CONFIG_KVM': kvm_targets }
117 if cpu in ['aarch64']
118   accelerator_targets += {
119     'CONFIG_HVF': ['aarch64-softmmu']
120   }
121 endif
123 if cpu in ['x86', 'x86_64', 'arm', 'aarch64']
124   # i386 emulator provides xenpv machine type for multiple architectures
125   accelerator_targets += {
126     'CONFIG_XEN': ['i386-softmmu', 'x86_64-softmmu'],
127   }
128 endif
129 if cpu in ['x86', 'x86_64']
130   accelerator_targets += {
131     'CONFIG_HAX': ['i386-softmmu', 'x86_64-softmmu'],
132     'CONFIG_HVF': ['x86_64-softmmu'],
133     'CONFIG_NVMM': ['i386-softmmu', 'x86_64-softmmu'],
134     'CONFIG_WHPX': ['i386-softmmu', 'x86_64-softmmu'],
135   }
136 endif
138 modular_tcg = []
139 # Darwin does not support references to thread-local variables in modules
140 if targetos != 'darwin'
141   modular_tcg = ['i386-softmmu', 'x86_64-softmmu']
142 endif
144 edk2_targets = [ 'arm-softmmu', 'aarch64-softmmu', 'i386-softmmu', 'x86_64-softmmu' ]
145 unpack_edk2_blobs = false
146 foreach target : edk2_targets
147   if target in target_dirs
148     bzip2 = find_program('bzip2', required: get_option('install_blobs'))
149     unpack_edk2_blobs = bzip2.found()
150     break
151   endif
152 endforeach
154 dtrace = not_found
155 stap = not_found
156 if 'dtrace' in get_option('trace_backends')
157   dtrace = find_program('dtrace', required: true)
158   stap = find_program('stap', required: false)
159   if stap.found()
160     # Workaround to avoid dtrace(1) producing a file with 'hidden' symbol
161     # visibility. Define STAP_SDT_V2 to produce 'default' symbol visibility
162     # instead. QEMU --enable-modules depends on this because the SystemTap
163     # semaphores are linked into the main binary and not the module's shared
164     # object.
165     add_global_arguments('-DSTAP_SDT_V2',
166                          native: false, language: ['c', 'cpp', 'objc'])
167   endif
168 endif
170 ##################
171 # Compiler flags #
172 ##################
174 qemu_cflags = config_host['QEMU_CFLAGS'].split()
175 qemu_cxxflags = config_host['QEMU_CXXFLAGS'].split()
176 qemu_ldflags = config_host['QEMU_LDFLAGS'].split()
178 if get_option('gprof')
179   qemu_cflags += ['-p']
180   qemu_cxxflags += ['-p']
181   qemu_ldflags += ['-p']
182 endif
184 # Specify linker-script with add_project_link_arguments so that it is not placed
185 # within a linker --start-group/--end-group pair
186 if get_option('fuzzing')
187   add_project_link_arguments(['-Wl,-T,',
188                               (meson.current_source_dir() / 'tests/qtest/fuzz/fork_fuzz.ld')],
189                              native: false, language: ['c', 'cpp', 'objc'])
191   # Specify a filter to only instrument code that is directly related to
192   # virtual-devices.
193   configure_file(output: 'instrumentation-filter',
194                  input: 'scripts/oss-fuzz/instrumentation-filter-template',
195                  copy: true)
196   add_global_arguments(
197       cc.get_supported_arguments('-fsanitize-coverage-allowlist=instrumentation-filter'),
198       native: false, language: ['c', 'cpp', 'objc'])
200   if get_option('fuzzing_engine') == ''
201     # Add CFLAGS to tell clang to add fuzzer-related instrumentation to all the
202     # compiled code.  To build non-fuzzer binaries with --enable-fuzzing, link
203     # everything with fsanitize=fuzzer-no-link. Otherwise, the linker will be
204     # unable to bind the fuzzer-related callbacks added by instrumentation.
205     add_global_arguments('-fsanitize=fuzzer-no-link',
206                          native: false, language: ['c', 'cpp', 'objc'])
207     add_global_link_arguments('-fsanitize=fuzzer-no-link',
208                               native: false, language: ['c', 'cpp', 'objc'])
209     # For the actual fuzzer binaries, we need to link against the libfuzzer
210     # library. They need to be configurable, to support OSS-Fuzz
211     fuzz_exe_ldflags = ['-fsanitize=fuzzer']
212   else
213     # LIB_FUZZING_ENGINE was set; assume we are running on OSS-Fuzz, and
214     # the needed CFLAGS have already been provided
215     fuzz_exe_ldflags = get_option('fuzzing_engine').split()
216   endif
217 endif
219 add_global_arguments(qemu_cflags, native: false, language: ['c', 'objc'])
220 add_global_arguments(qemu_cxxflags, native: false, language: ['cpp'])
221 add_global_link_arguments(qemu_ldflags, native: false, language: ['c', 'cpp', 'objc'])
223 if targetos == 'linux'
224   add_project_arguments('-isystem', meson.current_source_dir() / 'linux-headers',
225                         '-isystem', 'linux-headers',
226                         language: ['c', 'cpp'])
227 endif
229 add_project_arguments('-iquote', '.',
230                       '-iquote', meson.current_source_dir(),
231                       '-iquote', meson.current_source_dir() / 'include',
232                       '-iquote', meson.current_source_dir() / 'disas/libvixl',
233                       language: ['c', 'cpp', 'objc'])
235 link_language = meson.get_external_property('link_language', 'cpp')
236 if link_language == 'cpp'
237   add_languages('cpp', required: true, native: false)
238   cxx = meson.get_compiler('cpp')
239   linker = cxx
240 else
241   linker = cc
242 endif
243 if host_machine.system() == 'darwin'
244   add_languages('objc', required: false, native: false)
245 endif
247 sparse = find_program('cgcc', required: get_option('sparse'))
248 if sparse.found()
249   run_target('sparse',
250              command: [find_program('scripts/check_sparse.py'),
251                        'compile_commands.json', sparse.full_path(), '-Wbitwise',
252                        '-Wno-transparent-union', '-Wno-old-initializer',
253                        '-Wno-non-pointer-null'])
254 endif
256 ###########################################
257 # Target-specific checks and dependencies #
258 ###########################################
260 # Fuzzing
261 if get_option('fuzzing') and get_option('fuzzing_engine') == '' and \
262     not cc.links('''
263           #include <stdint.h>
264           #include <sys/types.h>
265           int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
266           int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { return 0; }
267         ''',
268         args: ['-Werror', '-fsanitize=fuzzer'])
269   error('Your compiler does not support -fsanitize=fuzzer')
270 endif
272 # Tracing backends
273 if 'ftrace' in get_option('trace_backends') and targetos != 'linux'
274   error('ftrace is supported only on Linux')
275 endif
276 if 'syslog' in get_option('trace_backends') and not cc.compiles('''
277     #include <syslog.h>
278     int main(void) {
279         openlog("qemu", LOG_PID, LOG_DAEMON);
280         syslog(LOG_INFO, "configure");
281         return 0;
282     }''')
283   error('syslog is not supported on this system')
284 endif
286 # Miscellaneous Linux-only features
287 get_option('mpath') \
288   .require(targetos == 'linux', error_message: 'Multipath is supported only on Linux')
290 multiprocess_allowed = get_option('multiprocess') \
291   .require(targetos == 'linux', error_message: 'Multiprocess QEMU is supported only on Linux') \
292   .allowed()
294 have_tpm = get_option('tpm') \
295   .require(targetos != 'windows', error_message: 'TPM emulation only available on POSIX systems') \
296   .allowed()
298 # Target-specific libraries and flags
299 libm = cc.find_library('m', required: false)
300 threads = dependency('threads')
301 util = cc.find_library('util', required: false)
302 winmm = []
303 socket = []
304 version_res = []
305 coref = []
306 iokit = []
307 emulator_link_args = []
308 nvmm =not_found
309 hvf = not_found
310 midl = not_found
311 widl = not_found
312 host_dsosuf = '.so'
313 if targetos == 'windows'
314   midl = find_program('midl', required: false)
315   widl = find_program('widl', required: false)
316   socket = cc.find_library('ws2_32')
317   winmm = cc.find_library('winmm')
319   win = import('windows')
320   version_res = win.compile_resources('version.rc',
321                                       depend_files: files('pc-bios/qemu-nsis.ico'),
322                                       include_directories: include_directories('.'))
323   host_dsosuf = '.dll'
324 elif targetos == 'darwin'
325   coref = dependency('appleframeworks', modules: 'CoreFoundation')
326   iokit = dependency('appleframeworks', modules: 'IOKit', required: false)
327   host_dsosuf = '.dylib'
328 elif targetos == 'sunos'
329   socket = [cc.find_library('socket'),
330             cc.find_library('nsl'),
331             cc.find_library('resolv')]
332 elif targetos == 'haiku'
333   socket = [cc.find_library('posix_error_mapper'),
334             cc.find_library('network'),
335             cc.find_library('bsd')]
336 elif targetos == 'openbsd'
337   if get_option('tcg').allowed() and target_dirs.length() > 0
338     # Disable OpenBSD W^X if available
339     emulator_link_args = cc.get_supported_link_arguments('-Wl,-z,wxneeded')
340   endif
341 endif
343 # Target-specific configuration of accelerators
344 accelerators = []
345 if get_option('kvm').allowed() and targetos == 'linux'
346   accelerators += 'CONFIG_KVM'
347 endif
348 if get_option('xen').allowed() and 'CONFIG_XEN_BACKEND' in config_host
349   accelerators += 'CONFIG_XEN'
350   have_xen_pci_passthrough = get_option('xen_pci_passthrough').allowed() and targetos == 'linux'
351 else
352   have_xen_pci_passthrough = false
353 endif
354 if get_option('whpx').allowed() and targetos == 'windows'
355   if get_option('whpx').enabled() and host_machine.cpu() != 'x86_64'
356     error('WHPX requires 64-bit host')
357   elif cc.has_header('WinHvPlatform.h', required: get_option('whpx')) and \
358        cc.has_header('WinHvEmulation.h', required: get_option('whpx'))
359     accelerators += 'CONFIG_WHPX'
360   endif
361 endif
362 if get_option('hvf').allowed()
363   hvf = dependency('appleframeworks', modules: 'Hypervisor',
364                    required: get_option('hvf'))
365   if hvf.found()
366     accelerators += 'CONFIG_HVF'
367   endif
368 endif
369 if get_option('hax').allowed()
370   if get_option('hax').enabled() or targetos in ['windows', 'darwin', 'netbsd']
371     accelerators += 'CONFIG_HAX'
372   endif
373 endif
374 if targetos == 'netbsd'
375   nvmm = cc.find_library('nvmm', required: get_option('nvmm'))
376   if nvmm.found()
377     accelerators += 'CONFIG_NVMM'
378   endif
379 endif
381 tcg_arch = host_arch
382 if get_option('tcg').allowed()
383   if host_arch == 'unknown'
384     if get_option('tcg_interpreter')
385       warning('Unsupported CPU @0@, will use TCG with TCI (slow)'.format(cpu))
386     else
387       error('Unsupported CPU @0@, try --enable-tcg-interpreter'.format(cpu))
388     endif
389   elif get_option('tcg_interpreter')
390     warning('Use of the TCG interpreter is not recommended on this host')
391     warning('architecture. There is a native TCG execution backend available')
392     warning('which provides substantially better performance and reliability.')
393     warning('It is strongly recommended to remove the --enable-tcg-interpreter')
394     warning('configuration option on this architecture to use the native')
395     warning('backend.')
396   endif
397   if get_option('tcg_interpreter')
398     tcg_arch = 'tci'
399   elif host_arch == 'sparc64'
400     tcg_arch = 'sparc'
401   elif host_arch == 'x86_64'
402     tcg_arch = 'i386'
403   elif host_arch == 'ppc64'
404     tcg_arch = 'ppc'
405   endif
406   add_project_arguments('-iquote', meson.current_source_dir() / 'tcg' / tcg_arch,
407                         language: ['c', 'cpp', 'objc'])
409   accelerators += 'CONFIG_TCG'
410   config_host += { 'CONFIG_TCG': 'y' }
411 endif
413 if 'CONFIG_KVM' not in accelerators and get_option('kvm').enabled()
414   error('KVM not available on this platform')
415 endif
416 if 'CONFIG_HVF' not in accelerators and get_option('hvf').enabled()
417   error('HVF not available on this platform')
418 endif
419 if 'CONFIG_NVMM' not in accelerators and get_option('nvmm').enabled()
420   error('NVMM not available on this platform')
421 endif
422 if 'CONFIG_WHPX' not in accelerators and get_option('whpx').enabled()
423   error('WHPX not available on this platform')
424 endif
425 if not have_xen_pci_passthrough and get_option('xen_pci_passthrough').enabled()
426   if 'CONFIG_XEN' in accelerators
427     error('Xen PCI passthrough not available on this platform')
428   else
429     error('Xen PCI passthrough requested but Xen not enabled')
430   endif
431 endif
433 ################
434 # Dependencies #
435 ################
437 # The path to glib.h is added to all compilation commands.  This was
438 # grandfathered in from the QEMU Makefiles.
439 add_project_arguments(config_host['GLIB_CFLAGS'].split(),
440                       native: false, language: ['c', 'cpp', 'objc'])
441 glib = declare_dependency(compile_args: config_host['GLIB_CFLAGS'].split(),
442                           link_args: config_host['GLIB_LIBS'].split(),
443                           version: config_host['GLIB_VERSION'])
444 # override glib dep with the configure results (for subprojects)
445 meson.override_dependency('glib-2.0', glib)
447 gio = not_found
448 if 'CONFIG_GIO' in config_host
449   gio = declare_dependency(compile_args: config_host['GIO_CFLAGS'].split(),
450                            link_args: config_host['GIO_LIBS'].split(),
451                            version: config_host['GLIB_VERSION'])
452 endif
453 lttng = not_found
454 if 'ust' in get_option('trace_backends')
455   lttng = dependency('lttng-ust', required: true, method: 'pkg-config',
456                      kwargs: static_kwargs)
457 endif
458 pixman = not_found
459 if have_system or have_tools
460   pixman = dependency('pixman-1', required: have_system, version:'>=0.21.8',
461                       method: 'pkg-config', kwargs: static_kwargs)
462 endif
463 zlib = dependency('zlib', required: true, kwargs: static_kwargs)
465 libaio = not_found
466 if not get_option('linux_aio').auto() or have_block
467   libaio = cc.find_library('aio', has_headers: ['libaio.h'],
468                            required: get_option('linux_aio'),
469                            kwargs: static_kwargs)
470 endif
471 linux_io_uring = not_found
472 if not get_option('linux_io_uring').auto() or have_block
473   linux_io_uring = dependency('liburing', version: '>=0.3',
474                               required: get_option('linux_io_uring'),
475                               method: 'pkg-config', kwargs: static_kwargs)
476 endif
477 libnfs = not_found
478 if not get_option('libnfs').auto() or have_block
479   libnfs = dependency('libnfs', version: '>=1.9.3',
480                       required: get_option('libnfs'),
481                       method: 'pkg-config', kwargs: static_kwargs)
482 endif
484 libattr_test = '''
485   #include <stddef.h>
486   #include <sys/types.h>
487   #ifdef CONFIG_LIBATTR
488   #include <attr/xattr.h>
489   #else
490   #include <sys/xattr.h>
491   #endif
492   int main(void) { getxattr(NULL, NULL, NULL, 0); setxattr(NULL, NULL, NULL, 0, 0); return 0; }'''
494 libattr = not_found
495 have_old_libattr = false
496 if get_option('attr').allowed()
497   if cc.links(libattr_test)
498     libattr = declare_dependency()
499   else
500     libattr = cc.find_library('attr', has_headers: ['attr/xattr.h'],
501                               required: get_option('attr'),
502                               kwargs: static_kwargs)
503     if libattr.found() and not \
504       cc.links(libattr_test, dependencies: libattr, args: '-DCONFIG_LIBATTR')
505       libattr = not_found
506       if get_option('attr').enabled()
507         error('could not link libattr')
508       else
509         warning('could not link libattr, disabling')
510       endif
511     else
512       have_old_libattr = libattr.found()
513     endif
514   endif
515 endif
517 cocoa = dependency('appleframeworks', modules: 'Cocoa', required: get_option('cocoa'))
518 if cocoa.found() and get_option('sdl').enabled()
519   error('Cocoa and SDL cannot be enabled at the same time')
520 endif
521 if cocoa.found() and get_option('gtk').enabled()
522   error('Cocoa and GTK+ cannot be enabled at the same time')
523 endif
525 seccomp = not_found
526 if not get_option('seccomp').auto() or have_system or have_tools
527   seccomp = dependency('libseccomp', version: '>=2.3.0',
528                        required: get_option('seccomp'),
529                        method: 'pkg-config', kwargs: static_kwargs)
530 endif
532 libcap_ng = not_found
533 if not get_option('cap_ng').auto() or have_system or have_tools
534   libcap_ng = cc.find_library('cap-ng', has_headers: ['cap-ng.h'],
535                               required: get_option('cap_ng'),
536                               kwargs: static_kwargs)
537 endif
538 if libcap_ng.found() and not cc.links('''
539    #include <cap-ng.h>
540    int main(void)
541    {
542      capng_capability_to_name(CAPNG_EFFECTIVE);
543      return 0;
544    }''', dependencies: libcap_ng)
545   libcap_ng = not_found
546   if get_option('cap_ng').enabled()
547     error('could not link libcap-ng')
548   else
549     warning('could not link libcap-ng, disabling')
550   endif
551 endif
553 if get_option('xkbcommon').auto() and not have_system and not have_tools
554   xkbcommon = not_found
555 else
556   xkbcommon = dependency('xkbcommon', required: get_option('xkbcommon'),
557                          method: 'pkg-config', kwargs: static_kwargs)
558 endif
560 vde = not_found
561 if not get_option('vde').auto() or have_system or have_tools
562   vde = cc.find_library('vdeplug', has_headers: ['libvdeplug.h'],
563                            required: get_option('vde'),
564                            kwargs: static_kwargs)
565 endif
566 if vde.found() and not cc.links('''
567    #include <libvdeplug.h>
568    int main(void)
569    {
570      struct vde_open_args a = {0, 0, 0};
571      char s[] = "";
572      vde_open(s, s, &a);
573      return 0;
574    }''', dependencies: vde)
575   vde = not_found
576   if get_option('cap_ng').enabled()
577     error('could not link libvdeplug')
578   else
579     warning('could not link libvdeplug, disabling')
580   endif
581 endif
583 pulse = not_found
584 if not get_option('pa').auto() or (targetos == 'linux' and have_system)
585   pulse = dependency('libpulse', required: get_option('pa'),
586                      method: 'pkg-config', kwargs: static_kwargs)
587 endif
588 alsa = not_found
589 if not get_option('alsa').auto() or (targetos == 'linux' and have_system)
590   alsa = dependency('alsa', required: get_option('alsa'),
591                     method: 'pkg-config', kwargs: static_kwargs)
592 endif
593 jack = not_found
594 if not get_option('jack').auto() or have_system
595   jack = dependency('jack', required: get_option('jack'),
596                     method: 'pkg-config', kwargs: static_kwargs)
597 endif
599 spice_protocol = not_found
600 if not get_option('spice_protocol').auto() or have_system
601   spice_protocol = dependency('spice-protocol', version: '>=0.12.3',
602                               required: get_option('spice_protocol'),
603                               method: 'pkg-config', kwargs: static_kwargs)
604 endif
605 spice = not_found
606 if not get_option('spice').auto() or have_system
607   spice = dependency('spice-server', version: '>=0.12.5',
608                      required: get_option('spice'),
609                      method: 'pkg-config', kwargs: static_kwargs)
610 endif
611 spice_headers = spice.partial_dependency(compile_args: true, includes: true)
613 rt = cc.find_library('rt', required: false)
615 libiscsi = not_found
616 if not get_option('libiscsi').auto() or have_block
617   libiscsi = dependency('libiscsi', version: '>=1.9.0',
618                          required: get_option('libiscsi'),
619                          method: 'pkg-config', kwargs: static_kwargs)
620 endif
621 zstd = not_found
622 if not get_option('zstd').auto() or have_block
623   zstd = dependency('libzstd', version: '>=1.4.0',
624                     required: get_option('zstd'),
625                     method: 'pkg-config', kwargs: static_kwargs)
626 endif
627 virgl = not_found
629 have_vhost_user_gpu = have_tools and targetos == 'linux' and pixman.found()
630 if not get_option('virglrenderer').auto() or have_system or have_vhost_user_gpu
631   virgl = dependency('virglrenderer',
632                      method: 'pkg-config',
633                      required: get_option('virglrenderer'),
634                      kwargs: static_kwargs)
635 endif
636 curl = not_found
637 if not get_option('curl').auto() or have_block
638   curl = dependency('libcurl', version: '>=7.29.0',
639                     method: 'pkg-config',
640                     required: get_option('curl'),
641                     kwargs: static_kwargs)
642 endif
643 libudev = not_found
644 if targetos == 'linux' and (have_system or have_tools)
645   libudev = dependency('libudev',
646                        method: 'pkg-config',
647                        required: get_option('libudev'),
648                        kwargs: static_kwargs)
649 endif
651 mpathlibs = [libudev]
652 mpathpersist = not_found
653 mpathpersist_new_api = false
654 if targetos == 'linux' and have_tools and get_option('mpath').allowed()
655   mpath_test_source_new = '''
656     #include <libudev.h>
657     #include <mpath_persist.h>
658     unsigned mpath_mx_alloc_len = 1024;
659     int logsink;
660     static struct config *multipath_conf;
661     extern struct udev *udev;
662     extern struct config *get_multipath_config(void);
663     extern void put_multipath_config(struct config *conf);
664     struct udev *udev;
665     struct config *get_multipath_config(void) { return multipath_conf; }
666     void put_multipath_config(struct config *conf) { }
667     int main(void) {
668         udev = udev_new();
669         multipath_conf = mpath_lib_init();
670         return 0;
671     }'''
672   mpath_test_source_old = '''
673       #include <libudev.h>
674       #include <mpath_persist.h>
675       unsigned mpath_mx_alloc_len = 1024;
676       int logsink;
677       int main(void) {
678           struct udev *udev = udev_new();
679           mpath_lib_init(udev);
680           return 0;
681       }'''
682   libmpathpersist = cc.find_library('mpathpersist',
683                                     required: get_option('mpath'),
684                                     kwargs: static_kwargs)
685   if libmpathpersist.found()
686     mpathlibs += libmpathpersist
687     if enable_static
688       mpathlibs += cc.find_library('devmapper',
689                                      required: get_option('mpath'),
690                                      kwargs: static_kwargs)
691     endif
692     mpathlibs += cc.find_library('multipath',
693                                  required: get_option('mpath'),
694                                  kwargs: static_kwargs)
695     foreach lib: mpathlibs
696       if not lib.found()
697         mpathlibs = []
698         break
699       endif
700     endforeach
701     if mpathlibs.length() == 0
702       msg = 'Dependencies missing for libmpathpersist'
703     elif cc.links(mpath_test_source_new, dependencies: mpathlibs)
704       mpathpersist = declare_dependency(dependencies: mpathlibs)
705       mpathpersist_new_api = true
706     elif cc.links(mpath_test_source_old, dependencies: mpathlibs)
707       mpathpersist = declare_dependency(dependencies: mpathlibs)
708     else
709       msg = 'Cannot detect libmpathpersist API'
710     endif
711     if not mpathpersist.found()
712       if get_option('mpath').enabled()
713         error(msg)
714       else
715         warning(msg + ', disabling')
716       endif
717     endif
718   endif
719 endif
721 iconv = not_found
722 curses = not_found
723 if have_system and get_option('curses').allowed()
724   curses_test = '''
725     #if defined(__APPLE__) || defined(__OpenBSD__)
726     #define _XOPEN_SOURCE_EXTENDED 1
727     #endif
728     #include <locale.h>
729     #include <curses.h>
730     #include <wchar.h>
731     int main(void) {
732       wchar_t wch = L'w';
733       setlocale(LC_ALL, "");
734       resize_term(0, 0);
735       addwstr(L"wide chars\n");
736       addnwstr(&wch, 1);
737       add_wch(WACS_DEGREE);
738       return 0;
739     }'''
741   curses_dep_list = targetos == 'windows' ? ['ncurses', 'ncursesw'] : ['ncursesw']
742   foreach curses_dep : curses_dep_list
743     if not curses.found()
744       curses = dependency(curses_dep,
745                           required: false,
746                           method: 'pkg-config',
747                           kwargs: static_kwargs)
748     endif
749   endforeach
750   msg = get_option('curses').enabled() ? 'curses library not found' : ''
751   curses_compile_args = ['-DNCURSES_WIDECHAR=1']
752   if curses.found()
753     if cc.links(curses_test, args: curses_compile_args, dependencies: [curses])
754       curses = declare_dependency(compile_args: curses_compile_args, dependencies: [curses])
755     else
756       msg = 'curses package not usable'
757       curses = not_found
758     endif
759   endif
760   if not curses.found()
761     has_curses_h = cc.has_header('curses.h', args: curses_compile_args)
762     if targetos != 'windows' and not has_curses_h
763       message('Trying with /usr/include/ncursesw')
764       curses_compile_args += ['-I/usr/include/ncursesw']
765       has_curses_h = cc.has_header('curses.h', args: curses_compile_args)
766     endif
767     if has_curses_h
768       curses_libname_list = (targetos == 'windows' ? ['pdcurses'] : ['ncursesw', 'cursesw'])
769       foreach curses_libname : curses_libname_list
770         libcurses = cc.find_library(curses_libname,
771                                     required: false,
772                                     kwargs: static_kwargs)
773         if libcurses.found()
774           if cc.links(curses_test, args: curses_compile_args, dependencies: libcurses)
775             curses = declare_dependency(compile_args: curses_compile_args,
776                                         dependencies: [libcurses])
777             break
778           else
779             msg = 'curses library not usable'
780           endif
781         endif
782       endforeach
783     endif
784   endif
785   if get_option('iconv').allowed()
786     foreach link_args : [ ['-liconv'], [] ]
787       # Programs will be linked with glib and this will bring in libiconv on FreeBSD.
788       # We need to use libiconv if available because mixing libiconv's headers with
789       # the system libc does not work.
790       # However, without adding glib to the dependencies -L/usr/local/lib will not be
791       # included in the command line and libiconv will not be found.
792       if cc.links('''
793         #include <iconv.h>
794         int main(void) {
795           iconv_t conv = iconv_open("WCHAR_T", "UCS-2");
796           return conv != (iconv_t) -1;
797         }''', args: config_host['GLIB_CFLAGS'].split() + config_host['GLIB_LIBS'].split() + link_args)
798         iconv = declare_dependency(link_args: link_args, dependencies: glib)
799         break
800       endif
801     endforeach
802   endif
803   if curses.found() and not iconv.found()
804     if get_option('iconv').enabled()
805       error('iconv not available')
806     endif
807     msg = 'iconv required for curses UI but not available'
808     curses = not_found
809   endif
810   if not curses.found() and msg != ''
811     if get_option('curses').enabled()
812       error(msg)
813     else
814       warning(msg + ', disabling')
815     endif
816   endif
817 endif
819 brlapi = not_found
820 if not get_option('brlapi').auto() or have_system
821   brlapi = cc.find_library('brlapi', has_headers: ['brlapi.h'],
822                          required: get_option('brlapi'),
823                          kwargs: static_kwargs)
824   if brlapi.found() and not cc.links('''
825      #include <brlapi.h>
826      #include <stddef.h>
827      int main(void) { return brlapi__openConnection (NULL, NULL, NULL); }''', dependencies: brlapi)
828     brlapi = not_found
829     if get_option('brlapi').enabled()
830       error('could not link brlapi')
831     else
832       warning('could not link brlapi, disabling')
833     endif
834   endif
835 endif
837 sdl = not_found
838 if not get_option('sdl').auto() or (have_system and not cocoa.found())
839   sdl = dependency('sdl2', required: get_option('sdl'), kwargs: static_kwargs)
840   sdl_image = not_found
841 endif
842 if sdl.found()
843   # work around 2.0.8 bug
844   sdl = declare_dependency(compile_args: '-Wno-undef',
845                            dependencies: sdl)
846   sdl_image = dependency('SDL2_image', required: get_option('sdl_image'),
847                          method: 'pkg-config', kwargs: static_kwargs)
848 else
849   if get_option('sdl_image').enabled()
850     error('sdl-image required, but SDL was @0@'.format(
851           get_option('sdl').disabled() ? 'disabled' : 'not found'))
852   endif
853   sdl_image = not_found
854 endif
856 rbd = not_found
857 if not get_option('rbd').auto() or have_block
858   librados = cc.find_library('rados', required: get_option('rbd'),
859                              kwargs: static_kwargs)
860   librbd = cc.find_library('rbd', has_headers: ['rbd/librbd.h'],
861                            required: get_option('rbd'),
862                            kwargs: static_kwargs)
863   if librados.found() and librbd.found()
864     if cc.links('''
865       #include <stdio.h>
866       #include <rbd/librbd.h>
867       int main(void) {
868         rados_t cluster;
869         rados_create(&cluster, NULL);
870         #if LIBRBD_VERSION_CODE < LIBRBD_VERSION(1, 12, 0)
871         #error
872         #endif
873         return 0;
874       }''', dependencies: [librbd, librados])
875       rbd = declare_dependency(dependencies: [librbd, librados])
876     elif get_option('rbd').enabled()
877       error('librbd >= 1.12.0 required')
878     else
879       warning('librbd >= 1.12.0 not found, disabling')
880     endif
881   endif
882 endif
884 glusterfs = not_found
885 glusterfs_ftruncate_has_stat = false
886 glusterfs_iocb_has_stat = false
887 if not get_option('glusterfs').auto() or have_block
888   glusterfs = dependency('glusterfs-api', version: '>=3',
889                          required: get_option('glusterfs'),
890                          method: 'pkg-config', kwargs: static_kwargs)
891   if glusterfs.found()
892     glusterfs_ftruncate_has_stat = cc.links('''
893       #include <glusterfs/api/glfs.h>
895       int
896       main(void)
897       {
898           /* new glfs_ftruncate() passes two additional args */
899           return glfs_ftruncate(NULL, 0, NULL, NULL);
900       }
901     ''', dependencies: glusterfs)
902     glusterfs_iocb_has_stat = cc.links('''
903       #include <glusterfs/api/glfs.h>
905       /* new glfs_io_cbk() passes two additional glfs_stat structs */
906       static void
907       glusterfs_iocb(glfs_fd_t *fd, ssize_t ret, struct glfs_stat *prestat, struct glfs_stat *poststat, void *data)
908       {}
910       int
911       main(void)
912       {
913           glfs_io_cbk iocb = &glusterfs_iocb;
914           iocb(NULL, 0 , NULL, NULL, NULL);
915           return 0;
916       }
917     ''', dependencies: glusterfs)
918   endif
919 endif
921 libssh = not_found
922 if not get_option('libssh').auto() or have_block
923   libssh = dependency('libssh', version: '>=0.8.7',
924                     method: 'pkg-config',
925                     required: get_option('libssh'),
926                     kwargs: static_kwargs)
927 endif
929 libbzip2 = not_found
930 if not get_option('bzip2').auto() or have_block
931   libbzip2 = cc.find_library('bz2', has_headers: ['bzlib.h'],
932                              required: get_option('bzip2'),
933                              kwargs: static_kwargs)
934   if libbzip2.found() and not cc.links('''
935      #include <bzlib.h>
936      int main(void) { BZ2_bzlibVersion(); return 0; }''', dependencies: libbzip2)
937     libbzip2 = not_found
938     if get_option('bzip2').enabled()
939       error('could not link libbzip2')
940     else
941       warning('could not link libbzip2, disabling')
942     endif
943   endif
944 endif
946 liblzfse = not_found
947 if not get_option('lzfse').auto() or have_block
948   liblzfse = cc.find_library('lzfse', has_headers: ['lzfse.h'],
949                              required: get_option('lzfse'),
950                              kwargs: static_kwargs)
951 endif
952 if liblzfse.found() and not cc.links('''
953    #include <lzfse.h>
954    int main(void) { lzfse_decode_scratch_size(); return 0; }''', dependencies: liblzfse)
955   liblzfse = not_found
956   if get_option('lzfse').enabled()
957     error('could not link liblzfse')
958   else
959     warning('could not link liblzfse, disabling')
960   endif
961 endif
963 oss = not_found
964 if get_option('oss').allowed() and have_system
965   if not cc.has_header('sys/soundcard.h')
966     # not found
967   elif targetos == 'netbsd'
968     oss = cc.find_library('ossaudio', required: get_option('oss'),
969                           kwargs: static_kwargs)
970   else
971     oss = declare_dependency()
972   endif
974   if not oss.found()
975     if get_option('oss').enabled()
976       error('OSS not found')
977     endif
978   endif
979 endif
980 dsound = not_found
981 if not get_option('dsound').auto() or (targetos == 'windows' and have_system)
982   if cc.has_header('dsound.h')
983     dsound = declare_dependency(link_args: ['-lole32', '-ldxguid'])
984   endif
986   if not dsound.found()
987     if get_option('dsound').enabled()
988       error('DirectSound not found')
989     endif
990   endif
991 endif
993 coreaudio = not_found
994 if not get_option('coreaudio').auto() or (targetos == 'darwin' and have_system)
995   coreaudio = dependency('appleframeworks', modules: 'CoreAudio',
996                          required: get_option('coreaudio'))
997 endif
999 opengl = not_found
1000 if 'CONFIG_OPENGL' in config_host
1001   opengl = declare_dependency(compile_args: config_host['OPENGL_CFLAGS'].split(),
1002                               link_args: config_host['OPENGL_LIBS'].split())
1003 endif
1004 gbm = not_found
1005 if (have_system or have_tools) and (virgl.found() or opengl.found())
1006   gbm = dependency('gbm', method: 'pkg-config', required: false,
1007                    kwargs: static_kwargs)
1008 endif
1009 have_vhost_user_gpu = have_vhost_user_gpu and virgl.found() and gbm.found()
1011 gnutls = not_found
1012 gnutls_crypto = not_found
1013 if get_option('gnutls').enabled() or (get_option('gnutls').auto() and have_system)
1014   # For general TLS support our min gnutls matches
1015   # that implied by our platform support matrix
1016   #
1017   # For the crypto backends, we look for a newer
1018   # gnutls:
1019   #
1020   #   Version 3.6.8  is needed to get XTS
1021   #   Version 3.6.13 is needed to get PBKDF
1022   #   Version 3.6.14 is needed to get HW accelerated XTS
1023   #
1024   # If newer enough gnutls isn't available, we can
1025   # still use a different crypto backend to satisfy
1026   # the platform support requirements
1027   gnutls_crypto = dependency('gnutls', version: '>=3.6.14',
1028                              method: 'pkg-config',
1029                              required: false,
1030                              kwargs: static_kwargs)
1031   if gnutls_crypto.found()
1032     gnutls = gnutls_crypto
1033   else
1034     # Our min version if all we need is TLS
1035     gnutls = dependency('gnutls', version: '>=3.5.18',
1036                         method: 'pkg-config',
1037                         required: get_option('gnutls'),
1038                         kwargs: static_kwargs)
1039   endif
1040 endif
1042 # We prefer use of gnutls for crypto, unless the options
1043 # explicitly asked for nettle or gcrypt.
1045 # If gnutls isn't available for crypto, then we'll prefer
1046 # gcrypt over nettle for performance reasons.
1047 gcrypt = not_found
1048 nettle = not_found
1049 xts = 'none'
1051 if get_option('nettle').enabled() and get_option('gcrypt').enabled()
1052   error('Only one of gcrypt & nettle can be enabled')
1053 endif
1055 # Explicit nettle/gcrypt request, so ignore gnutls for crypto
1056 if get_option('nettle').enabled() or get_option('gcrypt').enabled()
1057   gnutls_crypto = not_found
1058 endif
1060 if not gnutls_crypto.found()
1061   if (not get_option('gcrypt').auto() or have_system) and not get_option('nettle').enabled()
1062     gcrypt = dependency('libgcrypt', version: '>=1.8',
1063                         method: 'config-tool',
1064                         required: get_option('gcrypt'),
1065                         kwargs: static_kwargs)
1066     # Debian has removed -lgpg-error from libgcrypt-config
1067     # as it "spreads unnecessary dependencies" which in
1068     # turn breaks static builds...
1069     if gcrypt.found() and enable_static
1070       gcrypt = declare_dependency(dependencies: [
1071         gcrypt,
1072         cc.find_library('gpg-error', required: true, kwargs: static_kwargs)])
1073     endif
1074   endif
1075   if (not get_option('nettle').auto() or have_system) and not gcrypt.found()
1076     nettle = dependency('nettle', version: '>=3.4',
1077                         method: 'pkg-config',
1078                         required: get_option('nettle'),
1079                         kwargs: static_kwargs)
1080     if nettle.found() and not cc.has_header('nettle/xts.h', dependencies: nettle)
1081       xts = 'private'
1082     endif
1083   endif
1084 endif
1086 gtk = not_found
1087 gtkx11 = not_found
1088 vte = not_found
1089 if not get_option('gtk').auto() or (have_system and not cocoa.found())
1090   gtk = dependency('gtk+-3.0', version: '>=3.22.0',
1091                    method: 'pkg-config',
1092                    required: get_option('gtk'),
1093                    kwargs: static_kwargs)
1094   if gtk.found()
1095     gtkx11 = dependency('gtk+-x11-3.0', version: '>=3.22.0',
1096                         method: 'pkg-config',
1097                         required: false,
1098                         kwargs: static_kwargs)
1099     gtk = declare_dependency(dependencies: [gtk, gtkx11])
1101     if not get_option('vte').auto() or have_system
1102       vte = dependency('vte-2.91',
1103                        method: 'pkg-config',
1104                        required: get_option('vte'),
1105                        kwargs: static_kwargs)
1106     endif
1107   endif
1108 endif
1110 x11 = not_found
1111 if gtkx11.found()
1112   x11 = dependency('x11', method: 'pkg-config', required: gtkx11.found(),
1113                    kwargs: static_kwargs)
1114 endif
1115 vnc = not_found
1116 png = not_found
1117 jpeg = not_found
1118 sasl = not_found
1119 if get_option('vnc').allowed() and have_system
1120   vnc = declare_dependency() # dummy dependency
1121   png = dependency('libpng', required: get_option('vnc_png'),
1122                    method: 'pkg-config', kwargs: static_kwargs)
1123   jpeg = dependency('libjpeg', required: get_option('vnc_jpeg'),
1124                     method: 'pkg-config', kwargs: static_kwargs)
1125   sasl = cc.find_library('sasl2', has_headers: ['sasl/sasl.h'],
1126                          required: get_option('vnc_sasl'),
1127                          kwargs: static_kwargs)
1128   if sasl.found()
1129     sasl = declare_dependency(dependencies: sasl,
1130                               compile_args: '-DSTRUCT_IOVEC_DEFINED')
1131   endif
1132 endif
1134 pam = not_found
1135 if not get_option('auth_pam').auto() or have_system
1136   pam = cc.find_library('pam', has_headers: ['security/pam_appl.h'],
1137                         required: get_option('auth_pam'),
1138                         kwargs: static_kwargs)
1139 endif
1140 if pam.found() and not cc.links('''
1141    #include <stddef.h>
1142    #include <security/pam_appl.h>
1143    int main(void) {
1144      const char *service_name = "qemu";
1145      const char *user = "frank";
1146      const struct pam_conv pam_conv = { 0 };
1147      pam_handle_t *pamh = NULL;
1148      pam_start(service_name, user, &pam_conv, &pamh);
1149      return 0;
1150    }''', dependencies: pam)
1151   pam = not_found
1152   if get_option('auth_pam').enabled()
1153     error('could not link libpam')
1154   else
1155     warning('could not link libpam, disabling')
1156   endif
1157 endif
1159 snappy = not_found
1160 if not get_option('snappy').auto() or have_system
1161   snappy = cc.find_library('snappy', has_headers: ['snappy-c.h'],
1162                            required: get_option('snappy'),
1163                            kwargs: static_kwargs)
1164 endif
1165 if snappy.found() and not linker.links('''
1166    #include <snappy-c.h>
1167    int main(void) { snappy_max_compressed_length(4096); return 0; }''', dependencies: snappy)
1168   snappy = not_found
1169   if get_option('snappy').enabled()
1170     error('could not link libsnappy')
1171   else
1172     warning('could not link libsnappy, disabling')
1173   endif
1174 endif
1176 lzo = not_found
1177 if not get_option('lzo').auto() or have_system
1178   lzo = cc.find_library('lzo2', has_headers: ['lzo/lzo1x.h'],
1179                         required: get_option('lzo'),
1180                         kwargs: static_kwargs)
1181 endif
1182 if lzo.found() and not cc.links('''
1183    #include <lzo/lzo1x.h>
1184    int main(void) { lzo_version(); return 0; }''', dependencies: lzo)
1185   lzo = not_found
1186   if get_option('lzo').enabled()
1187     error('could not link liblzo2')
1188   else
1189     warning('could not link liblzo2, disabling')
1190   endif
1191 endif
1193 numa = not_found
1194 if not get_option('numa').auto() or have_system or have_tools
1195   numa = cc.find_library('numa', has_headers: ['numa.h'],
1196                               required: get_option('numa'),
1197                               kwargs: static_kwargs)
1198 endif
1199 if numa.found() and not cc.links('''
1200    #include <numa.h>
1201    int main(void) { return numa_available(); }
1202    ''', dependencies: numa)
1203   numa = not_found
1204   if get_option('numa').enabled()
1205     error('could not link numa')
1206   else
1207     warning('could not link numa, disabling')
1208   endif
1209 endif
1211 rdma = not_found
1212 if 'CONFIG_RDMA' in config_host
1213   rdma = declare_dependency(link_args: config_host['RDMA_LIBS'].split())
1214 endif
1215 xen = not_found
1216 if 'CONFIG_XEN_BACKEND' in config_host
1217   xen = declare_dependency(compile_args: config_host['XEN_CFLAGS'].split(),
1218                            link_args: config_host['XEN_LIBS'].split())
1219 endif
1220 cacard = not_found
1221 if not get_option('smartcard').auto() or have_system
1222   cacard = dependency('libcacard', required: get_option('smartcard'),
1223                       version: '>=2.5.1', method: 'pkg-config',
1224                       kwargs: static_kwargs)
1225 endif
1226 u2f = not_found
1227 if have_system
1228   u2f = dependency('u2f-emu', required: get_option('u2f'),
1229                    method: 'pkg-config',
1230                    kwargs: static_kwargs)
1231 endif
1232 usbredir = not_found
1233 if not get_option('usb_redir').auto() or have_system
1234   usbredir = dependency('libusbredirparser-0.5', required: get_option('usb_redir'),
1235                         version: '>=0.6', method: 'pkg-config',
1236                         kwargs: static_kwargs)
1237 endif
1238 libusb = not_found
1239 if not get_option('libusb').auto() or have_system
1240   libusb = dependency('libusb-1.0', required: get_option('libusb'),
1241                       version: '>=1.0.13', method: 'pkg-config',
1242                       kwargs: static_kwargs)
1243 endif
1245 libpmem = not_found
1246 if not get_option('libpmem').auto() or have_system
1247   libpmem = dependency('libpmem', required: get_option('libpmem'),
1248                        method: 'pkg-config', kwargs: static_kwargs)
1249 endif
1250 libdaxctl = not_found
1251 if not get_option('libdaxctl').auto() or have_system
1252   libdaxctl = dependency('libdaxctl', required: get_option('libdaxctl'),
1253                          version: '>=57', method: 'pkg-config',
1254                          kwargs: static_kwargs)
1255 endif
1256 tasn1 = not_found
1257 if gnutls.found()
1258   tasn1 = dependency('libtasn1',
1259                      method: 'pkg-config',
1260                      kwargs: static_kwargs)
1261 endif
1262 keyutils = dependency('libkeyutils', required: false,
1263                       method: 'pkg-config', kwargs: static_kwargs)
1265 has_gettid = cc.has_function('gettid')
1267 # libselinux
1268 selinux = dependency('libselinux',
1269                      required: get_option('selinux'),
1270                      method: 'pkg-config', kwargs: static_kwargs)
1272 # Malloc tests
1274 malloc = []
1275 if get_option('malloc') == 'system'
1276   has_malloc_trim = \
1277     get_option('malloc_trim').allowed() and \
1278     cc.links('''#include <malloc.h>
1279                 int main(void) { malloc_trim(0); return 0; }''')
1280 else
1281   has_malloc_trim = false
1282   malloc = cc.find_library(get_option('malloc'), required: true)
1283 endif
1284 if not has_malloc_trim and get_option('malloc_trim').enabled()
1285   if get_option('malloc') == 'system'
1286     error('malloc_trim not available on this platform.')
1287   else
1288     error('malloc_trim not available with non-libc memory allocator')
1289   endif
1290 endif
1292 # Check whether the glibc provides statx()
1294 gnu_source_prefix = '''
1295   #ifndef _GNU_SOURCE
1296   #define _GNU_SOURCE
1297   #endif
1299 statx_test = gnu_source_prefix + '''
1300   #include <sys/stat.h>
1301   int main(void) {
1302     struct statx statxbuf;
1303     statx(0, "", 0, STATX_BASIC_STATS, &statxbuf);
1304     return 0;
1305   }'''
1307 has_statx = cc.links(statx_test)
1309 # Check whether statx() provides mount ID information
1311 statx_mnt_id_test = gnu_source_prefix + '''
1312   #include <sys/stat.h>
1313   int main(void) {
1314     struct statx statxbuf;
1315     statx(0, "", 0, STATX_BASIC_STATS | STATX_MNT_ID, &statxbuf);
1316     return statxbuf.stx_mnt_id;
1317   }'''
1319 has_statx_mnt_id = cc.links(statx_mnt_id_test)
1321 have_vhost_user_blk_server = get_option('vhost_user_blk_server') \
1322   .require(targetos == 'linux',
1323            error_message: 'vhost_user_blk_server requires linux') \
1324   .require('CONFIG_VHOST_USER' in config_host,
1325            error_message: 'vhost_user_blk_server requires vhost-user support') \
1326   .disable_auto_if(not have_system) \
1327   .allowed()
1329 if get_option('fuse').disabled() and get_option('fuse_lseek').enabled()
1330   error('Cannot enable fuse-lseek while fuse is disabled')
1331 endif
1333 fuse = dependency('fuse3', required: get_option('fuse'),
1334                   version: '>=3.1', method: 'pkg-config',
1335                   kwargs: static_kwargs)
1337 fuse_lseek = not_found
1338 if get_option('fuse_lseek').allowed()
1339   if fuse.version().version_compare('>=3.8')
1340     # Dummy dependency
1341     fuse_lseek = declare_dependency()
1342   elif get_option('fuse_lseek').enabled()
1343     if fuse.found()
1344       error('fuse-lseek requires libfuse >=3.8, found ' + fuse.version())
1345     else
1346       error('fuse-lseek requires libfuse, which was not found')
1347     endif
1348   endif
1349 endif
1351 # libbpf
1352 libbpf = dependency('libbpf', required: get_option('bpf'), method: 'pkg-config')
1353 if libbpf.found() and not cc.links('''
1354    #include <bpf/libbpf.h>
1355    int main(void)
1356    {
1357      bpf_object__destroy_skeleton(NULL);
1358      return 0;
1359    }''', dependencies: libbpf)
1360   libbpf = not_found
1361   if get_option('bpf').enabled()
1362     error('libbpf skeleton test failed')
1363   else
1364     warning('libbpf skeleton test failed, disabling')
1365   endif
1366 endif
1368 #################
1369 # config-host.h #
1370 #################
1372 audio_drivers_selected = []
1373 if have_system
1374   audio_drivers_available = {
1375     'alsa': alsa.found(),
1376     'coreaudio': coreaudio.found(),
1377     'dsound': dsound.found(),
1378     'jack': jack.found(),
1379     'oss': oss.found(),
1380     'pa': pulse.found(),
1381     'sdl': sdl.found(),
1382   }
1383   foreach k, v: audio_drivers_available
1384     config_host_data.set('CONFIG_AUDIO_' + k.to_upper(), v)
1385   endforeach
1387   # Default to native drivers first, OSS second, SDL third
1388   audio_drivers_priority = \
1389     [ 'pa', 'coreaudio', 'dsound', 'oss' ] + \
1390     (targetos == 'linux' ? [] : [ 'sdl' ])
1391   audio_drivers_default = []
1392   foreach k: audio_drivers_priority
1393     if audio_drivers_available[k]
1394       audio_drivers_default += k
1395     endif
1396   endforeach
1398   foreach k: get_option('audio_drv_list')
1399     if k == 'default'
1400       audio_drivers_selected += audio_drivers_default
1401     elif not audio_drivers_available[k]
1402       error('Audio driver "@0@" not available.'.format(k))
1403     else
1404       audio_drivers_selected += k
1405     endif
1406   endforeach
1407 endif
1408 config_host_data.set('CONFIG_AUDIO_DRIVERS',
1409                      '"' + '", "'.join(audio_drivers_selected) + '", ')
1411 if get_option('cfi')
1412   cfi_flags=[]
1413   # Check for dependency on LTO
1414   if not get_option('b_lto')
1415     error('Selected Control-Flow Integrity but LTO is disabled')
1416   endif
1417   if config_host.has_key('CONFIG_MODULES')
1418     error('Selected Control-Flow Integrity is not compatible with modules')
1419   endif
1420   # Check for cfi flags. CFI requires LTO so we can't use
1421   # get_supported_arguments, but need a more complex "compiles" which allows
1422   # custom arguments
1423   if cc.compiles('int main () { return 0; }', name: '-fsanitize=cfi-icall',
1424                  args: ['-flto', '-fsanitize=cfi-icall'] )
1425     cfi_flags += '-fsanitize=cfi-icall'
1426   else
1427     error('-fsanitize=cfi-icall is not supported by the compiler')
1428   endif
1429   if cc.compiles('int main () { return 0; }',
1430                  name: '-fsanitize-cfi-icall-generalize-pointers',
1431                  args: ['-flto', '-fsanitize=cfi-icall',
1432                         '-fsanitize-cfi-icall-generalize-pointers'] )
1433     cfi_flags += '-fsanitize-cfi-icall-generalize-pointers'
1434   else
1435     error('-fsanitize-cfi-icall-generalize-pointers is not supported by the compiler')
1436   endif
1437   if get_option('cfi_debug')
1438     if cc.compiles('int main () { return 0; }',
1439                    name: '-fno-sanitize-trap=cfi-icall',
1440                    args: ['-flto', '-fsanitize=cfi-icall',
1441                           '-fno-sanitize-trap=cfi-icall'] )
1442       cfi_flags += '-fno-sanitize-trap=cfi-icall'
1443     else
1444       error('-fno-sanitize-trap=cfi-icall is not supported by the compiler')
1445     endif
1446   endif
1447   add_global_arguments(cfi_flags, native: false, language: ['c', 'cpp', 'objc'])
1448   add_global_link_arguments(cfi_flags, native: false, language: ['c', 'cpp', 'objc'])
1449 endif
1451 have_host_block_device = (targetos != 'darwin' or
1452     cc.has_header('IOKit/storage/IOMedia.h'))
1454 # FIXME enable_modules shouldn't be necessary, but: https://github.com/mesonbuild/meson/issues/8333
1455 dbus_display = get_option('dbus_display') \
1456   .require(gio.version().version_compare('>=2.64'),
1457            error_message: '-display dbus requires glib>=2.64') \
1458   .require(enable_modules,
1459            error_message: '-display dbus requires --enable-modules') \
1460   .require(config_host.has_key('GDBUS_CODEGEN'),
1461            error_message: '-display dbus requires gdbus-codegen') \
1462   .allowed()
1464 have_virtfs = get_option('virtfs') \
1465     .require(targetos == 'linux' or targetos == 'darwin',
1466              error_message: 'virtio-9p (virtfs) requires Linux or macOS') \
1467     .require(targetos == 'linux' or cc.has_function('pthread_fchdir_np'),
1468              error_message: 'virtio-9p (virtfs) on macOS requires the presence of pthread_fchdir_np') \
1469     .require(targetos == 'darwin' or (libattr.found() and libcap_ng.found()),
1470              error_message: 'virtio-9p (virtfs) on Linux requires libcap-ng-devel and libattr-devel') \
1471     .disable_auto_if(not have_tools and not have_system) \
1472     .allowed()
1474 have_virtfs_proxy_helper = targetos != 'darwin' and have_virtfs and have_tools
1476 foreach k : get_option('trace_backends')
1477   config_host_data.set('CONFIG_TRACE_' + k.to_upper(), true)
1478 endforeach
1479 config_host_data.set_quoted('CONFIG_TRACE_FILE', get_option('trace_file'))
1480 if get_option('iasl') != ''
1481   config_host_data.set_quoted('CONFIG_IASL', get_option('iasl'))
1482 endif
1483 config_host_data.set_quoted('CONFIG_BINDIR', get_option('prefix') / get_option('bindir'))
1484 config_host_data.set_quoted('CONFIG_PREFIX', get_option('prefix'))
1485 config_host_data.set_quoted('CONFIG_QEMU_CONFDIR', get_option('prefix') / qemu_confdir)
1486 config_host_data.set_quoted('CONFIG_QEMU_DATADIR', get_option('prefix') / qemu_datadir)
1487 config_host_data.set_quoted('CONFIG_QEMU_DESKTOPDIR', get_option('prefix') / qemu_desktopdir)
1488 config_host_data.set_quoted('CONFIG_QEMU_FIRMWAREPATH', get_option('qemu_firmwarepath'))
1489 config_host_data.set_quoted('CONFIG_QEMU_HELPERDIR', get_option('prefix') / get_option('libexecdir'))
1490 config_host_data.set_quoted('CONFIG_QEMU_ICONDIR', get_option('prefix') / qemu_icondir)
1491 config_host_data.set_quoted('CONFIG_QEMU_LOCALEDIR', get_option('prefix') / get_option('localedir'))
1492 config_host_data.set_quoted('CONFIG_QEMU_LOCALSTATEDIR', get_option('prefix') / get_option('localstatedir'))
1493 config_host_data.set_quoted('CONFIG_QEMU_MODDIR', get_option('prefix') / qemu_moddir)
1494 config_host_data.set_quoted('CONFIG_SYSCONFDIR', get_option('prefix') / get_option('sysconfdir'))
1496 have_slirp_smbd = get_option('slirp_smbd') \
1497   .require(targetos != 'windows', error_message: 'Host smbd not supported on this platform.') \
1498   .allowed()
1499 if have_slirp_smbd
1500   smbd_path = get_option('smbd')
1501   if smbd_path == ''
1502     smbd_path = (targetos == 'solaris' ? '/usr/sfw/sbin/smbd' : '/usr/sbin/smbd')
1503   endif
1504   config_host_data.set_quoted('CONFIG_SMBD_COMMAND', smbd_path)
1505 endif
1507 config_host_data.set('HOST_' + host_arch.to_upper(), 1)
1509 config_host_data.set('CONFIG_ATTR', libattr.found())
1510 config_host_data.set('CONFIG_BDRV_WHITELIST_TOOLS', get_option('block_drv_whitelist_in_tools'))
1511 config_host_data.set('CONFIG_BRLAPI', brlapi.found())
1512 config_host_data.set('CONFIG_COCOA', cocoa.found())
1513 config_host_data.set('CONFIG_FUZZ', get_option('fuzzing'))
1514 config_host_data.set('CONFIG_GCOV', get_option('b_coverage'))
1515 config_host_data.set('CONFIG_LIBUDEV', libudev.found())
1516 config_host_data.set('CONFIG_LZO', lzo.found())
1517 config_host_data.set('CONFIG_MPATH', mpathpersist.found())
1518 config_host_data.set('CONFIG_MPATH_NEW_API', mpathpersist_new_api)
1519 config_host_data.set('CONFIG_CURL', curl.found())
1520 config_host_data.set('CONFIG_CURSES', curses.found())
1521 config_host_data.set('CONFIG_GBM', gbm.found())
1522 config_host_data.set('CONFIG_GLUSTERFS', glusterfs.found())
1523 if glusterfs.found()
1524   config_host_data.set('CONFIG_GLUSTERFS_XLATOR_OPT', glusterfs.version().version_compare('>=4'))
1525   config_host_data.set('CONFIG_GLUSTERFS_DISCARD', glusterfs.version().version_compare('>=5'))
1526   config_host_data.set('CONFIG_GLUSTERFS_FALLOCATE', glusterfs.version().version_compare('>=6'))
1527   config_host_data.set('CONFIG_GLUSTERFS_ZEROFILL', glusterfs.version().version_compare('>=6'))
1528   config_host_data.set('CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT', glusterfs_ftruncate_has_stat)
1529   config_host_data.set('CONFIG_GLUSTERFS_IOCB_HAS_STAT', glusterfs_iocb_has_stat)
1530 endif
1531 config_host_data.set('CONFIG_GTK', gtk.found())
1532 config_host_data.set('CONFIG_VTE', vte.found())
1533 config_host_data.set('CONFIG_LIBATTR', have_old_libattr)
1534 config_host_data.set('CONFIG_LIBCAP_NG', libcap_ng.found())
1535 config_host_data.set('CONFIG_EBPF', libbpf.found())
1536 config_host_data.set('CONFIG_LIBDAXCTL', libdaxctl.found())
1537 config_host_data.set('CONFIG_LIBISCSI', libiscsi.found())
1538 config_host_data.set('CONFIG_LIBNFS', libnfs.found())
1539 config_host_data.set('CONFIG_LIBSSH', libssh.found())
1540 config_host_data.set('CONFIG_LINUX_AIO', libaio.found())
1541 config_host_data.set('CONFIG_LINUX_IO_URING', linux_io_uring.found())
1542 config_host_data.set('CONFIG_LIBPMEM', libpmem.found())
1543 config_host_data.set('CONFIG_NUMA', numa.found())
1544 config_host_data.set('CONFIG_PROFILER', get_option('profiler'))
1545 config_host_data.set('CONFIG_RBD', rbd.found())
1546 config_host_data.set('CONFIG_SDL', sdl.found())
1547 config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found())
1548 config_host_data.set('CONFIG_SECCOMP', seccomp.found())
1549 config_host_data.set('CONFIG_SNAPPY', snappy.found())
1550 config_host_data.set('CONFIG_TPM', have_tpm)
1551 config_host_data.set('CONFIG_USB_LIBUSB', libusb.found())
1552 config_host_data.set('CONFIG_VDE', vde.found())
1553 config_host_data.set('CONFIG_VHOST_USER_BLK_SERVER', have_vhost_user_blk_server)
1554 config_host_data.set('CONFIG_VNC', vnc.found())
1555 config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
1556 config_host_data.set('CONFIG_VNC_PNG', png.found())
1557 config_host_data.set('CONFIG_VNC_SASL', sasl.found())
1558 config_host_data.set('CONFIG_VIRTFS', have_virtfs)
1559 config_host_data.set('CONFIG_VTE', vte.found())
1560 config_host_data.set('CONFIG_XKBCOMMON', xkbcommon.found())
1561 config_host_data.set('CONFIG_KEYUTILS', keyutils.found())
1562 config_host_data.set('CONFIG_GETTID', has_gettid)
1563 config_host_data.set('CONFIG_GNUTLS', gnutls.found())
1564 config_host_data.set('CONFIG_GNUTLS_CRYPTO', gnutls_crypto.found())
1565 config_host_data.set('CONFIG_GCRYPT', gcrypt.found())
1566 config_host_data.set('CONFIG_NETTLE', nettle.found())
1567 config_host_data.set('CONFIG_QEMU_PRIVATE_XTS', xts == 'private')
1568 config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim)
1569 config_host_data.set('CONFIG_STATX', has_statx)
1570 config_host_data.set('CONFIG_STATX_MNT_ID', has_statx_mnt_id)
1571 config_host_data.set('CONFIG_ZSTD', zstd.found())
1572 config_host_data.set('CONFIG_FUSE', fuse.found())
1573 config_host_data.set('CONFIG_FUSE_LSEEK', fuse_lseek.found())
1574 config_host_data.set('CONFIG_SPICE_PROTOCOL', spice_protocol.found())
1575 if spice_protocol.found()
1576 config_host_data.set('CONFIG_SPICE_PROTOCOL_MAJOR', spice_protocol.version().split('.')[0])
1577 config_host_data.set('CONFIG_SPICE_PROTOCOL_MINOR', spice_protocol.version().split('.')[1])
1578 config_host_data.set('CONFIG_SPICE_PROTOCOL_MICRO', spice_protocol.version().split('.')[2])
1579 endif
1580 config_host_data.set('CONFIG_SPICE', spice.found())
1581 config_host_data.set('CONFIG_X11', x11.found())
1582 config_host_data.set('CONFIG_DBUS_DISPLAY', dbus_display)
1583 config_host_data.set('CONFIG_CFI', get_option('cfi'))
1584 config_host_data.set('CONFIG_SELINUX', selinux.found())
1585 config_host_data.set('QEMU_VERSION', '"@0@"'.format(meson.project_version()))
1586 config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0])
1587 config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1])
1588 config_host_data.set('QEMU_VERSION_MICRO', meson.project_version().split('.')[2])
1590 config_host_data.set_quoted('CONFIG_HOST_DSOSUF', host_dsosuf)
1591 config_host_data.set('HAVE_HOST_BLOCK_DEVICE', have_host_block_device)
1592 config_host_data.set('HOST_WORDS_BIGENDIAN', host_machine.endian() == 'big')
1594 have_coroutine_pool = get_option('coroutine_pool')
1595 if get_option('debug_stack_usage') and have_coroutine_pool
1596   message('Disabling coroutine pool to measure stack usage')
1597   have_coroutine_pool = false
1598 endif
1599 config_host_data.set10('CONFIG_COROUTINE_POOL', have_coroutine_pool)
1600 config_host_data.set('CONFIG_DEBUG_MUTEX', get_option('debug_mutex'))
1601 config_host_data.set('CONFIG_DEBUG_STACK_USAGE', get_option('debug_stack_usage'))
1602 config_host_data.set('CONFIG_GPROF', get_option('gprof'))
1603 config_host_data.set('CONFIG_LIVE_BLOCK_MIGRATION', get_option('live_block_migration').allowed())
1604 config_host_data.set('CONFIG_QOM_CAST_DEBUG', get_option('qom_cast_debug'))
1605 config_host_data.set('CONFIG_REPLICATION', get_option('live_block_migration').allowed())
1607 # has_header
1608 config_host_data.set('CONFIG_EPOLL', cc.has_header('sys/epoll.h'))
1609 config_host_data.set('CONFIG_LINUX_MAGIC_H', cc.has_header('linux/magic.h'))
1610 config_host_data.set('CONFIG_VALGRIND_H', cc.has_header('valgrind/valgrind.h'))
1611 config_host_data.set('HAVE_BTRFS_H', cc.has_header('linux/btrfs.h'))
1612 config_host_data.set('HAVE_DRM_H', cc.has_header('libdrm/drm.h'))
1613 config_host_data.set('HAVE_PTY_H', cc.has_header('pty.h'))
1614 config_host_data.set('HAVE_SYS_DISK_H', cc.has_header('sys/disk.h'))
1615 config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h'))
1616 config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h'))
1618 # has_function
1619 config_host_data.set('CONFIG_ACCEPT4', cc.has_function('accept4'))
1620 config_host_data.set('CONFIG_CLOCK_ADJTIME', cc.has_function('clock_adjtime'))
1621 config_host_data.set('CONFIG_DUP3', cc.has_function('dup3'))
1622 config_host_data.set('CONFIG_FALLOCATE', cc.has_function('fallocate'))
1623 config_host_data.set('CONFIG_POSIX_FALLOCATE', cc.has_function('posix_fallocate'))
1624 # Note that we need to specify prefix: here to avoid incorrectly
1625 # thinking that Windows has posix_memalign()
1626 config_host_data.set('CONFIG_POSIX_MEMALIGN', cc.has_function('posix_memalign', prefix: '#include <stdlib.h>'))
1627 config_host_data.set('CONFIG_ALIGNED_MALLOC', cc.has_function('_aligned_malloc'))
1628 config_host_data.set('CONFIG_VALLOC', cc.has_function('valloc'))
1629 config_host_data.set('CONFIG_MEMALIGN', cc.has_function('memalign'))
1630 config_host_data.set('CONFIG_PPOLL', cc.has_function('ppoll'))
1631 config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include <sys/uio.h>'))
1632 config_host_data.set('CONFIG_PTHREAD_FCHDIR_NP', cc.has_function('pthread_fchdir_np'))
1633 config_host_data.set('CONFIG_SEM_TIMEDWAIT', cc.has_function('sem_timedwait', dependencies: threads))
1634 config_host_data.set('CONFIG_SENDFILE', cc.has_function('sendfile'))
1635 config_host_data.set('CONFIG_SETNS', cc.has_function('setns') and cc.has_function('unshare'))
1636 config_host_data.set('CONFIG_SYNCFS', cc.has_function('syncfs'))
1637 config_host_data.set('CONFIG_SYNC_FILE_RANGE', cc.has_function('sync_file_range'))
1638 config_host_data.set('CONFIG_TIMERFD', cc.has_function('timerfd_create'))
1639 config_host_data.set('HAVE_COPY_FILE_RANGE', cc.has_function('copy_file_range'))
1640 config_host_data.set('HAVE_OPENPTY', cc.has_function('openpty', dependencies: util))
1641 config_host_data.set('HAVE_STRCHRNUL', cc.has_function('strchrnul'))
1642 config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: '#include <stdlib.h>'))
1643 if rdma.found()
1644   config_host_data.set('HAVE_IBV_ADVISE_MR',
1645                        cc.has_function('ibv_advise_mr',
1646                                        args: config_host['RDMA_LIBS'].split(),
1647                                        prefix: '#include <infiniband/verbs.h>'))
1648 endif
1650 # has_header_symbol
1651 config_host_data.set('CONFIG_BYTESWAP_H',
1652                      cc.has_header_symbol('byteswap.h', 'bswap_32'))
1653 config_host_data.set('CONFIG_EPOLL_CREATE1',
1654                      cc.has_header_symbol('sys/epoll.h', 'epoll_create1'))
1655 config_host_data.set('CONFIG_HAS_ENVIRON',
1656                      cc.has_header_symbol('unistd.h', 'environ', prefix: gnu_source_prefix))
1657 config_host_data.set('CONFIG_FALLOCATE_PUNCH_HOLE',
1658                      cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_PUNCH_HOLE') and
1659                      cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_KEEP_SIZE'))
1660 config_host_data.set('CONFIG_FALLOCATE_ZERO_RANGE',
1661                      cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_ZERO_RANGE'))
1662 config_host_data.set('CONFIG_FIEMAP',
1663                      cc.has_header('linux/fiemap.h') and
1664                      cc.has_header_symbol('linux/fs.h', 'FS_IOC_FIEMAP'))
1665 config_host_data.set('CONFIG_GETRANDOM',
1666                      cc.has_function('getrandom') and
1667                      cc.has_header_symbol('sys/random.h', 'GRND_NONBLOCK'))
1668 config_host_data.set('CONFIG_INOTIFY',
1669                      cc.has_header_symbol('sys/inotify.h', 'inotify_init'))
1670 config_host_data.set('CONFIG_INOTIFY1',
1671                      cc.has_header_symbol('sys/inotify.h', 'inotify_init1'))
1672 config_host_data.set('CONFIG_MACHINE_BSWAP_H',
1673                      cc.has_header_symbol('machine/bswap.h', 'bswap32',
1674                                           prefix: '''#include <sys/endian.h>
1675                                                      #include <sys/types.h>'''))
1676 config_host_data.set('CONFIG_PRCTL_PR_SET_TIMERSLACK',
1677                      cc.has_header_symbol('sys/prctl.h', 'PR_SET_TIMERSLACK'))
1678 config_host_data.set('CONFIG_RTNETLINK',
1679                      cc.has_header_symbol('linux/rtnetlink.h', 'IFLA_PROTO_DOWN'))
1680 config_host_data.set('CONFIG_SYSMACROS',
1681                      cc.has_header_symbol('sys/sysmacros.h', 'makedev'))
1682 config_host_data.set('HAVE_OPTRESET',
1683                      cc.has_header_symbol('getopt.h', 'optreset'))
1684 config_host_data.set('HAVE_IPPROTO_MPTCP',
1685                      cc.has_header_symbol('netinet/in.h', 'IPPROTO_MPTCP'))
1687 # has_member
1688 config_host_data.set('HAVE_SIGEV_NOTIFY_THREAD_ID',
1689                      cc.has_member('struct sigevent', 'sigev_notify_thread_id',
1690                                    prefix: '#include <signal.h>'))
1691 config_host_data.set('HAVE_STRUCT_STAT_ST_ATIM',
1692                      cc.has_member('struct stat', 'st_atim',
1693                                    prefix: '#include <sys/stat.h>'))
1695 # has_type
1696 config_host_data.set('CONFIG_IOVEC',
1697                      cc.has_type('struct iovec',
1698                                  prefix: '#include <sys/uio.h>'))
1699 config_host_data.set('HAVE_UTMPX',
1700                      cc.has_type('struct utmpx',
1701                                  prefix: '#include <utmpx.h>'))
1703 config_host_data.set('CONFIG_EVENTFD', cc.links('''
1704   #include <sys/eventfd.h>
1705   int main(void) { return eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); }'''))
1706 config_host_data.set('CONFIG_FDATASYNC', cc.links(gnu_source_prefix + '''
1707   #include <unistd.h>
1708   int main(void) {
1709   #if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
1710   return fdatasync(0);
1711   #else
1712   #error Not supported
1713   #endif
1714   }'''))
1715 config_host_data.set('CONFIG_MADVISE', cc.links(gnu_source_prefix + '''
1716   #include <sys/types.h>
1717   #include <sys/mman.h>
1718   #include <stddef.h>
1719   int main(void) { return madvise(NULL, 0, MADV_DONTNEED); }'''))
1720 config_host_data.set('CONFIG_MEMFD', cc.links(gnu_source_prefix + '''
1721   #include <sys/mman.h>
1722   int main(void) { return memfd_create("foo", MFD_ALLOW_SEALING); }'''))
1723 config_host_data.set('CONFIG_OPEN_BY_HANDLE', cc.links(gnu_source_prefix + '''
1724   #include <fcntl.h>
1725   #if !defined(AT_EMPTY_PATH)
1726   # error missing definition
1727   #else
1728   int main(void) { struct file_handle fh; return open_by_handle_at(0, &fh, 0); }
1729   #endif'''))
1730 config_host_data.set('CONFIG_PIPE2', cc.links(gnu_source_prefix + '''
1731   #include <unistd.h>
1732   #include <fcntl.h>
1734   int main(void)
1735   {
1736       int pipefd[2];
1737       return pipe2(pipefd, O_CLOEXEC);
1738   }'''))
1739 config_host_data.set('CONFIG_POSIX_MADVISE', cc.links(gnu_source_prefix + '''
1740   #include <sys/mman.h>
1741   #include <stddef.h>
1742   int main(void) { return posix_madvise(NULL, 0, POSIX_MADV_DONTNEED); }'''))
1744 config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_W_TID', cc.links(gnu_source_prefix + '''
1745   #include <pthread.h>
1747   static void *f(void *p) { return NULL; }
1748   int main(void)
1749   {
1750     pthread_t thread;
1751     pthread_create(&thread, 0, f, 0);
1752     pthread_setname_np(thread, "QEMU");
1753     return 0;
1754   }''', dependencies: threads))
1755 config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_WO_TID', cc.links(gnu_source_prefix + '''
1756   #include <pthread.h>
1758   static void *f(void *p) { pthread_setname_np("QEMU"); return NULL; }
1759   int main(void)
1760   {
1761     pthread_t thread;
1762     pthread_create(&thread, 0, f, 0);
1763     return 0;
1764   }''', dependencies: threads))
1766 config_host_data.set('CONFIG_SIGNALFD', cc.links(gnu_source_prefix + '''
1767   #include <sys/signalfd.h>
1768   #include <stddef.h>
1769   int main(void) { return signalfd(-1, NULL, SFD_CLOEXEC); }'''))
1770 config_host_data.set('CONFIG_SPLICE', cc.links(gnu_source_prefix + '''
1771   #include <unistd.h>
1772   #include <fcntl.h>
1773   #include <limits.h>
1775   int main(void)
1776   {
1777     int len, fd = 0;
1778     len = tee(STDIN_FILENO, STDOUT_FILENO, INT_MAX, SPLICE_F_NONBLOCK);
1779     splice(STDIN_FILENO, NULL, fd, NULL, len, SPLICE_F_MOVE);
1780     return 0;
1781   }'''))
1783 config_host_data.set('HAVE_MLOCKALL', cc.links(gnu_source_prefix + '''
1784   #include <sys/mman.h>
1785   int main(int argc, char *argv[]) {
1786     return mlockall(MCL_FUTURE);
1787   }'''))
1789 have_l2tpv3 = false
1790 if get_option('l2tpv3').allowed() and have_system
1791   have_l2tpv3 = cc.has_type('struct mmsghdr',
1792     prefix: gnu_source_prefix + '''
1793       #include <sys/socket.h>
1794       #include <linux/ip.h>''')
1795 endif
1796 config_host_data.set('CONFIG_L2TPV3', have_l2tpv3)
1798 have_netmap = false
1799 if get_option('netmap').allowed() and have_system
1800   have_netmap = cc.compiles('''
1801     #include <inttypes.h>
1802     #include <net/if.h>
1803     #include <net/netmap.h>
1804     #include <net/netmap_user.h>
1805     #if (NETMAP_API < 11) || (NETMAP_API > 15)
1806     #error
1807     #endif
1808     int main(void) { return 0; }''')
1809   if not have_netmap and get_option('netmap').enabled()
1810     error('Netmap headers not available')
1811   endif
1812 endif
1813 config_host_data.set('CONFIG_NETMAP', have_netmap)
1815 # Work around a system header bug with some kernel/XFS header
1816 # versions where they both try to define 'struct fsxattr':
1817 # xfs headers will not try to redefine structs from linux headers
1818 # if this macro is set.
1819 config_host_data.set('HAVE_FSXATTR', cc.links('''
1820   #include <linux/fs.h>
1821   struct fsxattr foo;
1822   int main(void) {
1823     return 0;
1824   }'''))
1826 # Some versions of Mac OS X incorrectly define SIZE_MAX
1827 config_host_data.set('HAVE_BROKEN_SIZE_MAX', not cc.compiles('''
1828     #include <stdint.h>
1829     #include <stdio.h>
1830     int main(int argc, char *argv[]) {
1831         return printf("%zu", SIZE_MAX);
1832     }''', args: ['-Werror']))
1834 # See if 64-bit atomic operations are supported.
1835 # Note that without __atomic builtins, we can only
1836 # assume atomic loads/stores max at pointer size.
1837 config_host_data.set('CONFIG_ATOMIC64', cc.links('''
1838   #include <stdint.h>
1839   int main(void)
1840   {
1841     uint64_t x = 0, y = 0;
1842     y = __atomic_load_n(&x, __ATOMIC_RELAXED);
1843     __atomic_store_n(&x, y, __ATOMIC_RELAXED);
1844     __atomic_compare_exchange_n(&x, &y, x, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
1845     __atomic_exchange_n(&x, y, __ATOMIC_RELAXED);
1846     __atomic_fetch_add(&x, y, __ATOMIC_RELAXED);
1847     return 0;
1848   }'''))
1850 config_host_data.set('CONFIG_GETAUXVAL', cc.links(gnu_source_prefix + '''
1851   #include <sys/auxv.h>
1852   int main(void) {
1853     return getauxval(AT_HWCAP) == 0;
1854   }'''))
1856 have_cpuid_h = cc.links('''
1857   #include <cpuid.h>
1858   int main(void) {
1859     unsigned a, b, c, d;
1860     unsigned max = __get_cpuid_max(0, 0);
1862     if (max >= 1) {
1863         __cpuid(1, a, b, c, d);
1864     }
1866     if (max >= 7) {
1867         __cpuid_count(7, 0, a, b, c, d);
1868     }
1870     return 0;
1871   }''')
1872 config_host_data.set('CONFIG_CPUID_H', have_cpuid_h)
1874 config_host_data.set('CONFIG_AVX2_OPT', get_option('avx2') \
1875   .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX2') \
1876   .require(cc.links('''
1877     #pragma GCC push_options
1878     #pragma GCC target("avx2")
1879     #include <cpuid.h>
1880     #include <immintrin.h>
1881     static int bar(void *a) {
1882       __m256i x = *(__m256i *)a;
1883       return _mm256_testz_si256(x, x);
1884     }
1885     int main(int argc, char *argv[]) { return bar(argv[0]); }
1886   '''), error_message: 'AVX2 not available').allowed())
1888 config_host_data.set('CONFIG_AVX512F_OPT', get_option('avx512f') \
1889   .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX512F') \
1890   .require(cc.links('''
1891     #pragma GCC push_options
1892     #pragma GCC target("avx512f")
1893     #include <cpuid.h>
1894     #include <immintrin.h>
1895     static int bar(void *a) {
1896       __m512i x = *(__m512i *)a;
1897       return _mm512_test_epi64_mask(x, x);
1898     }
1899     int main(int argc, char *argv[]) { return bar(argv[0]); }
1900   '''), error_message: 'AVX512F not available').allowed())
1902 if get_option('membarrier').disabled()
1903   have_membarrier = false
1904 elif targetos == 'windows'
1905   have_membarrier = true
1906 elif targetos == 'linux'
1907   have_membarrier = cc.compiles('''
1908     #include <linux/membarrier.h>
1909     #include <sys/syscall.h>
1910     #include <unistd.h>
1911     #include <stdlib.h>
1912     int main(void) {
1913         syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0);
1914         syscall(__NR_membarrier, MEMBARRIER_CMD_SHARED, 0);
1915         exit(0);
1916     }''')
1917 endif
1918 config_host_data.set('CONFIG_MEMBARRIER', get_option('membarrier') \
1919   .require(have_membarrier, error_message: 'membarrier system call not available') \
1920   .allowed())
1922 have_afalg = get_option('crypto_afalg') \
1923   .require(cc.compiles(gnu_source_prefix + '''
1924     #include <errno.h>
1925     #include <sys/types.h>
1926     #include <sys/socket.h>
1927     #include <linux/if_alg.h>
1928     int main(void) {
1929       int sock;
1930       sock = socket(AF_ALG, SOCK_SEQPACKET, 0);
1931       return sock;
1932     }
1933   '''), error_message: 'AF_ALG requested but could not be detected').allowed()
1934 config_host_data.set('CONFIG_AF_ALG', have_afalg)
1936 config_host_data.set('CONFIG_AF_VSOCK', cc.compiles(gnu_source_prefix + '''
1937   #include <errno.h>
1938   #include <sys/types.h>
1939   #include <sys/socket.h>
1940   #if !defined(AF_VSOCK)
1941   # error missing AF_VSOCK flag
1942   #endif
1943   #include <linux/vm_sockets.h>
1944   int main(void) {
1945     int sock, ret;
1946     struct sockaddr_vm svm;
1947     socklen_t len = sizeof(svm);
1948     sock = socket(AF_VSOCK, SOCK_STREAM, 0);
1949     ret = getpeername(sock, (struct sockaddr *)&svm, &len);
1950     if ((ret == -1) && (errno == ENOTCONN)) {
1951         return 0;
1952     }
1953     return -1;
1954   }'''))
1956 have_vss = false
1957 have_vss_sdk = false # old xp/2003 SDK
1958 if targetos == 'windows' and link_language == 'cpp'
1959   have_vss = cxx.compiles('''
1960     #define __MIDL_user_allocate_free_DEFINED__
1961     #include <vss.h>
1962     int main(void) { return VSS_CTX_BACKUP; }''')
1963   have_vss_sdk = cxx.has_header('vscoordint.h')
1964 endif
1965 config_host_data.set('HAVE_VSS_SDK', have_vss_sdk)
1967 have_ntddscsi = false
1968 if targetos == 'windows'
1969   have_ntddscsi = cc.compiles('''
1970     #include <windows.h>
1971     #include <ntddscsi.h>
1972     int main(void) {
1973     #if !defined(IOCTL_SCSI_GET_ADDRESS)
1974     #error Missing required ioctl definitions
1975     #endif
1976       SCSI_ADDRESS addr = { .Lun = 0, .TargetId = 0, .PathId = 0 };
1977       return addr.Lun;
1978     }
1979 ''')
1980 endif
1981 config_host_data.set('HAVE_NTDDSCSI', have_ntddscsi)
1983 ignored = ['CONFIG_QEMU_INTERP_PREFIX', # actually per-target
1984     'HAVE_GDB_BIN']
1985 arrays = ['CONFIG_BDRV_RW_WHITELIST', 'CONFIG_BDRV_RO_WHITELIST']
1986 foreach k, v: config_host
1987   if ignored.contains(k)
1988     # do nothing
1989   elif arrays.contains(k)
1990     if v != ''
1991       v = '"' + '", "'.join(v.split()) + '", '
1992     endif
1993     config_host_data.set(k, v)
1994   elif k.startswith('CONFIG_')
1995     config_host_data.set(k, v == 'y' ? 1 : v)
1996   endif
1997 endforeach
1999 ########################
2000 # Target configuration #
2001 ########################
2003 minikconf = find_program('scripts/minikconf.py')
2004 config_all = {}
2005 config_all_devices = {}
2006 config_all_disas = {}
2007 config_devices_mak_list = []
2008 config_devices_h = {}
2009 config_target_h = {}
2010 config_target_mak = {}
2012 disassemblers = {
2013   'alpha' : ['CONFIG_ALPHA_DIS'],
2014   'arm' : ['CONFIG_ARM_DIS'],
2015   'avr' : ['CONFIG_AVR_DIS'],
2016   'cris' : ['CONFIG_CRIS_DIS'],
2017   'hexagon' : ['CONFIG_HEXAGON_DIS'],
2018   'hppa' : ['CONFIG_HPPA_DIS'],
2019   'i386' : ['CONFIG_I386_DIS'],
2020   'x86_64' : ['CONFIG_I386_DIS'],
2021   'm68k' : ['CONFIG_M68K_DIS'],
2022   'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
2023   'mips' : ['CONFIG_MIPS_DIS'],
2024   'nios2' : ['CONFIG_NIOS2_DIS'],
2025   'or1k' : ['CONFIG_OPENRISC_DIS'],
2026   'ppc' : ['CONFIG_PPC_DIS'],
2027   'riscv' : ['CONFIG_RISCV_DIS'],
2028   'rx' : ['CONFIG_RX_DIS'],
2029   's390' : ['CONFIG_S390_DIS'],
2030   'sh4' : ['CONFIG_SH4_DIS'],
2031   'sparc' : ['CONFIG_SPARC_DIS'],
2032   'xtensa' : ['CONFIG_XTENSA_DIS'],
2034 if link_language == 'cpp'
2035   disassemblers += {
2036     'aarch64' : [ 'CONFIG_ARM_A64_DIS'],
2037     'arm' : [ 'CONFIG_ARM_DIS', 'CONFIG_ARM_A64_DIS'],
2038     'mips' : [ 'CONFIG_MIPS_DIS', 'CONFIG_NANOMIPS_DIS'],
2039   }
2040 endif
2042 have_ivshmem = config_host_data.get('CONFIG_EVENTFD')
2043 host_kconfig = \
2044   (get_option('fuzzing') ? ['CONFIG_FUZZ=y'] : []) + \
2045   (have_tpm ? ['CONFIG_TPM=y'] : []) + \
2046   (spice.found() ? ['CONFIG_SPICE=y'] : []) + \
2047   (have_ivshmem ? ['CONFIG_IVSHMEM=y'] : []) + \
2048   ('CONFIG_OPENGL' in config_host ? ['CONFIG_OPENGL=y'] : []) + \
2049   (x11.found() ? ['CONFIG_X11=y'] : []) + \
2050   ('CONFIG_VHOST_USER' in config_host ? ['CONFIG_VHOST_USER=y'] : []) + \
2051   ('CONFIG_VHOST_VDPA' in config_host ? ['CONFIG_VHOST_VDPA=y'] : []) + \
2052   ('CONFIG_VHOST_KERNEL' in config_host ? ['CONFIG_VHOST_KERNEL=y'] : []) + \
2053   (have_virtfs ? ['CONFIG_VIRTFS=y'] : []) + \
2054   ('CONFIG_LINUX' in config_host ? ['CONFIG_LINUX=y'] : []) + \
2055   ('CONFIG_PVRDMA' in config_host ? ['CONFIG_PVRDMA=y'] : []) + \
2056   (multiprocess_allowed ? ['CONFIG_MULTIPROCESS_ALLOWED=y'] : [])
2058 ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ]
2060 default_targets = 'CONFIG_DEFAULT_TARGETS' in config_host
2061 actual_target_dirs = []
2062 fdt_required = []
2063 foreach target : target_dirs
2064   config_target = { 'TARGET_NAME': target.split('-')[0] }
2065   if target.endswith('linux-user')
2066     if targetos != 'linux'
2067       if default_targets
2068         continue
2069       endif
2070       error('Target @0@ is only available on a Linux host'.format(target))
2071     endif
2072     config_target += { 'CONFIG_LINUX_USER': 'y' }
2073   elif target.endswith('bsd-user')
2074     if 'CONFIG_BSD' not in config_host
2075       if default_targets
2076         continue
2077       endif
2078       error('Target @0@ is only available on a BSD host'.format(target))
2079     endif
2080     config_target += { 'CONFIG_BSD_USER': 'y' }
2081   elif target.endswith('softmmu')
2082     config_target += { 'CONFIG_SOFTMMU': 'y' }
2083   endif
2084   if target.endswith('-user')
2085     config_target += {
2086       'CONFIG_USER_ONLY': 'y',
2087       'CONFIG_QEMU_INTERP_PREFIX':
2088         config_host['CONFIG_QEMU_INTERP_PREFIX'].format(config_target['TARGET_NAME'])
2089     }
2090   endif
2092   accel_kconfig = []
2093   foreach sym: accelerators
2094     if sym == 'CONFIG_TCG' or target in accelerator_targets.get(sym, [])
2095       config_target += { sym: 'y' }
2096       config_all += { sym: 'y' }
2097       if sym == 'CONFIG_TCG' and tcg_arch == 'tci'
2098         config_target += { 'CONFIG_TCG_INTERPRETER': 'y' }
2099       elif sym == 'CONFIG_XEN' and have_xen_pci_passthrough
2100         config_target += { 'CONFIG_XEN_PCI_PASSTHROUGH': 'y' }
2101       endif
2102       if target in modular_tcg
2103         config_target += { 'CONFIG_TCG_MODULAR': 'y' }
2104       else
2105         config_target += { 'CONFIG_TCG_BUILTIN': 'y' }
2106       endif
2107       accel_kconfig += [ sym + '=y' ]
2108     endif
2109   endforeach
2110   if accel_kconfig.length() == 0
2111     if default_targets
2112       continue
2113     endif
2114     error('No accelerator available for target @0@'.format(target))
2115   endif
2117   actual_target_dirs += target
2118   config_target += keyval.load('configs/targets' / target + '.mak')
2119   config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
2121   if 'TARGET_NEED_FDT' in config_target
2122     fdt_required += target
2123   endif
2125   # Add default keys
2126   if 'TARGET_BASE_ARCH' not in config_target
2127     config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
2128   endif
2129   if 'TARGET_ABI_DIR' not in config_target
2130     config_target += {'TARGET_ABI_DIR': config_target['TARGET_ARCH']}
2131   endif
2133   foreach k, v: disassemblers
2134     if host_arch.startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k)
2135       foreach sym: v
2136         config_target += { sym: 'y' }
2137         config_all_disas += { sym: 'y' }
2138       endforeach
2139     endif
2140   endforeach
2142   config_target_data = configuration_data()
2143   foreach k, v: config_target
2144     if not k.startswith('TARGET_') and not k.startswith('CONFIG_')
2145       # do nothing
2146     elif ignored.contains(k)
2147       # do nothing
2148     elif k == 'TARGET_BASE_ARCH'
2149       # Note that TARGET_BASE_ARCH ends up in config-target.h but it is
2150       # not used to select files from sourcesets.
2151       config_target_data.set('TARGET_' + v.to_upper(), 1)
2152     elif k == 'TARGET_NAME' or k == 'CONFIG_QEMU_INTERP_PREFIX'
2153       config_target_data.set_quoted(k, v)
2154     elif v == 'y'
2155       config_target_data.set(k, 1)
2156     else
2157       config_target_data.set(k, v)
2158     endif
2159   endforeach
2160   config_target_data.set('QEMU_ARCH',
2161                          'QEMU_ARCH_' + config_target['TARGET_BASE_ARCH'].to_upper())
2162   config_target_h += {target: configure_file(output: target + '-config-target.h',
2163                                                configuration: config_target_data)}
2165   if target.endswith('-softmmu')
2166     config_input = meson.get_external_property(target, 'default')
2167     config_devices_mak = target + '-config-devices.mak'
2168     config_devices_mak = configure_file(
2169       input: ['configs/devices' / target / config_input + '.mak', 'Kconfig'],
2170       output: config_devices_mak,
2171       depfile: config_devices_mak + '.d',
2172       capture: true,
2173       command: [minikconf,
2174                 get_option('default_devices') ? '--defconfig' : '--allnoconfig',
2175                 config_devices_mak, '@DEPFILE@', '@INPUT@',
2176                 host_kconfig, accel_kconfig,
2177                 'CONFIG_' + config_target['TARGET_ARCH'].to_upper() + '=y'])
2179     config_devices_data = configuration_data()
2180     config_devices = keyval.load(config_devices_mak)
2181     foreach k, v: config_devices
2182       config_devices_data.set(k, 1)
2183     endforeach
2184     config_devices_mak_list += config_devices_mak
2185     config_devices_h += {target: configure_file(output: target + '-config-devices.h',
2186                                                 configuration: config_devices_data)}
2187     config_target += config_devices
2188     config_all_devices += config_devices
2189   endif
2190   config_target_mak += {target: config_target}
2191 endforeach
2192 target_dirs = actual_target_dirs
2194 # This configuration is used to build files that are shared by
2195 # multiple binaries, and then extracted out of the "common"
2196 # static_library target.
2198 # We do not use all_sources()/all_dependencies(), because it would
2199 # build literally all source files, including devices only used by
2200 # targets that are not built for this compilation.  The CONFIG_ALL
2201 # pseudo symbol replaces it.
2203 config_all += config_all_devices
2204 config_all += config_host
2205 config_all += config_all_disas
2206 config_all += {
2207   'CONFIG_XEN': config_host.has_key('CONFIG_XEN_BACKEND'),
2208   'CONFIG_SOFTMMU': have_system,
2209   'CONFIG_USER_ONLY': have_user,
2210   'CONFIG_ALL': true,
2213 target_configs_h = []
2214 foreach target: target_dirs
2215   target_configs_h += config_target_h[target]
2216   target_configs_h += config_devices_h.get(target, [])
2217 endforeach
2218 genh += custom_target('config-poison.h',
2219                       input: [target_configs_h],
2220                       output: 'config-poison.h',
2221                       capture: true,
2222                       command: [find_program('scripts/make-config-poison.sh'),
2223                                 target_configs_h])
2225 ##############
2226 # Submodules #
2227 ##############
2229 capstone = not_found
2230 capstone_opt = get_option('capstone')
2231 if capstone_opt in ['enabled', 'auto', 'system']
2232   have_internal = fs.exists(meson.current_source_dir() / 'capstone/Makefile')
2233   capstone = dependency('capstone', version: '>=4.0',
2234                         kwargs: static_kwargs, method: 'pkg-config',
2235                         required: capstone_opt == 'system' or
2236                                   capstone_opt == 'enabled' and not have_internal)
2238   # Some versions of capstone have broken pkg-config file
2239   # that reports a wrong -I path, causing the #include to
2240   # fail later. If the system has such a broken version
2241   # do not use it.
2242   if capstone.found() and not cc.compiles('#include <capstone.h>',
2243                                           dependencies: [capstone])
2244     capstone = not_found
2245     if capstone_opt == 'system'
2246       error('system capstone requested, it does not appear to work')
2247     endif
2248   endif
2250   if capstone.found()
2251     capstone_opt = 'system'
2252   elif have_internal
2253     capstone_opt = 'internal'
2254   else
2255     capstone_opt = 'disabled'
2256   endif
2257 endif
2258 if capstone_opt == 'internal'
2259   capstone_data = configuration_data()
2260   capstone_data.set('CAPSTONE_USE_SYS_DYN_MEM', '1')
2262   capstone_files = files(
2263     'capstone/cs.c',
2264     'capstone/MCInst.c',
2265     'capstone/MCInstrDesc.c',
2266     'capstone/MCRegisterInfo.c',
2267     'capstone/SStream.c',
2268     'capstone/utils.c'
2269   )
2271   if 'CONFIG_ARM_DIS' in config_all_disas
2272     capstone_data.set('CAPSTONE_HAS_ARM', '1')
2273     capstone_files += files(
2274       'capstone/arch/ARM/ARMDisassembler.c',
2275       'capstone/arch/ARM/ARMInstPrinter.c',
2276       'capstone/arch/ARM/ARMMapping.c',
2277       'capstone/arch/ARM/ARMModule.c'
2278     )
2279   endif
2281   # FIXME: This config entry currently depends on a c++ compiler.
2282   # Which is needed for building libvixl, but not for capstone.
2283   if 'CONFIG_ARM_A64_DIS' in config_all_disas
2284     capstone_data.set('CAPSTONE_HAS_ARM64', '1')
2285     capstone_files += files(
2286       'capstone/arch/AArch64/AArch64BaseInfo.c',
2287       'capstone/arch/AArch64/AArch64Disassembler.c',
2288       'capstone/arch/AArch64/AArch64InstPrinter.c',
2289       'capstone/arch/AArch64/AArch64Mapping.c',
2290       'capstone/arch/AArch64/AArch64Module.c'
2291     )
2292   endif
2294   if 'CONFIG_PPC_DIS' in config_all_disas
2295     capstone_data.set('CAPSTONE_HAS_POWERPC', '1')
2296     capstone_files += files(
2297       'capstone/arch/PowerPC/PPCDisassembler.c',
2298       'capstone/arch/PowerPC/PPCInstPrinter.c',
2299       'capstone/arch/PowerPC/PPCMapping.c',
2300       'capstone/arch/PowerPC/PPCModule.c'
2301     )
2302   endif
2304   if 'CONFIG_S390_DIS' in config_all_disas
2305     capstone_data.set('CAPSTONE_HAS_SYSZ', '1')
2306     capstone_files += files(
2307       'capstone/arch/SystemZ/SystemZDisassembler.c',
2308       'capstone/arch/SystemZ/SystemZInstPrinter.c',
2309       'capstone/arch/SystemZ/SystemZMapping.c',
2310       'capstone/arch/SystemZ/SystemZModule.c',
2311       'capstone/arch/SystemZ/SystemZMCTargetDesc.c'
2312     )
2313   endif
2315   if 'CONFIG_I386_DIS' in config_all_disas
2316     capstone_data.set('CAPSTONE_HAS_X86', 1)
2317     capstone_files += files(
2318       'capstone/arch/X86/X86Disassembler.c',
2319       'capstone/arch/X86/X86DisassemblerDecoder.c',
2320       'capstone/arch/X86/X86ATTInstPrinter.c',
2321       'capstone/arch/X86/X86IntelInstPrinter.c',
2322       'capstone/arch/X86/X86InstPrinterCommon.c',
2323       'capstone/arch/X86/X86Mapping.c',
2324       'capstone/arch/X86/X86Module.c'
2325     )
2326   endif
2328   configure_file(output: 'capstone-defs.h', configuration: capstone_data)
2330   capstone_cargs = [
2331     # FIXME: There does not seem to be a way to completely replace the c_args
2332     # that come from add_project_arguments() -- we can only add to them.
2333     # So: disable all warnings with a big hammer.
2334     '-Wno-error', '-w',
2336     # Include all configuration defines via a header file, which will wind up
2337     # as a dependency on the object file, and thus changes here will result
2338     # in a rebuild.
2339     '-include', 'capstone-defs.h'
2340   ]
2342   libcapstone = static_library('capstone',
2343                                build_by_default: false,
2344                                sources: capstone_files,
2345                                c_args: capstone_cargs,
2346                                include_directories: 'capstone/include')
2347   capstone = declare_dependency(link_with: libcapstone,
2348                                 include_directories: 'capstone/include/capstone')
2349 endif
2351 slirp = not_found
2352 slirp_opt = 'disabled'
2353 if have_system
2354   slirp_opt = get_option('slirp')
2355   if slirp_opt in ['enabled', 'auto', 'system']
2356     have_internal = fs.exists(meson.current_source_dir() / 'slirp/meson.build')
2357     slirp = dependency('slirp', kwargs: static_kwargs,
2358                        method: 'pkg-config',
2359                        required: slirp_opt == 'system' or
2360                                  slirp_opt == 'enabled' and not have_internal)
2361     if slirp.found()
2362       slirp_opt = 'system'
2363     elif have_internal
2364       slirp_opt = 'internal'
2365     else
2366       slirp_opt = 'disabled'
2367     endif
2368   endif
2369   if slirp_opt == 'internal'
2370     slirp_deps = []
2371     if targetos == 'windows'
2372       slirp_deps = cc.find_library('iphlpapi')
2373     elif targetos == 'darwin'
2374       slirp_deps = cc.find_library('resolv')
2375     endif
2376     slirp_conf = configuration_data()
2377     slirp_conf.set('SLIRP_MAJOR_VERSION', meson.project_version().split('.')[0])
2378     slirp_conf.set('SLIRP_MINOR_VERSION', meson.project_version().split('.')[1])
2379     slirp_conf.set('SLIRP_MICRO_VERSION', meson.project_version().split('.')[2])
2380     slirp_conf.set_quoted('SLIRP_VERSION_STRING', meson.project_version())
2381     slirp_cargs = ['-DG_LOG_DOMAIN="Slirp"']
2382     slirp_files = [
2383       'slirp/src/arp_table.c',
2384       'slirp/src/bootp.c',
2385       'slirp/src/cksum.c',
2386       'slirp/src/dhcpv6.c',
2387       'slirp/src/dnssearch.c',
2388       'slirp/src/if.c',
2389       'slirp/src/ip6_icmp.c',
2390       'slirp/src/ip6_input.c',
2391       'slirp/src/ip6_output.c',
2392       'slirp/src/ip_icmp.c',
2393       'slirp/src/ip_input.c',
2394       'slirp/src/ip_output.c',
2395       'slirp/src/mbuf.c',
2396       'slirp/src/misc.c',
2397       'slirp/src/ncsi.c',
2398       'slirp/src/ndp_table.c',
2399       'slirp/src/sbuf.c',
2400       'slirp/src/slirp.c',
2401       'slirp/src/socket.c',
2402       'slirp/src/state.c',
2403       'slirp/src/stream.c',
2404       'slirp/src/tcp_input.c',
2405       'slirp/src/tcp_output.c',
2406       'slirp/src/tcp_subr.c',
2407       'slirp/src/tcp_timer.c',
2408       'slirp/src/tftp.c',
2409       'slirp/src/udp.c',
2410       'slirp/src/udp6.c',
2411       'slirp/src/util.c',
2412       'slirp/src/version.c',
2413       'slirp/src/vmstate.c',
2414     ]
2416     configure_file(
2417       input : 'slirp/src/libslirp-version.h.in',
2418       output : 'libslirp-version.h',
2419       configuration: slirp_conf)
2421     slirp_inc = include_directories('slirp', 'slirp/src')
2422     libslirp = static_library('slirp',
2423                               build_by_default: false,
2424                               sources: slirp_files,
2425                               c_args: slirp_cargs,
2426                               include_directories: slirp_inc)
2427     slirp = declare_dependency(link_with: libslirp,
2428                                dependencies: slirp_deps,
2429                                include_directories: slirp_inc)
2430   endif
2431 endif
2433 # For CFI, we need to compile slirp as a static library together with qemu.
2434 # This is because we register slirp functions as callbacks for QEMU Timers.
2435 # When using a system-wide shared libslirp, the type information for the
2436 # callback is missing and the timer call produces a false positive with CFI.
2438 # Now that slirp_opt has been defined, check if the selected slirp is compatible
2439 # with control-flow integrity.
2440 if get_option('cfi') and slirp_opt == 'system'
2441   error('Control-Flow Integrity is not compatible with system-wide slirp.' \
2442          + ' Please configure with --enable-slirp=git')
2443 endif
2445 fdt = not_found
2446 if have_system
2447   fdt_opt = get_option('fdt')
2448   if fdt_opt in ['enabled', 'auto', 'system']
2449     have_internal = fs.exists(meson.current_source_dir() / 'dtc/libfdt/Makefile.libfdt')
2450     fdt = cc.find_library('fdt', kwargs: static_kwargs,
2451                           required: fdt_opt == 'system' or
2452                                     fdt_opt == 'enabled' and not have_internal)
2453     if fdt.found() and cc.links('''
2454        #include <libfdt.h>
2455        #include <libfdt_env.h>
2456        int main(void) { fdt_find_max_phandle(NULL, NULL); return 0; }''',
2457          dependencies: fdt)
2458       fdt_opt = 'system'
2459     elif fdt_opt == 'system'
2460        error('system libfdt requested, but it is too old (1.5.1 or newer required)')
2461     elif have_internal
2462       fdt_opt = 'internal'
2463     else
2464       fdt_opt = 'disabled'
2465       fdt = not_found
2466     endif
2467   endif
2468   if fdt_opt == 'internal'
2469     fdt_files = files(
2470       'dtc/libfdt/fdt.c',
2471       'dtc/libfdt/fdt_ro.c',
2472       'dtc/libfdt/fdt_wip.c',
2473       'dtc/libfdt/fdt_sw.c',
2474       'dtc/libfdt/fdt_rw.c',
2475       'dtc/libfdt/fdt_strerror.c',
2476       'dtc/libfdt/fdt_empty_tree.c',
2477       'dtc/libfdt/fdt_addresses.c',
2478       'dtc/libfdt/fdt_overlay.c',
2479       'dtc/libfdt/fdt_check.c',
2480     )
2482     fdt_inc = include_directories('dtc/libfdt')
2483     libfdt = static_library('fdt',
2484                             build_by_default: false,
2485                             sources: fdt_files,
2486                             include_directories: fdt_inc)
2487     fdt = declare_dependency(link_with: libfdt,
2488                              include_directories: fdt_inc)
2489   endif
2490 else
2491   fdt_opt = 'disabled'
2492 endif
2493 if not fdt.found() and fdt_required.length() > 0
2494   error('fdt not available but required by targets ' + ', '.join(fdt_required))
2495 endif
2497 config_host_data.set('CONFIG_CAPSTONE', capstone.found())
2498 config_host_data.set('CONFIG_FDT', fdt.found())
2499 config_host_data.set('CONFIG_SLIRP', slirp.found())
2501 #####################
2502 # Generated sources #
2503 #####################
2505 genh += configure_file(output: 'config-host.h', configuration: config_host_data)
2507 hxtool = find_program('scripts/hxtool')
2508 shaderinclude = find_program('scripts/shaderinclude.pl')
2509 qapi_gen = find_program('scripts/qapi-gen.py')
2510 qapi_gen_depends = [ meson.current_source_dir() / 'scripts/qapi/__init__.py',
2511                      meson.current_source_dir() / 'scripts/qapi/commands.py',
2512                      meson.current_source_dir() / 'scripts/qapi/common.py',
2513                      meson.current_source_dir() / 'scripts/qapi/error.py',
2514                      meson.current_source_dir() / 'scripts/qapi/events.py',
2515                      meson.current_source_dir() / 'scripts/qapi/expr.py',
2516                      meson.current_source_dir() / 'scripts/qapi/gen.py',
2517                      meson.current_source_dir() / 'scripts/qapi/introspect.py',
2518                      meson.current_source_dir() / 'scripts/qapi/parser.py',
2519                      meson.current_source_dir() / 'scripts/qapi/schema.py',
2520                      meson.current_source_dir() / 'scripts/qapi/source.py',
2521                      meson.current_source_dir() / 'scripts/qapi/types.py',
2522                      meson.current_source_dir() / 'scripts/qapi/visit.py',
2523                      meson.current_source_dir() / 'scripts/qapi/common.py',
2524                      meson.current_source_dir() / 'scripts/qapi-gen.py'
2527 tracetool = [
2528   python, files('scripts/tracetool.py'),
2529    '--backend=' + ','.join(get_option('trace_backends'))
2531 tracetool_depends = files(
2532   'scripts/tracetool/backend/log.py',
2533   'scripts/tracetool/backend/__init__.py',
2534   'scripts/tracetool/backend/dtrace.py',
2535   'scripts/tracetool/backend/ftrace.py',
2536   'scripts/tracetool/backend/simple.py',
2537   'scripts/tracetool/backend/syslog.py',
2538   'scripts/tracetool/backend/ust.py',
2539   'scripts/tracetool/format/ust_events_c.py',
2540   'scripts/tracetool/format/ust_events_h.py',
2541   'scripts/tracetool/format/__init__.py',
2542   'scripts/tracetool/format/d.py',
2543   'scripts/tracetool/format/simpletrace_stap.py',
2544   'scripts/tracetool/format/c.py',
2545   'scripts/tracetool/format/h.py',
2546   'scripts/tracetool/format/log_stap.py',
2547   'scripts/tracetool/format/stap.py',
2548   'scripts/tracetool/__init__.py',
2549   'scripts/tracetool/transform.py',
2550   'scripts/tracetool/vcpu.py'
2553 qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
2554                     meson.current_source_dir(),
2555                     config_host['PKGVERSION'], meson.project_version()]
2556 qemu_version = custom_target('qemu-version.h',
2557                              output: 'qemu-version.h',
2558                              command: qemu_version_cmd,
2559                              capture: true,
2560                              build_by_default: true,
2561                              build_always_stale: true)
2562 genh += qemu_version
2564 hxdep = []
2565 hx_headers = [
2566   ['qemu-options.hx', 'qemu-options.def'],
2567   ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
2569 if have_system
2570   hx_headers += [
2571     ['hmp-commands.hx', 'hmp-commands.h'],
2572     ['hmp-commands-info.hx', 'hmp-commands-info.h'],
2573   ]
2574 endif
2575 foreach d : hx_headers
2576   hxdep += custom_target(d[1],
2577                 input: files(d[0]),
2578                 output: d[1],
2579                 capture: true,
2580                 build_by_default: true, # to be removed when added to a target
2581                 command: [hxtool, '-h', '@INPUT0@'])
2582 endforeach
2583 genh += hxdep
2585 ###################
2586 # Collect sources #
2587 ###################
2589 authz_ss = ss.source_set()
2590 blockdev_ss = ss.source_set()
2591 block_ss = ss.source_set()
2592 chardev_ss = ss.source_set()
2593 common_ss = ss.source_set()
2594 crypto_ss = ss.source_set()
2595 hwcore_ss = ss.source_set()
2596 io_ss = ss.source_set()
2597 qmp_ss = ss.source_set()
2598 qom_ss = ss.source_set()
2599 softmmu_ss = ss.source_set()
2600 specific_fuzz_ss = ss.source_set()
2601 specific_ss = ss.source_set()
2602 stub_ss = ss.source_set()
2603 trace_ss = ss.source_set()
2604 user_ss = ss.source_set()
2605 util_ss = ss.source_set()
2607 # accel modules
2608 qtest_module_ss = ss.source_set()
2609 tcg_module_ss = ss.source_set()
2611 modules = {}
2612 target_modules = {}
2613 hw_arch = {}
2614 target_arch = {}
2615 target_softmmu_arch = {}
2616 target_user_arch = {}
2618 ###############
2619 # Trace files #
2620 ###############
2622 # TODO: add each directory to the subdirs from its own meson.build, once
2623 # we have those
2624 trace_events_subdirs = [
2625   'crypto',
2626   'qapi',
2627   'qom',
2628   'monitor',
2629   'util',
2631 if have_linux_user
2632   trace_events_subdirs += [ 'linux-user' ]
2633 endif
2634 if have_bsd_user
2635   trace_events_subdirs += [ 'bsd-user' ]
2636 endif
2637 if have_block
2638   trace_events_subdirs += [
2639     'authz',
2640     'block',
2641     'io',
2642     'nbd',
2643     'scsi',
2644   ]
2645 endif
2646 if have_system
2647   trace_events_subdirs += [
2648     'accel/kvm',
2649     'audio',
2650     'backends',
2651     'backends/tpm',
2652     'chardev',
2653     'ebpf',
2654     'hw/9pfs',
2655     'hw/acpi',
2656     'hw/adc',
2657     'hw/alpha',
2658     'hw/arm',
2659     'hw/audio',
2660     'hw/block',
2661     'hw/block/dataplane',
2662     'hw/char',
2663     'hw/display',
2664     'hw/dma',
2665     'hw/hppa',
2666     'hw/hyperv',
2667     'hw/i2c',
2668     'hw/i386',
2669     'hw/i386/xen',
2670     'hw/ide',
2671     'hw/input',
2672     'hw/intc',
2673     'hw/isa',
2674     'hw/mem',
2675     'hw/mips',
2676     'hw/misc',
2677     'hw/misc/macio',
2678     'hw/net',
2679     'hw/net/can',
2680     'hw/nubus',
2681     'hw/nvme',
2682     'hw/nvram',
2683     'hw/pci',
2684     'hw/pci-host',
2685     'hw/ppc',
2686     'hw/rdma',
2687     'hw/rdma/vmw',
2688     'hw/rtc',
2689     'hw/s390x',
2690     'hw/scsi',
2691     'hw/sd',
2692     'hw/sh4',
2693     'hw/sparc',
2694     'hw/sparc64',
2695     'hw/ssi',
2696     'hw/timer',
2697     'hw/tpm',
2698     'hw/usb',
2699     'hw/vfio',
2700     'hw/virtio',
2701     'hw/watchdog',
2702     'hw/xen',
2703     'hw/gpio',
2704     'migration',
2705     'net',
2706     'softmmu',
2707     'ui',
2708     'hw/remote',
2709   ]
2710 endif
2711 if have_system or have_user
2712   trace_events_subdirs += [
2713     'accel/tcg',
2714     'hw/core',
2715     'target/arm',
2716     'target/arm/hvf',
2717     'target/hppa',
2718     'target/i386',
2719     'target/i386/kvm',
2720     'target/mips/tcg',
2721     'target/nios2',
2722     'target/ppc',
2723     'target/riscv',
2724     'target/s390x',
2725     'target/s390x/kvm',
2726     'target/sparc',
2727   ]
2728 endif
2730 vhost_user = not_found
2731 if targetos == 'linux' and 'CONFIG_VHOST_USER' in config_host
2732   libvhost_user = subproject('libvhost-user')
2733   vhost_user = libvhost_user.get_variable('vhost_user_dep')
2734 endif
2736 # NOTE: the trace/ subdirectory needs the qapi_trace_events variable
2737 # that is filled in by qapi/.
2738 subdir('qapi')
2739 subdir('qobject')
2740 subdir('stubs')
2741 subdir('trace')
2742 subdir('util')
2743 subdir('qom')
2744 subdir('authz')
2745 subdir('crypto')
2746 subdir('ui')
2749 if enable_modules
2750   libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
2751   modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
2752 endif
2754 stub_ss = stub_ss.apply(config_all, strict: false)
2756 util_ss.add_all(trace_ss)
2757 util_ss = util_ss.apply(config_all, strict: false)
2758 libqemuutil = static_library('qemuutil',
2759                              sources: util_ss.sources() + stub_ss.sources() + genh,
2760                              dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc, pixman])
2761 qemuutil = declare_dependency(link_with: libqemuutil,
2762                               sources: genh + version_res)
2764 if have_system or have_user
2765   decodetree = generator(find_program('scripts/decodetree.py'),
2766                          output: 'decode-@BASENAME@.c.inc',
2767                          arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
2768   subdir('libdecnumber')
2769   subdir('target')
2770 endif
2772 subdir('audio')
2773 subdir('io')
2774 subdir('chardev')
2775 subdir('fsdev')
2776 subdir('dump')
2778 if have_block
2779   block_ss.add(files(
2780     'block.c',
2781     'blockjob.c',
2782     'job.c',
2783     'qemu-io-cmds.c',
2784   ))
2785   if config_host_data.get('CONFIG_REPLICATION')
2786     block_ss.add(files('replication.c'))
2787   endif
2789   subdir('nbd')
2790   subdir('scsi')
2791   subdir('block')
2793   blockdev_ss.add(files(
2794     'blockdev.c',
2795     'blockdev-nbd.c',
2796     'iothread.c',
2797     'job-qmp.c',
2798   ), gnutls)
2800   # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
2801   # os-win32.c does not
2802   blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
2803   softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
2804 endif
2806 common_ss.add(files('cpus-common.c'))
2808 subdir('softmmu')
2810 common_ss.add(capstone)
2811 specific_ss.add(files('cpu.c', 'disas.c', 'gdbstub.c'), capstone)
2813 # Work around a gcc bug/misfeature wherein constant propagation looks
2814 # through an alias:
2815 #   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99696
2816 # to guess that a const variable is always zero.  Without lto, this is
2817 # impossible, as the alias is restricted to page-vary-common.c.  Indeed,
2818 # without lto, not even the alias is required -- we simply use different
2819 # declarations in different compilation units.
2820 pagevary = files('page-vary-common.c')
2821 if get_option('b_lto')
2822   pagevary_flags = ['-fno-lto']
2823   if get_option('cfi')
2824     pagevary_flags += '-fno-sanitize=cfi-icall'
2825   endif
2826   pagevary = static_library('page-vary-common', sources: pagevary,
2827                             c_args: pagevary_flags)
2828   pagevary = declare_dependency(link_with: pagevary)
2829 endif
2830 common_ss.add(pagevary)
2831 specific_ss.add(files('page-vary.c'))
2833 subdir('backends')
2834 subdir('disas')
2835 subdir('migration')
2836 subdir('monitor')
2837 subdir('net')
2838 subdir('replay')
2839 subdir('semihosting')
2840 subdir('hw')
2841 subdir('tcg')
2842 subdir('fpu')
2843 subdir('accel')
2844 subdir('plugins')
2845 subdir('ebpf')
2847 common_user_inc = []
2849 subdir('common-user')
2850 subdir('bsd-user')
2851 subdir('linux-user')
2853 # needed for fuzzing binaries
2854 subdir('tests/qtest/libqos')
2855 subdir('tests/qtest/fuzz')
2857 # accel modules
2858 tcg_real_module_ss = ss.source_set()
2859 tcg_real_module_ss.add_all(when: 'CONFIG_TCG_MODULAR', if_true: tcg_module_ss)
2860 specific_ss.add_all(when: 'CONFIG_TCG_BUILTIN', if_true: tcg_module_ss)
2861 target_modules += { 'accel' : { 'qtest': qtest_module_ss,
2862                                 'tcg': tcg_real_module_ss }}
2864 ########################
2865 # Library dependencies #
2866 ########################
2868 modinfo_collect = find_program('scripts/modinfo-collect.py')
2869 modinfo_generate = find_program('scripts/modinfo-generate.py')
2870 modinfo_files = []
2872 block_mods = []
2873 softmmu_mods = []
2874 foreach d, list : modules
2875   foreach m, module_ss : list
2876     if enable_modules and targetos != 'windows'
2877       module_ss = module_ss.apply(config_all, strict: false)
2878       sl = static_library(d + '-' + m, [genh, module_ss.sources()],
2879                           dependencies: [modulecommon, module_ss.dependencies()], pic: true)
2880       if d == 'block'
2881         block_mods += sl
2882       else
2883         softmmu_mods += sl
2884       endif
2885       if module_ss.sources() != []
2886         # FIXME: Should use sl.extract_all_objects(recursive: true) as
2887         # input. Sources can be used multiple times but objects are
2888         # unique when it comes to lookup in compile_commands.json.
2889         # Depnds on a mesion version with
2890         # https://github.com/mesonbuild/meson/pull/8900
2891         modinfo_files += custom_target(d + '-' + m + '.modinfo',
2892                                        output: d + '-' + m + '.modinfo',
2893                                        input: module_ss.sources() + genh,
2894                                        capture: true,
2895                                        command: [modinfo_collect, module_ss.sources()])
2896       endif
2897     else
2898       if d == 'block'
2899         block_ss.add_all(module_ss)
2900       else
2901         softmmu_ss.add_all(module_ss)
2902       endif
2903     endif
2904   endforeach
2905 endforeach
2907 foreach d, list : target_modules
2908   foreach m, module_ss : list
2909     if enable_modules and targetos != 'windows'
2910       foreach target : target_dirs
2911         if target.endswith('-softmmu')
2912           config_target = config_target_mak[target]
2913           config_target += config_host
2914           target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
2915           c_args = ['-DNEED_CPU_H',
2916                     '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
2917                     '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
2918           target_module_ss = module_ss.apply(config_target, strict: false)
2919           if target_module_ss.sources() != []
2920             module_name = d + '-' + m + '-' + config_target['TARGET_NAME']
2921             sl = static_library(module_name,
2922                                 [genh, target_module_ss.sources()],
2923                                 dependencies: [modulecommon, target_module_ss.dependencies()],
2924                                 include_directories: target_inc,
2925                                 c_args: c_args,
2926                                 pic: true)
2927             softmmu_mods += sl
2928             # FIXME: Should use sl.extract_all_objects(recursive: true) too.
2929             modinfo_files += custom_target(module_name + '.modinfo',
2930                                            output: module_name + '.modinfo',
2931                                            input: target_module_ss.sources() + genh,
2932                                            capture: true,
2933                                            command: [modinfo_collect, '--target', target, target_module_ss.sources()])
2934           endif
2935         endif
2936       endforeach
2937     else
2938       specific_ss.add_all(module_ss)
2939     endif
2940   endforeach
2941 endforeach
2943 if enable_modules
2944   modinfo_src = custom_target('modinfo.c',
2945                               output: 'modinfo.c',
2946                               input: modinfo_files,
2947                               command: [modinfo_generate, '@INPUT@'],
2948                               capture: true)
2949   modinfo_lib = static_library('modinfo', modinfo_src)
2950   modinfo_dep = declare_dependency(link_whole: modinfo_lib)
2951   softmmu_ss.add(modinfo_dep)
2952 endif
2954 nm = find_program('nm')
2955 undefsym = find_program('scripts/undefsym.py')
2956 block_syms = custom_target('block.syms', output: 'block.syms',
2957                              input: [libqemuutil, block_mods],
2958                              capture: true,
2959                              command: [undefsym, nm, '@INPUT@'])
2960 qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
2961                              input: [libqemuutil, softmmu_mods],
2962                              capture: true,
2963                              command: [undefsym, nm, '@INPUT@'])
2965 qom_ss = qom_ss.apply(config_host, strict: false)
2966 libqom = static_library('qom', qom_ss.sources() + genh,
2967                         dependencies: [qom_ss.dependencies()],
2968                         name_suffix: 'fa')
2970 qom = declare_dependency(link_whole: libqom)
2972 authz_ss = authz_ss.apply(config_host, strict: false)
2973 libauthz = static_library('authz', authz_ss.sources() + genh,
2974                           dependencies: [authz_ss.dependencies()],
2975                           name_suffix: 'fa',
2976                           build_by_default: false)
2978 authz = declare_dependency(link_whole: libauthz,
2979                            dependencies: qom)
2981 crypto_ss = crypto_ss.apply(config_host, strict: false)
2982 libcrypto = static_library('crypto', crypto_ss.sources() + genh,
2983                            dependencies: [crypto_ss.dependencies()],
2984                            name_suffix: 'fa',
2985                            build_by_default: false)
2987 crypto = declare_dependency(link_whole: libcrypto,
2988                             dependencies: [authz, qom])
2990 io_ss = io_ss.apply(config_host, strict: false)
2991 libio = static_library('io', io_ss.sources() + genh,
2992                        dependencies: [io_ss.dependencies()],
2993                        link_with: libqemuutil,
2994                        name_suffix: 'fa',
2995                        build_by_default: false)
2997 io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
2999 libmigration = static_library('migration', sources: migration_files + genh,
3000                               name_suffix: 'fa',
3001                               build_by_default: false)
3002 migration = declare_dependency(link_with: libmigration,
3003                                dependencies: [zlib, qom, io])
3004 softmmu_ss.add(migration)
3006 block_ss = block_ss.apply(config_host, strict: false)
3007 libblock = static_library('block', block_ss.sources() + genh,
3008                           dependencies: block_ss.dependencies(),
3009                           link_depends: block_syms,
3010                           name_suffix: 'fa',
3011                           build_by_default: false)
3013 block = declare_dependency(link_whole: [libblock],
3014                            link_args: '@block.syms',
3015                            dependencies: [crypto, io])
3017 blockdev_ss = blockdev_ss.apply(config_host, strict: false)
3018 libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
3019                              dependencies: blockdev_ss.dependencies(),
3020                              name_suffix: 'fa',
3021                              build_by_default: false)
3023 blockdev = declare_dependency(link_whole: [libblockdev],
3024                               dependencies: [block])
3026 qmp_ss = qmp_ss.apply(config_host, strict: false)
3027 libqmp = static_library('qmp', qmp_ss.sources() + genh,
3028                         dependencies: qmp_ss.dependencies(),
3029                         name_suffix: 'fa',
3030                         build_by_default: false)
3032 qmp = declare_dependency(link_whole: [libqmp])
3034 libchardev = static_library('chardev', chardev_ss.sources() + genh,
3035                             name_suffix: 'fa',
3036                             dependencies: [gnutls],
3037                             build_by_default: false)
3039 chardev = declare_dependency(link_whole: libchardev)
3041 hwcore_ss = hwcore_ss.apply(config_host, strict: false)
3042 libhwcore = static_library('hwcore', sources: hwcore_ss.sources() + genh,
3043                            name_suffix: 'fa',
3044                            build_by_default: false)
3045 hwcore = declare_dependency(link_whole: libhwcore)
3046 common_ss.add(hwcore)
3048 ###########
3049 # Targets #
3050 ###########
3052 emulator_modules = []
3053 foreach m : block_mods + softmmu_mods
3054   emulator_modules += shared_module(m.name(),
3055                 build_by_default: true,
3056                 name_prefix: '',
3057                 link_whole: m,
3058                 install: true,
3059                 install_dir: qemu_moddir)
3060 endforeach
3062 softmmu_ss.add(authz, blockdev, chardev, crypto, io, qmp)
3063 common_ss.add(qom, qemuutil)
3065 common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
3066 common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
3068 common_all = common_ss.apply(config_all, strict: false)
3069 common_all = static_library('common',
3070                             build_by_default: false,
3071                             sources: common_all.sources() + genh,
3072                             include_directories: common_user_inc,
3073                             implicit_include_directories: false,
3074                             dependencies: common_all.dependencies(),
3075                             name_suffix: 'fa')
3077 feature_to_c = find_program('scripts/feature_to_c.sh')
3079 emulators = {}
3080 foreach target : target_dirs
3081   config_target = config_target_mak[target]
3082   target_name = config_target['TARGET_NAME']
3083   target_base_arch = config_target['TARGET_BASE_ARCH']
3084   arch_srcs = [config_target_h[target]]
3085   arch_deps = []
3086   c_args = ['-DNEED_CPU_H',
3087             '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3088             '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3089   link_args = emulator_link_args
3091   config_target += config_host
3092   target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3093   if targetos == 'linux'
3094     target_inc += include_directories('linux-headers', is_system: true)
3095   endif
3096   if target.endswith('-softmmu')
3097     qemu_target_name = 'qemu-system-' + target_name
3098     target_type='system'
3099     t = target_softmmu_arch[target_base_arch].apply(config_target, strict: false)
3100     arch_srcs += t.sources()
3101     arch_deps += t.dependencies()
3103     hw_dir = target_name == 'sparc64' ? 'sparc64' : target_base_arch
3104     hw = hw_arch[hw_dir].apply(config_target, strict: false)
3105     arch_srcs += hw.sources()
3106     arch_deps += hw.dependencies()
3108     arch_srcs += config_devices_h[target]
3109     link_args += ['@block.syms', '@qemu.syms']
3110   else
3111     abi = config_target['TARGET_ABI_DIR']
3112     target_type='user'
3113     target_inc += common_user_inc
3114     qemu_target_name = 'qemu-' + target_name
3115     if target_base_arch in target_user_arch
3116       t = target_user_arch[target_base_arch].apply(config_target, strict: false)
3117       arch_srcs += t.sources()
3118       arch_deps += t.dependencies()
3119     endif
3120     if 'CONFIG_LINUX_USER' in config_target
3121       base_dir = 'linux-user'
3122     endif
3123     if 'CONFIG_BSD_USER' in config_target
3124       base_dir = 'bsd-user'
3125       target_inc += include_directories('bsd-user/' / targetos)
3126       target_inc += include_directories('bsd-user/host/' / host_arch)
3127       dir = base_dir / abi
3128       arch_srcs += files(dir / 'signal.c', dir / 'target_arch_cpu.c')
3129     endif
3130     target_inc += include_directories(
3131       base_dir,
3132       base_dir / abi,
3133     )
3134     if 'CONFIG_LINUX_USER' in config_target
3135       dir = base_dir / abi
3136       arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
3137       if config_target.has_key('TARGET_SYSTBL_ABI')
3138         arch_srcs += \
3139           syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
3140                                              extra_args : config_target['TARGET_SYSTBL_ABI'])
3141       endif
3142     endif
3143   endif
3145   if 'TARGET_XML_FILES' in config_target
3146     gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
3147                                 output: target + '-gdbstub-xml.c',
3148                                 input: files(config_target['TARGET_XML_FILES'].split()),
3149                                 command: [feature_to_c, '@INPUT@'],
3150                                 capture: true)
3151     arch_srcs += gdbstub_xml
3152   endif
3154   t = target_arch[target_base_arch].apply(config_target, strict: false)
3155   arch_srcs += t.sources()
3156   arch_deps += t.dependencies()
3158   target_common = common_ss.apply(config_target, strict: false)
3159   objects = common_all.extract_objects(target_common.sources())
3160   deps = target_common.dependencies()
3162   target_specific = specific_ss.apply(config_target, strict: false)
3163   arch_srcs += target_specific.sources()
3164   arch_deps += target_specific.dependencies()
3166   lib = static_library('qemu-' + target,
3167                  sources: arch_srcs + genh,
3168                  dependencies: arch_deps,
3169                  objects: objects,
3170                  include_directories: target_inc,
3171                  c_args: c_args,
3172                  build_by_default: false,
3173                  name_suffix: 'fa')
3175   if target.endswith('-softmmu')
3176     execs = [{
3177       'name': 'qemu-system-' + target_name,
3178       'win_subsystem': 'console',
3179       'sources': files('softmmu/main.c'),
3180       'dependencies': []
3181     }]
3182     if targetos == 'windows' and (sdl.found() or gtk.found())
3183       execs += [{
3184         'name': 'qemu-system-' + target_name + 'w',
3185         'win_subsystem': 'windows',
3186         'sources': files('softmmu/main.c'),
3187         'dependencies': []
3188       }]
3189     endif
3190     if get_option('fuzzing')
3191       specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
3192       execs += [{
3193         'name': 'qemu-fuzz-' + target_name,
3194         'win_subsystem': 'console',
3195         'sources': specific_fuzz.sources(),
3196         'dependencies': specific_fuzz.dependencies(),
3197       }]
3198     endif
3199   else
3200     execs = [{
3201       'name': 'qemu-' + target_name,
3202       'win_subsystem': 'console',
3203       'sources': [],
3204       'dependencies': []
3205     }]
3206   endif
3207   foreach exe: execs
3208     exe_name = exe['name']
3209     if targetos == 'darwin'
3210       exe_name += '-unsigned'
3211     endif
3213     emulator = executable(exe_name, exe['sources'],
3214                install: true,
3215                c_args: c_args,
3216                dependencies: arch_deps + deps + exe['dependencies'],
3217                objects: lib.extract_all_objects(recursive: true),
3218                link_language: link_language,
3219                link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
3220                link_args: link_args,
3221                win_subsystem: exe['win_subsystem'])
3223     if targetos == 'darwin'
3224       icon = 'pc-bios/qemu.rsrc'
3225       build_input = [emulator, files(icon)]
3226       install_input = [
3227         get_option('bindir') / exe_name,
3228         meson.current_source_dir() / icon
3229       ]
3230       if 'CONFIG_HVF' in config_target
3231         entitlements = 'accel/hvf/entitlements.plist'
3232         build_input += files(entitlements)
3233         install_input += meson.current_source_dir() / entitlements
3234       endif
3236       entitlement = find_program('scripts/entitlement.sh')
3237       emulators += {exe['name'] : custom_target(exe['name'],
3238                    input: build_input,
3239                    output: exe['name'],
3240                    command: [entitlement, '@OUTPUT@', '@INPUT@'])
3241       }
3243       meson.add_install_script(entitlement, '--install',
3244                                get_option('bindir') / exe['name'],
3245                                install_input)
3246     else
3247       emulators += {exe['name']: emulator}
3248     endif
3250     if stap.found()
3251       foreach stp: [
3252         {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
3253         {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
3254         {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
3255         {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
3256       ]
3257         custom_target(exe['name'] + stp['ext'],
3258                       input: trace_events_all,
3259                       output: exe['name'] + stp['ext'],
3260                       install: stp['install'],
3261                       install_dir: get_option('datadir') / 'systemtap/tapset',
3262                       command: [
3263                         tracetool, '--group=all', '--format=' + stp['fmt'],
3264                         '--binary=' + stp['bin'],
3265                         '--target-name=' + target_name,
3266                         '--target-type=' + target_type,
3267                         '--probe-prefix=qemu.' + target_type + '.' + target_name,
3268                         '@INPUT@', '@OUTPUT@'
3269                       ],
3270                       depend_files: tracetool_depends)
3271       endforeach
3272     endif
3273   endforeach
3274 endforeach
3276 # Other build targets
3278 if 'CONFIG_PLUGIN' in config_host
3279   install_headers('include/qemu/qemu-plugin.h')
3280 endif
3282 subdir('qga')
3284 # Don't build qemu-keymap if xkbcommon is not explicitly enabled
3285 # when we don't build tools or system
3286 if xkbcommon.found()
3287   # used for the update-keymaps target, so include rules even if !have_tools
3288   qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
3289                            dependencies: [qemuutil, xkbcommon], install: have_tools)
3290 endif
3292 if have_tools
3293   qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
3294              dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
3295   qemu_io = executable('qemu-io', files('qemu-io.c'),
3296              dependencies: [block, qemuutil], install: true)
3297   qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
3298                dependencies: [blockdev, qemuutil, gnutls, selinux],
3299                install: true)
3301   subdir('storage-daemon')
3302   subdir('contrib/rdmacm-mux')
3303   subdir('contrib/elf2dmp')
3305   executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
3306              dependencies: qemuutil,
3307              install: true)
3309   if 'CONFIG_VHOST_USER' in config_host
3310     subdir('contrib/vhost-user-blk')
3311     subdir('contrib/vhost-user-gpu')
3312     subdir('contrib/vhost-user-input')
3313     subdir('contrib/vhost-user-scsi')
3314   endif
3316   if targetos == 'linux'
3317     executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
3318                dependencies: [qemuutil, libcap_ng],
3319                install: true,
3320                install_dir: get_option('libexecdir'))
3322     executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
3323                dependencies: [authz, crypto, io, qom, qemuutil,
3324                               libcap_ng, mpathpersist],
3325                install: true)
3326   endif
3328   if have_ivshmem
3329     subdir('contrib/ivshmem-client')
3330     subdir('contrib/ivshmem-server')
3331   endif
3332 endif
3334 subdir('scripts')
3335 subdir('tools')
3336 subdir('pc-bios')
3337 subdir('docs')
3338 subdir('tests')
3339 if gtk.found()
3340   subdir('po')
3341 endif
3343 if host_machine.system() == 'windows'
3344   nsis_cmd = [
3345     find_program('scripts/nsis.py'),
3346     '@OUTPUT@',
3347     get_option('prefix'),
3348     meson.current_source_dir(),
3349     host_machine.cpu(),
3350     '--',
3351     '-DDISPLAYVERSION=' + meson.project_version(),
3352   ]
3353   if build_docs
3354     nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
3355   endif
3356   if gtk.found()
3357     nsis_cmd += '-DCONFIG_GTK=y'
3358   endif
3360   nsis = custom_target('nsis',
3361                        output: 'qemu-setup-' + meson.project_version() + '.exe',
3362                        input: files('qemu.nsi'),
3363                        build_always_stale: true,
3364                        command: nsis_cmd + ['@INPUT@'])
3365   alias_target('installer', nsis)
3366 endif
3368 #########################
3369 # Configuration summary #
3370 #########################
3372 # Directories
3373 summary_info = {}
3374 summary_info += {'Install prefix':    get_option('prefix')}
3375 summary_info += {'BIOS directory':    qemu_datadir}
3376 summary_info += {'firmware path':     get_option('qemu_firmwarepath')}
3377 summary_info += {'binary directory':  get_option('bindir')}
3378 summary_info += {'library directory': get_option('libdir')}
3379 summary_info += {'module directory':  qemu_moddir}
3380 summary_info += {'libexec directory': get_option('libexecdir')}
3381 summary_info += {'include directory': get_option('includedir')}
3382 summary_info += {'config directory':  get_option('sysconfdir')}
3383 if targetos != 'windows'
3384   summary_info += {'local state directory': get_option('localstatedir')}
3385   summary_info += {'Manual directory':      get_option('mandir')}
3386 else
3387   summary_info += {'local state directory': 'queried at runtime'}
3388 endif
3389 summary_info += {'Doc directory':     get_option('docdir')}
3390 summary_info += {'Build directory':   meson.current_build_dir()}
3391 summary_info += {'Source path':       meson.current_source_dir()}
3392 summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
3393 summary(summary_info, bool_yn: true, section: 'Directories')
3395 # Host binaries
3396 summary_info = {}
3397 summary_info += {'git':               config_host['GIT']}
3398 summary_info += {'make':              config_host['MAKE']}
3399 summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
3400 summary_info += {'sphinx-build':      sphinx_build}
3401 if config_host.has_key('HAVE_GDB_BIN')
3402   summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
3403 endif
3404 if get_option('iasl') != ''
3405   summary_info += {'iasl':            get_option('iasl')}
3406 else
3407   summary_info += {'iasl':            false}
3408 endif
3409 summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
3410 if targetos == 'windows' and have_ga
3411   summary_info += {'wixl':            wixl}
3412 endif
3413 if slirp_opt != 'disabled' and have_system
3414   summary_info += {'smbd':            have_slirp_smbd ? smbd_path : false}
3415 endif
3416 summary(summary_info, bool_yn: true, section: 'Host binaries')
3418 # Configurable features
3419 summary_info = {}
3420 summary_info += {'Documentation':     build_docs}
3421 summary_info += {'system-mode emulation': have_system}
3422 summary_info += {'user-mode emulation': have_user}
3423 summary_info += {'block layer':       have_block}
3424 summary_info += {'Install blobs':     get_option('install_blobs')}
3425 summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
3426 if config_host.has_key('CONFIG_MODULES')
3427   summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')}
3428 endif
3429 summary_info += {'fuzzing support':   get_option('fuzzing')}
3430 if have_system
3431   summary_info += {'Audio drivers':     ' '.join(audio_drivers_selected)}
3432 endif
3433 summary_info += {'Trace backends':    ','.join(get_option('trace_backends'))}
3434 if 'simple' in get_option('trace_backends')
3435   summary_info += {'Trace output file': get_option('trace_file') + '-<pid>'}
3436 endif
3437 summary_info += {'D-Bus display':     dbus_display}
3438 summary_info += {'QOM debugging':     get_option('qom_cast_debug')}
3439 summary_info += {'vhost-kernel support': config_host.has_key('CONFIG_VHOST_KERNEL')}
3440 summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')}
3441 summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')}
3442 summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')}
3443 summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')}
3444 summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_USER')}
3445 summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
3446 summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')}
3447 summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')}
3448 summary_info += {'build guest agent': have_ga}
3449 summary(summary_info, bool_yn: true, section: 'Configurable features')
3451 # Compilation information
3452 summary_info = {}
3453 summary_info += {'host CPU':          cpu}
3454 summary_info += {'host endianness':   build_machine.endian()}
3455 summary_info += {'C compiler':        ' '.join(meson.get_compiler('c').cmd_array())}
3456 summary_info += {'Host C compiler':   ' '.join(meson.get_compiler('c', native: true).cmd_array())}
3457 if link_language == 'cpp'
3458   summary_info += {'C++ compiler':    ' '.join(meson.get_compiler('cpp').cmd_array())}
3459 else
3460   summary_info += {'C++ compiler':      false}
3461 endif
3462 if targetos == 'darwin'
3463   summary_info += {'Objective-C compiler': ' '.join(meson.get_compiler('objc').cmd_array())}
3464 endif
3465 summary_info += {'CFLAGS':            ' '.join(get_option('c_args')
3466                                                + ['-O' + get_option('optimization')]
3467                                                + (get_option('debug') ? ['-g'] : []))}
3468 if link_language == 'cpp'
3469   summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args')
3470                                                + ['-O' + get_option('optimization')]
3471                                                + (get_option('debug') ? ['-g'] : []))}
3472 endif
3473 link_args = get_option(link_language + '_link_args')
3474 if link_args.length() > 0
3475   summary_info += {'LDFLAGS':         ' '.join(link_args)}
3476 endif
3477 summary_info += {'QEMU_CFLAGS':       config_host['QEMU_CFLAGS']}
3478 summary_info += {'QEMU_LDFLAGS':      config_host['QEMU_LDFLAGS']}
3479 summary_info += {'profiler':          get_option('profiler')}
3480 summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
3481 summary_info += {'PIE':               get_option('b_pie')}
3482 summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
3483 summary_info += {'malloc trim support': has_malloc_trim}
3484 summary_info += {'membarrier':        have_membarrier}
3485 summary_info += {'debug stack usage': get_option('debug_stack_usage')}
3486 summary_info += {'mutex debugging':   get_option('debug_mutex')}
3487 summary_info += {'memory allocator':  get_option('malloc')}
3488 summary_info += {'avx2 optimization': config_host_data.get('CONFIG_AVX2_OPT')}
3489 summary_info += {'avx512f optimization': config_host_data.get('CONFIG_AVX512F_OPT')}
3490 summary_info += {'gprof enabled':     get_option('gprof')}
3491 summary_info += {'gcov':              get_option('b_coverage')}
3492 summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
3493 summary_info += {'CFI support':       get_option('cfi')}
3494 if get_option('cfi')
3495   summary_info += {'CFI debug support': get_option('cfi_debug')}
3496 endif
3497 summary_info += {'strip binaries':    get_option('strip')}
3498 summary_info += {'sparse':            sparse}
3499 summary_info += {'mingw32 support':   targetos == 'windows'}
3501 # snarf the cross-compilation information for tests
3502 foreach target: target_dirs
3503   tcg_mak = meson.current_build_dir() / 'tests/tcg' / 'config-' + target + '.mak'
3504   if fs.exists(tcg_mak)
3505     config_cross_tcg = keyval.load(tcg_mak)
3506     target = config_cross_tcg['TARGET_NAME']
3507     compiler = ''
3508     if 'DOCKER_CROSS_CC_GUEST' in config_cross_tcg
3509       summary_info += {target + ' tests': config_cross_tcg['DOCKER_CROSS_CC_GUEST'] +
3510                                           ' via ' + config_cross_tcg['DOCKER_IMAGE']}
3511     elif 'CROSS_CC_GUEST' in config_cross_tcg
3512       summary_info += {target + ' tests'
3513                                 : config_cross_tcg['CROSS_CC_GUEST'] }
3514     endif
3515    endif
3516 endforeach
3518 summary(summary_info, bool_yn: true, section: 'Compilation')
3520 # Targets and accelerators
3521 summary_info = {}
3522 if have_system
3523   summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
3524   summary_info += {'HAX support':       config_all.has_key('CONFIG_HAX')}
3525   summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
3526   summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
3527   summary_info += {'NVMM support':      config_all.has_key('CONFIG_NVMM')}
3528   summary_info += {'Xen support':       config_host.has_key('CONFIG_XEN_BACKEND')}
3529   if config_host.has_key('CONFIG_XEN_BACKEND')
3530     summary_info += {'xen ctrl version':  config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
3531   endif
3532 endif
3533 summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
3534 if config_all.has_key('CONFIG_TCG')
3535   if get_option('tcg_interpreter')
3536     summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, slow)'}
3537   else
3538     summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
3539   endif
3540   summary_info += {'TCG plugins': config_host.has_key('CONFIG_PLUGIN')}
3541   summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
3542 endif
3543 summary_info += {'target list':       ' '.join(target_dirs)}
3544 if have_system
3545   summary_info += {'default devices':   get_option('default_devices')}
3546   summary_info += {'out of process emulation': multiprocess_allowed}
3547 endif
3548 summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
3550 # Block layer
3551 summary_info = {}
3552 summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
3553 summary_info += {'coroutine pool':    have_coroutine_pool}
3554 if have_block
3555   summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']}
3556   summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']}
3557   summary_info += {'Use block whitelist in tools': get_option('block_drv_whitelist_in_tools')}
3558   summary_info += {'VirtFS support':    have_virtfs}
3559   summary_info += {'build virtiofs daemon': have_virtiofsd}
3560   summary_info += {'Live block migration': config_host_data.get('CONFIG_LIVE_BLOCK_MIGRATION')}
3561   summary_info += {'replication support': config_host_data.get('CONFIG_REPLICATION')}
3562   summary_info += {'bochs support':     get_option('bochs').allowed()}
3563   summary_info += {'cloop support':     get_option('cloop').allowed()}
3564   summary_info += {'dmg support':       get_option('dmg').allowed()}
3565   summary_info += {'qcow v1 support':   get_option('qcow1').allowed()}
3566   summary_info += {'vdi support':       get_option('vdi').allowed()}
3567   summary_info += {'vvfat support':     get_option('vvfat').allowed()}
3568   summary_info += {'qed support':       get_option('qed').allowed()}
3569   summary_info += {'parallels support': get_option('parallels').allowed()}
3570   summary_info += {'FUSE exports':      fuse}
3571 endif
3572 summary(summary_info, bool_yn: true, section: 'Block layer support')
3574 # Crypto
3575 summary_info = {}
3576 summary_info += {'TLS priority':      config_host['CONFIG_TLS_PRIORITY']}
3577 summary_info += {'GNUTLS support':    gnutls}
3578 if gnutls.found()
3579   summary_info += {'  GNUTLS crypto':   gnutls_crypto.found()}
3580 endif
3581 summary_info += {'libgcrypt':         gcrypt}
3582 summary_info += {'nettle':            nettle}
3583 if nettle.found()
3584    summary_info += {'  XTS':             xts != 'private'}
3585 endif
3586 summary_info += {'AF_ALG support':    have_afalg}
3587 summary_info += {'rng-none':          get_option('rng_none')}
3588 summary_info += {'Linux keyring':     config_host.has_key('CONFIG_SECRET_KEYRING')}
3589 summary(summary_info, bool_yn: true, section: 'Crypto')
3591 # Libraries
3592 summary_info = {}
3593 if targetos == 'darwin'
3594   summary_info += {'Cocoa support':   cocoa}
3595 endif
3596 summary_info += {'SDL support':       sdl}
3597 summary_info += {'SDL image support': sdl_image}
3598 summary_info += {'GTK support':       gtk}
3599 summary_info += {'pixman':            pixman}
3600 summary_info += {'VTE support':       vte}
3601 summary_info += {'slirp support':     slirp_opt == 'internal' ? slirp_opt : slirp}
3602 summary_info += {'libtasn1':          tasn1}
3603 summary_info += {'PAM':               pam}
3604 summary_info += {'iconv support':     iconv}
3605 summary_info += {'curses support':    curses}
3606 summary_info += {'virgl support':     virgl}
3607 summary_info += {'curl support':      curl}
3608 summary_info += {'Multipath support': mpathpersist}
3609 summary_info += {'VNC support':       vnc}
3610 if vnc.found()
3611   summary_info += {'VNC SASL support':  sasl}
3612   summary_info += {'VNC JPEG support':  jpeg}
3613   summary_info += {'VNC PNG support':   png}
3614 endif
3615 if targetos not in ['darwin', 'haiku', 'windows']
3616   summary_info += {'OSS support':     oss}
3617 elif targetos == 'darwin'
3618   summary_info += {'CoreAudio support': coreaudio}
3619 elif targetos == 'windows'
3620   summary_info += {'DirectSound support': dsound}
3621 endif
3622 if targetos == 'linux'
3623   summary_info += {'ALSA support':    alsa}
3624   summary_info += {'PulseAudio support': pulse}
3625 endif
3626 summary_info += {'JACK support':      jack}
3627 summary_info += {'brlapi support':    brlapi}
3628 summary_info += {'vde support':       vde}
3629 summary_info += {'netmap support':    have_netmap}
3630 summary_info += {'l2tpv3 support':    have_l2tpv3}
3631 summary_info += {'Linux AIO support': libaio}
3632 summary_info += {'Linux io_uring support': linux_io_uring}
3633 summary_info += {'ATTR/XATTR support': libattr}
3634 summary_info += {'RDMA support':      config_host.has_key('CONFIG_RDMA')}
3635 summary_info += {'PVRDMA support':    config_host.has_key('CONFIG_PVRDMA')}
3636 summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
3637 summary_info += {'libcap-ng support': libcap_ng}
3638 summary_info += {'bpf support':       libbpf}
3639 summary_info += {'spice protocol support': spice_protocol}
3640 if spice_protocol.found()
3641   summary_info += {'  spice server support': spice}
3642 endif
3643 summary_info += {'rbd support':       rbd}
3644 summary_info += {'smartcard support': cacard}
3645 summary_info += {'U2F support':       u2f}
3646 summary_info += {'libusb':            libusb}
3647 summary_info += {'usb net redir':     usbredir}
3648 summary_info += {'OpenGL support':    config_host.has_key('CONFIG_OPENGL')}
3649 summary_info += {'GBM':               gbm}
3650 summary_info += {'libiscsi support':  libiscsi}
3651 summary_info += {'libnfs support':    libnfs}
3652 if targetos == 'windows'
3653   if have_ga
3654     summary_info += {'QGA VSS support':   have_qga_vss}
3655     summary_info += {'QGA w32 disk info': have_ntddscsi}
3656   endif
3657 endif
3658 summary_info += {'seccomp support':   seccomp}
3659 summary_info += {'GlusterFS support': glusterfs}
3660 summary_info += {'TPM support':       have_tpm}
3661 summary_info += {'libssh support':    libssh}
3662 summary_info += {'lzo support':       lzo}
3663 summary_info += {'snappy support':    snappy}
3664 summary_info += {'bzip2 support':     libbzip2}
3665 summary_info += {'lzfse support':     liblzfse}
3666 summary_info += {'zstd support':      zstd}
3667 summary_info += {'NUMA host support': numa}
3668 summary_info += {'capstone':          capstone_opt == 'internal' ? capstone_opt : capstone}
3669 summary_info += {'libpmem support':   libpmem}
3670 summary_info += {'libdaxctl support': libdaxctl}
3671 summary_info += {'libudev':           libudev}
3672 # Dummy dependency, keep .found()
3673 summary_info += {'FUSE lseek':        fuse_lseek.found()}
3674 summary_info += {'selinux':           selinux}
3675 summary(summary_info, bool_yn: true, section: 'Dependencies')
3677 if not supported_cpus.contains(cpu)
3678   message()
3679   warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
3680   message()
3681   message('CPU host architecture ' + cpu + ' support is not currently maintained.')
3682   message('The QEMU project intends to remove support for this host CPU in')
3683   message('a future release if nobody volunteers to maintain it and to')
3684   message('provide a build host for our continuous integration setup.')
3685   message('configure has succeeded and you can continue to build, but')
3686   message('if you care about QEMU on this platform you should contact')
3687   message('us upstream at qemu-devel@nongnu.org.')
3688 endif
3690 if not supported_oses.contains(targetos)
3691   message()
3692   warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
3693   message()
3694   message('Host OS ' + targetos + 'support is not currently maintained.')
3695   message('The QEMU project intends to remove support for this host OS in')
3696   message('a future release if nobody volunteers to maintain it and to')
3697   message('provide a build host for our continuous integration setup.')
3698   message('configure has succeeded and you can continue to build, but')
3699   message('if you care about QEMU on this platform you should contact')
3700   message('us upstream at qemu-devel@nongnu.org.')
3701 endif