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