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