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