Merge remote-tracking branch 'remotes/rth-gitlab/tags/pull-nios-20220303' into staging
[qemu/rayw.git] / meson.build
blob038502714ab942cf4b75277360a7a28c6bc9829a
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 config_host_data.set('CONFIG_POSIX_MEMALIGN', cc.has_function('posix_memalign'))
1623 config_host_data.set('CONFIG_PPOLL', cc.has_function('ppoll'))
1624 config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include <sys/uio.h>'))
1625 config_host_data.set('CONFIG_SEM_TIMEDWAIT', cc.has_function('sem_timedwait', dependencies: threads))
1626 config_host_data.set('CONFIG_SENDFILE', cc.has_function('sendfile'))
1627 config_host_data.set('CONFIG_SETNS', cc.has_function('setns') and cc.has_function('unshare'))
1628 config_host_data.set('CONFIG_SYNCFS', cc.has_function('syncfs'))
1629 config_host_data.set('CONFIG_SYNC_FILE_RANGE', cc.has_function('sync_file_range'))
1630 config_host_data.set('CONFIG_TIMERFD', cc.has_function('timerfd_create'))
1631 config_host_data.set('HAVE_COPY_FILE_RANGE', cc.has_function('copy_file_range'))
1632 config_host_data.set('HAVE_OPENPTY', cc.has_function('openpty', dependencies: util))
1633 config_host_data.set('HAVE_STRCHRNUL', cc.has_function('strchrnul'))
1634 config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: '#include <stdlib.h>'))
1635 if rdma.found()
1636   config_host_data.set('HAVE_IBV_ADVISE_MR',
1637                        cc.has_function('ibv_advise_mr',
1638                                        args: config_host['RDMA_LIBS'].split(),
1639                                        prefix: '#include <infiniband/verbs.h>'))
1640 endif
1642 # has_header_symbol
1643 config_host_data.set('CONFIG_BYTESWAP_H',
1644                      cc.has_header_symbol('byteswap.h', 'bswap_32'))
1645 config_host_data.set('CONFIG_EPOLL_CREATE1',
1646                      cc.has_header_symbol('sys/epoll.h', 'epoll_create1'))
1647 config_host_data.set('CONFIG_HAS_ENVIRON',
1648                      cc.has_header_symbol('unistd.h', 'environ', prefix: gnu_source_prefix))
1649 config_host_data.set('CONFIG_FALLOCATE_PUNCH_HOLE',
1650                      cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_PUNCH_HOLE') and
1651                      cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_KEEP_SIZE'))
1652 config_host_data.set('CONFIG_FALLOCATE_ZERO_RANGE',
1653                      cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_ZERO_RANGE'))
1654 config_host_data.set('CONFIG_FIEMAP',
1655                      cc.has_header('linux/fiemap.h') and
1656                      cc.has_header_symbol('linux/fs.h', 'FS_IOC_FIEMAP'))
1657 config_host_data.set('CONFIG_GETRANDOM',
1658                      cc.has_function('getrandom') and
1659                      cc.has_header_symbol('sys/random.h', 'GRND_NONBLOCK'))
1660 config_host_data.set('CONFIG_INOTIFY',
1661                      cc.has_header_symbol('sys/inotify.h', 'inotify_init'))
1662 config_host_data.set('CONFIG_INOTIFY1',
1663                      cc.has_header_symbol('sys/inotify.h', 'inotify_init1'))
1664 config_host_data.set('CONFIG_MACHINE_BSWAP_H',
1665                      cc.has_header_symbol('machine/bswap.h', 'bswap32',
1666                                           prefix: '''#include <sys/endian.h>
1667                                                      #include <sys/types.h>'''))
1668 config_host_data.set('CONFIG_PRCTL_PR_SET_TIMERSLACK',
1669                      cc.has_header_symbol('sys/prctl.h', 'PR_SET_TIMERSLACK'))
1670 config_host_data.set('CONFIG_RTNETLINK',
1671                      cc.has_header_symbol('linux/rtnetlink.h', 'IFLA_PROTO_DOWN'))
1672 config_host_data.set('CONFIG_SYSMACROS',
1673                      cc.has_header_symbol('sys/sysmacros.h', 'makedev'))
1674 config_host_data.set('HAVE_OPTRESET',
1675                      cc.has_header_symbol('getopt.h', 'optreset'))
1676 config_host_data.set('HAVE_IPPROTO_MPTCP',
1677                      cc.has_header_symbol('netinet/in.h', 'IPPROTO_MPTCP'))
1679 # has_member
1680 config_host_data.set('HAVE_SIGEV_NOTIFY_THREAD_ID',
1681                      cc.has_member('struct sigevent', 'sigev_notify_thread_id',
1682                                    prefix: '#include <signal.h>'))
1683 config_host_data.set('HAVE_STRUCT_STAT_ST_ATIM',
1684                      cc.has_member('struct stat', 'st_atim',
1685                                    prefix: '#include <sys/stat.h>'))
1687 # has_type
1688 config_host_data.set('CONFIG_IOVEC',
1689                      cc.has_type('struct iovec',
1690                                  prefix: '#include <sys/uio.h>'))
1691 config_host_data.set('HAVE_UTMPX',
1692                      cc.has_type('struct utmpx',
1693                                  prefix: '#include <utmpx.h>'))
1695 config_host_data.set('CONFIG_EVENTFD', cc.links('''
1696   #include <sys/eventfd.h>
1697   int main(void) { return eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); }'''))
1698 config_host_data.set('CONFIG_FDATASYNC', cc.links(gnu_source_prefix + '''
1699   #include <unistd.h>
1700   int main(void) {
1701   #if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
1702   return fdatasync(0);
1703   #else
1704   #error Not supported
1705   #endif
1706   }'''))
1707 config_host_data.set('CONFIG_MADVISE', cc.links(gnu_source_prefix + '''
1708   #include <sys/types.h>
1709   #include <sys/mman.h>
1710   #include <stddef.h>
1711   int main(void) { return madvise(NULL, 0, MADV_DONTNEED); }'''))
1712 config_host_data.set('CONFIG_MEMFD', cc.links(gnu_source_prefix + '''
1713   #include <sys/mman.h>
1714   int main(void) { return memfd_create("foo", MFD_ALLOW_SEALING); }'''))
1715 config_host_data.set('CONFIG_OPEN_BY_HANDLE', cc.links(gnu_source_prefix + '''
1716   #include <fcntl.h>
1717   #if !defined(AT_EMPTY_PATH)
1718   # error missing definition
1719   #else
1720   int main(void) { struct file_handle fh; return open_by_handle_at(0, &fh, 0); }
1721   #endif'''))
1722 config_host_data.set('CONFIG_PIPE2', cc.links(gnu_source_prefix + '''
1723   #include <unistd.h>
1724   #include <fcntl.h>
1726   int main(void)
1727   {
1728       int pipefd[2];
1729       return pipe2(pipefd, O_CLOEXEC);
1730   }'''))
1731 config_host_data.set('CONFIG_POSIX_MADVISE', cc.links(gnu_source_prefix + '''
1732   #include <sys/mman.h>
1733   #include <stddef.h>
1734   int main(void) { return posix_madvise(NULL, 0, POSIX_MADV_DONTNEED); }'''))
1736 config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_W_TID', cc.links(gnu_source_prefix + '''
1737   #include <pthread.h>
1739   static void *f(void *p) { return NULL; }
1740   int main(void)
1741   {
1742     pthread_t thread;
1743     pthread_create(&thread, 0, f, 0);
1744     pthread_setname_np(thread, "QEMU");
1745     return 0;
1746   }''', dependencies: threads))
1747 config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_WO_TID', cc.links(gnu_source_prefix + '''
1748   #include <pthread.h>
1750   static void *f(void *p) { pthread_setname_np("QEMU"); return NULL; }
1751   int main(void)
1752   {
1753     pthread_t thread;
1754     pthread_create(&thread, 0, f, 0);
1755     return 0;
1756   }''', dependencies: threads))
1758 config_host_data.set('CONFIG_SIGNALFD', cc.links(gnu_source_prefix + '''
1759   #include <sys/signalfd.h>
1760   #include <stddef.h>
1761   int main(void) { return signalfd(-1, NULL, SFD_CLOEXEC); }'''))
1762 config_host_data.set('CONFIG_SPLICE', cc.links(gnu_source_prefix + '''
1763   #include <unistd.h>
1764   #include <fcntl.h>
1765   #include <limits.h>
1767   int main(void)
1768   {
1769     int len, fd = 0;
1770     len = tee(STDIN_FILENO, STDOUT_FILENO, INT_MAX, SPLICE_F_NONBLOCK);
1771     splice(STDIN_FILENO, NULL, fd, NULL, len, SPLICE_F_MOVE);
1772     return 0;
1773   }'''))
1775 config_host_data.set('HAVE_MLOCKALL', cc.links(gnu_source_prefix + '''
1776   #include <sys/mman.h>
1777   int main(int argc, char *argv[]) {
1778     return mlockall(MCL_FUTURE);
1779   }'''))
1781 have_l2tpv3 = false
1782 if get_option('l2tpv3').allowed() and have_system
1783   have_l2tpv3 = cc.has_type('struct mmsghdr',
1784     prefix: gnu_source_prefix + '''
1785       #include <sys/socket.h>
1786       #include <linux/ip.h>''')
1787 endif
1788 config_host_data.set('CONFIG_L2TPV3', have_l2tpv3)
1790 have_netmap = false
1791 if get_option('netmap').allowed() and have_system
1792   have_netmap = cc.compiles('''
1793     #include <inttypes.h>
1794     #include <net/if.h>
1795     #include <net/netmap.h>
1796     #include <net/netmap_user.h>
1797     #if (NETMAP_API < 11) || (NETMAP_API > 15)
1798     #error
1799     #endif
1800     int main(void) { return 0; }''')
1801   if not have_netmap and get_option('netmap').enabled()
1802     error('Netmap headers not available')
1803   endif
1804 endif
1805 config_host_data.set('CONFIG_NETMAP', have_netmap)
1807 # Work around a system header bug with some kernel/XFS header
1808 # versions where they both try to define 'struct fsxattr':
1809 # xfs headers will not try to redefine structs from linux headers
1810 # if this macro is set.
1811 config_host_data.set('HAVE_FSXATTR', cc.links('''
1812   #include <linux/fs.h>
1813   struct fsxattr foo;
1814   int main(void) {
1815     return 0;
1816   }'''))
1818 # Some versions of Mac OS X incorrectly define SIZE_MAX
1819 config_host_data.set('HAVE_BROKEN_SIZE_MAX', not cc.compiles('''
1820     #include <stdint.h>
1821     #include <stdio.h>
1822     int main(int argc, char *argv[]) {
1823         return printf("%zu", SIZE_MAX);
1824     }''', args: ['-Werror']))
1826 # See if 64-bit atomic operations are supported.
1827 # Note that without __atomic builtins, we can only
1828 # assume atomic loads/stores max at pointer size.
1829 config_host_data.set('CONFIG_ATOMIC64', cc.links('''
1830   #include <stdint.h>
1831   int main(void)
1832   {
1833     uint64_t x = 0, y = 0;
1834     y = __atomic_load_n(&x, __ATOMIC_RELAXED);
1835     __atomic_store_n(&x, y, __ATOMIC_RELAXED);
1836     __atomic_compare_exchange_n(&x, &y, x, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
1837     __atomic_exchange_n(&x, y, __ATOMIC_RELAXED);
1838     __atomic_fetch_add(&x, y, __ATOMIC_RELAXED);
1839     return 0;
1840   }'''))
1842 config_host_data.set('CONFIG_GETAUXVAL', cc.links(gnu_source_prefix + '''
1843   #include <sys/auxv.h>
1844   int main(void) {
1845     return getauxval(AT_HWCAP) == 0;
1846   }'''))
1848 have_cpuid_h = cc.links('''
1849   #include <cpuid.h>
1850   int main(void) {
1851     unsigned a, b, c, d;
1852     unsigned max = __get_cpuid_max(0, 0);
1854     if (max >= 1) {
1855         __cpuid(1, a, b, c, d);
1856     }
1858     if (max >= 7) {
1859         __cpuid_count(7, 0, a, b, c, d);
1860     }
1862     return 0;
1863   }''')
1864 config_host_data.set('CONFIG_CPUID_H', have_cpuid_h)
1866 config_host_data.set('CONFIG_AVX2_OPT', get_option('avx2') \
1867   .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX2') \
1868   .require(cc.links('''
1869     #pragma GCC push_options
1870     #pragma GCC target("avx2")
1871     #include <cpuid.h>
1872     #include <immintrin.h>
1873     static int bar(void *a) {
1874       __m256i x = *(__m256i *)a;
1875       return _mm256_testz_si256(x, x);
1876     }
1877     int main(int argc, char *argv[]) { return bar(argv[0]); }
1878   '''), error_message: 'AVX2 not available').allowed())
1880 config_host_data.set('CONFIG_AVX512F_OPT', get_option('avx512f') \
1881   .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX512F') \
1882   .require(cc.links('''
1883     #pragma GCC push_options
1884     #pragma GCC target("avx512f")
1885     #include <cpuid.h>
1886     #include <immintrin.h>
1887     static int bar(void *a) {
1888       __m512i x = *(__m512i *)a;
1889       return _mm512_test_epi64_mask(x, x);
1890     }
1891     int main(int argc, char *argv[]) { return bar(argv[0]); }
1892   '''), error_message: 'AVX512F not available').allowed())
1894 if get_option('membarrier').disabled()
1895   have_membarrier = false
1896 elif targetos == 'windows'
1897   have_membarrier = true
1898 elif targetos == 'linux'
1899   have_membarrier = cc.compiles('''
1900     #include <linux/membarrier.h>
1901     #include <sys/syscall.h>
1902     #include <unistd.h>
1903     #include <stdlib.h>
1904     int main(void) {
1905         syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0);
1906         syscall(__NR_membarrier, MEMBARRIER_CMD_SHARED, 0);
1907         exit(0);
1908     }''')
1909 endif
1910 config_host_data.set('CONFIG_MEMBARRIER', get_option('membarrier') \
1911   .require(have_membarrier, error_message: 'membarrier system call not available') \
1912   .allowed())
1914 have_afalg = get_option('crypto_afalg') \
1915   .require(cc.compiles(gnu_source_prefix + '''
1916     #include <errno.h>
1917     #include <sys/types.h>
1918     #include <sys/socket.h>
1919     #include <linux/if_alg.h>
1920     int main(void) {
1921       int sock;
1922       sock = socket(AF_ALG, SOCK_SEQPACKET, 0);
1923       return sock;
1924     }
1925   '''), error_message: 'AF_ALG requested but could not be detected').allowed()
1926 config_host_data.set('CONFIG_AF_ALG', have_afalg)
1928 config_host_data.set('CONFIG_AF_VSOCK', cc.compiles(gnu_source_prefix + '''
1929   #include <errno.h>
1930   #include <sys/types.h>
1931   #include <sys/socket.h>
1932   #if !defined(AF_VSOCK)
1933   # error missing AF_VSOCK flag
1934   #endif
1935   #include <linux/vm_sockets.h>
1936   int main(void) {
1937     int sock, ret;
1938     struct sockaddr_vm svm;
1939     socklen_t len = sizeof(svm);
1940     sock = socket(AF_VSOCK, SOCK_STREAM, 0);
1941     ret = getpeername(sock, (struct sockaddr *)&svm, &len);
1942     if ((ret == -1) && (errno == ENOTCONN)) {
1943         return 0;
1944     }
1945     return -1;
1946   }'''))
1948 have_vss = false
1949 if targetos == 'windows' and link_language == 'cpp'
1950   have_vss = cxx.compiles('''
1951     #define __MIDL_user_allocate_free_DEFINED__
1952     #include <inc/win2003/vss.h>
1953     int main(void) { return VSS_CTX_BACKUP; }''')
1954 endif
1956 have_ntddscsi = false
1957 if targetos == 'windows'
1958   have_ntddscsi = cc.compiles('''
1959     #include <windows.h>
1960     #include <ntddscsi.h>
1961     int main(void) {
1962     #if !defined(IOCTL_SCSI_GET_ADDRESS)
1963     #error Missing required ioctl definitions
1964     #endif
1965       SCSI_ADDRESS addr = { .Lun = 0, .TargetId = 0, .PathId = 0 };
1966       return addr.Lun;
1967     }
1968 ''')
1969 endif
1970 config_host_data.set('HAVE_NTDDSCSI', have_ntddscsi)
1972 ignored = ['CONFIG_QEMU_INTERP_PREFIX', # actually per-target
1973     'HAVE_GDB_BIN']
1974 arrays = ['CONFIG_BDRV_RW_WHITELIST', 'CONFIG_BDRV_RO_WHITELIST']
1975 foreach k, v: config_host
1976   if ignored.contains(k)
1977     # do nothing
1978   elif arrays.contains(k)
1979     if v != ''
1980       v = '"' + '", "'.join(v.split()) + '", '
1981     endif
1982     config_host_data.set(k, v)
1983   elif k.startswith('CONFIG_')
1984     config_host_data.set(k, v == 'y' ? 1 : v)
1985   endif
1986 endforeach
1988 ########################
1989 # Target configuration #
1990 ########################
1992 minikconf = find_program('scripts/minikconf.py')
1993 config_all = {}
1994 config_all_devices = {}
1995 config_all_disas = {}
1996 config_devices_mak_list = []
1997 config_devices_h = {}
1998 config_target_h = {}
1999 config_target_mak = {}
2001 disassemblers = {
2002   'alpha' : ['CONFIG_ALPHA_DIS'],
2003   'arm' : ['CONFIG_ARM_DIS'],
2004   'avr' : ['CONFIG_AVR_DIS'],
2005   'cris' : ['CONFIG_CRIS_DIS'],
2006   'hexagon' : ['CONFIG_HEXAGON_DIS'],
2007   'hppa' : ['CONFIG_HPPA_DIS'],
2008   'i386' : ['CONFIG_I386_DIS'],
2009   'x86_64' : ['CONFIG_I386_DIS'],
2010   'm68k' : ['CONFIG_M68K_DIS'],
2011   'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
2012   'mips' : ['CONFIG_MIPS_DIS'],
2013   'nios2' : ['CONFIG_NIOS2_DIS'],
2014   'or1k' : ['CONFIG_OPENRISC_DIS'],
2015   'ppc' : ['CONFIG_PPC_DIS'],
2016   'riscv' : ['CONFIG_RISCV_DIS'],
2017   'rx' : ['CONFIG_RX_DIS'],
2018   's390' : ['CONFIG_S390_DIS'],
2019   'sh4' : ['CONFIG_SH4_DIS'],
2020   'sparc' : ['CONFIG_SPARC_DIS'],
2021   'xtensa' : ['CONFIG_XTENSA_DIS'],
2023 if link_language == 'cpp'
2024   disassemblers += {
2025     'aarch64' : [ 'CONFIG_ARM_A64_DIS'],
2026     'arm' : [ 'CONFIG_ARM_DIS', 'CONFIG_ARM_A64_DIS'],
2027     'mips' : [ 'CONFIG_MIPS_DIS', 'CONFIG_NANOMIPS_DIS'],
2028   }
2029 endif
2031 have_ivshmem = config_host_data.get('CONFIG_EVENTFD')
2032 host_kconfig = \
2033   (get_option('fuzzing') ? ['CONFIG_FUZZ=y'] : []) + \
2034   (have_tpm ? ['CONFIG_TPM=y'] : []) + \
2035   (spice.found() ? ['CONFIG_SPICE=y'] : []) + \
2036   (have_ivshmem ? ['CONFIG_IVSHMEM=y'] : []) + \
2037   ('CONFIG_OPENGL' in config_host ? ['CONFIG_OPENGL=y'] : []) + \
2038   (x11.found() ? ['CONFIG_X11=y'] : []) + \
2039   ('CONFIG_VHOST_USER' in config_host ? ['CONFIG_VHOST_USER=y'] : []) + \
2040   ('CONFIG_VHOST_VDPA' in config_host ? ['CONFIG_VHOST_VDPA=y'] : []) + \
2041   ('CONFIG_VHOST_KERNEL' in config_host ? ['CONFIG_VHOST_KERNEL=y'] : []) + \
2042   (have_virtfs ? ['CONFIG_VIRTFS=y'] : []) + \
2043   ('CONFIG_LINUX' in config_host ? ['CONFIG_LINUX=y'] : []) + \
2044   ('CONFIG_PVRDMA' in config_host ? ['CONFIG_PVRDMA=y'] : []) + \
2045   (multiprocess_allowed ? ['CONFIG_MULTIPROCESS_ALLOWED=y'] : [])
2047 ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ]
2049 default_targets = 'CONFIG_DEFAULT_TARGETS' in config_host
2050 actual_target_dirs = []
2051 fdt_required = []
2052 foreach target : target_dirs
2053   config_target = { 'TARGET_NAME': target.split('-')[0] }
2054   if target.endswith('linux-user')
2055     if targetos != 'linux'
2056       if default_targets
2057         continue
2058       endif
2059       error('Target @0@ is only available on a Linux host'.format(target))
2060     endif
2061     config_target += { 'CONFIG_LINUX_USER': 'y' }
2062   elif target.endswith('bsd-user')
2063     if 'CONFIG_BSD' not in config_host
2064       if default_targets
2065         continue
2066       endif
2067       error('Target @0@ is only available on a BSD host'.format(target))
2068     endif
2069     config_target += { 'CONFIG_BSD_USER': 'y' }
2070   elif target.endswith('softmmu')
2071     config_target += { 'CONFIG_SOFTMMU': 'y' }
2072   endif
2073   if target.endswith('-user')
2074     config_target += {
2075       'CONFIG_USER_ONLY': 'y',
2076       'CONFIG_QEMU_INTERP_PREFIX':
2077         config_host['CONFIG_QEMU_INTERP_PREFIX'].format(config_target['TARGET_NAME'])
2078     }
2079   endif
2081   accel_kconfig = []
2082   foreach sym: accelerators
2083     if sym == 'CONFIG_TCG' or target in accelerator_targets.get(sym, [])
2084       config_target += { sym: 'y' }
2085       config_all += { sym: 'y' }
2086       if sym == 'CONFIG_TCG' and tcg_arch == 'tci'
2087         config_target += { 'CONFIG_TCG_INTERPRETER': 'y' }
2088       elif sym == 'CONFIG_XEN' and have_xen_pci_passthrough
2089         config_target += { 'CONFIG_XEN_PCI_PASSTHROUGH': 'y' }
2090       endif
2091       if target in modular_tcg
2092         config_target += { 'CONFIG_TCG_MODULAR': 'y' }
2093       else
2094         config_target += { 'CONFIG_TCG_BUILTIN': 'y' }
2095       endif
2096       accel_kconfig += [ sym + '=y' ]
2097     endif
2098   endforeach
2099   if accel_kconfig.length() == 0
2100     if default_targets
2101       continue
2102     endif
2103     error('No accelerator available for target @0@'.format(target))
2104   endif
2106   actual_target_dirs += target
2107   config_target += keyval.load('configs/targets' / target + '.mak')
2108   config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
2110   if 'TARGET_NEED_FDT' in config_target
2111     fdt_required += target
2112   endif
2114   # Add default keys
2115   if 'TARGET_BASE_ARCH' not in config_target
2116     config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
2117   endif
2118   if 'TARGET_ABI_DIR' not in config_target
2119     config_target += {'TARGET_ABI_DIR': config_target['TARGET_ARCH']}
2120   endif
2122   foreach k, v: disassemblers
2123     if host_arch.startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k)
2124       foreach sym: v
2125         config_target += { sym: 'y' }
2126         config_all_disas += { sym: 'y' }
2127       endforeach
2128     endif
2129   endforeach
2131   config_target_data = configuration_data()
2132   foreach k, v: config_target
2133     if not k.startswith('TARGET_') and not k.startswith('CONFIG_')
2134       # do nothing
2135     elif ignored.contains(k)
2136       # do nothing
2137     elif k == 'TARGET_BASE_ARCH'
2138       # Note that TARGET_BASE_ARCH ends up in config-target.h but it is
2139       # not used to select files from sourcesets.
2140       config_target_data.set('TARGET_' + v.to_upper(), 1)
2141     elif k == 'TARGET_NAME' or k == 'CONFIG_QEMU_INTERP_PREFIX'
2142       config_target_data.set_quoted(k, v)
2143     elif v == 'y'
2144       config_target_data.set(k, 1)
2145     else
2146       config_target_data.set(k, v)
2147     endif
2148   endforeach
2149   config_target_data.set('QEMU_ARCH',
2150                          'QEMU_ARCH_' + config_target['TARGET_BASE_ARCH'].to_upper())
2151   config_target_h += {target: configure_file(output: target + '-config-target.h',
2152                                                configuration: config_target_data)}
2154   if target.endswith('-softmmu')
2155     config_input = meson.get_external_property(target, 'default')
2156     config_devices_mak = target + '-config-devices.mak'
2157     config_devices_mak = configure_file(
2158       input: ['configs/devices' / target / config_input + '.mak', 'Kconfig'],
2159       output: config_devices_mak,
2160       depfile: config_devices_mak + '.d',
2161       capture: true,
2162       command: [minikconf,
2163                 get_option('default_devices') ? '--defconfig' : '--allnoconfig',
2164                 config_devices_mak, '@DEPFILE@', '@INPUT@',
2165                 host_kconfig, accel_kconfig,
2166                 'CONFIG_' + config_target['TARGET_ARCH'].to_upper() + '=y'])
2168     config_devices_data = configuration_data()
2169     config_devices = keyval.load(config_devices_mak)
2170     foreach k, v: config_devices
2171       config_devices_data.set(k, 1)
2172     endforeach
2173     config_devices_mak_list += config_devices_mak
2174     config_devices_h += {target: configure_file(output: target + '-config-devices.h',
2175                                                 configuration: config_devices_data)}
2176     config_target += config_devices
2177     config_all_devices += config_devices
2178   endif
2179   config_target_mak += {target: config_target}
2180 endforeach
2181 target_dirs = actual_target_dirs
2183 # This configuration is used to build files that are shared by
2184 # multiple binaries, and then extracted out of the "common"
2185 # static_library target.
2187 # We do not use all_sources()/all_dependencies(), because it would
2188 # build literally all source files, including devices only used by
2189 # targets that are not built for this compilation.  The CONFIG_ALL
2190 # pseudo symbol replaces it.
2192 config_all += config_all_devices
2193 config_all += config_host
2194 config_all += config_all_disas
2195 config_all += {
2196   'CONFIG_XEN': config_host.has_key('CONFIG_XEN_BACKEND'),
2197   'CONFIG_SOFTMMU': have_system,
2198   'CONFIG_USER_ONLY': have_user,
2199   'CONFIG_ALL': true,
2202 target_configs_h = []
2203 foreach target: target_dirs
2204   target_configs_h += config_target_h[target]
2205   target_configs_h += config_devices_h.get(target, [])
2206 endforeach
2207 genh += custom_target('config-poison.h',
2208                       input: [target_configs_h],
2209                       output: 'config-poison.h',
2210                       capture: true,
2211                       command: [find_program('scripts/make-config-poison.sh'),
2212                                 target_configs_h])
2214 ##############
2215 # Submodules #
2216 ##############
2218 capstone = not_found
2219 capstone_opt = get_option('capstone')
2220 if capstone_opt in ['enabled', 'auto', 'system']
2221   have_internal = fs.exists(meson.current_source_dir() / 'capstone/Makefile')
2222   capstone = dependency('capstone', version: '>=4.0',
2223                         kwargs: static_kwargs, method: 'pkg-config',
2224                         required: capstone_opt == 'system' or
2225                                   capstone_opt == 'enabled' and not have_internal)
2227   # Some versions of capstone have broken pkg-config file
2228   # that reports a wrong -I path, causing the #include to
2229   # fail later. If the system has such a broken version
2230   # do not use it.
2231   if capstone.found() and not cc.compiles('#include <capstone.h>',
2232                                           dependencies: [capstone])
2233     capstone = not_found
2234     if capstone_opt == 'system'
2235       error('system capstone requested, it does not appear to work')
2236     endif
2237   endif
2239   if capstone.found()
2240     capstone_opt = 'system'
2241   elif have_internal
2242     capstone_opt = 'internal'
2243   else
2244     capstone_opt = 'disabled'
2245   endif
2246 endif
2247 if capstone_opt == 'internal'
2248   capstone_data = configuration_data()
2249   capstone_data.set('CAPSTONE_USE_SYS_DYN_MEM', '1')
2251   capstone_files = files(
2252     'capstone/cs.c',
2253     'capstone/MCInst.c',
2254     'capstone/MCInstrDesc.c',
2255     'capstone/MCRegisterInfo.c',
2256     'capstone/SStream.c',
2257     'capstone/utils.c'
2258   )
2260   if 'CONFIG_ARM_DIS' in config_all_disas
2261     capstone_data.set('CAPSTONE_HAS_ARM', '1')
2262     capstone_files += files(
2263       'capstone/arch/ARM/ARMDisassembler.c',
2264       'capstone/arch/ARM/ARMInstPrinter.c',
2265       'capstone/arch/ARM/ARMMapping.c',
2266       'capstone/arch/ARM/ARMModule.c'
2267     )
2268   endif
2270   # FIXME: This config entry currently depends on a c++ compiler.
2271   # Which is needed for building libvixl, but not for capstone.
2272   if 'CONFIG_ARM_A64_DIS' in config_all_disas
2273     capstone_data.set('CAPSTONE_HAS_ARM64', '1')
2274     capstone_files += files(
2275       'capstone/arch/AArch64/AArch64BaseInfo.c',
2276       'capstone/arch/AArch64/AArch64Disassembler.c',
2277       'capstone/arch/AArch64/AArch64InstPrinter.c',
2278       'capstone/arch/AArch64/AArch64Mapping.c',
2279       'capstone/arch/AArch64/AArch64Module.c'
2280     )
2281   endif
2283   if 'CONFIG_PPC_DIS' in config_all_disas
2284     capstone_data.set('CAPSTONE_HAS_POWERPC', '1')
2285     capstone_files += files(
2286       'capstone/arch/PowerPC/PPCDisassembler.c',
2287       'capstone/arch/PowerPC/PPCInstPrinter.c',
2288       'capstone/arch/PowerPC/PPCMapping.c',
2289       'capstone/arch/PowerPC/PPCModule.c'
2290     )
2291   endif
2293   if 'CONFIG_S390_DIS' in config_all_disas
2294     capstone_data.set('CAPSTONE_HAS_SYSZ', '1')
2295     capstone_files += files(
2296       'capstone/arch/SystemZ/SystemZDisassembler.c',
2297       'capstone/arch/SystemZ/SystemZInstPrinter.c',
2298       'capstone/arch/SystemZ/SystemZMapping.c',
2299       'capstone/arch/SystemZ/SystemZModule.c',
2300       'capstone/arch/SystemZ/SystemZMCTargetDesc.c'
2301     )
2302   endif
2304   if 'CONFIG_I386_DIS' in config_all_disas
2305     capstone_data.set('CAPSTONE_HAS_X86', 1)
2306     capstone_files += files(
2307       'capstone/arch/X86/X86Disassembler.c',
2308       'capstone/arch/X86/X86DisassemblerDecoder.c',
2309       'capstone/arch/X86/X86ATTInstPrinter.c',
2310       'capstone/arch/X86/X86IntelInstPrinter.c',
2311       'capstone/arch/X86/X86InstPrinterCommon.c',
2312       'capstone/arch/X86/X86Mapping.c',
2313       'capstone/arch/X86/X86Module.c'
2314     )
2315   endif
2317   configure_file(output: 'capstone-defs.h', configuration: capstone_data)
2319   capstone_cargs = [
2320     # FIXME: There does not seem to be a way to completely replace the c_args
2321     # that come from add_project_arguments() -- we can only add to them.
2322     # So: disable all warnings with a big hammer.
2323     '-Wno-error', '-w',
2325     # Include all configuration defines via a header file, which will wind up
2326     # as a dependency on the object file, and thus changes here will result
2327     # in a rebuild.
2328     '-include', 'capstone-defs.h'
2329   ]
2331   libcapstone = static_library('capstone',
2332                                build_by_default: false,
2333                                sources: capstone_files,
2334                                c_args: capstone_cargs,
2335                                include_directories: 'capstone/include')
2336   capstone = declare_dependency(link_with: libcapstone,
2337                                 include_directories: 'capstone/include/capstone')
2338 endif
2340 slirp = not_found
2341 slirp_opt = 'disabled'
2342 if have_system
2343   slirp_opt = get_option('slirp')
2344   if slirp_opt in ['enabled', 'auto', 'system']
2345     have_internal = fs.exists(meson.current_source_dir() / 'slirp/meson.build')
2346     slirp = dependency('slirp', kwargs: static_kwargs,
2347                        method: 'pkg-config',
2348                        required: slirp_opt == 'system' or
2349                                  slirp_opt == 'enabled' and not have_internal)
2350     if slirp.found()
2351       slirp_opt = 'system'
2352     elif have_internal
2353       slirp_opt = 'internal'
2354     else
2355       slirp_opt = 'disabled'
2356     endif
2357   endif
2358   if slirp_opt == 'internal'
2359     slirp_deps = []
2360     if targetos == 'windows'
2361       slirp_deps = cc.find_library('iphlpapi')
2362     elif targetos == 'darwin'
2363       slirp_deps = cc.find_library('resolv')
2364     endif
2365     slirp_conf = configuration_data()
2366     slirp_conf.set('SLIRP_MAJOR_VERSION', meson.project_version().split('.')[0])
2367     slirp_conf.set('SLIRP_MINOR_VERSION', meson.project_version().split('.')[1])
2368     slirp_conf.set('SLIRP_MICRO_VERSION', meson.project_version().split('.')[2])
2369     slirp_conf.set_quoted('SLIRP_VERSION_STRING', meson.project_version())
2370     slirp_cargs = ['-DG_LOG_DOMAIN="Slirp"']
2371     slirp_files = [
2372       'slirp/src/arp_table.c',
2373       'slirp/src/bootp.c',
2374       'slirp/src/cksum.c',
2375       'slirp/src/dhcpv6.c',
2376       'slirp/src/dnssearch.c',
2377       'slirp/src/if.c',
2378       'slirp/src/ip6_icmp.c',
2379       'slirp/src/ip6_input.c',
2380       'slirp/src/ip6_output.c',
2381       'slirp/src/ip_icmp.c',
2382       'slirp/src/ip_input.c',
2383       'slirp/src/ip_output.c',
2384       'slirp/src/mbuf.c',
2385       'slirp/src/misc.c',
2386       'slirp/src/ncsi.c',
2387       'slirp/src/ndp_table.c',
2388       'slirp/src/sbuf.c',
2389       'slirp/src/slirp.c',
2390       'slirp/src/socket.c',
2391       'slirp/src/state.c',
2392       'slirp/src/stream.c',
2393       'slirp/src/tcp_input.c',
2394       'slirp/src/tcp_output.c',
2395       'slirp/src/tcp_subr.c',
2396       'slirp/src/tcp_timer.c',
2397       'slirp/src/tftp.c',
2398       'slirp/src/udp.c',
2399       'slirp/src/udp6.c',
2400       'slirp/src/util.c',
2401       'slirp/src/version.c',
2402       'slirp/src/vmstate.c',
2403     ]
2405     configure_file(
2406       input : 'slirp/src/libslirp-version.h.in',
2407       output : 'libslirp-version.h',
2408       configuration: slirp_conf)
2410     slirp_inc = include_directories('slirp', 'slirp/src')
2411     libslirp = static_library('slirp',
2412                               build_by_default: false,
2413                               sources: slirp_files,
2414                               c_args: slirp_cargs,
2415                               include_directories: slirp_inc)
2416     slirp = declare_dependency(link_with: libslirp,
2417                                dependencies: slirp_deps,
2418                                include_directories: slirp_inc)
2419   endif
2420 endif
2422 # For CFI, we need to compile slirp as a static library together with qemu.
2423 # This is because we register slirp functions as callbacks for QEMU Timers.
2424 # When using a system-wide shared libslirp, the type information for the
2425 # callback is missing and the timer call produces a false positive with CFI.
2427 # Now that slirp_opt has been defined, check if the selected slirp is compatible
2428 # with control-flow integrity.
2429 if get_option('cfi') and slirp_opt == 'system'
2430   error('Control-Flow Integrity is not compatible with system-wide slirp.' \
2431          + ' Please configure with --enable-slirp=git')
2432 endif
2434 fdt = not_found
2435 fdt_opt = get_option('fdt')
2436 if have_system
2437   if fdt_opt in ['enabled', 'auto', 'system']
2438     have_internal = fs.exists(meson.current_source_dir() / 'dtc/libfdt/Makefile.libfdt')
2439     fdt = cc.find_library('fdt', kwargs: static_kwargs,
2440                           required: fdt_opt == 'system' or
2441                                     fdt_opt == 'enabled' and not have_internal)
2442     if fdt.found() and cc.links('''
2443        #include <libfdt.h>
2444        #include <libfdt_env.h>
2445        int main(void) { fdt_find_max_phandle(NULL, NULL); return 0; }''',
2446          dependencies: fdt)
2447       fdt_opt = 'system'
2448     elif fdt_opt == 'system'
2449        error('system libfdt requested, but it is too old (1.5.1 or newer required)')
2450     elif have_internal
2451       fdt_opt = 'internal'
2452     else
2453       fdt_opt = 'disabled'
2454       fdt = not_found
2455     endif
2456   endif
2457   if fdt_opt == 'internal'
2458     fdt_files = files(
2459       'dtc/libfdt/fdt.c',
2460       'dtc/libfdt/fdt_ro.c',
2461       'dtc/libfdt/fdt_wip.c',
2462       'dtc/libfdt/fdt_sw.c',
2463       'dtc/libfdt/fdt_rw.c',
2464       'dtc/libfdt/fdt_strerror.c',
2465       'dtc/libfdt/fdt_empty_tree.c',
2466       'dtc/libfdt/fdt_addresses.c',
2467       'dtc/libfdt/fdt_overlay.c',
2468       'dtc/libfdt/fdt_check.c',
2469     )
2471     fdt_inc = include_directories('dtc/libfdt')
2472     libfdt = static_library('fdt',
2473                             build_by_default: false,
2474                             sources: fdt_files,
2475                             include_directories: fdt_inc)
2476     fdt = declare_dependency(link_with: libfdt,
2477                              include_directories: fdt_inc)
2478   endif
2479 endif
2480 if not fdt.found() and fdt_required.length() > 0
2481   error('fdt not available but required by targets ' + ', '.join(fdt_required))
2482 endif
2484 config_host_data.set('CONFIG_CAPSTONE', capstone.found())
2485 config_host_data.set('CONFIG_FDT', fdt.found())
2486 config_host_data.set('CONFIG_SLIRP', slirp.found())
2488 #####################
2489 # Generated sources #
2490 #####################
2492 genh += configure_file(output: 'config-host.h', configuration: config_host_data)
2494 hxtool = find_program('scripts/hxtool')
2495 shaderinclude = find_program('scripts/shaderinclude.pl')
2496 qapi_gen = find_program('scripts/qapi-gen.py')
2497 qapi_gen_depends = [ meson.current_source_dir() / 'scripts/qapi/__init__.py',
2498                      meson.current_source_dir() / 'scripts/qapi/commands.py',
2499                      meson.current_source_dir() / 'scripts/qapi/common.py',
2500                      meson.current_source_dir() / 'scripts/qapi/error.py',
2501                      meson.current_source_dir() / 'scripts/qapi/events.py',
2502                      meson.current_source_dir() / 'scripts/qapi/expr.py',
2503                      meson.current_source_dir() / 'scripts/qapi/gen.py',
2504                      meson.current_source_dir() / 'scripts/qapi/introspect.py',
2505                      meson.current_source_dir() / 'scripts/qapi/parser.py',
2506                      meson.current_source_dir() / 'scripts/qapi/schema.py',
2507                      meson.current_source_dir() / 'scripts/qapi/source.py',
2508                      meson.current_source_dir() / 'scripts/qapi/types.py',
2509                      meson.current_source_dir() / 'scripts/qapi/visit.py',
2510                      meson.current_source_dir() / 'scripts/qapi/common.py',
2511                      meson.current_source_dir() / 'scripts/qapi-gen.py'
2514 tracetool = [
2515   python, files('scripts/tracetool.py'),
2516    '--backend=' + ','.join(get_option('trace_backends'))
2518 tracetool_depends = files(
2519   'scripts/tracetool/backend/log.py',
2520   'scripts/tracetool/backend/__init__.py',
2521   'scripts/tracetool/backend/dtrace.py',
2522   'scripts/tracetool/backend/ftrace.py',
2523   'scripts/tracetool/backend/simple.py',
2524   'scripts/tracetool/backend/syslog.py',
2525   'scripts/tracetool/backend/ust.py',
2526   'scripts/tracetool/format/ust_events_c.py',
2527   'scripts/tracetool/format/ust_events_h.py',
2528   'scripts/tracetool/format/__init__.py',
2529   'scripts/tracetool/format/d.py',
2530   'scripts/tracetool/format/simpletrace_stap.py',
2531   'scripts/tracetool/format/c.py',
2532   'scripts/tracetool/format/h.py',
2533   'scripts/tracetool/format/log_stap.py',
2534   'scripts/tracetool/format/stap.py',
2535   'scripts/tracetool/__init__.py',
2536   'scripts/tracetool/transform.py',
2537   'scripts/tracetool/vcpu.py'
2540 qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
2541                     meson.current_source_dir(),
2542                     config_host['PKGVERSION'], meson.project_version()]
2543 qemu_version = custom_target('qemu-version.h',
2544                              output: 'qemu-version.h',
2545                              command: qemu_version_cmd,
2546                              capture: true,
2547                              build_by_default: true,
2548                              build_always_stale: true)
2549 genh += qemu_version
2551 hxdep = []
2552 hx_headers = [
2553   ['qemu-options.hx', 'qemu-options.def'],
2554   ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
2556 if have_system
2557   hx_headers += [
2558     ['hmp-commands.hx', 'hmp-commands.h'],
2559     ['hmp-commands-info.hx', 'hmp-commands-info.h'],
2560   ]
2561 endif
2562 foreach d : hx_headers
2563   hxdep += custom_target(d[1],
2564                 input: files(d[0]),
2565                 output: d[1],
2566                 capture: true,
2567                 build_by_default: true, # to be removed when added to a target
2568                 command: [hxtool, '-h', '@INPUT0@'])
2569 endforeach
2570 genh += hxdep
2572 ###################
2573 # Collect sources #
2574 ###################
2576 authz_ss = ss.source_set()
2577 blockdev_ss = ss.source_set()
2578 block_ss = ss.source_set()
2579 chardev_ss = ss.source_set()
2580 common_ss = ss.source_set()
2581 crypto_ss = ss.source_set()
2582 hwcore_ss = ss.source_set()
2583 io_ss = ss.source_set()
2584 qmp_ss = ss.source_set()
2585 qom_ss = ss.source_set()
2586 softmmu_ss = ss.source_set()
2587 specific_fuzz_ss = ss.source_set()
2588 specific_ss = ss.source_set()
2589 stub_ss = ss.source_set()
2590 trace_ss = ss.source_set()
2591 user_ss = ss.source_set()
2592 util_ss = ss.source_set()
2594 # accel modules
2595 qtest_module_ss = ss.source_set()
2596 tcg_module_ss = ss.source_set()
2598 modules = {}
2599 target_modules = {}
2600 hw_arch = {}
2601 target_arch = {}
2602 target_softmmu_arch = {}
2603 target_user_arch = {}
2605 ###############
2606 # Trace files #
2607 ###############
2609 # TODO: add each directory to the subdirs from its own meson.build, once
2610 # we have those
2611 trace_events_subdirs = [
2612   'crypto',
2613   'qapi',
2614   'qom',
2615   'monitor',
2616   'util',
2618 if have_linux_user
2619   trace_events_subdirs += [ 'linux-user' ]
2620 endif
2621 if have_bsd_user
2622   trace_events_subdirs += [ 'bsd-user' ]
2623 endif
2624 if have_block
2625   trace_events_subdirs += [
2626     'authz',
2627     'block',
2628     'io',
2629     'nbd',
2630     'scsi',
2631   ]
2632 endif
2633 if have_system
2634   trace_events_subdirs += [
2635     'accel/kvm',
2636     'audio',
2637     'backends',
2638     'backends/tpm',
2639     'chardev',
2640     'ebpf',
2641     'hw/9pfs',
2642     'hw/acpi',
2643     'hw/adc',
2644     'hw/alpha',
2645     'hw/arm',
2646     'hw/audio',
2647     'hw/block',
2648     'hw/block/dataplane',
2649     'hw/char',
2650     'hw/display',
2651     'hw/dma',
2652     'hw/hppa',
2653     'hw/hyperv',
2654     'hw/i2c',
2655     'hw/i386',
2656     'hw/i386/xen',
2657     'hw/ide',
2658     'hw/input',
2659     'hw/intc',
2660     'hw/isa',
2661     'hw/mem',
2662     'hw/mips',
2663     'hw/misc',
2664     'hw/misc/macio',
2665     'hw/net',
2666     'hw/net/can',
2667     'hw/nubus',
2668     'hw/nvme',
2669     'hw/nvram',
2670     'hw/pci',
2671     'hw/pci-host',
2672     'hw/ppc',
2673     'hw/rdma',
2674     'hw/rdma/vmw',
2675     'hw/rtc',
2676     'hw/s390x',
2677     'hw/scsi',
2678     'hw/sd',
2679     'hw/sh4',
2680     'hw/sparc',
2681     'hw/sparc64',
2682     'hw/ssi',
2683     'hw/timer',
2684     'hw/tpm',
2685     'hw/usb',
2686     'hw/vfio',
2687     'hw/virtio',
2688     'hw/watchdog',
2689     'hw/xen',
2690     'hw/gpio',
2691     'migration',
2692     'net',
2693     'softmmu',
2694     'ui',
2695     'hw/remote',
2696   ]
2697 endif
2698 if have_system or have_user
2699   trace_events_subdirs += [
2700     'accel/tcg',
2701     'hw/core',
2702     'target/arm',
2703     'target/arm/hvf',
2704     'target/hppa',
2705     'target/i386',
2706     'target/i386/kvm',
2707     'target/mips/tcg',
2708     'target/nios2',
2709     'target/ppc',
2710     'target/riscv',
2711     'target/s390x',
2712     'target/s390x/kvm',
2713     'target/sparc',
2714   ]
2715 endif
2717 vhost_user = not_found
2718 if 'CONFIG_VHOST_USER' in config_host
2719   libvhost_user = subproject('libvhost-user')
2720   vhost_user = libvhost_user.get_variable('vhost_user_dep')
2721 endif
2723 # NOTE: the trace/ subdirectory needs the qapi_trace_events variable
2724 # that is filled in by qapi/.
2725 subdir('qapi')
2726 subdir('qobject')
2727 subdir('stubs')
2728 subdir('trace')
2729 subdir('util')
2730 subdir('qom')
2731 subdir('authz')
2732 subdir('crypto')
2733 subdir('ui')
2736 if enable_modules
2737   libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
2738   modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
2739 endif
2741 stub_ss = stub_ss.apply(config_all, strict: false)
2743 util_ss.add_all(trace_ss)
2744 util_ss = util_ss.apply(config_all, strict: false)
2745 libqemuutil = static_library('qemuutil',
2746                              sources: util_ss.sources() + stub_ss.sources() + genh,
2747                              dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc, pixman])
2748 qemuutil = declare_dependency(link_with: libqemuutil,
2749                               sources: genh + version_res)
2751 if have_system or have_user
2752   decodetree = generator(find_program('scripts/decodetree.py'),
2753                          output: 'decode-@BASENAME@.c.inc',
2754                          arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
2755   subdir('libdecnumber')
2756   subdir('target')
2757 endif
2759 subdir('audio')
2760 subdir('io')
2761 subdir('chardev')
2762 subdir('fsdev')
2763 subdir('dump')
2765 if have_block
2766   block_ss.add(files(
2767     'block.c',
2768     'blockjob.c',
2769     'job.c',
2770     'qemu-io-cmds.c',
2771   ))
2772   if config_host_data.get('CONFIG_REPLICATION')
2773     block_ss.add(files('replication.c'))
2774   endif
2776   subdir('nbd')
2777   subdir('scsi')
2778   subdir('block')
2780   blockdev_ss.add(files(
2781     'blockdev.c',
2782     'blockdev-nbd.c',
2783     'iothread.c',
2784     'job-qmp.c',
2785   ), gnutls)
2787   # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
2788   # os-win32.c does not
2789   blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
2790   softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
2791 endif
2793 common_ss.add(files('cpus-common.c'))
2795 subdir('softmmu')
2797 common_ss.add(capstone)
2798 specific_ss.add(files('cpu.c', 'disas.c', 'gdbstub.c'), capstone)
2800 # Work around a gcc bug/misfeature wherein constant propagation looks
2801 # through an alias:
2802 #   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99696
2803 # to guess that a const variable is always zero.  Without lto, this is
2804 # impossible, as the alias is restricted to page-vary-common.c.  Indeed,
2805 # without lto, not even the alias is required -- we simply use different
2806 # declarations in different compilation units.
2807 pagevary = files('page-vary-common.c')
2808 if get_option('b_lto')
2809   pagevary_flags = ['-fno-lto']
2810   if get_option('cfi')
2811     pagevary_flags += '-fno-sanitize=cfi-icall'
2812   endif
2813   pagevary = static_library('page-vary-common', sources: pagevary,
2814                             c_args: pagevary_flags)
2815   pagevary = declare_dependency(link_with: pagevary)
2816 endif
2817 common_ss.add(pagevary)
2818 specific_ss.add(files('page-vary.c'))
2820 subdir('backends')
2821 subdir('disas')
2822 subdir('migration')
2823 subdir('monitor')
2824 subdir('net')
2825 subdir('replay')
2826 subdir('semihosting')
2827 subdir('hw')
2828 subdir('tcg')
2829 subdir('fpu')
2830 subdir('accel')
2831 subdir('plugins')
2832 subdir('ebpf')
2834 common_user_inc = []
2836 subdir('common-user')
2837 subdir('bsd-user')
2838 subdir('linux-user')
2840 # needed for fuzzing binaries
2841 subdir('tests/qtest/libqos')
2842 subdir('tests/qtest/fuzz')
2844 # accel modules
2845 tcg_real_module_ss = ss.source_set()
2846 tcg_real_module_ss.add_all(when: 'CONFIG_TCG_MODULAR', if_true: tcg_module_ss)
2847 specific_ss.add_all(when: 'CONFIG_TCG_BUILTIN', if_true: tcg_module_ss)
2848 target_modules += { 'accel' : { 'qtest': qtest_module_ss,
2849                                 'tcg': tcg_real_module_ss }}
2851 ########################
2852 # Library dependencies #
2853 ########################
2855 modinfo_collect = find_program('scripts/modinfo-collect.py')
2856 modinfo_generate = find_program('scripts/modinfo-generate.py')
2857 modinfo_files = []
2859 block_mods = []
2860 softmmu_mods = []
2861 foreach d, list : modules
2862   foreach m, module_ss : list
2863     if enable_modules and targetos != 'windows'
2864       module_ss = module_ss.apply(config_all, strict: false)
2865       sl = static_library(d + '-' + m, [genh, module_ss.sources()],
2866                           dependencies: [modulecommon, module_ss.dependencies()], pic: true)
2867       if d == 'block'
2868         block_mods += sl
2869       else
2870         softmmu_mods += sl
2871       endif
2872       if module_ss.sources() != []
2873         # FIXME: Should use sl.extract_all_objects(recursive: true) as
2874         # input. Sources can be used multiple times but objects are
2875         # unique when it comes to lookup in compile_commands.json.
2876         # Depnds on a mesion version with
2877         # https://github.com/mesonbuild/meson/pull/8900
2878         modinfo_files += custom_target(d + '-' + m + '.modinfo',
2879                                        output: d + '-' + m + '.modinfo',
2880                                        input: module_ss.sources() + genh,
2881                                        capture: true,
2882                                        command: [modinfo_collect, module_ss.sources()])
2883       endif
2884     else
2885       if d == 'block'
2886         block_ss.add_all(module_ss)
2887       else
2888         softmmu_ss.add_all(module_ss)
2889       endif
2890     endif
2891   endforeach
2892 endforeach
2894 foreach d, list : target_modules
2895   foreach m, module_ss : list
2896     if enable_modules and targetos != 'windows'
2897       foreach target : target_dirs
2898         if target.endswith('-softmmu')
2899           config_target = config_target_mak[target]
2900           config_target += config_host
2901           target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
2902           c_args = ['-DNEED_CPU_H',
2903                     '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
2904                     '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
2905           target_module_ss = module_ss.apply(config_target, strict: false)
2906           if target_module_ss.sources() != []
2907             module_name = d + '-' + m + '-' + config_target['TARGET_NAME']
2908             sl = static_library(module_name,
2909                                 [genh, target_module_ss.sources()],
2910                                 dependencies: [modulecommon, target_module_ss.dependencies()],
2911                                 include_directories: target_inc,
2912                                 c_args: c_args,
2913                                 pic: true)
2914             softmmu_mods += sl
2915             # FIXME: Should use sl.extract_all_objects(recursive: true) too.
2916             modinfo_files += custom_target(module_name + '.modinfo',
2917                                            output: module_name + '.modinfo',
2918                                            input: target_module_ss.sources() + genh,
2919                                            capture: true,
2920                                            command: [modinfo_collect, '--target', target, target_module_ss.sources()])
2921           endif
2922         endif
2923       endforeach
2924     else
2925       specific_ss.add_all(module_ss)
2926     endif
2927   endforeach
2928 endforeach
2930 if enable_modules
2931   modinfo_src = custom_target('modinfo.c',
2932                               output: 'modinfo.c',
2933                               input: modinfo_files,
2934                               command: [modinfo_generate, '@INPUT@'],
2935                               capture: true)
2936   modinfo_lib = static_library('modinfo', modinfo_src)
2937   modinfo_dep = declare_dependency(link_whole: modinfo_lib)
2938   softmmu_ss.add(modinfo_dep)
2939 endif
2941 nm = find_program('nm')
2942 undefsym = find_program('scripts/undefsym.py')
2943 block_syms = custom_target('block.syms', output: 'block.syms',
2944                              input: [libqemuutil, block_mods],
2945                              capture: true,
2946                              command: [undefsym, nm, '@INPUT@'])
2947 qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
2948                              input: [libqemuutil, softmmu_mods],
2949                              capture: true,
2950                              command: [undefsym, nm, '@INPUT@'])
2952 qom_ss = qom_ss.apply(config_host, strict: false)
2953 libqom = static_library('qom', qom_ss.sources() + genh,
2954                         dependencies: [qom_ss.dependencies()],
2955                         name_suffix: 'fa')
2957 qom = declare_dependency(link_whole: libqom)
2959 authz_ss = authz_ss.apply(config_host, strict: false)
2960 libauthz = static_library('authz', authz_ss.sources() + genh,
2961                           dependencies: [authz_ss.dependencies()],
2962                           name_suffix: 'fa',
2963                           build_by_default: false)
2965 authz = declare_dependency(link_whole: libauthz,
2966                            dependencies: qom)
2968 crypto_ss = crypto_ss.apply(config_host, strict: false)
2969 libcrypto = static_library('crypto', crypto_ss.sources() + genh,
2970                            dependencies: [crypto_ss.dependencies()],
2971                            name_suffix: 'fa',
2972                            build_by_default: false)
2974 crypto = declare_dependency(link_whole: libcrypto,
2975                             dependencies: [authz, qom])
2977 io_ss = io_ss.apply(config_host, strict: false)
2978 libio = static_library('io', io_ss.sources() + genh,
2979                        dependencies: [io_ss.dependencies()],
2980                        link_with: libqemuutil,
2981                        name_suffix: 'fa',
2982                        build_by_default: false)
2984 io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
2986 libmigration = static_library('migration', sources: migration_files + genh,
2987                               name_suffix: 'fa',
2988                               build_by_default: false)
2989 migration = declare_dependency(link_with: libmigration,
2990                                dependencies: [zlib, qom, io])
2991 softmmu_ss.add(migration)
2993 block_ss = block_ss.apply(config_host, strict: false)
2994 libblock = static_library('block', block_ss.sources() + genh,
2995                           dependencies: block_ss.dependencies(),
2996                           link_depends: block_syms,
2997                           name_suffix: 'fa',
2998                           build_by_default: false)
3000 block = declare_dependency(link_whole: [libblock],
3001                            link_args: '@block.syms',
3002                            dependencies: [crypto, io])
3004 blockdev_ss = blockdev_ss.apply(config_host, strict: false)
3005 libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
3006                              dependencies: blockdev_ss.dependencies(),
3007                              name_suffix: 'fa',
3008                              build_by_default: false)
3010 blockdev = declare_dependency(link_whole: [libblockdev],
3011                               dependencies: [block])
3013 qmp_ss = qmp_ss.apply(config_host, strict: false)
3014 libqmp = static_library('qmp', qmp_ss.sources() + genh,
3015                         dependencies: qmp_ss.dependencies(),
3016                         name_suffix: 'fa',
3017                         build_by_default: false)
3019 qmp = declare_dependency(link_whole: [libqmp])
3021 libchardev = static_library('chardev', chardev_ss.sources() + genh,
3022                             name_suffix: 'fa',
3023                             dependencies: [gnutls],
3024                             build_by_default: false)
3026 chardev = declare_dependency(link_whole: libchardev)
3028 hwcore_ss = hwcore_ss.apply(config_host, strict: false)
3029 libhwcore = static_library('hwcore', sources: hwcore_ss.sources() + genh,
3030                            name_suffix: 'fa',
3031                            build_by_default: false)
3032 hwcore = declare_dependency(link_whole: libhwcore)
3033 common_ss.add(hwcore)
3035 ###########
3036 # Targets #
3037 ###########
3039 emulator_modules = []
3040 foreach m : block_mods + softmmu_mods
3041   emulator_modules += shared_module(m.name(),
3042                 build_by_default: true,
3043                 name_prefix: '',
3044                 link_whole: m,
3045                 install: true,
3046                 install_dir: qemu_moddir)
3047 endforeach
3049 softmmu_ss.add(authz, blockdev, chardev, crypto, io, qmp)
3050 common_ss.add(qom, qemuutil)
3052 common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
3053 common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
3055 common_all = common_ss.apply(config_all, strict: false)
3056 common_all = static_library('common',
3057                             build_by_default: false,
3058                             sources: common_all.sources() + genh,
3059                             include_directories: common_user_inc,
3060                             implicit_include_directories: false,
3061                             dependencies: common_all.dependencies(),
3062                             name_suffix: 'fa')
3064 feature_to_c = find_program('scripts/feature_to_c.sh')
3066 emulators = {}
3067 foreach target : target_dirs
3068   config_target = config_target_mak[target]
3069   target_name = config_target['TARGET_NAME']
3070   target_base_arch = config_target['TARGET_BASE_ARCH']
3071   arch_srcs = [config_target_h[target]]
3072   arch_deps = []
3073   c_args = ['-DNEED_CPU_H',
3074             '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3075             '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3076   link_args = emulator_link_args
3078   config_target += config_host
3079   target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3080   if targetos == 'linux'
3081     target_inc += include_directories('linux-headers', is_system: true)
3082   endif
3083   if target.endswith('-softmmu')
3084     qemu_target_name = 'qemu-system-' + target_name
3085     target_type='system'
3086     t = target_softmmu_arch[target_base_arch].apply(config_target, strict: false)
3087     arch_srcs += t.sources()
3088     arch_deps += t.dependencies()
3090     hw_dir = target_name == 'sparc64' ? 'sparc64' : target_base_arch
3091     hw = hw_arch[hw_dir].apply(config_target, strict: false)
3092     arch_srcs += hw.sources()
3093     arch_deps += hw.dependencies()
3095     arch_srcs += config_devices_h[target]
3096     link_args += ['@block.syms', '@qemu.syms']
3097   else
3098     abi = config_target['TARGET_ABI_DIR']
3099     target_type='user'
3100     target_inc += common_user_inc
3101     qemu_target_name = 'qemu-' + target_name
3102     if target_base_arch in target_user_arch
3103       t = target_user_arch[target_base_arch].apply(config_target, strict: false)
3104       arch_srcs += t.sources()
3105       arch_deps += t.dependencies()
3106     endif
3107     if 'CONFIG_LINUX_USER' in config_target
3108       base_dir = 'linux-user'
3109     endif
3110     if 'CONFIG_BSD_USER' in config_target
3111       base_dir = 'bsd-user'
3112       target_inc += include_directories('bsd-user/' / targetos)
3113       target_inc += include_directories('bsd-user/host/' / host_arch)
3114       dir = base_dir / abi
3115       arch_srcs += files(dir / 'signal.c', dir / 'target_arch_cpu.c')
3116     endif
3117     target_inc += include_directories(
3118       base_dir,
3119       base_dir / abi,
3120     )
3121     if 'CONFIG_LINUX_USER' in config_target
3122       dir = base_dir / abi
3123       arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
3124       if config_target.has_key('TARGET_SYSTBL_ABI')
3125         arch_srcs += \
3126           syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
3127                                              extra_args : config_target['TARGET_SYSTBL_ABI'])
3128       endif
3129     endif
3130   endif
3132   if 'TARGET_XML_FILES' in config_target
3133     gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
3134                                 output: target + '-gdbstub-xml.c',
3135                                 input: files(config_target['TARGET_XML_FILES'].split()),
3136                                 command: [feature_to_c, '@INPUT@'],
3137                                 capture: true)
3138     arch_srcs += gdbstub_xml
3139   endif
3141   t = target_arch[target_base_arch].apply(config_target, strict: false)
3142   arch_srcs += t.sources()
3143   arch_deps += t.dependencies()
3145   target_common = common_ss.apply(config_target, strict: false)
3146   objects = common_all.extract_objects(target_common.sources())
3147   deps = target_common.dependencies()
3149   target_specific = specific_ss.apply(config_target, strict: false)
3150   arch_srcs += target_specific.sources()
3151   arch_deps += target_specific.dependencies()
3153   lib = static_library('qemu-' + target,
3154                  sources: arch_srcs + genh,
3155                  dependencies: arch_deps,
3156                  objects: objects,
3157                  include_directories: target_inc,
3158                  c_args: c_args,
3159                  build_by_default: false,
3160                  name_suffix: 'fa')
3162   if target.endswith('-softmmu')
3163     execs = [{
3164       'name': 'qemu-system-' + target_name,
3165       'win_subsystem': 'console',
3166       'sources': files('softmmu/main.c'),
3167       'dependencies': []
3168     }]
3169     if targetos == 'windows' and (sdl.found() or gtk.found())
3170       execs += [{
3171         'name': 'qemu-system-' + target_name + 'w',
3172         'win_subsystem': 'windows',
3173         'sources': files('softmmu/main.c'),
3174         'dependencies': []
3175       }]
3176     endif
3177     if get_option('fuzzing')
3178       specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
3179       execs += [{
3180         'name': 'qemu-fuzz-' + target_name,
3181         'win_subsystem': 'console',
3182         'sources': specific_fuzz.sources(),
3183         'dependencies': specific_fuzz.dependencies(),
3184       }]
3185     endif
3186   else
3187     execs = [{
3188       'name': 'qemu-' + target_name,
3189       'win_subsystem': 'console',
3190       'sources': [],
3191       'dependencies': []
3192     }]
3193   endif
3194   foreach exe: execs
3195     exe_name = exe['name']
3196     if targetos == 'darwin'
3197       exe_name += '-unsigned'
3198     endif
3200     emulator = executable(exe_name, exe['sources'],
3201                install: true,
3202                c_args: c_args,
3203                dependencies: arch_deps + deps + exe['dependencies'],
3204                objects: lib.extract_all_objects(recursive: true),
3205                link_language: link_language,
3206                link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
3207                link_args: link_args,
3208                win_subsystem: exe['win_subsystem'])
3210     if targetos == 'darwin'
3211       icon = 'pc-bios/qemu.rsrc'
3212       build_input = [emulator, files(icon)]
3213       install_input = [
3214         get_option('bindir') / exe_name,
3215         meson.current_source_dir() / icon
3216       ]
3217       if 'CONFIG_HVF' in config_target
3218         entitlements = 'accel/hvf/entitlements.plist'
3219         build_input += files(entitlements)
3220         install_input += meson.current_source_dir() / entitlements
3221       endif
3223       entitlement = find_program('scripts/entitlement.sh')
3224       emulators += {exe['name'] : custom_target(exe['name'],
3225                    input: build_input,
3226                    output: exe['name'],
3227                    command: [entitlement, '@OUTPUT@', '@INPUT@'])
3228       }
3230       meson.add_install_script(entitlement, '--install',
3231                                get_option('bindir') / exe['name'],
3232                                install_input)
3233     else
3234       emulators += {exe['name']: emulator}
3235     endif
3237     if stap.found()
3238       foreach stp: [
3239         {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
3240         {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
3241         {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
3242         {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
3243       ]
3244         custom_target(exe['name'] + stp['ext'],
3245                       input: trace_events_all,
3246                       output: exe['name'] + stp['ext'],
3247                       install: stp['install'],
3248                       install_dir: get_option('datadir') / 'systemtap/tapset',
3249                       command: [
3250                         tracetool, '--group=all', '--format=' + stp['fmt'],
3251                         '--binary=' + stp['bin'],
3252                         '--target-name=' + target_name,
3253                         '--target-type=' + target_type,
3254                         '--probe-prefix=qemu.' + target_type + '.' + target_name,
3255                         '@INPUT@', '@OUTPUT@'
3256                       ],
3257                       depend_files: tracetool_depends)
3258       endforeach
3259     endif
3260   endforeach
3261 endforeach
3263 # Other build targets
3265 if 'CONFIG_PLUGIN' in config_host
3266   install_headers('include/qemu/qemu-plugin.h')
3267 endif
3269 subdir('qga')
3271 # Don't build qemu-keymap if xkbcommon is not explicitly enabled
3272 # when we don't build tools or system
3273 if xkbcommon.found()
3274   # used for the update-keymaps target, so include rules even if !have_tools
3275   qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
3276                            dependencies: [qemuutil, xkbcommon], install: have_tools)
3277 endif
3279 if have_tools
3280   qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
3281              dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
3282   qemu_io = executable('qemu-io', files('qemu-io.c'),
3283              dependencies: [block, qemuutil], install: true)
3284   qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
3285                dependencies: [blockdev, qemuutil, gnutls, selinux],
3286                install: true)
3288   subdir('storage-daemon')
3289   subdir('contrib/rdmacm-mux')
3290   subdir('contrib/elf2dmp')
3292   executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
3293              dependencies: qemuutil,
3294              install: true)
3296   if 'CONFIG_VHOST_USER' in config_host
3297     subdir('contrib/vhost-user-blk')
3298     subdir('contrib/vhost-user-gpu')
3299     subdir('contrib/vhost-user-input')
3300     subdir('contrib/vhost-user-scsi')
3301   endif
3303   if targetos == 'linux'
3304     executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
3305                dependencies: [qemuutil, libcap_ng],
3306                install: true,
3307                install_dir: get_option('libexecdir'))
3309     executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
3310                dependencies: [authz, crypto, io, qom, qemuutil,
3311                               libcap_ng, mpathpersist],
3312                install: true)
3313   endif
3315   if have_ivshmem
3316     subdir('contrib/ivshmem-client')
3317     subdir('contrib/ivshmem-server')
3318   endif
3319 endif
3321 subdir('scripts')
3322 subdir('tools')
3323 subdir('pc-bios')
3324 subdir('docs')
3325 subdir('tests')
3326 if gtk.found()
3327   subdir('po')
3328 endif
3330 if host_machine.system() == 'windows'
3331   nsis_cmd = [
3332     find_program('scripts/nsis.py'),
3333     '@OUTPUT@',
3334     get_option('prefix'),
3335     meson.current_source_dir(),
3336     host_machine.cpu(),
3337     '--',
3338     '-DDISPLAYVERSION=' + meson.project_version(),
3339   ]
3340   if build_docs
3341     nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
3342   endif
3343   if gtk.found()
3344     nsis_cmd += '-DCONFIG_GTK=y'
3345   endif
3347   nsis = custom_target('nsis',
3348                        output: 'qemu-setup-' + meson.project_version() + '.exe',
3349                        input: files('qemu.nsi'),
3350                        build_always_stale: true,
3351                        command: nsis_cmd + ['@INPUT@'])
3352   alias_target('installer', nsis)
3353 endif
3355 #########################
3356 # Configuration summary #
3357 #########################
3359 # Directories
3360 summary_info = {}
3361 summary_info += {'Install prefix':    get_option('prefix')}
3362 summary_info += {'BIOS directory':    qemu_datadir}
3363 summary_info += {'firmware path':     get_option('qemu_firmwarepath')}
3364 summary_info += {'binary directory':  get_option('bindir')}
3365 summary_info += {'library directory': get_option('libdir')}
3366 summary_info += {'module directory':  qemu_moddir}
3367 summary_info += {'libexec directory': get_option('libexecdir')}
3368 summary_info += {'include directory': get_option('includedir')}
3369 summary_info += {'config directory':  get_option('sysconfdir')}
3370 if targetos != 'windows'
3371   summary_info += {'local state directory': get_option('localstatedir')}
3372   summary_info += {'Manual directory':      get_option('mandir')}
3373 else
3374   summary_info += {'local state directory': 'queried at runtime'}
3375 endif
3376 summary_info += {'Doc directory':     get_option('docdir')}
3377 summary_info += {'Build directory':   meson.current_build_dir()}
3378 summary_info += {'Source path':       meson.current_source_dir()}
3379 summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
3380 summary(summary_info, bool_yn: true, section: 'Directories')
3382 # Host binaries
3383 summary_info = {}
3384 summary_info += {'git':               config_host['GIT']}
3385 summary_info += {'make':              config_host['MAKE']}
3386 summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
3387 summary_info += {'sphinx-build':      sphinx_build}
3388 if config_host.has_key('HAVE_GDB_BIN')
3389   summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
3390 endif
3391 if get_option('iasl') != ''
3392   summary_info += {'iasl':            get_option('iasl')}
3393 else
3394   summary_info += {'iasl':            false}
3395 endif
3396 summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
3397 if targetos == 'windows' and have_ga
3398   summary_info += {'wixl':            wixl}
3399 endif
3400 if slirp_opt != 'disabled' and have_system
3401   summary_info += {'smbd':            have_slirp_smbd ? smbd_path : false}
3402 endif
3403 summary(summary_info, bool_yn: true, section: 'Host binaries')
3405 # Configurable features
3406 summary_info = {}
3407 summary_info += {'Documentation':     build_docs}
3408 summary_info += {'system-mode emulation': have_system}
3409 summary_info += {'user-mode emulation': have_user}
3410 summary_info += {'block layer':       have_block}
3411 summary_info += {'Install blobs':     get_option('install_blobs')}
3412 summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
3413 if config_host.has_key('CONFIG_MODULES')
3414   summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')}
3415 endif
3416 summary_info += {'fuzzing support':   get_option('fuzzing')}
3417 if have_system
3418   summary_info += {'Audio drivers':     ' '.join(audio_drivers_selected)}
3419 endif
3420 summary_info += {'Trace backends':    ','.join(get_option('trace_backends'))}
3421 if 'simple' in get_option('trace_backends')
3422   summary_info += {'Trace output file': get_option('trace_file') + '-<pid>'}
3423 endif
3424 summary_info += {'D-Bus display':     dbus_display}
3425 summary_info += {'QOM debugging':     get_option('qom_cast_debug')}
3426 summary_info += {'vhost-kernel support': config_host.has_key('CONFIG_VHOST_KERNEL')}
3427 summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')}
3428 summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')}
3429 summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')}
3430 summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')}
3431 summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_USER')}
3432 summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
3433 summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')}
3434 summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')}
3435 summary_info += {'build guest agent': have_ga}
3436 summary(summary_info, bool_yn: true, section: 'Configurable features')
3438 # Compilation information
3439 summary_info = {}
3440 summary_info += {'host CPU':          cpu}
3441 summary_info += {'host endianness':   build_machine.endian()}
3442 summary_info += {'C compiler':        ' '.join(meson.get_compiler('c').cmd_array())}
3443 summary_info += {'Host C compiler':   ' '.join(meson.get_compiler('c', native: true).cmd_array())}
3444 if link_language == 'cpp'
3445   summary_info += {'C++ compiler':    ' '.join(meson.get_compiler('cpp').cmd_array())}
3446 else
3447   summary_info += {'C++ compiler':      false}
3448 endif
3449 if targetos == 'darwin'
3450   summary_info += {'Objective-C compiler': ' '.join(meson.get_compiler('objc').cmd_array())}
3451 endif
3452 summary_info += {'CFLAGS':            ' '.join(get_option('c_args')
3453                                                + ['-O' + get_option('optimization')]
3454                                                + (get_option('debug') ? ['-g'] : []))}
3455 if link_language == 'cpp'
3456   summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args')
3457                                                + ['-O' + get_option('optimization')]
3458                                                + (get_option('debug') ? ['-g'] : []))}
3459 endif
3460 link_args = get_option(link_language + '_link_args')
3461 if link_args.length() > 0
3462   summary_info += {'LDFLAGS':         ' '.join(link_args)}
3463 endif
3464 summary_info += {'QEMU_CFLAGS':       config_host['QEMU_CFLAGS']}
3465 summary_info += {'QEMU_LDFLAGS':      config_host['QEMU_LDFLAGS']}
3466 summary_info += {'profiler':          get_option('profiler')}
3467 summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
3468 summary_info += {'PIE':               get_option('b_pie')}
3469 summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
3470 summary_info += {'malloc trim support': has_malloc_trim}
3471 summary_info += {'membarrier':        have_membarrier}
3472 summary_info += {'debug stack usage': get_option('debug_stack_usage')}
3473 summary_info += {'mutex debugging':   get_option('debug_mutex')}
3474 summary_info += {'memory allocator':  get_option('malloc')}
3475 summary_info += {'avx2 optimization': config_host_data.get('CONFIG_AVX2_OPT')}
3476 summary_info += {'avx512f optimization': config_host_data.get('CONFIG_AVX512F_OPT')}
3477 summary_info += {'gprof enabled':     get_option('gprof')}
3478 summary_info += {'gcov':              get_option('b_coverage')}
3479 summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
3480 summary_info += {'CFI support':       get_option('cfi')}
3481 if get_option('cfi')
3482   summary_info += {'CFI debug support': get_option('cfi_debug')}
3483 endif
3484 summary_info += {'strip binaries':    get_option('strip')}
3485 summary_info += {'sparse':            sparse}
3486 summary_info += {'mingw32 support':   targetos == 'windows'}
3488 # snarf the cross-compilation information for tests
3489 foreach target: target_dirs
3490   tcg_mak = meson.current_build_dir() / 'tests/tcg' / 'config-' + target + '.mak'
3491   if fs.exists(tcg_mak)
3492     config_cross_tcg = keyval.load(tcg_mak)
3493     target = config_cross_tcg['TARGET_NAME']
3494     compiler = ''
3495     if 'DOCKER_CROSS_CC_GUEST' in config_cross_tcg
3496       summary_info += {target + ' tests': config_cross_tcg['DOCKER_CROSS_CC_GUEST'] +
3497                                           ' via ' + config_cross_tcg['DOCKER_IMAGE']}
3498     elif 'CROSS_CC_GUEST' in config_cross_tcg
3499       summary_info += {target + ' tests'
3500                                 : config_cross_tcg['CROSS_CC_GUEST'] }
3501     endif
3502    endif
3503 endforeach
3505 summary(summary_info, bool_yn: true, section: 'Compilation')
3507 # Targets and accelerators
3508 summary_info = {}
3509 if have_system
3510   summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
3511   summary_info += {'HAX support':       config_all.has_key('CONFIG_HAX')}
3512   summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
3513   summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
3514   summary_info += {'NVMM support':      config_all.has_key('CONFIG_NVMM')}
3515   summary_info += {'Xen support':       config_host.has_key('CONFIG_XEN_BACKEND')}
3516   if config_host.has_key('CONFIG_XEN_BACKEND')
3517     summary_info += {'xen ctrl version':  config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
3518   endif
3519 endif
3520 summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
3521 if config_all.has_key('CONFIG_TCG')
3522   if get_option('tcg_interpreter')
3523     summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, slow)'}
3524   else
3525     summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
3526   endif
3527   summary_info += {'TCG plugins': config_host.has_key('CONFIG_PLUGIN')}
3528   summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
3529 endif
3530 summary_info += {'target list':       ' '.join(target_dirs)}
3531 if have_system
3532   summary_info += {'default devices':   get_option('default_devices')}
3533   summary_info += {'out of process emulation': multiprocess_allowed}
3534 endif
3535 summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
3537 # Block layer
3538 summary_info = {}
3539 summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
3540 summary_info += {'coroutine pool':    have_coroutine_pool}
3541 if have_block
3542   summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']}
3543   summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']}
3544   summary_info += {'Use block whitelist in tools': get_option('block_drv_whitelist_in_tools')}
3545   summary_info += {'VirtFS support':    have_virtfs}
3546   summary_info += {'build virtiofs daemon': have_virtiofsd}
3547   summary_info += {'Live block migration': config_host_data.get('CONFIG_LIVE_BLOCK_MIGRATION')}
3548   summary_info += {'replication support': config_host_data.get('CONFIG_REPLICATION')}
3549   summary_info += {'bochs support':     get_option('bochs').allowed()}
3550   summary_info += {'cloop support':     get_option('cloop').allowed()}
3551   summary_info += {'dmg support':       get_option('dmg').allowed()}
3552   summary_info += {'qcow v1 support':   get_option('qcow1').allowed()}
3553   summary_info += {'vdi support':       get_option('vdi').allowed()}
3554   summary_info += {'vvfat support':     get_option('vvfat').allowed()}
3555   summary_info += {'qed support':       get_option('qed').allowed()}
3556   summary_info += {'parallels support': get_option('parallels').allowed()}
3557   summary_info += {'FUSE exports':      fuse}
3558 endif
3559 summary(summary_info, bool_yn: true, section: 'Block layer support')
3561 # Crypto
3562 summary_info = {}
3563 summary_info += {'TLS priority':      config_host['CONFIG_TLS_PRIORITY']}
3564 summary_info += {'GNUTLS support':    gnutls}
3565 if gnutls.found()
3566   summary_info += {'  GNUTLS crypto':   gnutls_crypto.found()}
3567 endif
3568 summary_info += {'libgcrypt':         gcrypt}
3569 summary_info += {'nettle':            nettle}
3570 if nettle.found()
3571    summary_info += {'  XTS':             xts != 'private'}
3572 endif
3573 summary_info += {'AF_ALG support':    have_afalg}
3574 summary_info += {'rng-none':          get_option('rng_none')}
3575 summary_info += {'Linux keyring':     config_host.has_key('CONFIG_SECRET_KEYRING')}
3576 summary(summary_info, bool_yn: true, section: 'Crypto')
3578 # Libraries
3579 summary_info = {}
3580 if targetos == 'darwin'
3581   summary_info += {'Cocoa support':   cocoa}
3582 endif
3583 summary_info += {'SDL support':       sdl}
3584 summary_info += {'SDL image support': sdl_image}
3585 summary_info += {'GTK support':       gtk}
3586 summary_info += {'pixman':            pixman}
3587 summary_info += {'VTE support':       vte}
3588 summary_info += {'slirp support':     slirp_opt == 'internal' ? slirp_opt : slirp}
3589 summary_info += {'libtasn1':          tasn1}
3590 summary_info += {'PAM':               pam}
3591 summary_info += {'iconv support':     iconv}
3592 summary_info += {'curses support':    curses}
3593 summary_info += {'virgl support':     virgl}
3594 summary_info += {'curl support':      curl}
3595 summary_info += {'Multipath support': mpathpersist}
3596 summary_info += {'VNC support':       vnc}
3597 if vnc.found()
3598   summary_info += {'VNC SASL support':  sasl}
3599   summary_info += {'VNC JPEG support':  jpeg}
3600   summary_info += {'VNC PNG support':   png}
3601 endif
3602 if targetos not in ['darwin', 'haiku', 'windows']
3603   summary_info += {'OSS support':     oss}
3604 elif targetos == 'darwin'
3605   summary_info += {'CoreAudio support': coreaudio}
3606 elif targetos == 'windows'
3607   summary_info += {'DirectSound support': dsound}
3608 endif
3609 if targetos == 'linux'
3610   summary_info += {'ALSA support':    alsa}
3611   summary_info += {'PulseAudio support': pulse}
3612 endif
3613 summary_info += {'JACK support':      jack}
3614 summary_info += {'brlapi support':    brlapi}
3615 summary_info += {'vde support':       vde}
3616 summary_info += {'netmap support':    have_netmap}
3617 summary_info += {'l2tpv3 support':    have_l2tpv3}
3618 summary_info += {'Linux AIO support': libaio}
3619 summary_info += {'Linux io_uring support': linux_io_uring}
3620 summary_info += {'ATTR/XATTR support': libattr}
3621 summary_info += {'RDMA support':      config_host.has_key('CONFIG_RDMA')}
3622 summary_info += {'PVRDMA support':    config_host.has_key('CONFIG_PVRDMA')}
3623 summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
3624 summary_info += {'libcap-ng support': libcap_ng}
3625 summary_info += {'bpf support':       libbpf}
3626 summary_info += {'spice protocol support': spice_protocol}
3627 if spice_protocol.found()
3628   summary_info += {'  spice server support': spice}
3629 endif
3630 summary_info += {'rbd support':       rbd}
3631 summary_info += {'smartcard support': cacard}
3632 summary_info += {'U2F support':       u2f}
3633 summary_info += {'libusb':            libusb}
3634 summary_info += {'usb net redir':     usbredir}
3635 summary_info += {'OpenGL support':    config_host.has_key('CONFIG_OPENGL')}
3636 summary_info += {'GBM':               gbm}
3637 summary_info += {'libiscsi support':  libiscsi}
3638 summary_info += {'libnfs support':    libnfs}
3639 if targetos == 'windows'
3640   if have_ga
3641     summary_info += {'QGA VSS support':   have_qga_vss}
3642     summary_info += {'QGA w32 disk info': have_ntddscsi}
3643   endif
3644 endif
3645 summary_info += {'seccomp support':   seccomp}
3646 summary_info += {'GlusterFS support': glusterfs}
3647 summary_info += {'TPM support':       have_tpm}
3648 summary_info += {'libssh support':    libssh}
3649 summary_info += {'lzo support':       lzo}
3650 summary_info += {'snappy support':    snappy}
3651 summary_info += {'bzip2 support':     libbzip2}
3652 summary_info += {'lzfse support':     liblzfse}
3653 summary_info += {'zstd support':      zstd}
3654 summary_info += {'NUMA host support': numa}
3655 summary_info += {'capstone':          capstone_opt == 'internal' ? capstone_opt : capstone}
3656 summary_info += {'libpmem support':   libpmem}
3657 summary_info += {'libdaxctl support': libdaxctl}
3658 summary_info += {'libudev':           libudev}
3659 # Dummy dependency, keep .found()
3660 summary_info += {'FUSE lseek':        fuse_lseek.found()}
3661 summary_info += {'selinux':           selinux}
3662 summary(summary_info, bool_yn: true, section: 'Dependencies')
3664 if not supported_cpus.contains(cpu)
3665   message()
3666   warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
3667   message()
3668   message('CPU host architecture ' + cpu + ' support is not currently maintained.')
3669   message('The QEMU project intends to remove support for this host CPU in')
3670   message('a future release if nobody volunteers to maintain it and to')
3671   message('provide a build host for our continuous integration setup.')
3672   message('configure has succeeded and you can continue to build, but')
3673   message('if you care about QEMU on this platform you should contact')
3674   message('us upstream at qemu-devel@nongnu.org.')
3675 endif
3677 if not supported_oses.contains(targetos)
3678   message()
3679   warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
3680   message()
3681   message('Host OS ' + targetos + 'support is not currently maintained.')
3682   message('The QEMU project intends to remove support for this host OS in')
3683   message('a future release if nobody volunteers to maintain it and to')
3684   message('provide a build host for our continuous integration setup.')
3685   message('configure has succeeded and you can continue to build, but')
3686   message('if you care about QEMU on this platform you should contact')
3687   message('us upstream at qemu-devel@nongnu.org.')
3688 endif