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