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