xive2: Add a get_config() handler for the router configuration
[qemu.git] / meson.build
blob8df40bfac4d70964951433b707b640cfa5cdcee7
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 have_vhost_user_blk_server = get_option('vhost_user_blk_server') \
1310   .require(targetos == 'linux',
1311            error_message: 'vhost_user_blk_server requires linux') \
1312   .require('CONFIG_VHOST_USER' in config_host,
1313            error_message: 'vhost_user_blk_server requires vhost-user support') \
1314   .disable_auto_if(not have_system) \
1315   .allowed()
1317 if get_option('fuse').disabled() and get_option('fuse_lseek').enabled()
1318   error('Cannot enable fuse-lseek while fuse is disabled')
1319 endif
1321 fuse = dependency('fuse3', required: get_option('fuse'),
1322                   version: '>=3.1', method: 'pkg-config',
1323                   kwargs: static_kwargs)
1325 fuse_lseek = not_found
1326 if get_option('fuse_lseek').allowed()
1327   if fuse.version().version_compare('>=3.8')
1328     # Dummy dependency
1329     fuse_lseek = declare_dependency()
1330   elif get_option('fuse_lseek').enabled()
1331     if fuse.found()
1332       error('fuse-lseek requires libfuse >=3.8, found ' + fuse.version())
1333     else
1334       error('fuse-lseek requires libfuse, which was not found')
1335     endif
1336   endif
1337 endif
1339 # libbpf
1340 libbpf = dependency('libbpf', required: get_option('bpf'), method: 'pkg-config')
1341 if libbpf.found() and not cc.links('''
1342    #include <bpf/libbpf.h>
1343    int main(void)
1344    {
1345      bpf_object__destroy_skeleton(NULL);
1346      return 0;
1347    }''', dependencies: libbpf)
1348   libbpf = not_found
1349   if get_option('bpf').enabled()
1350     error('libbpf skeleton test failed')
1351   else
1352     warning('libbpf skeleton test failed, disabling')
1353   endif
1354 endif
1356 #################
1357 # config-host.h #
1358 #################
1360 audio_drivers_selected = []
1361 if have_system
1362   audio_drivers_available = {
1363     'alsa': alsa.found(),
1364     'coreaudio': coreaudio.found(),
1365     'dsound': dsound.found(),
1366     'jack': jack.found(),
1367     'oss': oss.found(),
1368     'pa': pulse.found(),
1369     'sdl': sdl.found(),
1370   }
1371   foreach k, v: audio_drivers_available
1372     config_host_data.set('CONFIG_AUDIO_' + k.to_upper(), v)
1373   endforeach
1375   # Default to native drivers first, OSS second, SDL third
1376   audio_drivers_priority = \
1377     [ 'pa', 'coreaudio', 'dsound', 'oss' ] + \
1378     (targetos == 'linux' ? [] : [ 'sdl' ])
1379   audio_drivers_default = []
1380   foreach k: audio_drivers_priority
1381     if audio_drivers_available[k]
1382       audio_drivers_default += k
1383     endif
1384   endforeach
1386   foreach k: get_option('audio_drv_list')
1387     if k == 'default'
1388       audio_drivers_selected += audio_drivers_default
1389     elif not audio_drivers_available[k]
1390       error('Audio driver "@0@" not available.'.format(k))
1391     else
1392       audio_drivers_selected += k
1393     endif
1394   endforeach
1395 endif
1396 config_host_data.set('CONFIG_AUDIO_DRIVERS',
1397                      '"' + '", "'.join(audio_drivers_selected) + '", ')
1399 if get_option('cfi')
1400   cfi_flags=[]
1401   # Check for dependency on LTO
1402   if not get_option('b_lto')
1403     error('Selected Control-Flow Integrity but LTO is disabled')
1404   endif
1405   if config_host.has_key('CONFIG_MODULES')
1406     error('Selected Control-Flow Integrity is not compatible with modules')
1407   endif
1408   # Check for cfi flags. CFI requires LTO so we can't use
1409   # get_supported_arguments, but need a more complex "compiles" which allows
1410   # custom arguments
1411   if cc.compiles('int main () { return 0; }', name: '-fsanitize=cfi-icall',
1412                  args: ['-flto', '-fsanitize=cfi-icall'] )
1413     cfi_flags += '-fsanitize=cfi-icall'
1414   else
1415     error('-fsanitize=cfi-icall is not supported by the compiler')
1416   endif
1417   if cc.compiles('int main () { return 0; }',
1418                  name: '-fsanitize-cfi-icall-generalize-pointers',
1419                  args: ['-flto', '-fsanitize=cfi-icall',
1420                         '-fsanitize-cfi-icall-generalize-pointers'] )
1421     cfi_flags += '-fsanitize-cfi-icall-generalize-pointers'
1422   else
1423     error('-fsanitize-cfi-icall-generalize-pointers is not supported by the compiler')
1424   endif
1425   if get_option('cfi_debug')
1426     if cc.compiles('int main () { return 0; }',
1427                    name: '-fno-sanitize-trap=cfi-icall',
1428                    args: ['-flto', '-fsanitize=cfi-icall',
1429                           '-fno-sanitize-trap=cfi-icall'] )
1430       cfi_flags += '-fno-sanitize-trap=cfi-icall'
1431     else
1432       error('-fno-sanitize-trap=cfi-icall is not supported by the compiler')
1433     endif
1434   endif
1435   add_global_arguments(cfi_flags, native: false, language: ['c', 'cpp', 'objc'])
1436   add_global_link_arguments(cfi_flags, native: false, language: ['c', 'cpp', 'objc'])
1437 endif
1439 have_host_block_device = (targetos != 'darwin' or
1440     cc.has_header('IOKit/storage/IOMedia.h'))
1442 # FIXME enable_modules shouldn't be necessary, but: https://github.com/mesonbuild/meson/issues/8333
1443 dbus_display = get_option('dbus_display') \
1444   .require(gio.version().version_compare('>=2.64'),
1445            error_message: '-display dbus requires glib>=2.64') \
1446   .require(enable_modules,
1447            error_message: '-display dbus requires --enable-modules') \
1448   .require(config_host.has_key('GDBUS_CODEGEN'),
1449            error_message: '-display dbus requires gdbus-codegen') \
1450   .allowed()
1452 have_virtfs = get_option('virtfs') \
1453     .require(targetos == 'linux',
1454              error_message: 'virtio-9p (virtfs) requires Linux') \
1455     .require(libattr.found() and libcap_ng.found(),
1456              error_message: 'virtio-9p (virtfs) requires libcap-ng-devel and libattr-devel') \
1457     .disable_auto_if(not have_tools and not have_system) \
1458     .allowed()
1460 have_virtfs_proxy_helper = have_virtfs and have_tools
1462 foreach k : get_option('trace_backends')
1463   config_host_data.set('CONFIG_TRACE_' + k.to_upper(), true)
1464 endforeach
1465 config_host_data.set_quoted('CONFIG_TRACE_FILE', get_option('trace_file'))
1466 if get_option('iasl') != ''
1467   config_host_data.set_quoted('CONFIG_IASL', get_option('iasl'))
1468 endif
1469 config_host_data.set_quoted('CONFIG_BINDIR', get_option('prefix') / get_option('bindir'))
1470 config_host_data.set_quoted('CONFIG_PREFIX', get_option('prefix'))
1471 config_host_data.set_quoted('CONFIG_QEMU_CONFDIR', get_option('prefix') / qemu_confdir)
1472 config_host_data.set_quoted('CONFIG_QEMU_DATADIR', get_option('prefix') / qemu_datadir)
1473 config_host_data.set_quoted('CONFIG_QEMU_DESKTOPDIR', get_option('prefix') / qemu_desktopdir)
1474 config_host_data.set_quoted('CONFIG_QEMU_FIRMWAREPATH', get_option('qemu_firmwarepath'))
1475 config_host_data.set_quoted('CONFIG_QEMU_HELPERDIR', get_option('prefix') / get_option('libexecdir'))
1476 config_host_data.set_quoted('CONFIG_QEMU_ICONDIR', get_option('prefix') / qemu_icondir)
1477 config_host_data.set_quoted('CONFIG_QEMU_LOCALEDIR', get_option('prefix') / get_option('localedir'))
1478 config_host_data.set_quoted('CONFIG_QEMU_LOCALSTATEDIR', get_option('prefix') / get_option('localstatedir'))
1479 config_host_data.set_quoted('CONFIG_QEMU_MODDIR', get_option('prefix') / qemu_moddir)
1480 config_host_data.set_quoted('CONFIG_SYSCONFDIR', get_option('prefix') / get_option('sysconfdir'))
1482 have_slirp_smbd = get_option('slirp_smbd') \
1483   .require(targetos != 'windows', error_message: 'Host smbd not supported on this platform.') \
1484   .allowed()
1485 if have_slirp_smbd
1486   smbd_path = get_option('smbd')
1487   if smbd_path == ''
1488     smbd_path = (targetos == 'solaris' ? '/usr/sfw/sbin/smbd' : '/usr/sbin/smbd')
1489   endif
1490   config_host_data.set_quoted('CONFIG_SMBD_COMMAND', smbd_path)
1491 endif
1493 config_host_data.set('HOST_' + host_arch.to_upper(), 1)
1495 config_host_data.set('CONFIG_ATTR', libattr.found())
1496 config_host_data.set('CONFIG_BDRV_WHITELIST_TOOLS', get_option('block_drv_whitelist_in_tools'))
1497 config_host_data.set('CONFIG_BRLAPI', brlapi.found())
1498 config_host_data.set('CONFIG_COCOA', cocoa.found())
1499 config_host_data.set('CONFIG_FUZZ', get_option('fuzzing'))
1500 config_host_data.set('CONFIG_GCOV', get_option('b_coverage'))
1501 config_host_data.set('CONFIG_LIBUDEV', libudev.found())
1502 config_host_data.set('CONFIG_LZO', lzo.found())
1503 config_host_data.set('CONFIG_MPATH', mpathpersist.found())
1504 config_host_data.set('CONFIG_MPATH_NEW_API', mpathpersist_new_api)
1505 config_host_data.set('CONFIG_CURL', curl.found())
1506 config_host_data.set('CONFIG_CURSES', curses.found())
1507 config_host_data.set('CONFIG_GBM', gbm.found())
1508 config_host_data.set('CONFIG_GLUSTERFS', glusterfs.found())
1509 if glusterfs.found()
1510   config_host_data.set('CONFIG_GLUSTERFS_XLATOR_OPT', glusterfs.version().version_compare('>=4'))
1511   config_host_data.set('CONFIG_GLUSTERFS_DISCARD', glusterfs.version().version_compare('>=5'))
1512   config_host_data.set('CONFIG_GLUSTERFS_FALLOCATE', glusterfs.version().version_compare('>=6'))
1513   config_host_data.set('CONFIG_GLUSTERFS_ZEROFILL', glusterfs.version().version_compare('>=6'))
1514   config_host_data.set('CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT', glusterfs_ftruncate_has_stat)
1515   config_host_data.set('CONFIG_GLUSTERFS_IOCB_HAS_STAT', glusterfs_iocb_has_stat)
1516 endif
1517 config_host_data.set('CONFIG_GTK', gtk.found())
1518 config_host_data.set('CONFIG_VTE', vte.found())
1519 config_host_data.set('CONFIG_LIBATTR', have_old_libattr)
1520 config_host_data.set('CONFIG_LIBCAP_NG', libcap_ng.found())
1521 config_host_data.set('CONFIG_EBPF', libbpf.found())
1522 config_host_data.set('CONFIG_LIBDAXCTL', libdaxctl.found())
1523 config_host_data.set('CONFIG_LIBISCSI', libiscsi.found())
1524 config_host_data.set('CONFIG_LIBNFS', libnfs.found())
1525 config_host_data.set('CONFIG_LIBSSH', libssh.found())
1526 config_host_data.set('CONFIG_LINUX_AIO', libaio.found())
1527 config_host_data.set('CONFIG_LINUX_IO_URING', linux_io_uring.found())
1528 config_host_data.set('CONFIG_LIBPMEM', libpmem.found())
1529 config_host_data.set('CONFIG_NUMA', numa.found())
1530 config_host_data.set('CONFIG_PROFILER', get_option('profiler'))
1531 config_host_data.set('CONFIG_RBD', rbd.found())
1532 config_host_data.set('CONFIG_SDL', sdl.found())
1533 config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found())
1534 config_host_data.set('CONFIG_SECCOMP', seccomp.found())
1535 config_host_data.set('CONFIG_SNAPPY', snappy.found())
1536 config_host_data.set('CONFIG_TPM', have_tpm)
1537 config_host_data.set('CONFIG_USB_LIBUSB', libusb.found())
1538 config_host_data.set('CONFIG_VDE', vde.found())
1539 config_host_data.set('CONFIG_VHOST_USER_BLK_SERVER', have_vhost_user_blk_server)
1540 config_host_data.set('CONFIG_VNC', vnc.found())
1541 config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
1542 config_host_data.set('CONFIG_VNC_PNG', png.found())
1543 config_host_data.set('CONFIG_VNC_SASL', sasl.found())
1544 config_host_data.set('CONFIG_VIRTFS', have_virtfs)
1545 config_host_data.set('CONFIG_VTE', vte.found())
1546 config_host_data.set('CONFIG_XKBCOMMON', xkbcommon.found())
1547 config_host_data.set('CONFIG_KEYUTILS', keyutils.found())
1548 config_host_data.set('CONFIG_GETTID', has_gettid)
1549 config_host_data.set('CONFIG_GNUTLS', gnutls.found())
1550 config_host_data.set('CONFIG_GNUTLS_CRYPTO', gnutls_crypto.found())
1551 config_host_data.set('CONFIG_GCRYPT', gcrypt.found())
1552 config_host_data.set('CONFIG_NETTLE', nettle.found())
1553 config_host_data.set('CONFIG_QEMU_PRIVATE_XTS', xts == 'private')
1554 config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim)
1555 config_host_data.set('CONFIG_STATX', has_statx)
1556 config_host_data.set('CONFIG_ZSTD', zstd.found())
1557 config_host_data.set('CONFIG_FUSE', fuse.found())
1558 config_host_data.set('CONFIG_FUSE_LSEEK', fuse_lseek.found())
1559 config_host_data.set('CONFIG_SPICE_PROTOCOL', spice_protocol.found())
1560 if spice_protocol.found()
1561 config_host_data.set('CONFIG_SPICE_PROTOCOL_MAJOR', spice_protocol.version().split('.')[0])
1562 config_host_data.set('CONFIG_SPICE_PROTOCOL_MINOR', spice_protocol.version().split('.')[1])
1563 config_host_data.set('CONFIG_SPICE_PROTOCOL_MICRO', spice_protocol.version().split('.')[2])
1564 endif
1565 config_host_data.set('CONFIG_SPICE', spice.found())
1566 config_host_data.set('CONFIG_X11', x11.found())
1567 config_host_data.set('CONFIG_DBUS_DISPLAY', dbus_display)
1568 config_host_data.set('CONFIG_CFI', get_option('cfi'))
1569 config_host_data.set('CONFIG_SELINUX', selinux.found())
1570 config_host_data.set('QEMU_VERSION', '"@0@"'.format(meson.project_version()))
1571 config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0])
1572 config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1])
1573 config_host_data.set('QEMU_VERSION_MICRO', meson.project_version().split('.')[2])
1575 config_host_data.set_quoted('CONFIG_HOST_DSOSUF', host_dsosuf)
1576 config_host_data.set('HAVE_HOST_BLOCK_DEVICE', have_host_block_device)
1577 config_host_data.set('HOST_WORDS_BIGENDIAN', host_machine.endian() == 'big')
1579 have_coroutine_pool = get_option('coroutine_pool')
1580 if get_option('debug_stack_usage') and have_coroutine_pool
1581   message('Disabling coroutine pool to measure stack usage')
1582   have_coroutine_pool = false
1583 endif
1584 config_host_data.set10('CONFIG_COROUTINE_POOL', have_coroutine_pool)
1585 config_host_data.set('CONFIG_DEBUG_MUTEX', get_option('debug_mutex'))
1586 config_host_data.set('CONFIG_DEBUG_STACK_USAGE', get_option('debug_stack_usage'))
1587 config_host_data.set('CONFIG_GPROF', get_option('gprof'))
1588 config_host_data.set('CONFIG_LIVE_BLOCK_MIGRATION', get_option('live_block_migration').allowed())
1589 config_host_data.set('CONFIG_QOM_CAST_DEBUG', get_option('qom_cast_debug'))
1590 config_host_data.set('CONFIG_REPLICATION', get_option('live_block_migration').allowed())
1592 # has_header
1593 config_host_data.set('CONFIG_EPOLL', cc.has_header('sys/epoll.h'))
1594 config_host_data.set('CONFIG_LINUX_MAGIC_H', cc.has_header('linux/magic.h'))
1595 config_host_data.set('CONFIG_VALGRIND_H', cc.has_header('valgrind/valgrind.h'))
1596 config_host_data.set('HAVE_BTRFS_H', cc.has_header('linux/btrfs.h'))
1597 config_host_data.set('HAVE_DRM_H', cc.has_header('libdrm/drm.h'))
1598 config_host_data.set('HAVE_PTY_H', cc.has_header('pty.h'))
1599 config_host_data.set('HAVE_SYS_DISK_H', cc.has_header('sys/disk.h'))
1600 config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h'))
1601 config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h'))
1603 # has_function
1604 config_host_data.set('CONFIG_ACCEPT4', cc.has_function('accept4'))
1605 config_host_data.set('CONFIG_CLOCK_ADJTIME', cc.has_function('clock_adjtime'))
1606 config_host_data.set('CONFIG_DUP3', cc.has_function('dup3'))
1607 config_host_data.set('CONFIG_FALLOCATE', cc.has_function('fallocate'))
1608 config_host_data.set('CONFIG_POSIX_FALLOCATE', cc.has_function('posix_fallocate'))
1609 config_host_data.set('CONFIG_POSIX_MEMALIGN', cc.has_function('posix_memalign'))
1610 config_host_data.set('CONFIG_PPOLL', cc.has_function('ppoll'))
1611 config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include <sys/uio.h>'))
1612 config_host_data.set('CONFIG_SEM_TIMEDWAIT', cc.has_function('sem_timedwait', dependencies: threads))
1613 config_host_data.set('CONFIG_SENDFILE', cc.has_function('sendfile'))
1614 config_host_data.set('CONFIG_SETNS', cc.has_function('setns') and cc.has_function('unshare'))
1615 config_host_data.set('CONFIG_SYNCFS', cc.has_function('syncfs'))
1616 config_host_data.set('CONFIG_SYNC_FILE_RANGE', cc.has_function('sync_file_range'))
1617 config_host_data.set('CONFIG_TIMERFD', cc.has_function('timerfd_create'))
1618 config_host_data.set('HAVE_COPY_FILE_RANGE', cc.has_function('copy_file_range'))
1619 config_host_data.set('HAVE_OPENPTY', cc.has_function('openpty', dependencies: util))
1620 config_host_data.set('HAVE_STRCHRNUL', cc.has_function('strchrnul'))
1621 config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: '#include <stdlib.h>'))
1622 if rdma.found()
1623   config_host_data.set('HAVE_IBV_ADVISE_MR',
1624                        cc.has_function('ibv_advise_mr',
1625                                        args: config_host['RDMA_LIBS'].split(),
1626                                        prefix: '#include <infiniband/verbs.h>'))
1627 endif
1629 # has_header_symbol
1630 config_host_data.set('CONFIG_BYTESWAP_H',
1631                      cc.has_header_symbol('byteswap.h', 'bswap_32'))
1632 config_host_data.set('CONFIG_EPOLL_CREATE1',
1633                      cc.has_header_symbol('sys/epoll.h', 'epoll_create1'))
1634 config_host_data.set('CONFIG_HAS_ENVIRON',
1635                      cc.has_header_symbol('unistd.h', 'environ', prefix: gnu_source_prefix))
1636 config_host_data.set('CONFIG_FALLOCATE_PUNCH_HOLE',
1637                      cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_PUNCH_HOLE') and
1638                      cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_KEEP_SIZE'))
1639 config_host_data.set('CONFIG_FALLOCATE_ZERO_RANGE',
1640                      cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_ZERO_RANGE'))
1641 config_host_data.set('CONFIG_FIEMAP',
1642                      cc.has_header('linux/fiemap.h') and
1643                      cc.has_header_symbol('linux/fs.h', 'FS_IOC_FIEMAP'))
1644 config_host_data.set('CONFIG_GETRANDOM',
1645                      cc.has_function('getrandom') and
1646                      cc.has_header_symbol('sys/random.h', 'GRND_NONBLOCK'))
1647 config_host_data.set('CONFIG_INOTIFY',
1648                      cc.has_header_symbol('sys/inotify.h', 'inotify_init'))
1649 config_host_data.set('CONFIG_INOTIFY1',
1650                      cc.has_header_symbol('sys/inotify.h', 'inotify_init1'))
1651 config_host_data.set('CONFIG_MACHINE_BSWAP_H',
1652                      cc.has_header_symbol('machine/bswap.h', 'bswap32',
1653                                           prefix: '''#include <sys/endian.h>
1654                                                      #include <sys/types.h>'''))
1655 config_host_data.set('CONFIG_PRCTL_PR_SET_TIMERSLACK',
1656                      cc.has_header_symbol('sys/prctl.h', 'PR_SET_TIMERSLACK'))
1657 config_host_data.set('CONFIG_RTNETLINK',
1658                      cc.has_header_symbol('linux/rtnetlink.h', 'IFLA_PROTO_DOWN'))
1659 config_host_data.set('CONFIG_SYSMACROS',
1660                      cc.has_header_symbol('sys/sysmacros.h', 'makedev'))
1661 config_host_data.set('HAVE_OPTRESET',
1662                      cc.has_header_symbol('getopt.h', 'optreset'))
1663 config_host_data.set('HAVE_IPPROTO_MPTCP',
1664                      cc.has_header_symbol('netinet/in.h', 'IPPROTO_MPTCP'))
1666 # has_member
1667 config_host_data.set('HAVE_SIGEV_NOTIFY_THREAD_ID',
1668                      cc.has_member('struct sigevent', 'sigev_notify_thread_id',
1669                                    prefix: '#include <signal.h>'))
1670 config_host_data.set('HAVE_STRUCT_STAT_ST_ATIM',
1671                      cc.has_member('struct stat', 'st_atim',
1672                                    prefix: '#include <sys/stat.h>'))
1674 # has_type
1675 config_host_data.set('CONFIG_IOVEC',
1676                      cc.has_type('struct iovec',
1677                                  prefix: '#include <sys/uio.h>'))
1678 config_host_data.set('HAVE_UTMPX',
1679                      cc.has_type('struct utmpx',
1680                                  prefix: '#include <utmpx.h>'))
1682 config_host_data.set('CONFIG_EVENTFD', cc.links('''
1683   #include <sys/eventfd.h>
1684   int main(void) { return eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); }'''))
1685 config_host_data.set('CONFIG_FDATASYNC', cc.links(gnu_source_prefix + '''
1686   #include <unistd.h>
1687   int main(void) {
1688   #if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
1689   return fdatasync(0);
1690   #else
1691   #error Not supported
1692   #endif
1693   }'''))
1694 config_host_data.set('CONFIG_MADVISE', cc.links(gnu_source_prefix + '''
1695   #include <sys/types.h>
1696   #include <sys/mman.h>
1697   #include <stddef.h>
1698   int main(void) { return madvise(NULL, 0, MADV_DONTNEED); }'''))
1699 config_host_data.set('CONFIG_MEMFD', cc.links(gnu_source_prefix + '''
1700   #include <sys/mman.h>
1701   int main(void) { return memfd_create("foo", MFD_ALLOW_SEALING); }'''))
1702 config_host_data.set('CONFIG_OPEN_BY_HANDLE', cc.links(gnu_source_prefix + '''
1703   #include <fcntl.h>
1704   #if !defined(AT_EMPTY_PATH)
1705   # error missing definition
1706   #else
1707   int main(void) { struct file_handle fh; return open_by_handle_at(0, &fh, 0); }
1708   #endif'''))
1709 config_host_data.set('CONFIG_PIPE2', cc.links(gnu_source_prefix + '''
1710   #include <unistd.h>
1711   #include <fcntl.h>
1713   int main(void)
1714   {
1715       int pipefd[2];
1716       return pipe2(pipefd, O_CLOEXEC);
1717   }'''))
1718 config_host_data.set('CONFIG_POSIX_MADVISE', cc.links(gnu_source_prefix + '''
1719   #include <sys/mman.h>
1720   #include <stddef.h>
1721   int main(void) { return posix_madvise(NULL, 0, POSIX_MADV_DONTNEED); }'''))
1723 config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_W_TID', cc.links(gnu_source_prefix + '''
1724   #include <pthread.h>
1726   static void *f(void *p) { return NULL; }
1727   int main(void)
1728   {
1729     pthread_t thread;
1730     pthread_create(&thread, 0, f, 0);
1731     pthread_setname_np(thread, "QEMU");
1732     return 0;
1733   }''', dependencies: threads))
1734 config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_WO_TID', cc.links(gnu_source_prefix + '''
1735   #include <pthread.h>
1737   static void *f(void *p) { pthread_setname_np("QEMU"); return NULL; }
1738   int main(void)
1739   {
1740     pthread_t thread;
1741     pthread_create(&thread, 0, f, 0);
1742     return 0;
1743   }''', dependencies: threads))
1745 config_host_data.set('CONFIG_SIGNALFD', cc.links(gnu_source_prefix + '''
1746   #include <sys/signalfd.h>
1747   #include <stddef.h>
1748   int main(void) { return signalfd(-1, NULL, SFD_CLOEXEC); }'''))
1749 config_host_data.set('CONFIG_SPLICE', cc.links(gnu_source_prefix + '''
1750   #include <unistd.h>
1751   #include <fcntl.h>
1752   #include <limits.h>
1754   int main(void)
1755   {
1756     int len, fd = 0;
1757     len = tee(STDIN_FILENO, STDOUT_FILENO, INT_MAX, SPLICE_F_NONBLOCK);
1758     splice(STDIN_FILENO, NULL, fd, NULL, len, SPLICE_F_MOVE);
1759     return 0;
1760   }'''))
1762 config_host_data.set('HAVE_MLOCKALL', cc.links(gnu_source_prefix + '''
1763   #include <sys/mman.h>
1764   int main(int argc, char *argv[]) {
1765     return mlockall(MCL_FUTURE);
1766   }'''))
1768 have_l2tpv3 = false
1769 if get_option('l2tpv3').allowed() and have_system
1770   have_l2tpv3 = cc.has_type('struct mmsghdr',
1771     prefix: gnu_source_prefix + '''
1772       #include <sys/socket.h>
1773       #include <linux/ip.h>''')
1774 endif
1775 config_host_data.set('CONFIG_L2TPV3', have_l2tpv3)
1777 have_netmap = false
1778 if get_option('netmap').allowed() and have_system
1779   have_netmap = cc.compiles('''
1780     #include <inttypes.h>
1781     #include <net/if.h>
1782     #include <net/netmap.h>
1783     #include <net/netmap_user.h>
1784     #if (NETMAP_API < 11) || (NETMAP_API > 15)
1785     #error
1786     #endif
1787     int main(void) { return 0; }''')
1788   if not have_netmap and get_option('netmap').enabled()
1789     error('Netmap headers not available')
1790   endif
1791 endif
1792 config_host_data.set('CONFIG_NETMAP', have_netmap)
1794 # Work around a system header bug with some kernel/XFS header
1795 # versions where they both try to define 'struct fsxattr':
1796 # xfs headers will not try to redefine structs from linux headers
1797 # if this macro is set.
1798 config_host_data.set('HAVE_FSXATTR', cc.links('''
1799   #include <linux/fs.h>
1800   struct fsxattr foo;
1801   int main(void) {
1802     return 0;
1803   }'''))
1805 # Some versions of Mac OS X incorrectly define SIZE_MAX
1806 config_host_data.set('HAVE_BROKEN_SIZE_MAX', not cc.compiles('''
1807     #include <stdint.h>
1808     #include <stdio.h>
1809     int main(int argc, char *argv[]) {
1810         return printf("%zu", SIZE_MAX);
1811     }''', args: ['-Werror']))
1813 # See if 64-bit atomic operations are supported.
1814 # Note that without __atomic builtins, we can only
1815 # assume atomic loads/stores max at pointer size.
1816 config_host_data.set('CONFIG_ATOMIC64', cc.links('''
1817   #include <stdint.h>
1818   int main(void)
1819   {
1820     uint64_t x = 0, y = 0;
1821     y = __atomic_load_n(&x, __ATOMIC_RELAXED);
1822     __atomic_store_n(&x, y, __ATOMIC_RELAXED);
1823     __atomic_compare_exchange_n(&x, &y, x, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
1824     __atomic_exchange_n(&x, y, __ATOMIC_RELAXED);
1825     __atomic_fetch_add(&x, y, __ATOMIC_RELAXED);
1826     return 0;
1827   }'''))
1829 config_host_data.set('CONFIG_GETAUXVAL', cc.links(gnu_source_prefix + '''
1830   #include <sys/auxv.h>
1831   int main(void) {
1832     return getauxval(AT_HWCAP) == 0;
1833   }'''))
1835 have_cpuid_h = cc.links('''
1836   #include <cpuid.h>
1837   int main(void) {
1838     unsigned a, b, c, d;
1839     unsigned max = __get_cpuid_max(0, 0);
1841     if (max >= 1) {
1842         __cpuid(1, a, b, c, d);
1843     }
1845     if (max >= 7) {
1846         __cpuid_count(7, 0, a, b, c, d);
1847     }
1849     return 0;
1850   }''')
1851 config_host_data.set('CONFIG_CPUID_H', have_cpuid_h)
1853 config_host_data.set('CONFIG_AVX2_OPT', get_option('avx2') \
1854   .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX2') \
1855   .require(cc.links('''
1856     #pragma GCC push_options
1857     #pragma GCC target("avx2")
1858     #include <cpuid.h>
1859     #include <immintrin.h>
1860     static int bar(void *a) {
1861       __m256i x = *(__m256i *)a;
1862       return _mm256_testz_si256(x, x);
1863     }
1864     int main(int argc, char *argv[]) { return bar(argv[0]); }
1865   '''), error_message: 'AVX2 not available').allowed())
1867 config_host_data.set('CONFIG_AVX512F_OPT', get_option('avx512f') \
1868   .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX512F') \
1869   .require(cc.links('''
1870     #pragma GCC push_options
1871     #pragma GCC target("avx512f")
1872     #include <cpuid.h>
1873     #include <immintrin.h>
1874     static int bar(void *a) {
1875       __m512i x = *(__m512i *)a;
1876       return _mm512_test_epi64_mask(x, x);
1877     }
1878     int main(int argc, char *argv[]) { return bar(argv[0]); }
1879   '''), error_message: 'AVX512F not available').allowed())
1881 if get_option('membarrier').disabled()
1882   have_membarrier = false
1883 elif targetos == 'windows'
1884   have_membarrier = true
1885 elif targetos == 'linux'
1886   have_membarrier = cc.compiles('''
1887     #include <linux/membarrier.h>
1888     #include <sys/syscall.h>
1889     #include <unistd.h>
1890     #include <stdlib.h>
1891     int main(void) {
1892         syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0);
1893         syscall(__NR_membarrier, MEMBARRIER_CMD_SHARED, 0);
1894         exit(0);
1895     }''')
1896 endif
1897 config_host_data.set('CONFIG_MEMBARRIER', get_option('membarrier') \
1898   .require(have_membarrier, error_message: 'membarrier system call not available') \
1899   .allowed())
1901 have_afalg = get_option('crypto_afalg') \
1902   .require(cc.compiles(gnu_source_prefix + '''
1903     #include <errno.h>
1904     #include <sys/types.h>
1905     #include <sys/socket.h>
1906     #include <linux/if_alg.h>
1907     int main(void) {
1908       int sock;
1909       sock = socket(AF_ALG, SOCK_SEQPACKET, 0);
1910       return sock;
1911     }
1912   '''), error_message: 'AF_ALG requested but could not be detected').allowed()
1913 config_host_data.set('CONFIG_AF_ALG', have_afalg)
1915 config_host_data.set('CONFIG_AF_VSOCK', cc.compiles(gnu_source_prefix + '''
1916   #include <errno.h>
1917   #include <sys/types.h>
1918   #include <sys/socket.h>
1919   #if !defined(AF_VSOCK)
1920   # error missing AF_VSOCK flag
1921   #endif
1922   #include <linux/vm_sockets.h>
1923   int main(void) {
1924     int sock, ret;
1925     struct sockaddr_vm svm;
1926     socklen_t len = sizeof(svm);
1927     sock = socket(AF_VSOCK, SOCK_STREAM, 0);
1928     ret = getpeername(sock, (struct sockaddr *)&svm, &len);
1929     if ((ret == -1) && (errno == ENOTCONN)) {
1930         return 0;
1931     }
1932     return -1;
1933   }'''))
1935 have_vss = false
1936 if targetos == 'windows' and link_language == 'cpp'
1937   have_vss = cxx.compiles('''
1938     #define __MIDL_user_allocate_free_DEFINED__
1939     #include <inc/win2003/vss.h>
1940     int main(void) { return VSS_CTX_BACKUP; }''')
1941 endif
1943 have_ntddscsi = false
1944 if targetos == 'windows'
1945   have_ntddscsi = cc.compiles('''
1946     #include <windows.h>
1947     #include <ntddscsi.h>
1948     int main(void) {
1949     #if !defined(IOCTL_SCSI_GET_ADDRESS)
1950     #error Missing required ioctl definitions
1951     #endif
1952       SCSI_ADDRESS addr = { .Lun = 0, .TargetId = 0, .PathId = 0 };
1953       return addr.Lun;
1954     }
1955 ''')
1956 endif
1957 config_host_data.set('HAVE_NTDDSCSI', have_ntddscsi)
1959 ignored = ['CONFIG_QEMU_INTERP_PREFIX', # actually per-target
1960     'HAVE_GDB_BIN']
1961 arrays = ['CONFIG_BDRV_RW_WHITELIST', 'CONFIG_BDRV_RO_WHITELIST']
1962 foreach k, v: config_host
1963   if ignored.contains(k)
1964     # do nothing
1965   elif arrays.contains(k)
1966     if v != ''
1967       v = '"' + '", "'.join(v.split()) + '", '
1968     endif
1969     config_host_data.set(k, v)
1970   elif k.startswith('CONFIG_')
1971     config_host_data.set(k, v == 'y' ? 1 : v)
1972   endif
1973 endforeach
1975 ########################
1976 # Target configuration #
1977 ########################
1979 minikconf = find_program('scripts/minikconf.py')
1980 config_all = {}
1981 config_all_devices = {}
1982 config_all_disas = {}
1983 config_devices_mak_list = []
1984 config_devices_h = {}
1985 config_target_h = {}
1986 config_target_mak = {}
1988 disassemblers = {
1989   'alpha' : ['CONFIG_ALPHA_DIS'],
1990   'arm' : ['CONFIG_ARM_DIS'],
1991   'avr' : ['CONFIG_AVR_DIS'],
1992   'cris' : ['CONFIG_CRIS_DIS'],
1993   'hexagon' : ['CONFIG_HEXAGON_DIS'],
1994   'hppa' : ['CONFIG_HPPA_DIS'],
1995   'i386' : ['CONFIG_I386_DIS'],
1996   'x86_64' : ['CONFIG_I386_DIS'],
1997   'm68k' : ['CONFIG_M68K_DIS'],
1998   'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
1999   'mips' : ['CONFIG_MIPS_DIS'],
2000   'nios2' : ['CONFIG_NIOS2_DIS'],
2001   'or1k' : ['CONFIG_OPENRISC_DIS'],
2002   'ppc' : ['CONFIG_PPC_DIS'],
2003   'riscv' : ['CONFIG_RISCV_DIS'],
2004   'rx' : ['CONFIG_RX_DIS'],
2005   's390' : ['CONFIG_S390_DIS'],
2006   'sh4' : ['CONFIG_SH4_DIS'],
2007   'sparc' : ['CONFIG_SPARC_DIS'],
2008   'xtensa' : ['CONFIG_XTENSA_DIS'],
2010 if link_language == 'cpp'
2011   disassemblers += {
2012     'aarch64' : [ 'CONFIG_ARM_A64_DIS'],
2013     'arm' : [ 'CONFIG_ARM_DIS', 'CONFIG_ARM_A64_DIS'],
2014     'mips' : [ 'CONFIG_MIPS_DIS', 'CONFIG_NANOMIPS_DIS'],
2015   }
2016 endif
2018 have_ivshmem = config_host_data.get('CONFIG_EVENTFD')
2019 host_kconfig = \
2020   (get_option('fuzzing') ? ['CONFIG_FUZZ=y'] : []) + \
2021   (have_tpm ? ['CONFIG_TPM=y'] : []) + \
2022   (spice.found() ? ['CONFIG_SPICE=y'] : []) + \
2023   (have_ivshmem ? ['CONFIG_IVSHMEM=y'] : []) + \
2024   ('CONFIG_OPENGL' in config_host ? ['CONFIG_OPENGL=y'] : []) + \
2025   (x11.found() ? ['CONFIG_X11=y'] : []) + \
2026   ('CONFIG_VHOST_USER' in config_host ? ['CONFIG_VHOST_USER=y'] : []) + \
2027   ('CONFIG_VHOST_VDPA' in config_host ? ['CONFIG_VHOST_VDPA=y'] : []) + \
2028   ('CONFIG_VHOST_KERNEL' in config_host ? ['CONFIG_VHOST_KERNEL=y'] : []) + \
2029   (have_virtfs ? ['CONFIG_VIRTFS=y'] : []) + \
2030   ('CONFIG_LINUX' in config_host ? ['CONFIG_LINUX=y'] : []) + \
2031   ('CONFIG_PVRDMA' in config_host ? ['CONFIG_PVRDMA=y'] : []) + \
2032   (multiprocess_allowed ? ['CONFIG_MULTIPROCESS_ALLOWED=y'] : [])
2034 ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ]
2036 default_targets = 'CONFIG_DEFAULT_TARGETS' in config_host
2037 actual_target_dirs = []
2038 fdt_required = []
2039 foreach target : target_dirs
2040   config_target = { 'TARGET_NAME': target.split('-')[0] }
2041   if target.endswith('linux-user')
2042     if targetos != 'linux'
2043       if default_targets
2044         continue
2045       endif
2046       error('Target @0@ is only available on a Linux host'.format(target))
2047     endif
2048     config_target += { 'CONFIG_LINUX_USER': 'y' }
2049   elif target.endswith('bsd-user')
2050     if 'CONFIG_BSD' not in config_host
2051       if default_targets
2052         continue
2053       endif
2054       error('Target @0@ is only available on a BSD host'.format(target))
2055     endif
2056     config_target += { 'CONFIG_BSD_USER': 'y' }
2057   elif target.endswith('softmmu')
2058     config_target += { 'CONFIG_SOFTMMU': 'y' }
2059   endif
2060   if target.endswith('-user')
2061     config_target += {
2062       'CONFIG_USER_ONLY': 'y',
2063       'CONFIG_QEMU_INTERP_PREFIX':
2064         config_host['CONFIG_QEMU_INTERP_PREFIX'].format(config_target['TARGET_NAME'])
2065     }
2066   endif
2068   accel_kconfig = []
2069   foreach sym: accelerators
2070     if sym == 'CONFIG_TCG' or target in accelerator_targets.get(sym, [])
2071       config_target += { sym: 'y' }
2072       config_all += { sym: 'y' }
2073       if sym == 'CONFIG_TCG' and tcg_arch == 'tci'
2074         config_target += { 'CONFIG_TCG_INTERPRETER': 'y' }
2075       elif sym == 'CONFIG_XEN' and have_xen_pci_passthrough
2076         config_target += { 'CONFIG_XEN_PCI_PASSTHROUGH': 'y' }
2077       endif
2078       if target in modular_tcg
2079         config_target += { 'CONFIG_TCG_MODULAR': 'y' }
2080       else
2081         config_target += { 'CONFIG_TCG_BUILTIN': 'y' }
2082       endif
2083       accel_kconfig += [ sym + '=y' ]
2084     endif
2085   endforeach
2086   if accel_kconfig.length() == 0
2087     if default_targets
2088       continue
2089     endif
2090     error('No accelerator available for target @0@'.format(target))
2091   endif
2093   actual_target_dirs += target
2094   config_target += keyval.load('configs/targets' / target + '.mak')
2095   config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
2097   if 'TARGET_NEED_FDT' in config_target
2098     fdt_required += target
2099   endif
2101   # Add default keys
2102   if 'TARGET_BASE_ARCH' not in config_target
2103     config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
2104   endif
2105   if 'TARGET_ABI_DIR' not in config_target
2106     config_target += {'TARGET_ABI_DIR': config_target['TARGET_ARCH']}
2107   endif
2109   foreach k, v: disassemblers
2110     if host_arch.startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k)
2111       foreach sym: v
2112         config_target += { sym: 'y' }
2113         config_all_disas += { sym: 'y' }
2114       endforeach
2115     endif
2116   endforeach
2118   config_target_data = configuration_data()
2119   foreach k, v: config_target
2120     if not k.startswith('TARGET_') and not k.startswith('CONFIG_')
2121       # do nothing
2122     elif ignored.contains(k)
2123       # do nothing
2124     elif k == 'TARGET_BASE_ARCH'
2125       # Note that TARGET_BASE_ARCH ends up in config-target.h but it is
2126       # not used to select files from sourcesets.
2127       config_target_data.set('TARGET_' + v.to_upper(), 1)
2128     elif k == 'TARGET_NAME' or k == 'CONFIG_QEMU_INTERP_PREFIX'
2129       config_target_data.set_quoted(k, v)
2130     elif v == 'y'
2131       config_target_data.set(k, 1)
2132     else
2133       config_target_data.set(k, v)
2134     endif
2135   endforeach
2136   config_target_data.set('QEMU_ARCH',
2137                          'QEMU_ARCH_' + config_target['TARGET_BASE_ARCH'].to_upper())
2138   config_target_h += {target: configure_file(output: target + '-config-target.h',
2139                                                configuration: config_target_data)}
2141   if target.endswith('-softmmu')
2142     config_input = meson.get_external_property(target, 'default')
2143     config_devices_mak = target + '-config-devices.mak'
2144     config_devices_mak = configure_file(
2145       input: ['configs/devices' / target / config_input + '.mak', 'Kconfig'],
2146       output: config_devices_mak,
2147       depfile: config_devices_mak + '.d',
2148       capture: true,
2149       command: [minikconf,
2150                 get_option('default_devices') ? '--defconfig' : '--allnoconfig',
2151                 config_devices_mak, '@DEPFILE@', '@INPUT@',
2152                 host_kconfig, accel_kconfig,
2153                 'CONFIG_' + config_target['TARGET_ARCH'].to_upper() + '=y'])
2155     config_devices_data = configuration_data()
2156     config_devices = keyval.load(config_devices_mak)
2157     foreach k, v: config_devices
2158       config_devices_data.set(k, 1)
2159     endforeach
2160     config_devices_mak_list += config_devices_mak
2161     config_devices_h += {target: configure_file(output: target + '-config-devices.h',
2162                                                 configuration: config_devices_data)}
2163     config_target += config_devices
2164     config_all_devices += config_devices
2165   endif
2166   config_target_mak += {target: config_target}
2167 endforeach
2168 target_dirs = actual_target_dirs
2170 # This configuration is used to build files that are shared by
2171 # multiple binaries, and then extracted out of the "common"
2172 # static_library target.
2174 # We do not use all_sources()/all_dependencies(), because it would
2175 # build literally all source files, including devices only used by
2176 # targets that are not built for this compilation.  The CONFIG_ALL
2177 # pseudo symbol replaces it.
2179 config_all += config_all_devices
2180 config_all += config_host
2181 config_all += config_all_disas
2182 config_all += {
2183   'CONFIG_XEN': config_host.has_key('CONFIG_XEN_BACKEND'),
2184   'CONFIG_SOFTMMU': have_system,
2185   'CONFIG_USER_ONLY': have_user,
2186   'CONFIG_ALL': true,
2189 target_configs_h = []
2190 foreach target: target_dirs
2191   target_configs_h += config_target_h[target]
2192   target_configs_h += config_devices_h.get(target, [])
2193 endforeach
2194 genh += custom_target('config-poison.h',
2195                       input: [target_configs_h],
2196                       output: 'config-poison.h',
2197                       capture: true,
2198                       command: [find_program('scripts/make-config-poison.sh'),
2199                                 target_configs_h])
2201 ##############
2202 # Submodules #
2203 ##############
2205 capstone = not_found
2206 capstone_opt = get_option('capstone')
2207 if capstone_opt in ['enabled', 'auto', 'system']
2208   have_internal = fs.exists(meson.current_source_dir() / 'capstone/Makefile')
2209   capstone = dependency('capstone', version: '>=4.0',
2210                         kwargs: static_kwargs, method: 'pkg-config',
2211                         required: capstone_opt == 'system' or
2212                                   capstone_opt == 'enabled' and not have_internal)
2214   # Some versions of capstone have broken pkg-config file
2215   # that reports a wrong -I path, causing the #include to
2216   # fail later. If the system has such a broken version
2217   # do not use it.
2218   if capstone.found() and not cc.compiles('#include <capstone.h>',
2219                                           dependencies: [capstone])
2220     capstone = not_found
2221     if capstone_opt == 'system'
2222       error('system capstone requested, it does not appear to work')
2223     endif
2224   endif
2226   if capstone.found()
2227     capstone_opt = 'system'
2228   elif have_internal
2229     capstone_opt = 'internal'
2230   else
2231     capstone_opt = 'disabled'
2232   endif
2233 endif
2234 if capstone_opt == 'internal'
2235   capstone_data = configuration_data()
2236   capstone_data.set('CAPSTONE_USE_SYS_DYN_MEM', '1')
2238   capstone_files = files(
2239     'capstone/cs.c',
2240     'capstone/MCInst.c',
2241     'capstone/MCInstrDesc.c',
2242     'capstone/MCRegisterInfo.c',
2243     'capstone/SStream.c',
2244     'capstone/utils.c'
2245   )
2247   if 'CONFIG_ARM_DIS' in config_all_disas
2248     capstone_data.set('CAPSTONE_HAS_ARM', '1')
2249     capstone_files += files(
2250       'capstone/arch/ARM/ARMDisassembler.c',
2251       'capstone/arch/ARM/ARMInstPrinter.c',
2252       'capstone/arch/ARM/ARMMapping.c',
2253       'capstone/arch/ARM/ARMModule.c'
2254     )
2255   endif
2257   # FIXME: This config entry currently depends on a c++ compiler.
2258   # Which is needed for building libvixl, but not for capstone.
2259   if 'CONFIG_ARM_A64_DIS' in config_all_disas
2260     capstone_data.set('CAPSTONE_HAS_ARM64', '1')
2261     capstone_files += files(
2262       'capstone/arch/AArch64/AArch64BaseInfo.c',
2263       'capstone/arch/AArch64/AArch64Disassembler.c',
2264       'capstone/arch/AArch64/AArch64InstPrinter.c',
2265       'capstone/arch/AArch64/AArch64Mapping.c',
2266       'capstone/arch/AArch64/AArch64Module.c'
2267     )
2268   endif
2270   if 'CONFIG_PPC_DIS' in config_all_disas
2271     capstone_data.set('CAPSTONE_HAS_POWERPC', '1')
2272     capstone_files += files(
2273       'capstone/arch/PowerPC/PPCDisassembler.c',
2274       'capstone/arch/PowerPC/PPCInstPrinter.c',
2275       'capstone/arch/PowerPC/PPCMapping.c',
2276       'capstone/arch/PowerPC/PPCModule.c'
2277     )
2278   endif
2280   if 'CONFIG_S390_DIS' in config_all_disas
2281     capstone_data.set('CAPSTONE_HAS_SYSZ', '1')
2282     capstone_files += files(
2283       'capstone/arch/SystemZ/SystemZDisassembler.c',
2284       'capstone/arch/SystemZ/SystemZInstPrinter.c',
2285       'capstone/arch/SystemZ/SystemZMapping.c',
2286       'capstone/arch/SystemZ/SystemZModule.c',
2287       'capstone/arch/SystemZ/SystemZMCTargetDesc.c'
2288     )
2289   endif
2291   if 'CONFIG_I386_DIS' in config_all_disas
2292     capstone_data.set('CAPSTONE_HAS_X86', 1)
2293     capstone_files += files(
2294       'capstone/arch/X86/X86Disassembler.c',
2295       'capstone/arch/X86/X86DisassemblerDecoder.c',
2296       'capstone/arch/X86/X86ATTInstPrinter.c',
2297       'capstone/arch/X86/X86IntelInstPrinter.c',
2298       'capstone/arch/X86/X86InstPrinterCommon.c',
2299       'capstone/arch/X86/X86Mapping.c',
2300       'capstone/arch/X86/X86Module.c'
2301     )
2302   endif
2304   configure_file(output: 'capstone-defs.h', configuration: capstone_data)
2306   capstone_cargs = [
2307     # FIXME: There does not seem to be a way to completely replace the c_args
2308     # that come from add_project_arguments() -- we can only add to them.
2309     # So: disable all warnings with a big hammer.
2310     '-Wno-error', '-w',
2312     # Include all configuration defines via a header file, which will wind up
2313     # as a dependency on the object file, and thus changes here will result
2314     # in a rebuild.
2315     '-include', 'capstone-defs.h'
2316   ]
2318   libcapstone = static_library('capstone',
2319                                build_by_default: false,
2320                                sources: capstone_files,
2321                                c_args: capstone_cargs,
2322                                include_directories: 'capstone/include')
2323   capstone = declare_dependency(link_with: libcapstone,
2324                                 include_directories: 'capstone/include/capstone')
2325 endif
2327 slirp = not_found
2328 slirp_opt = 'disabled'
2329 if have_system
2330   slirp_opt = get_option('slirp')
2331   if slirp_opt in ['enabled', 'auto', 'system']
2332     have_internal = fs.exists(meson.current_source_dir() / 'slirp/meson.build')
2333     slirp = dependency('slirp', kwargs: static_kwargs,
2334                        method: 'pkg-config',
2335                        required: slirp_opt == 'system' or
2336                                  slirp_opt == 'enabled' and not have_internal)
2337     if slirp.found()
2338       slirp_opt = 'system'
2339     elif have_internal
2340       slirp_opt = 'internal'
2341     else
2342       slirp_opt = 'disabled'
2343     endif
2344   endif
2345   if slirp_opt == 'internal'
2346     slirp_deps = []
2347     if targetos == 'windows'
2348       slirp_deps = cc.find_library('iphlpapi')
2349     elif targetos == 'darwin'
2350       slirp_deps = cc.find_library('resolv')
2351     endif
2352     slirp_conf = configuration_data()
2353     slirp_conf.set('SLIRP_MAJOR_VERSION', meson.project_version().split('.')[0])
2354     slirp_conf.set('SLIRP_MINOR_VERSION', meson.project_version().split('.')[1])
2355     slirp_conf.set('SLIRP_MICRO_VERSION', meson.project_version().split('.')[2])
2356     slirp_conf.set_quoted('SLIRP_VERSION_STRING', meson.project_version())
2357     slirp_cargs = ['-DG_LOG_DOMAIN="Slirp"']
2358     slirp_files = [
2359       'slirp/src/arp_table.c',
2360       'slirp/src/bootp.c',
2361       'slirp/src/cksum.c',
2362       'slirp/src/dhcpv6.c',
2363       'slirp/src/dnssearch.c',
2364       'slirp/src/if.c',
2365       'slirp/src/ip6_icmp.c',
2366       'slirp/src/ip6_input.c',
2367       'slirp/src/ip6_output.c',
2368       'slirp/src/ip_icmp.c',
2369       'slirp/src/ip_input.c',
2370       'slirp/src/ip_output.c',
2371       'slirp/src/mbuf.c',
2372       'slirp/src/misc.c',
2373       'slirp/src/ncsi.c',
2374       'slirp/src/ndp_table.c',
2375       'slirp/src/sbuf.c',
2376       'slirp/src/slirp.c',
2377       'slirp/src/socket.c',
2378       'slirp/src/state.c',
2379       'slirp/src/stream.c',
2380       'slirp/src/tcp_input.c',
2381       'slirp/src/tcp_output.c',
2382       'slirp/src/tcp_subr.c',
2383       'slirp/src/tcp_timer.c',
2384       'slirp/src/tftp.c',
2385       'slirp/src/udp.c',
2386       'slirp/src/udp6.c',
2387       'slirp/src/util.c',
2388       'slirp/src/version.c',
2389       'slirp/src/vmstate.c',
2390     ]
2392     configure_file(
2393       input : 'slirp/src/libslirp-version.h.in',
2394       output : 'libslirp-version.h',
2395       configuration: slirp_conf)
2397     slirp_inc = include_directories('slirp', 'slirp/src')
2398     libslirp = static_library('slirp',
2399                               build_by_default: false,
2400                               sources: slirp_files,
2401                               c_args: slirp_cargs,
2402                               include_directories: slirp_inc)
2403     slirp = declare_dependency(link_with: libslirp,
2404                                dependencies: slirp_deps,
2405                                include_directories: slirp_inc)
2406   endif
2407 endif
2409 # For CFI, we need to compile slirp as a static library together with qemu.
2410 # This is because we register slirp functions as callbacks for QEMU Timers.
2411 # When using a system-wide shared libslirp, the type information for the
2412 # callback is missing and the timer call produces a false positive with CFI.
2414 # Now that slirp_opt has been defined, check if the selected slirp is compatible
2415 # with control-flow integrity.
2416 if get_option('cfi') and slirp_opt == 'system'
2417   error('Control-Flow Integrity is not compatible with system-wide slirp.' \
2418          + ' Please configure with --enable-slirp=git')
2419 endif
2421 fdt = not_found
2422 fdt_opt = get_option('fdt')
2423 if have_system
2424   if fdt_opt in ['enabled', 'auto', 'system']
2425     have_internal = fs.exists(meson.current_source_dir() / 'dtc/libfdt/Makefile.libfdt')
2426     fdt = cc.find_library('fdt', kwargs: static_kwargs,
2427                           required: fdt_opt == 'system' or
2428                                     fdt_opt == 'enabled' and not have_internal)
2429     if fdt.found() and cc.links('''
2430        #include <libfdt.h>
2431        #include <libfdt_env.h>
2432        int main(void) { fdt_find_max_phandle(NULL, NULL); return 0; }''',
2433          dependencies: fdt)
2434       fdt_opt = 'system'
2435     elif fdt_opt == 'system'
2436        error('system libfdt requested, but it is too old (1.5.1 or newer required)')
2437     elif have_internal
2438       fdt_opt = 'internal'
2439     else
2440       fdt_opt = 'disabled'
2441       fdt = not_found
2442     endif
2443   endif
2444   if fdt_opt == 'internal'
2445     fdt_files = files(
2446       'dtc/libfdt/fdt.c',
2447       'dtc/libfdt/fdt_ro.c',
2448       'dtc/libfdt/fdt_wip.c',
2449       'dtc/libfdt/fdt_sw.c',
2450       'dtc/libfdt/fdt_rw.c',
2451       'dtc/libfdt/fdt_strerror.c',
2452       'dtc/libfdt/fdt_empty_tree.c',
2453       'dtc/libfdt/fdt_addresses.c',
2454       'dtc/libfdt/fdt_overlay.c',
2455       'dtc/libfdt/fdt_check.c',
2456     )
2458     fdt_inc = include_directories('dtc/libfdt')
2459     libfdt = static_library('fdt',
2460                             build_by_default: false,
2461                             sources: fdt_files,
2462                             include_directories: fdt_inc)
2463     fdt = declare_dependency(link_with: libfdt,
2464                              include_directories: fdt_inc)
2465   endif
2466 endif
2467 if not fdt.found() and fdt_required.length() > 0
2468   error('fdt not available but required by targets ' + ', '.join(fdt_required))
2469 endif
2471 config_host_data.set('CONFIG_CAPSTONE', capstone.found())
2472 config_host_data.set('CONFIG_FDT', fdt.found())
2473 config_host_data.set('CONFIG_SLIRP', slirp.found())
2475 #####################
2476 # Generated sources #
2477 #####################
2479 genh += configure_file(output: 'config-host.h', configuration: config_host_data)
2481 hxtool = find_program('scripts/hxtool')
2482 shaderinclude = find_program('scripts/shaderinclude.pl')
2483 qapi_gen = find_program('scripts/qapi-gen.py')
2484 qapi_gen_depends = [ meson.current_source_dir() / 'scripts/qapi/__init__.py',
2485                      meson.current_source_dir() / 'scripts/qapi/commands.py',
2486                      meson.current_source_dir() / 'scripts/qapi/common.py',
2487                      meson.current_source_dir() / 'scripts/qapi/error.py',
2488                      meson.current_source_dir() / 'scripts/qapi/events.py',
2489                      meson.current_source_dir() / 'scripts/qapi/expr.py',
2490                      meson.current_source_dir() / 'scripts/qapi/gen.py',
2491                      meson.current_source_dir() / 'scripts/qapi/introspect.py',
2492                      meson.current_source_dir() / 'scripts/qapi/parser.py',
2493                      meson.current_source_dir() / 'scripts/qapi/schema.py',
2494                      meson.current_source_dir() / 'scripts/qapi/source.py',
2495                      meson.current_source_dir() / 'scripts/qapi/types.py',
2496                      meson.current_source_dir() / 'scripts/qapi/visit.py',
2497                      meson.current_source_dir() / 'scripts/qapi/common.py',
2498                      meson.current_source_dir() / 'scripts/qapi-gen.py'
2501 tracetool = [
2502   python, files('scripts/tracetool.py'),
2503    '--backend=' + ','.join(get_option('trace_backends'))
2505 tracetool_depends = files(
2506   'scripts/tracetool/backend/log.py',
2507   'scripts/tracetool/backend/__init__.py',
2508   'scripts/tracetool/backend/dtrace.py',
2509   'scripts/tracetool/backend/ftrace.py',
2510   'scripts/tracetool/backend/simple.py',
2511   'scripts/tracetool/backend/syslog.py',
2512   'scripts/tracetool/backend/ust.py',
2513   'scripts/tracetool/format/ust_events_c.py',
2514   'scripts/tracetool/format/ust_events_h.py',
2515   'scripts/tracetool/format/__init__.py',
2516   'scripts/tracetool/format/d.py',
2517   'scripts/tracetool/format/simpletrace_stap.py',
2518   'scripts/tracetool/format/c.py',
2519   'scripts/tracetool/format/h.py',
2520   'scripts/tracetool/format/log_stap.py',
2521   'scripts/tracetool/format/stap.py',
2522   'scripts/tracetool/__init__.py',
2523   'scripts/tracetool/transform.py',
2524   'scripts/tracetool/vcpu.py'
2527 qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
2528                     meson.current_source_dir(),
2529                     config_host['PKGVERSION'], meson.project_version()]
2530 qemu_version = custom_target('qemu-version.h',
2531                              output: 'qemu-version.h',
2532                              command: qemu_version_cmd,
2533                              capture: true,
2534                              build_by_default: true,
2535                              build_always_stale: true)
2536 genh += qemu_version
2538 hxdep = []
2539 hx_headers = [
2540   ['qemu-options.hx', 'qemu-options.def'],
2541   ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
2543 if have_system
2544   hx_headers += [
2545     ['hmp-commands.hx', 'hmp-commands.h'],
2546     ['hmp-commands-info.hx', 'hmp-commands-info.h'],
2547   ]
2548 endif
2549 foreach d : hx_headers
2550   hxdep += custom_target(d[1],
2551                 input: files(d[0]),
2552                 output: d[1],
2553                 capture: true,
2554                 build_by_default: true, # to be removed when added to a target
2555                 command: [hxtool, '-h', '@INPUT0@'])
2556 endforeach
2557 genh += hxdep
2559 ###################
2560 # Collect sources #
2561 ###################
2563 authz_ss = ss.source_set()
2564 blockdev_ss = ss.source_set()
2565 block_ss = ss.source_set()
2566 chardev_ss = ss.source_set()
2567 common_ss = ss.source_set()
2568 crypto_ss = ss.source_set()
2569 hwcore_ss = ss.source_set()
2570 io_ss = ss.source_set()
2571 qmp_ss = ss.source_set()
2572 qom_ss = ss.source_set()
2573 softmmu_ss = ss.source_set()
2574 specific_fuzz_ss = ss.source_set()
2575 specific_ss = ss.source_set()
2576 stub_ss = ss.source_set()
2577 trace_ss = ss.source_set()
2578 user_ss = ss.source_set()
2579 util_ss = ss.source_set()
2581 # accel modules
2582 qtest_module_ss = ss.source_set()
2583 tcg_module_ss = ss.source_set()
2585 modules = {}
2586 target_modules = {}
2587 hw_arch = {}
2588 target_arch = {}
2589 target_softmmu_arch = {}
2590 target_user_arch = {}
2592 ###############
2593 # Trace files #
2594 ###############
2596 # TODO: add each directory to the subdirs from its own meson.build, once
2597 # we have those
2598 trace_events_subdirs = [
2599   'crypto',
2600   'qapi',
2601   'qom',
2602   'monitor',
2603   'util',
2605 if have_linux_user
2606   trace_events_subdirs += [ 'linux-user' ]
2607 endif
2608 if have_bsd_user
2609   trace_events_subdirs += [ 'bsd-user' ]
2610 endif
2611 if have_block
2612   trace_events_subdirs += [
2613     'authz',
2614     'block',
2615     'io',
2616     'nbd',
2617     'scsi',
2618   ]
2619 endif
2620 if have_system
2621   trace_events_subdirs += [
2622     'accel/kvm',
2623     'audio',
2624     'backends',
2625     'backends/tpm',
2626     'chardev',
2627     'ebpf',
2628     'hw/9pfs',
2629     'hw/acpi',
2630     'hw/adc',
2631     'hw/alpha',
2632     'hw/arm',
2633     'hw/audio',
2634     'hw/block',
2635     'hw/block/dataplane',
2636     'hw/char',
2637     'hw/display',
2638     'hw/dma',
2639     'hw/hppa',
2640     'hw/hyperv',
2641     'hw/i2c',
2642     'hw/i386',
2643     'hw/i386/xen',
2644     'hw/ide',
2645     'hw/input',
2646     'hw/intc',
2647     'hw/isa',
2648     'hw/mem',
2649     'hw/mips',
2650     'hw/misc',
2651     'hw/misc/macio',
2652     'hw/net',
2653     'hw/net/can',
2654     'hw/nubus',
2655     'hw/nvme',
2656     'hw/nvram',
2657     'hw/pci',
2658     'hw/pci-host',
2659     'hw/ppc',
2660     'hw/rdma',
2661     'hw/rdma/vmw',
2662     'hw/rtc',
2663     'hw/s390x',
2664     'hw/scsi',
2665     'hw/sd',
2666     'hw/sh4',
2667     'hw/sparc',
2668     'hw/sparc64',
2669     'hw/ssi',
2670     'hw/timer',
2671     'hw/tpm',
2672     'hw/usb',
2673     'hw/vfio',
2674     'hw/virtio',
2675     'hw/watchdog',
2676     'hw/xen',
2677     'hw/gpio',
2678     'migration',
2679     'net',
2680     'softmmu',
2681     'ui',
2682     'hw/remote',
2683   ]
2684 endif
2685 if have_system or have_user
2686   trace_events_subdirs += [
2687     'accel/tcg',
2688     'hw/core',
2689     'target/arm',
2690     'target/arm/hvf',
2691     'target/hppa',
2692     'target/i386',
2693     'target/i386/kvm',
2694     'target/mips/tcg',
2695     'target/ppc',
2696     'target/riscv',
2697     'target/s390x',
2698     'target/s390x/kvm',
2699     'target/sparc',
2700   ]
2701 endif
2703 vhost_user = not_found
2704 if 'CONFIG_VHOST_USER' in config_host
2705   libvhost_user = subproject('libvhost-user')
2706   vhost_user = libvhost_user.get_variable('vhost_user_dep')
2707 endif
2709 # NOTE: the trace/ subdirectory needs the qapi_trace_events variable
2710 # that is filled in by qapi/.
2711 subdir('qapi')
2712 subdir('qobject')
2713 subdir('stubs')
2714 subdir('trace')
2715 subdir('util')
2716 subdir('qom')
2717 subdir('authz')
2718 subdir('crypto')
2719 subdir('ui')
2722 if enable_modules
2723   libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
2724   modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
2725 endif
2727 stub_ss = stub_ss.apply(config_all, strict: false)
2729 util_ss.add_all(trace_ss)
2730 util_ss = util_ss.apply(config_all, strict: false)
2731 libqemuutil = static_library('qemuutil',
2732                              sources: util_ss.sources() + stub_ss.sources() + genh,
2733                              dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc, pixman])
2734 qemuutil = declare_dependency(link_with: libqemuutil,
2735                               sources: genh + version_res)
2737 if have_system or have_user
2738   decodetree = generator(find_program('scripts/decodetree.py'),
2739                          output: 'decode-@BASENAME@.c.inc',
2740                          arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
2741   subdir('libdecnumber')
2742   subdir('target')
2743 endif
2745 subdir('audio')
2746 subdir('io')
2747 subdir('chardev')
2748 subdir('fsdev')
2749 subdir('dump')
2751 if have_block
2752   block_ss.add(files(
2753     'block.c',
2754     'blockjob.c',
2755     'job.c',
2756     'qemu-io-cmds.c',
2757   ))
2758   if config_host_data.get('CONFIG_REPLICATION')
2759     block_ss.add(files('replication.c'))
2760   endif
2762   subdir('nbd')
2763   subdir('scsi')
2764   subdir('block')
2766   blockdev_ss.add(files(
2767     'blockdev.c',
2768     'blockdev-nbd.c',
2769     'iothread.c',
2770     'job-qmp.c',
2771   ), gnutls)
2773   # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
2774   # os-win32.c does not
2775   blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
2776   softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
2777 endif
2779 common_ss.add(files('cpus-common.c'))
2781 subdir('softmmu')
2783 common_ss.add(capstone)
2784 specific_ss.add(files('cpu.c', 'disas.c', 'gdbstub.c'), capstone)
2786 # Work around a gcc bug/misfeature wherein constant propagation looks
2787 # through an alias:
2788 #   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99696
2789 # to guess that a const variable is always zero.  Without lto, this is
2790 # impossible, as the alias is restricted to page-vary-common.c.  Indeed,
2791 # without lto, not even the alias is required -- we simply use different
2792 # declarations in different compilation units.
2793 pagevary = files('page-vary-common.c')
2794 if get_option('b_lto')
2795   pagevary_flags = ['-fno-lto']
2796   if get_option('cfi')
2797     pagevary_flags += '-fno-sanitize=cfi-icall'
2798   endif
2799   pagevary = static_library('page-vary-common', sources: pagevary,
2800                             c_args: pagevary_flags)
2801   pagevary = declare_dependency(link_with: pagevary)
2802 endif
2803 common_ss.add(pagevary)
2804 specific_ss.add(files('page-vary.c'))
2806 subdir('backends')
2807 subdir('disas')
2808 subdir('migration')
2809 subdir('monitor')
2810 subdir('net')
2811 subdir('replay')
2812 subdir('semihosting')
2813 subdir('hw')
2814 subdir('tcg')
2815 subdir('fpu')
2816 subdir('accel')
2817 subdir('plugins')
2818 subdir('ebpf')
2820 common_user_inc = []
2822 subdir('common-user')
2823 subdir('bsd-user')
2824 subdir('linux-user')
2826 # needed for fuzzing binaries
2827 subdir('tests/qtest/libqos')
2828 subdir('tests/qtest/fuzz')
2830 # accel modules
2831 tcg_real_module_ss = ss.source_set()
2832 tcg_real_module_ss.add_all(when: 'CONFIG_TCG_MODULAR', if_true: tcg_module_ss)
2833 specific_ss.add_all(when: 'CONFIG_TCG_BUILTIN', if_true: tcg_module_ss)
2834 target_modules += { 'accel' : { 'qtest': qtest_module_ss,
2835                                 'tcg': tcg_real_module_ss }}
2837 ########################
2838 # Library dependencies #
2839 ########################
2841 modinfo_collect = find_program('scripts/modinfo-collect.py')
2842 modinfo_generate = find_program('scripts/modinfo-generate.py')
2843 modinfo_files = []
2845 block_mods = []
2846 softmmu_mods = []
2847 foreach d, list : modules
2848   foreach m, module_ss : list
2849     if enable_modules and targetos != 'windows'
2850       module_ss = module_ss.apply(config_all, strict: false)
2851       sl = static_library(d + '-' + m, [genh, module_ss.sources()],
2852                           dependencies: [modulecommon, module_ss.dependencies()], pic: true)
2853       if d == 'block'
2854         block_mods += sl
2855       else
2856         softmmu_mods += sl
2857       endif
2858       if module_ss.sources() != []
2859         # FIXME: Should use sl.extract_all_objects(recursive: true) as
2860         # input. Sources can be used multiple times but objects are
2861         # unique when it comes to lookup in compile_commands.json.
2862         # Depnds on a mesion version with
2863         # https://github.com/mesonbuild/meson/pull/8900
2864         modinfo_files += custom_target(d + '-' + m + '.modinfo',
2865                                        output: d + '-' + m + '.modinfo',
2866                                        input: module_ss.sources() + genh,
2867                                        capture: true,
2868                                        command: [modinfo_collect, module_ss.sources()])
2869       endif
2870     else
2871       if d == 'block'
2872         block_ss.add_all(module_ss)
2873       else
2874         softmmu_ss.add_all(module_ss)
2875       endif
2876     endif
2877   endforeach
2878 endforeach
2880 foreach d, list : target_modules
2881   foreach m, module_ss : list
2882     if enable_modules and targetos != 'windows'
2883       foreach target : target_dirs
2884         if target.endswith('-softmmu')
2885           config_target = config_target_mak[target]
2886           config_target += config_host
2887           target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
2888           c_args = ['-DNEED_CPU_H',
2889                     '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
2890                     '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
2891           target_module_ss = module_ss.apply(config_target, strict: false)
2892           if target_module_ss.sources() != []
2893             module_name = d + '-' + m + '-' + config_target['TARGET_NAME']
2894             sl = static_library(module_name,
2895                                 [genh, target_module_ss.sources()],
2896                                 dependencies: [modulecommon, target_module_ss.dependencies()],
2897                                 include_directories: target_inc,
2898                                 c_args: c_args,
2899                                 pic: true)
2900             softmmu_mods += sl
2901             # FIXME: Should use sl.extract_all_objects(recursive: true) too.
2902             modinfo_files += custom_target(module_name + '.modinfo',
2903                                            output: module_name + '.modinfo',
2904                                            input: target_module_ss.sources() + genh,
2905                                            capture: true,
2906                                            command: [modinfo_collect, '--target', target, target_module_ss.sources()])
2907           endif
2908         endif
2909       endforeach
2910     else
2911       specific_ss.add_all(module_ss)
2912     endif
2913   endforeach
2914 endforeach
2916 if enable_modules
2917   modinfo_src = custom_target('modinfo.c',
2918                               output: 'modinfo.c',
2919                               input: modinfo_files,
2920                               command: [modinfo_generate, '@INPUT@'],
2921                               capture: true)
2922   modinfo_lib = static_library('modinfo', modinfo_src)
2923   modinfo_dep = declare_dependency(link_whole: modinfo_lib)
2924   softmmu_ss.add(modinfo_dep)
2925 endif
2927 nm = find_program('nm')
2928 undefsym = find_program('scripts/undefsym.py')
2929 block_syms = custom_target('block.syms', output: 'block.syms',
2930                              input: [libqemuutil, block_mods],
2931                              capture: true,
2932                              command: [undefsym, nm, '@INPUT@'])
2933 qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
2934                              input: [libqemuutil, softmmu_mods],
2935                              capture: true,
2936                              command: [undefsym, nm, '@INPUT@'])
2938 qom_ss = qom_ss.apply(config_host, strict: false)
2939 libqom = static_library('qom', qom_ss.sources() + genh,
2940                         dependencies: [qom_ss.dependencies()],
2941                         name_suffix: 'fa')
2943 qom = declare_dependency(link_whole: libqom)
2945 authz_ss = authz_ss.apply(config_host, strict: false)
2946 libauthz = static_library('authz', authz_ss.sources() + genh,
2947                           dependencies: [authz_ss.dependencies()],
2948                           name_suffix: 'fa',
2949                           build_by_default: false)
2951 authz = declare_dependency(link_whole: libauthz,
2952                            dependencies: qom)
2954 crypto_ss = crypto_ss.apply(config_host, strict: false)
2955 libcrypto = static_library('crypto', crypto_ss.sources() + genh,
2956                            dependencies: [crypto_ss.dependencies()],
2957                            name_suffix: 'fa',
2958                            build_by_default: false)
2960 crypto = declare_dependency(link_whole: libcrypto,
2961                             dependencies: [authz, qom])
2963 io_ss = io_ss.apply(config_host, strict: false)
2964 libio = static_library('io', io_ss.sources() + genh,
2965                        dependencies: [io_ss.dependencies()],
2966                        link_with: libqemuutil,
2967                        name_suffix: 'fa',
2968                        build_by_default: false)
2970 io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
2972 libmigration = static_library('migration', sources: migration_files + genh,
2973                               name_suffix: 'fa',
2974                               build_by_default: false)
2975 migration = declare_dependency(link_with: libmigration,
2976                                dependencies: [zlib, qom, io])
2977 softmmu_ss.add(migration)
2979 block_ss = block_ss.apply(config_host, strict: false)
2980 libblock = static_library('block', block_ss.sources() + genh,
2981                           dependencies: block_ss.dependencies(),
2982                           link_depends: block_syms,
2983                           name_suffix: 'fa',
2984                           build_by_default: false)
2986 block = declare_dependency(link_whole: [libblock],
2987                            link_args: '@block.syms',
2988                            dependencies: [crypto, io])
2990 blockdev_ss = blockdev_ss.apply(config_host, strict: false)
2991 libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
2992                              dependencies: blockdev_ss.dependencies(),
2993                              name_suffix: 'fa',
2994                              build_by_default: false)
2996 blockdev = declare_dependency(link_whole: [libblockdev],
2997                               dependencies: [block])
2999 qmp_ss = qmp_ss.apply(config_host, strict: false)
3000 libqmp = static_library('qmp', qmp_ss.sources() + genh,
3001                         dependencies: qmp_ss.dependencies(),
3002                         name_suffix: 'fa',
3003                         build_by_default: false)
3005 qmp = declare_dependency(link_whole: [libqmp])
3007 libchardev = static_library('chardev', chardev_ss.sources() + genh,
3008                             name_suffix: 'fa',
3009                             dependencies: [gnutls],
3010                             build_by_default: false)
3012 chardev = declare_dependency(link_whole: libchardev)
3014 hwcore_ss = hwcore_ss.apply(config_host, strict: false)
3015 libhwcore = static_library('hwcore', sources: hwcore_ss.sources() + genh,
3016                            name_suffix: 'fa',
3017                            build_by_default: false)
3018 hwcore = declare_dependency(link_whole: libhwcore)
3019 common_ss.add(hwcore)
3021 ###########
3022 # Targets #
3023 ###########
3025 emulator_modules = []
3026 foreach m : block_mods + softmmu_mods
3027   emulator_modules += shared_module(m.name(),
3028                 build_by_default: true,
3029                 name_prefix: '',
3030                 link_whole: m,
3031                 install: true,
3032                 install_dir: qemu_moddir)
3033 endforeach
3035 softmmu_ss.add(authz, blockdev, chardev, crypto, io, qmp)
3036 common_ss.add(qom, qemuutil)
3038 common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
3039 common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
3041 common_all = common_ss.apply(config_all, strict: false)
3042 common_all = static_library('common',
3043                             build_by_default: false,
3044                             sources: common_all.sources() + genh,
3045                             include_directories: common_user_inc,
3046                             implicit_include_directories: false,
3047                             dependencies: common_all.dependencies(),
3048                             name_suffix: 'fa')
3050 feature_to_c = find_program('scripts/feature_to_c.sh')
3052 emulators = {}
3053 foreach target : target_dirs
3054   config_target = config_target_mak[target]
3055   target_name = config_target['TARGET_NAME']
3056   target_base_arch = config_target['TARGET_BASE_ARCH']
3057   arch_srcs = [config_target_h[target]]
3058   arch_deps = []
3059   c_args = ['-DNEED_CPU_H',
3060             '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3061             '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3062   link_args = emulator_link_args
3064   config_target += config_host
3065   target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3066   if targetos == 'linux'
3067     target_inc += include_directories('linux-headers', is_system: true)
3068   endif
3069   if target.endswith('-softmmu')
3070     qemu_target_name = 'qemu-system-' + target_name
3071     target_type='system'
3072     t = target_softmmu_arch[target_base_arch].apply(config_target, strict: false)
3073     arch_srcs += t.sources()
3074     arch_deps += t.dependencies()
3076     hw_dir = target_name == 'sparc64' ? 'sparc64' : target_base_arch
3077     hw = hw_arch[hw_dir].apply(config_target, strict: false)
3078     arch_srcs += hw.sources()
3079     arch_deps += hw.dependencies()
3081     arch_srcs += config_devices_h[target]
3082     link_args += ['@block.syms', '@qemu.syms']
3083   else
3084     abi = config_target['TARGET_ABI_DIR']
3085     target_type='user'
3086     target_inc += common_user_inc
3087     qemu_target_name = 'qemu-' + target_name
3088     if target_base_arch in target_user_arch
3089       t = target_user_arch[target_base_arch].apply(config_target, strict: false)
3090       arch_srcs += t.sources()
3091       arch_deps += t.dependencies()
3092     endif
3093     if 'CONFIG_LINUX_USER' in config_target
3094       base_dir = 'linux-user'
3095     endif
3096     if 'CONFIG_BSD_USER' in config_target
3097       base_dir = 'bsd-user'
3098       target_inc += include_directories('bsd-user/' / targetos)
3099       target_inc += include_directories('bsd-user/host/' / host_arch)
3100       dir = base_dir / abi
3101       arch_srcs += files(dir / 'signal.c', dir / 'target_arch_cpu.c')
3102     endif
3103     target_inc += include_directories(
3104       base_dir,
3105       base_dir / abi,
3106     )
3107     if 'CONFIG_LINUX_USER' in config_target
3108       dir = base_dir / abi
3109       arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
3110       if config_target.has_key('TARGET_SYSTBL_ABI')
3111         arch_srcs += \
3112           syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
3113                                              extra_args : config_target['TARGET_SYSTBL_ABI'])
3114       endif
3115     endif
3116   endif
3118   if 'TARGET_XML_FILES' in config_target
3119     gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
3120                                 output: target + '-gdbstub-xml.c',
3121                                 input: files(config_target['TARGET_XML_FILES'].split()),
3122                                 command: [feature_to_c, '@INPUT@'],
3123                                 capture: true)
3124     arch_srcs += gdbstub_xml
3125   endif
3127   t = target_arch[target_base_arch].apply(config_target, strict: false)
3128   arch_srcs += t.sources()
3129   arch_deps += t.dependencies()
3131   target_common = common_ss.apply(config_target, strict: false)
3132   objects = common_all.extract_objects(target_common.sources())
3133   deps = target_common.dependencies()
3135   target_specific = specific_ss.apply(config_target, strict: false)
3136   arch_srcs += target_specific.sources()
3137   arch_deps += target_specific.dependencies()
3139   lib = static_library('qemu-' + target,
3140                  sources: arch_srcs + genh,
3141                  dependencies: arch_deps,
3142                  objects: objects,
3143                  include_directories: target_inc,
3144                  c_args: c_args,
3145                  build_by_default: false,
3146                  name_suffix: 'fa')
3148   if target.endswith('-softmmu')
3149     execs = [{
3150       'name': 'qemu-system-' + target_name,
3151       'win_subsystem': 'console',
3152       'sources': files('softmmu/main.c'),
3153       'dependencies': []
3154     }]
3155     if targetos == 'windows' and (sdl.found() or gtk.found())
3156       execs += [{
3157         'name': 'qemu-system-' + target_name + 'w',
3158         'win_subsystem': 'windows',
3159         'sources': files('softmmu/main.c'),
3160         'dependencies': []
3161       }]
3162     endif
3163     if get_option('fuzzing')
3164       specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
3165       execs += [{
3166         'name': 'qemu-fuzz-' + target_name,
3167         'win_subsystem': 'console',
3168         'sources': specific_fuzz.sources(),
3169         'dependencies': specific_fuzz.dependencies(),
3170       }]
3171     endif
3172   else
3173     execs = [{
3174       'name': 'qemu-' + target_name,
3175       'win_subsystem': 'console',
3176       'sources': [],
3177       'dependencies': []
3178     }]
3179   endif
3180   foreach exe: execs
3181     exe_name = exe['name']
3182     if targetos == 'darwin'
3183       exe_name += '-unsigned'
3184     endif
3186     emulator = executable(exe_name, exe['sources'],
3187                install: true,
3188                c_args: c_args,
3189                dependencies: arch_deps + deps + exe['dependencies'],
3190                objects: lib.extract_all_objects(recursive: true),
3191                link_language: link_language,
3192                link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
3193                link_args: link_args,
3194                win_subsystem: exe['win_subsystem'])
3196     if targetos == 'darwin'
3197       icon = 'pc-bios/qemu.rsrc'
3198       build_input = [emulator, files(icon)]
3199       install_input = [
3200         get_option('bindir') / exe_name,
3201         meson.current_source_dir() / icon
3202       ]
3203       if 'CONFIG_HVF' in config_target
3204         entitlements = 'accel/hvf/entitlements.plist'
3205         build_input += files(entitlements)
3206         install_input += meson.current_source_dir() / entitlements
3207       endif
3209       entitlement = find_program('scripts/entitlement.sh')
3210       emulators += {exe['name'] : custom_target(exe['name'],
3211                    input: build_input,
3212                    output: exe['name'],
3213                    command: [entitlement, '@OUTPUT@', '@INPUT@'])
3214       }
3216       meson.add_install_script(entitlement, '--install',
3217                                get_option('bindir') / exe['name'],
3218                                install_input)
3219     else
3220       emulators += {exe['name']: emulator}
3221     endif
3223     if stap.found()
3224       foreach stp: [
3225         {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
3226         {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
3227         {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
3228         {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
3229       ]
3230         custom_target(exe['name'] + stp['ext'],
3231                       input: trace_events_all,
3232                       output: exe['name'] + stp['ext'],
3233                       install: stp['install'],
3234                       install_dir: get_option('datadir') / 'systemtap/tapset',
3235                       command: [
3236                         tracetool, '--group=all', '--format=' + stp['fmt'],
3237                         '--binary=' + stp['bin'],
3238                         '--target-name=' + target_name,
3239                         '--target-type=' + target_type,
3240                         '--probe-prefix=qemu.' + target_type + '.' + target_name,
3241                         '@INPUT@', '@OUTPUT@'
3242                       ],
3243                       depend_files: tracetool_depends)
3244       endforeach
3245     endif
3246   endforeach
3247 endforeach
3249 # Other build targets
3251 if 'CONFIG_PLUGIN' in config_host
3252   install_headers('include/qemu/qemu-plugin.h')
3253 endif
3255 subdir('qga')
3257 # Don't build qemu-keymap if xkbcommon is not explicitly enabled
3258 # when we don't build tools or system
3259 if xkbcommon.found()
3260   # used for the update-keymaps target, so include rules even if !have_tools
3261   qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
3262                            dependencies: [qemuutil, xkbcommon], install: have_tools)
3263 endif
3265 if have_tools
3266   qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
3267              dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
3268   qemu_io = executable('qemu-io', files('qemu-io.c'),
3269              dependencies: [block, qemuutil], install: true)
3270   qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
3271                dependencies: [blockdev, qemuutil, gnutls, selinux],
3272                install: true)
3274   subdir('storage-daemon')
3275   subdir('contrib/rdmacm-mux')
3276   subdir('contrib/elf2dmp')
3278   executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
3279              dependencies: qemuutil,
3280              install: true)
3282   if 'CONFIG_VHOST_USER' in config_host
3283     subdir('contrib/vhost-user-blk')
3284     subdir('contrib/vhost-user-gpu')
3285     subdir('contrib/vhost-user-input')
3286     subdir('contrib/vhost-user-scsi')
3287   endif
3289   if targetos == 'linux'
3290     executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
3291                dependencies: [qemuutil, libcap_ng],
3292                install: true,
3293                install_dir: get_option('libexecdir'))
3295     executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
3296                dependencies: [authz, crypto, io, qom, qemuutil,
3297                               libcap_ng, mpathpersist],
3298                install: true)
3299   endif
3301   if have_ivshmem
3302     subdir('contrib/ivshmem-client')
3303     subdir('contrib/ivshmem-server')
3304   endif
3305 endif
3307 subdir('scripts')
3308 subdir('tools')
3309 subdir('pc-bios')
3310 subdir('docs')
3311 subdir('tests')
3312 if gtk.found()
3313   subdir('po')
3314 endif
3316 if host_machine.system() == 'windows'
3317   nsis_cmd = [
3318     find_program('scripts/nsis.py'),
3319     '@OUTPUT@',
3320     get_option('prefix'),
3321     meson.current_source_dir(),
3322     host_machine.cpu(),
3323     '--',
3324     '-DDISPLAYVERSION=' + meson.project_version(),
3325   ]
3326   if build_docs
3327     nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
3328   endif
3329   if gtk.found()
3330     nsis_cmd += '-DCONFIG_GTK=y'
3331   endif
3333   nsis = custom_target('nsis',
3334                        output: 'qemu-setup-' + meson.project_version() + '.exe',
3335                        input: files('qemu.nsi'),
3336                        build_always_stale: true,
3337                        command: nsis_cmd + ['@INPUT@'])
3338   alias_target('installer', nsis)
3339 endif
3341 #########################
3342 # Configuration summary #
3343 #########################
3345 # Directories
3346 summary_info = {}
3347 summary_info += {'Install prefix':    get_option('prefix')}
3348 summary_info += {'BIOS directory':    qemu_datadir}
3349 summary_info += {'firmware path':     get_option('qemu_firmwarepath')}
3350 summary_info += {'binary directory':  get_option('bindir')}
3351 summary_info += {'library directory': get_option('libdir')}
3352 summary_info += {'module directory':  qemu_moddir}
3353 summary_info += {'libexec directory': get_option('libexecdir')}
3354 summary_info += {'include directory': get_option('includedir')}
3355 summary_info += {'config directory':  get_option('sysconfdir')}
3356 if targetos != 'windows'
3357   summary_info += {'local state directory': get_option('localstatedir')}
3358   summary_info += {'Manual directory':      get_option('mandir')}
3359 else
3360   summary_info += {'local state directory': 'queried at runtime'}
3361 endif
3362 summary_info += {'Doc directory':     get_option('docdir')}
3363 summary_info += {'Build directory':   meson.current_build_dir()}
3364 summary_info += {'Source path':       meson.current_source_dir()}
3365 summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
3366 summary(summary_info, bool_yn: true, section: 'Directories')
3368 # Host binaries
3369 summary_info = {}
3370 summary_info += {'git':               config_host['GIT']}
3371 summary_info += {'make':              config_host['MAKE']}
3372 summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
3373 summary_info += {'sphinx-build':      sphinx_build}
3374 if config_host.has_key('HAVE_GDB_BIN')
3375   summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
3376 endif
3377 if get_option('iasl') != ''
3378   summary_info += {'iasl':            get_option('iasl')}
3379 else
3380   summary_info += {'iasl':            false}
3381 endif
3382 summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
3383 if targetos == 'windows' and have_ga
3384   summary_info += {'wixl':            wixl}
3385 endif
3386 if slirp_opt != 'disabled' and have_system
3387   summary_info += {'smbd':            have_slirp_smbd ? smbd_path : false}
3388 endif
3389 summary(summary_info, bool_yn: true, section: 'Host binaries')
3391 # Configurable features
3392 summary_info = {}
3393 summary_info += {'Documentation':     build_docs}
3394 summary_info += {'system-mode emulation': have_system}
3395 summary_info += {'user-mode emulation': have_user}
3396 summary_info += {'block layer':       have_block}
3397 summary_info += {'Install blobs':     get_option('install_blobs')}
3398 summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
3399 if config_host.has_key('CONFIG_MODULES')
3400   summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')}
3401 endif
3402 summary_info += {'fuzzing support':   get_option('fuzzing')}
3403 if have_system
3404   summary_info += {'Audio drivers':     ' '.join(audio_drivers_selected)}
3405 endif
3406 summary_info += {'Trace backends':    ','.join(get_option('trace_backends'))}
3407 if 'simple' in get_option('trace_backends')
3408   summary_info += {'Trace output file': get_option('trace_file') + '-<pid>'}
3409 endif
3410 summary_info += {'D-Bus display':     dbus_display}
3411 summary_info += {'QOM debugging':     get_option('qom_cast_debug')}
3412 summary_info += {'vhost-kernel support': config_host.has_key('CONFIG_VHOST_KERNEL')}
3413 summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')}
3414 summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')}
3415 summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')}
3416 summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')}
3417 summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_USER')}
3418 summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
3419 summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')}
3420 summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')}
3421 summary_info += {'build guest agent': have_ga}
3422 summary(summary_info, bool_yn: true, section: 'Configurable features')
3424 # Compilation information
3425 summary_info = {}
3426 summary_info += {'host CPU':          cpu}
3427 summary_info += {'host endianness':   build_machine.endian()}
3428 summary_info += {'C compiler':        ' '.join(meson.get_compiler('c').cmd_array())}
3429 summary_info += {'Host C compiler':   ' '.join(meson.get_compiler('c', native: true).cmd_array())}
3430 if link_language == 'cpp'
3431   summary_info += {'C++ compiler':    ' '.join(meson.get_compiler('cpp').cmd_array())}
3432 else
3433   summary_info += {'C++ compiler':      false}
3434 endif
3435 if targetos == 'darwin'
3436   summary_info += {'Objective-C compiler': ' '.join(meson.get_compiler('objc').cmd_array())}
3437 endif
3438 summary_info += {'CFLAGS':            ' '.join(get_option('c_args')
3439                                                + ['-O' + get_option('optimization')]
3440                                                + (get_option('debug') ? ['-g'] : []))}
3441 if link_language == 'cpp'
3442   summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args')
3443                                                + ['-O' + get_option('optimization')]
3444                                                + (get_option('debug') ? ['-g'] : []))}
3445 endif
3446 link_args = get_option(link_language + '_link_args')
3447 if link_args.length() > 0
3448   summary_info += {'LDFLAGS':         ' '.join(link_args)}
3449 endif
3450 summary_info += {'QEMU_CFLAGS':       config_host['QEMU_CFLAGS']}
3451 summary_info += {'QEMU_LDFLAGS':      config_host['QEMU_LDFLAGS']}
3452 summary_info += {'profiler':          get_option('profiler')}
3453 summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
3454 summary_info += {'PIE':               get_option('b_pie')}
3455 summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
3456 summary_info += {'malloc trim support': has_malloc_trim}
3457 summary_info += {'membarrier':        have_membarrier}
3458 summary_info += {'debug stack usage': get_option('debug_stack_usage')}
3459 summary_info += {'mutex debugging':   get_option('debug_mutex')}
3460 summary_info += {'memory allocator':  get_option('malloc')}
3461 summary_info += {'avx2 optimization': config_host_data.get('CONFIG_AVX2_OPT')}
3462 summary_info += {'avx512f optimization': config_host_data.get('CONFIG_AVX512F_OPT')}
3463 summary_info += {'gprof enabled':     get_option('gprof')}
3464 summary_info += {'gcov':              get_option('b_coverage')}
3465 summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
3466 summary_info += {'CFI support':       get_option('cfi')}
3467 if get_option('cfi')
3468   summary_info += {'CFI debug support': get_option('cfi_debug')}
3469 endif
3470 summary_info += {'strip binaries':    get_option('strip')}
3471 summary_info += {'sparse':            sparse}
3472 summary_info += {'mingw32 support':   targetos == 'windows'}
3474 # snarf the cross-compilation information for tests
3475 foreach target: target_dirs
3476   tcg_mak = meson.current_build_dir() / 'tests/tcg' / 'config-' + target + '.mak'
3477   if fs.exists(tcg_mak)
3478     config_cross_tcg = keyval.load(tcg_mak)
3479     target = config_cross_tcg['TARGET_NAME']
3480     compiler = ''
3481     if 'DOCKER_CROSS_CC_GUEST' in config_cross_tcg
3482       summary_info += {target + ' tests': config_cross_tcg['DOCKER_CROSS_CC_GUEST'] +
3483                                           ' via ' + config_cross_tcg['DOCKER_IMAGE']}
3484     elif 'CROSS_CC_GUEST' in config_cross_tcg
3485       summary_info += {target + ' tests'
3486                                 : config_cross_tcg['CROSS_CC_GUEST'] }
3487     endif
3488    endif
3489 endforeach
3491 summary(summary_info, bool_yn: true, section: 'Compilation')
3493 # Targets and accelerators
3494 summary_info = {}
3495 if have_system
3496   summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
3497   summary_info += {'HAX support':       config_all.has_key('CONFIG_HAX')}
3498   summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
3499   summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
3500   summary_info += {'NVMM support':      config_all.has_key('CONFIG_NVMM')}
3501   summary_info += {'Xen support':       config_host.has_key('CONFIG_XEN_BACKEND')}
3502   if config_host.has_key('CONFIG_XEN_BACKEND')
3503     summary_info += {'xen ctrl version':  config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
3504   endif
3505 endif
3506 summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
3507 if config_all.has_key('CONFIG_TCG')
3508   if get_option('tcg_interpreter')
3509     summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, slow)'}
3510   else
3511     summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
3512   endif
3513   summary_info += {'TCG plugins': config_host.has_key('CONFIG_PLUGIN')}
3514   summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
3515 endif
3516 summary_info += {'target list':       ' '.join(target_dirs)}
3517 if have_system
3518   summary_info += {'default devices':   get_option('default_devices')}
3519   summary_info += {'out of process emulation': multiprocess_allowed}
3520 endif
3521 summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
3523 # Block layer
3524 summary_info = {}
3525 summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
3526 summary_info += {'coroutine pool':    have_coroutine_pool}
3527 if have_block
3528   summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']}
3529   summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']}
3530   summary_info += {'Use block whitelist in tools': get_option('block_drv_whitelist_in_tools')}
3531   summary_info += {'VirtFS support':    have_virtfs}
3532   summary_info += {'build virtiofs daemon': have_virtiofsd}
3533   summary_info += {'Live block migration': config_host_data.get('CONFIG_LIVE_BLOCK_MIGRATION')}
3534   summary_info += {'replication support': config_host_data.get('CONFIG_REPLICATION')}
3535   summary_info += {'bochs support':     get_option('bochs').allowed()}
3536   summary_info += {'cloop support':     get_option('cloop').allowed()}
3537   summary_info += {'dmg support':       get_option('dmg').allowed()}
3538   summary_info += {'qcow v1 support':   get_option('qcow1').allowed()}
3539   summary_info += {'vdi support':       get_option('vdi').allowed()}
3540   summary_info += {'vvfat support':     get_option('vvfat').allowed()}
3541   summary_info += {'qed support':       get_option('qed').allowed()}
3542   summary_info += {'parallels support': get_option('parallels').allowed()}
3543   summary_info += {'FUSE exports':      fuse}
3544 endif
3545 summary(summary_info, bool_yn: true, section: 'Block layer support')
3547 # Crypto
3548 summary_info = {}
3549 summary_info += {'TLS priority':      config_host['CONFIG_TLS_PRIORITY']}
3550 summary_info += {'GNUTLS support':    gnutls}
3551 if gnutls.found()
3552   summary_info += {'  GNUTLS crypto':   gnutls_crypto.found()}
3553 endif
3554 summary_info += {'libgcrypt':         gcrypt}
3555 summary_info += {'nettle':            nettle}
3556 if nettle.found()
3557    summary_info += {'  XTS':             xts != 'private'}
3558 endif
3559 summary_info += {'AF_ALG support':    have_afalg}
3560 summary_info += {'rng-none':          get_option('rng_none')}
3561 summary_info += {'Linux keyring':     config_host.has_key('CONFIG_SECRET_KEYRING')}
3562 summary(summary_info, bool_yn: true, section: 'Crypto')
3564 # Libraries
3565 summary_info = {}
3566 if targetos == 'darwin'
3567   summary_info += {'Cocoa support':   cocoa}
3568 endif
3569 summary_info += {'SDL support':       sdl}
3570 summary_info += {'SDL image support': sdl_image}
3571 summary_info += {'GTK support':       gtk}
3572 summary_info += {'pixman':            pixman}
3573 summary_info += {'VTE support':       vte}
3574 summary_info += {'slirp support':     slirp_opt == 'internal' ? slirp_opt : slirp}
3575 summary_info += {'libtasn1':          tasn1}
3576 summary_info += {'PAM':               pam}
3577 summary_info += {'iconv support':     iconv}
3578 summary_info += {'curses support':    curses}
3579 summary_info += {'virgl support':     virgl}
3580 summary_info += {'curl support':      curl}
3581 summary_info += {'Multipath support': mpathpersist}
3582 summary_info += {'VNC support':       vnc}
3583 if vnc.found()
3584   summary_info += {'VNC SASL support':  sasl}
3585   summary_info += {'VNC JPEG support':  jpeg}
3586   summary_info += {'VNC PNG support':   png}
3587 endif
3588 if targetos not in ['darwin', 'haiku', 'windows']
3589   summary_info += {'OSS support':     oss}
3590 elif targetos == 'darwin'
3591   summary_info += {'CoreAudio support': coreaudio}
3592 elif targetos == 'windows'
3593   summary_info += {'DirectSound support': dsound}
3594 endif
3595 if targetos == 'linux'
3596   summary_info += {'ALSA support':    alsa}
3597   summary_info += {'PulseAudio support': pulse}
3598 endif
3599 summary_info += {'JACK support':      jack}
3600 summary_info += {'brlapi support':    brlapi}
3601 summary_info += {'vde support':       vde}
3602 summary_info += {'netmap support':    have_netmap}
3603 summary_info += {'l2tpv3 support':    have_l2tpv3}
3604 summary_info += {'Linux AIO support': libaio}
3605 summary_info += {'Linux io_uring support': linux_io_uring}
3606 summary_info += {'ATTR/XATTR support': libattr}
3607 summary_info += {'RDMA support':      config_host.has_key('CONFIG_RDMA')}
3608 summary_info += {'PVRDMA support':    config_host.has_key('CONFIG_PVRDMA')}
3609 summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
3610 summary_info += {'libcap-ng support': libcap_ng}
3611 summary_info += {'bpf support':       libbpf}
3612 summary_info += {'spice protocol support': spice_protocol}
3613 if spice_protocol.found()
3614   summary_info += {'  spice server support': spice}
3615 endif
3616 summary_info += {'rbd support':       rbd}
3617 summary_info += {'smartcard support': cacard}
3618 summary_info += {'U2F support':       u2f}
3619 summary_info += {'libusb':            libusb}
3620 summary_info += {'usb net redir':     usbredir}
3621 summary_info += {'OpenGL support':    config_host.has_key('CONFIG_OPENGL')}
3622 summary_info += {'GBM':               gbm}
3623 summary_info += {'libiscsi support':  libiscsi}
3624 summary_info += {'libnfs support':    libnfs}
3625 if targetos == 'windows'
3626   if have_ga
3627     summary_info += {'QGA VSS support':   have_qga_vss}
3628     summary_info += {'QGA w32 disk info': have_ntddscsi}
3629   endif
3630 endif
3631 summary_info += {'seccomp support':   seccomp}
3632 summary_info += {'GlusterFS support': glusterfs}
3633 summary_info += {'TPM support':       have_tpm}
3634 summary_info += {'libssh support':    libssh}
3635 summary_info += {'lzo support':       lzo}
3636 summary_info += {'snappy support':    snappy}
3637 summary_info += {'bzip2 support':     libbzip2}
3638 summary_info += {'lzfse support':     liblzfse}
3639 summary_info += {'zstd support':      zstd}
3640 summary_info += {'NUMA host support': numa}
3641 summary_info += {'capstone':          capstone_opt == 'internal' ? capstone_opt : capstone}
3642 summary_info += {'libpmem support':   libpmem}
3643 summary_info += {'libdaxctl support': libdaxctl}
3644 summary_info += {'libudev':           libudev}
3645 # Dummy dependency, keep .found()
3646 summary_info += {'FUSE lseek':        fuse_lseek.found()}
3647 summary_info += {'selinux':           selinux}
3648 summary(summary_info, bool_yn: true, section: 'Dependencies')
3650 if not supported_cpus.contains(cpu)
3651   message()
3652   warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
3653   message()
3654   message('CPU host architecture ' + cpu + ' support is not currently maintained.')
3655   message('The QEMU project intends to remove support for this host CPU in')
3656   message('a future release if nobody volunteers to maintain it and to')
3657   message('provide a build host for our continuous integration setup.')
3658   message('configure has succeeded and you can continue to build, but')
3659   message('if you care about QEMU on this platform you should contact')
3660   message('us upstream at qemu-devel@nongnu.org.')
3661 endif
3663 if not supported_oses.contains(targetos)
3664   message()
3665   warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
3666   message()
3667   message('Host OS ' + targetos + 'support is not currently maintained.')
3668   message('The QEMU project intends to remove support for this host OS in')
3669   message('a future release if nobody volunteers to maintain it and to')
3670   message('provide a build host for our continuous integration setup.')
3671   message('configure has succeeded and you can continue to build, but')
3672   message('if you care about QEMU on this platform you should contact')
3673   message('us upstream at qemu-devel@nongnu.org.')
3674 endif