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