xref: /openbmc/qemu/meson.build (revision fc309207)
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()
2368hwcore_ss = ss.source_set()
2369io_ss = ss.source_set()
2370linux_user_ss = ss.source_set()
2371qmp_ss = ss.source_set()
2372qom_ss = ss.source_set()
2373softmmu_ss = ss.source_set()
2374specific_fuzz_ss = ss.source_set()
2375specific_ss = ss.source_set()
2376stub_ss = ss.source_set()
2377trace_ss = ss.source_set()
2378user_ss = ss.source_set()
2379util_ss = ss.source_set()
2380
2381# accel modules
2382qtest_module_ss = ss.source_set()
2383tcg_module_ss = ss.source_set()
2384
2385modules = {}
2386target_modules = {}
2387hw_arch = {}
2388target_arch = {}
2389target_softmmu_arch = {}
2390target_user_arch = {}
2391
2392###############
2393# Trace files #
2394###############
2395
2396# TODO: add each directory to the subdirs from its own meson.build, once
2397# we have those
2398trace_events_subdirs = [
2399  'crypto',
2400  'qapi',
2401  'qom',
2402  'monitor',
2403  'util',
2404]
2405if have_user
2406  trace_events_subdirs += [ 'linux-user' ]
2407endif
2408if have_block
2409  trace_events_subdirs += [
2410    'authz',
2411    'block',
2412    'io',
2413    'nbd',
2414    'scsi',
2415  ]
2416endif
2417if have_system
2418  trace_events_subdirs += [
2419    'accel/kvm',
2420    'audio',
2421    'backends',
2422    'backends/tpm',
2423    'chardev',
2424    'ebpf',
2425    'hw/9pfs',
2426    'hw/acpi',
2427    'hw/adc',
2428    'hw/alpha',
2429    'hw/arm',
2430    'hw/audio',
2431    'hw/block',
2432    'hw/block/dataplane',
2433    'hw/char',
2434    'hw/display',
2435    'hw/dma',
2436    'hw/hppa',
2437    'hw/hyperv',
2438    'hw/i2c',
2439    'hw/i386',
2440    'hw/i386/xen',
2441    'hw/ide',
2442    'hw/input',
2443    'hw/intc',
2444    'hw/isa',
2445    'hw/mem',
2446    'hw/mips',
2447    'hw/misc',
2448    'hw/misc/macio',
2449    'hw/net',
2450    'hw/net/can',
2451    'hw/nubus',
2452    'hw/nvme',
2453    'hw/nvram',
2454    'hw/pci',
2455    'hw/pci-host',
2456    'hw/ppc',
2457    'hw/rdma',
2458    'hw/rdma/vmw',
2459    'hw/rtc',
2460    'hw/s390x',
2461    'hw/scsi',
2462    'hw/sd',
2463    'hw/sh4',
2464    'hw/sparc',
2465    'hw/sparc64',
2466    'hw/ssi',
2467    'hw/timer',
2468    'hw/tpm',
2469    'hw/usb',
2470    'hw/vfio',
2471    'hw/virtio',
2472    'hw/watchdog',
2473    'hw/xen',
2474    'hw/gpio',
2475    'migration',
2476    'net',
2477    'softmmu',
2478    'ui',
2479    'hw/remote',
2480  ]
2481endif
2482if have_system or have_user
2483  trace_events_subdirs += [
2484    'accel/tcg',
2485    'hw/core',
2486    'target/arm',
2487    'target/arm/hvf',
2488    'target/hppa',
2489    'target/i386',
2490    'target/i386/kvm',
2491    'target/mips/tcg',
2492    'target/ppc',
2493    'target/riscv',
2494    'target/s390x',
2495    'target/s390x/kvm',
2496    'target/sparc',
2497  ]
2498endif
2499
2500vhost_user = not_found
2501if 'CONFIG_VHOST_USER' in config_host
2502  libvhost_user = subproject('libvhost-user')
2503  vhost_user = libvhost_user.get_variable('vhost_user_dep')
2504endif
2505
2506subdir('qapi')
2507subdir('qobject')
2508subdir('stubs')
2509subdir('trace')
2510subdir('util')
2511subdir('qom')
2512subdir('authz')
2513subdir('crypto')
2514subdir('ui')
2515
2516
2517if enable_modules
2518  libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
2519  modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
2520endif
2521
2522stub_ss = stub_ss.apply(config_all, strict: false)
2523
2524util_ss.add_all(trace_ss)
2525util_ss = util_ss.apply(config_all, strict: false)
2526libqemuutil = static_library('qemuutil',
2527                             sources: util_ss.sources() + stub_ss.sources() + genh,
2528                             dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc, pixman])
2529qemuutil = declare_dependency(link_with: libqemuutil,
2530                              sources: genh + version_res)
2531
2532if have_system or have_user
2533  decodetree = generator(find_program('scripts/decodetree.py'),
2534                         output: 'decode-@BASENAME@.c.inc',
2535                         arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
2536  subdir('libdecnumber')
2537  subdir('target')
2538endif
2539
2540subdir('audio')
2541subdir('io')
2542subdir('chardev')
2543subdir('fsdev')
2544subdir('dump')
2545
2546if have_block
2547  block_ss.add(files(
2548    'block.c',
2549    'blockjob.c',
2550    'job.c',
2551    'qemu-io-cmds.c',
2552  ))
2553  block_ss.add(when: 'CONFIG_REPLICATION', if_true: files('replication.c'))
2554
2555  subdir('nbd')
2556  subdir('scsi')
2557  subdir('block')
2558
2559  blockdev_ss.add(files(
2560    'blockdev.c',
2561    'blockdev-nbd.c',
2562    'iothread.c',
2563    'job-qmp.c',
2564  ), gnutls)
2565
2566  # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
2567  # os-win32.c does not
2568  blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
2569  softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
2570endif
2571
2572common_ss.add(files('cpus-common.c'))
2573
2574subdir('softmmu')
2575
2576common_ss.add(capstone)
2577specific_ss.add(files('cpu.c', 'disas.c', 'gdbstub.c'), capstone)
2578
2579# Work around a gcc bug/misfeature wherein constant propagation looks
2580# through an alias:
2581#   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99696
2582# to guess that a const variable is always zero.  Without lto, this is
2583# impossible, as the alias is restricted to page-vary-common.c.  Indeed,
2584# without lto, not even the alias is required -- we simply use different
2585# declarations in different compilation units.
2586pagevary = files('page-vary-common.c')
2587if get_option('b_lto')
2588  pagevary_flags = ['-fno-lto']
2589  if get_option('cfi')
2590    pagevary_flags += '-fno-sanitize=cfi-icall'
2591  endif
2592  pagevary = static_library('page-vary-common', sources: pagevary,
2593                            c_args: pagevary_flags)
2594  pagevary = declare_dependency(link_with: pagevary)
2595endif
2596common_ss.add(pagevary)
2597specific_ss.add(files('page-vary.c'))
2598
2599subdir('backends')
2600subdir('disas')
2601subdir('migration')
2602subdir('monitor')
2603subdir('net')
2604subdir('replay')
2605subdir('semihosting')
2606subdir('hw')
2607subdir('tcg')
2608subdir('fpu')
2609subdir('accel')
2610subdir('plugins')
2611subdir('bsd-user')
2612subdir('linux-user')
2613subdir('ebpf')
2614
2615common_ss.add(libbpf)
2616
2617specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss)
2618
2619linux_user_ss.add(files('thunk.c'))
2620specific_ss.add_all(when: 'CONFIG_LINUX_USER', if_true: linux_user_ss)
2621
2622# needed for fuzzing binaries
2623subdir('tests/qtest/libqos')
2624subdir('tests/qtest/fuzz')
2625
2626# accel modules
2627tcg_real_module_ss = ss.source_set()
2628tcg_real_module_ss.add_all(when: 'CONFIG_TCG_MODULAR', if_true: tcg_module_ss)
2629specific_ss.add_all(when: 'CONFIG_TCG_BUILTIN', if_true: tcg_module_ss)
2630target_modules += { 'accel' : { 'qtest': qtest_module_ss,
2631                                'tcg': tcg_real_module_ss }}
2632
2633########################
2634# Library dependencies #
2635########################
2636
2637modinfo_collect = find_program('scripts/modinfo-collect.py')
2638modinfo_generate = find_program('scripts/modinfo-generate.py')
2639modinfo_files = []
2640
2641block_mods = []
2642softmmu_mods = []
2643foreach d, list : modules
2644  foreach m, module_ss : list
2645    if enable_modules and targetos != 'windows'
2646      module_ss = module_ss.apply(config_all, strict: false)
2647      sl = static_library(d + '-' + m, [genh, module_ss.sources()],
2648                          dependencies: [modulecommon, module_ss.dependencies()], pic: true)
2649      if d == 'block'
2650        block_mods += sl
2651      else
2652        softmmu_mods += sl
2653      endif
2654      if module_ss.sources() != []
2655        # FIXME: Should use sl.extract_all_objects(recursive: true) as
2656        # input. Sources can be used multiple times but objects are
2657        # unique when it comes to lookup in compile_commands.json.
2658        # Depnds on a mesion version with
2659        # https://github.com/mesonbuild/meson/pull/8900
2660        modinfo_files += custom_target(d + '-' + m + '.modinfo',
2661                                       output: d + '-' + m + '.modinfo',
2662                                       input: module_ss.sources() + genh,
2663                                       capture: true,
2664                                       command: [modinfo_collect, module_ss.sources()])
2665      endif
2666    else
2667      if d == 'block'
2668        block_ss.add_all(module_ss)
2669      else
2670        softmmu_ss.add_all(module_ss)
2671      endif
2672    endif
2673  endforeach
2674endforeach
2675
2676foreach d, list : target_modules
2677  foreach m, module_ss : list
2678    if enable_modules and targetos != 'windows'
2679      foreach target : target_dirs
2680        if target.endswith('-softmmu')
2681          config_target = config_target_mak[target]
2682          config_target += config_host
2683          target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
2684          c_args = ['-DNEED_CPU_H',
2685                    '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
2686                    '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
2687          target_module_ss = module_ss.apply(config_target, strict: false)
2688          if target_module_ss.sources() != []
2689            module_name = d + '-' + m + '-' + config_target['TARGET_NAME']
2690            sl = static_library(module_name,
2691                                [genh, target_module_ss.sources()],
2692                                dependencies: [modulecommon, target_module_ss.dependencies()],
2693                                include_directories: target_inc,
2694                                c_args: c_args,
2695                                pic: true)
2696            softmmu_mods += sl
2697            # FIXME: Should use sl.extract_all_objects(recursive: true) too.
2698            modinfo_files += custom_target(module_name + '.modinfo',
2699                                           output: module_name + '.modinfo',
2700                                           input: target_module_ss.sources() + genh,
2701                                           capture: true,
2702                                           command: [modinfo_collect, '--target', target, target_module_ss.sources()])
2703          endif
2704        endif
2705      endforeach
2706    else
2707      specific_ss.add_all(module_ss)
2708    endif
2709  endforeach
2710endforeach
2711
2712if enable_modules
2713  modinfo_src = custom_target('modinfo.c',
2714                              output: 'modinfo.c',
2715                              input: modinfo_files,
2716                              command: [modinfo_generate, '@INPUT@'],
2717                              capture: true)
2718  modinfo_lib = static_library('modinfo', modinfo_src)
2719  modinfo_dep = declare_dependency(link_whole: modinfo_lib)
2720  softmmu_ss.add(modinfo_dep)
2721endif
2722
2723nm = find_program('nm')
2724undefsym = find_program('scripts/undefsym.py')
2725block_syms = custom_target('block.syms', output: 'block.syms',
2726                             input: [libqemuutil, block_mods],
2727                             capture: true,
2728                             command: [undefsym, nm, '@INPUT@'])
2729qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
2730                             input: [libqemuutil, softmmu_mods],
2731                             capture: true,
2732                             command: [undefsym, nm, '@INPUT@'])
2733
2734qom_ss = qom_ss.apply(config_host, strict: false)
2735libqom = static_library('qom', qom_ss.sources() + genh,
2736                        dependencies: [qom_ss.dependencies()],
2737                        name_suffix: 'fa')
2738
2739qom = declare_dependency(link_whole: libqom)
2740
2741authz_ss = authz_ss.apply(config_host, strict: false)
2742libauthz = static_library('authz', authz_ss.sources() + genh,
2743                          dependencies: [authz_ss.dependencies()],
2744                          name_suffix: 'fa',
2745                          build_by_default: false)
2746
2747authz = declare_dependency(link_whole: libauthz,
2748                           dependencies: qom)
2749
2750crypto_ss = crypto_ss.apply(config_host, strict: false)
2751libcrypto = static_library('crypto', crypto_ss.sources() + genh,
2752                           dependencies: [crypto_ss.dependencies()],
2753                           name_suffix: 'fa',
2754                           build_by_default: false)
2755
2756crypto = declare_dependency(link_whole: libcrypto,
2757                            dependencies: [authz, qom])
2758
2759io_ss = io_ss.apply(config_host, strict: false)
2760libio = static_library('io', io_ss.sources() + genh,
2761                       dependencies: [io_ss.dependencies()],
2762                       link_with: libqemuutil,
2763                       name_suffix: 'fa',
2764                       build_by_default: false)
2765
2766io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
2767
2768libmigration = static_library('migration', sources: migration_files + genh,
2769                              name_suffix: 'fa',
2770                              build_by_default: false)
2771migration = declare_dependency(link_with: libmigration,
2772                               dependencies: [zlib, qom, io])
2773softmmu_ss.add(migration)
2774
2775block_ss = block_ss.apply(config_host, strict: false)
2776libblock = static_library('block', block_ss.sources() + genh,
2777                          dependencies: block_ss.dependencies(),
2778                          link_depends: block_syms,
2779                          name_suffix: 'fa',
2780                          build_by_default: false)
2781
2782block = declare_dependency(link_whole: [libblock],
2783                           link_args: '@block.syms',
2784                           dependencies: [crypto, io])
2785
2786blockdev_ss = blockdev_ss.apply(config_host, strict: false)
2787libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
2788                             dependencies: blockdev_ss.dependencies(),
2789                             name_suffix: 'fa',
2790                             build_by_default: false)
2791
2792blockdev = declare_dependency(link_whole: [libblockdev],
2793                              dependencies: [block])
2794
2795qmp_ss = qmp_ss.apply(config_host, strict: false)
2796libqmp = static_library('qmp', qmp_ss.sources() + genh,
2797                        dependencies: qmp_ss.dependencies(),
2798                        name_suffix: 'fa',
2799                        build_by_default: false)
2800
2801qmp = declare_dependency(link_whole: [libqmp])
2802
2803libchardev = static_library('chardev', chardev_ss.sources() + genh,
2804                            name_suffix: 'fa',
2805                            dependencies: [gnutls],
2806                            build_by_default: false)
2807
2808chardev = declare_dependency(link_whole: libchardev)
2809
2810hwcore_ss = hwcore_ss.apply(config_host, strict: false)
2811libhwcore = static_library('hwcore', sources: hwcore_ss.sources() + genh,
2812                           name_suffix: 'fa',
2813                           build_by_default: false)
2814hwcore = declare_dependency(link_whole: libhwcore)
2815common_ss.add(hwcore)
2816
2817###########
2818# Targets #
2819###########
2820
2821foreach m : block_mods + softmmu_mods
2822  shared_module(m.name(),
2823                name_prefix: '',
2824                link_whole: m,
2825                install: true,
2826                install_dir: qemu_moddir)
2827endforeach
2828
2829softmmu_ss.add(authz, blockdev, chardev, crypto, io, qmp)
2830common_ss.add(qom, qemuutil)
2831
2832common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
2833common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
2834
2835common_all = common_ss.apply(config_all, strict: false)
2836common_all = static_library('common',
2837                            build_by_default: false,
2838                            sources: common_all.sources() + genh,
2839                            implicit_include_directories: false,
2840                            dependencies: common_all.dependencies(),
2841                            name_suffix: 'fa')
2842
2843feature_to_c = find_program('scripts/feature_to_c.sh')
2844
2845emulators = {}
2846foreach target : target_dirs
2847  config_target = config_target_mak[target]
2848  target_name = config_target['TARGET_NAME']
2849  arch = config_target['TARGET_BASE_ARCH']
2850  arch_srcs = [config_target_h[target]]
2851  arch_deps = []
2852  c_args = ['-DNEED_CPU_H',
2853            '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
2854            '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
2855  link_args = emulator_link_args
2856
2857  config_target += config_host
2858  target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
2859  if targetos == 'linux'
2860    target_inc += include_directories('linux-headers', is_system: true)
2861  endif
2862  if target.endswith('-softmmu')
2863    qemu_target_name = 'qemu-system-' + target_name
2864    target_type='system'
2865    t = target_softmmu_arch[arch].apply(config_target, strict: false)
2866    arch_srcs += t.sources()
2867    arch_deps += t.dependencies()
2868
2869    hw_dir = target_name == 'sparc64' ? 'sparc64' : arch
2870    hw = hw_arch[hw_dir].apply(config_target, strict: false)
2871    arch_srcs += hw.sources()
2872    arch_deps += hw.dependencies()
2873
2874    arch_srcs += config_devices_h[target]
2875    link_args += ['@block.syms', '@qemu.syms']
2876  else
2877    abi = config_target['TARGET_ABI_DIR']
2878    target_type='user'
2879    qemu_target_name = 'qemu-' + target_name
2880    if arch in target_user_arch
2881      t = target_user_arch[arch].apply(config_target, strict: false)
2882      arch_srcs += t.sources()
2883      arch_deps += t.dependencies()
2884    endif
2885    if 'CONFIG_LINUX_USER' in config_target
2886      base_dir = 'linux-user'
2887      target_inc += include_directories('linux-user/host/' / config_host['ARCH'])
2888    endif
2889    if 'CONFIG_BSD_USER' in config_target
2890      base_dir = 'bsd-user'
2891      target_inc += include_directories('bsd-user/' / targetos)
2892      dir = base_dir / abi
2893      arch_srcs += files(dir / 'target_arch_cpu.c')
2894    endif
2895    target_inc += include_directories(
2896      base_dir,
2897      base_dir / abi,
2898    )
2899    if 'CONFIG_LINUX_USER' in config_target
2900      dir = base_dir / abi
2901      arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
2902      if config_target.has_key('TARGET_SYSTBL_ABI')
2903        arch_srcs += \
2904          syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
2905                                             extra_args : config_target['TARGET_SYSTBL_ABI'])
2906      endif
2907    endif
2908  endif
2909
2910  if 'TARGET_XML_FILES' in config_target
2911    gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
2912                                output: target + '-gdbstub-xml.c',
2913                                input: files(config_target['TARGET_XML_FILES'].split()),
2914                                command: [feature_to_c, '@INPUT@'],
2915                                capture: true)
2916    arch_srcs += gdbstub_xml
2917  endif
2918
2919  t = target_arch[arch].apply(config_target, strict: false)
2920  arch_srcs += t.sources()
2921  arch_deps += t.dependencies()
2922
2923  target_common = common_ss.apply(config_target, strict: false)
2924  objects = common_all.extract_objects(target_common.sources())
2925  deps = target_common.dependencies()
2926
2927  target_specific = specific_ss.apply(config_target, strict: false)
2928  arch_srcs += target_specific.sources()
2929  arch_deps += target_specific.dependencies()
2930
2931  lib = static_library('qemu-' + target,
2932                 sources: arch_srcs + genh,
2933                 dependencies: arch_deps,
2934                 objects: objects,
2935                 include_directories: target_inc,
2936                 c_args: c_args,
2937                 build_by_default: false,
2938                 name_suffix: 'fa')
2939
2940  if target.endswith('-softmmu')
2941    execs = [{
2942      'name': 'qemu-system-' + target_name,
2943      'win_subsystem': 'console',
2944      'sources': files('softmmu/main.c'),
2945      'dependencies': []
2946    }]
2947    if targetos == 'windows' and (sdl.found() or gtk.found())
2948      execs += [{
2949        'name': 'qemu-system-' + target_name + 'w',
2950        'win_subsystem': 'windows',
2951        'sources': files('softmmu/main.c'),
2952        'dependencies': []
2953      }]
2954    endif
2955    if get_option('fuzzing')
2956      specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
2957      execs += [{
2958        'name': 'qemu-fuzz-' + target_name,
2959        'win_subsystem': 'console',
2960        'sources': specific_fuzz.sources(),
2961        'dependencies': specific_fuzz.dependencies(),
2962      }]
2963    endif
2964  else
2965    execs = [{
2966      'name': 'qemu-' + target_name,
2967      'win_subsystem': 'console',
2968      'sources': [],
2969      'dependencies': []
2970    }]
2971  endif
2972  foreach exe: execs
2973    exe_name = exe['name']
2974    if targetos == 'darwin'
2975      exe_name += '-unsigned'
2976    endif
2977
2978    emulator = executable(exe_name, exe['sources'],
2979               install: true,
2980               c_args: c_args,
2981               dependencies: arch_deps + deps + exe['dependencies'],
2982               objects: lib.extract_all_objects(recursive: true),
2983               link_language: link_language,
2984               link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
2985               link_args: link_args,
2986               win_subsystem: exe['win_subsystem'])
2987
2988    if targetos == 'darwin'
2989      icon = 'pc-bios/qemu.rsrc'
2990      build_input = [emulator, files(icon)]
2991      install_input = [
2992        get_option('bindir') / exe_name,
2993        meson.current_source_dir() / icon
2994      ]
2995      if 'CONFIG_HVF' in config_target
2996        entitlements = 'accel/hvf/entitlements.plist'
2997        build_input += files(entitlements)
2998        install_input += meson.current_source_dir() / entitlements
2999      endif
3000
3001      emulators += {exe['name'] : custom_target(exe['name'],
3002                   input: build_input,
3003                   output: exe['name'],
3004                   command: [
3005                     files('scripts/entitlement.sh'),
3006                     '@OUTPUT@',
3007                     '@INPUT@'
3008                   ])
3009      }
3010
3011      meson.add_install_script('scripts/entitlement.sh', '--install',
3012                               get_option('bindir') / exe['name'],
3013                               install_input)
3014    else
3015      emulators += {exe['name']: emulator}
3016    endif
3017
3018    if stap.found()
3019      foreach stp: [
3020        {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
3021        {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
3022        {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
3023        {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
3024      ]
3025        custom_target(exe['name'] + stp['ext'],
3026                      input: trace_events_all,
3027                      output: exe['name'] + stp['ext'],
3028                      install: stp['install'],
3029                      install_dir: get_option('datadir') / 'systemtap/tapset',
3030                      command: [
3031                        tracetool, '--group=all', '--format=' + stp['fmt'],
3032                        '--binary=' + stp['bin'],
3033                        '--target-name=' + target_name,
3034                        '--target-type=' + target_type,
3035                        '--probe-prefix=qemu.' + target_type + '.' + target_name,
3036                        '@INPUT@', '@OUTPUT@'
3037                      ],
3038                      depend_files: tracetool_depends)
3039      endforeach
3040    endif
3041  endforeach
3042endforeach
3043
3044# Other build targets
3045
3046if 'CONFIG_PLUGIN' in config_host
3047  install_headers('include/qemu/qemu-plugin.h')
3048endif
3049
3050if 'CONFIG_GUEST_AGENT' in config_host
3051  subdir('qga')
3052elif get_option('guest_agent_msi').enabled()
3053  error('Guest agent MSI requested, but the guest agent is not being built')
3054endif
3055
3056# Don't build qemu-keymap if xkbcommon is not explicitly enabled
3057# when we don't build tools or system
3058if xkbcommon.found()
3059  # used for the update-keymaps target, so include rules even if !have_tools
3060  qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
3061                           dependencies: [qemuutil, xkbcommon], install: have_tools)
3062endif
3063
3064if have_tools
3065  qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
3066             dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
3067  qemu_io = executable('qemu-io', files('qemu-io.c'),
3068             dependencies: [block, qemuutil], install: true)
3069  qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
3070               dependencies: [blockdev, qemuutil, gnutls], install: true)
3071
3072  subdir('storage-daemon')
3073  subdir('contrib/rdmacm-mux')
3074  subdir('contrib/elf2dmp')
3075
3076  executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
3077             dependencies: qemuutil,
3078             install: true)
3079
3080  if 'CONFIG_VHOST_USER' in config_host
3081    subdir('contrib/vhost-user-blk')
3082    subdir('contrib/vhost-user-gpu')
3083    subdir('contrib/vhost-user-input')
3084    subdir('contrib/vhost-user-scsi')
3085  endif
3086
3087  if targetos == 'linux'
3088    executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
3089               dependencies: [qemuutil, libcap_ng],
3090               install: true,
3091               install_dir: get_option('libexecdir'))
3092
3093    executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
3094               dependencies: [authz, crypto, io, qom, qemuutil,
3095                              libcap_ng, mpathpersist],
3096               install: true)
3097  endif
3098
3099  if have_ivshmem
3100    subdir('contrib/ivshmem-client')
3101    subdir('contrib/ivshmem-server')
3102  endif
3103endif
3104
3105subdir('scripts')
3106subdir('tools')
3107subdir('pc-bios')
3108subdir('docs')
3109subdir('tests')
3110if gtk.found()
3111  subdir('po')
3112endif
3113
3114if host_machine.system() == 'windows'
3115  nsis_cmd = [
3116    find_program('scripts/nsis.py'),
3117    '@OUTPUT@',
3118    get_option('prefix'),
3119    meson.current_source_dir(),
3120    host_machine.cpu(),
3121    '--',
3122    '-DDISPLAYVERSION=' + meson.project_version(),
3123  ]
3124  if build_docs
3125    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
3126  endif
3127  if gtk.found()
3128    nsis_cmd += '-DCONFIG_GTK=y'
3129  endif
3130
3131  nsis = custom_target('nsis',
3132                       output: 'qemu-setup-' + meson.project_version() + '.exe',
3133                       input: files('qemu.nsi'),
3134                       build_always_stale: true,
3135                       command: nsis_cmd + ['@INPUT@'])
3136  alias_target('installer', nsis)
3137endif
3138
3139#########################
3140# Configuration summary #
3141#########################
3142
3143# Directories
3144summary_info = {}
3145summary_info += {'Install prefix':    get_option('prefix')}
3146summary_info += {'BIOS directory':    qemu_datadir}
3147summary_info += {'firmware path':     get_option('qemu_firmwarepath')}
3148summary_info += {'binary directory':  get_option('bindir')}
3149summary_info += {'library directory': get_option('libdir')}
3150summary_info += {'module directory':  qemu_moddir}
3151summary_info += {'libexec directory': get_option('libexecdir')}
3152summary_info += {'include directory': get_option('includedir')}
3153summary_info += {'config directory':  get_option('sysconfdir')}
3154if targetos != 'windows'
3155  summary_info += {'local state directory': get_option('localstatedir')}
3156  summary_info += {'Manual directory':      get_option('mandir')}
3157else
3158  summary_info += {'local state directory': 'queried at runtime'}
3159endif
3160summary_info += {'Doc directory':     get_option('docdir')}
3161summary_info += {'Build directory':   meson.current_build_dir()}
3162summary_info += {'Source path':       meson.current_source_dir()}
3163summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
3164summary(summary_info, bool_yn: true, section: 'Directories')
3165
3166# Host binaries
3167summary_info = {}
3168summary_info += {'git':               config_host['GIT']}
3169summary_info += {'make':              config_host['MAKE']}
3170summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
3171summary_info += {'sphinx-build':      sphinx_build}
3172if config_host.has_key('HAVE_GDB_BIN')
3173  summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
3174endif
3175summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
3176if targetos == 'windows' and config_host.has_key('CONFIG_GUEST_AGENT')
3177  summary_info += {'wixl':            wixl}
3178endif
3179if slirp_opt != 'disabled' and 'CONFIG_SLIRP_SMBD' in config_host
3180  summary_info += {'smbd':            config_host['CONFIG_SMBD_COMMAND']}
3181endif
3182summary(summary_info, bool_yn: true, section: 'Host binaries')
3183
3184# Configurable features
3185summary_info = {}
3186summary_info += {'Documentation':     build_docs}
3187summary_info += {'system-mode emulation': have_system}
3188summary_info += {'user-mode emulation': have_user}
3189summary_info += {'block layer':       have_block}
3190summary_info += {'Install blobs':     get_option('install_blobs')}
3191summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
3192if config_host.has_key('CONFIG_MODULES')
3193  summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')}
3194endif
3195summary_info += {'fuzzing support':   get_option('fuzzing')}
3196if have_system
3197  summary_info += {'Audio drivers':     ' '.join(audio_drivers_selected)}
3198endif
3199summary_info += {'Trace backends':    ','.join(get_option('trace_backends'))}
3200if 'simple' in get_option('trace_backends')
3201  summary_info += {'Trace output file': get_option('trace_file') + '-<pid>'}
3202endif
3203summary_info += {'QOM debugging':     config_host.has_key('CONFIG_QOM_CAST_DEBUG')}
3204summary_info += {'vhost-kernel support': config_host.has_key('CONFIG_VHOST_KERNEL')}
3205summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')}
3206summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')}
3207summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')}
3208summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')}
3209summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_USER')}
3210summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
3211summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')}
3212summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')}
3213summary_info += {'build guest agent': config_host.has_key('CONFIG_GUEST_AGENT')}
3214summary(summary_info, bool_yn: true, section: 'Configurable features')
3215
3216# Compilation information
3217summary_info = {}
3218summary_info += {'host CPU':          cpu}
3219summary_info += {'host endianness':   build_machine.endian()}
3220summary_info += {'C compiler':        ' '.join(meson.get_compiler('c').cmd_array())}
3221summary_info += {'Host C compiler':   ' '.join(meson.get_compiler('c', native: true).cmd_array())}
3222if link_language == 'cpp'
3223  summary_info += {'C++ compiler':    ' '.join(meson.get_compiler('cpp').cmd_array())}
3224else
3225  summary_info += {'C++ compiler':      false}
3226endif
3227if targetos == 'darwin'
3228  summary_info += {'Objective-C compiler': ' '.join(meson.get_compiler('objc').cmd_array())}
3229endif
3230if targetos == 'windows'
3231  if 'WIN_SDK' in config_host
3232    summary_info += {'Windows SDK':   config_host['WIN_SDK']}
3233  endif
3234endif
3235summary_info += {'CFLAGS':            ' '.join(get_option('c_args')
3236                                               + ['-O' + get_option('optimization')]
3237                                               + (get_option('debug') ? ['-g'] : []))}
3238if link_language == 'cpp'
3239  summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args')
3240                                               + ['-O' + get_option('optimization')]
3241                                               + (get_option('debug') ? ['-g'] : []))}
3242endif
3243link_args = get_option(link_language + '_link_args')
3244if link_args.length() > 0
3245  summary_info += {'LDFLAGS':         ' '.join(link_args)}
3246endif
3247summary_info += {'QEMU_CFLAGS':       config_host['QEMU_CFLAGS']}
3248summary_info += {'QEMU_LDFLAGS':      config_host['QEMU_LDFLAGS']}
3249summary_info += {'profiler':          config_host.has_key('CONFIG_PROFILER')}
3250summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
3251summary_info += {'PIE':               get_option('b_pie')}
3252summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
3253summary_info += {'malloc trim support': has_malloc_trim}
3254summary_info += {'membarrier':        config_host.has_key('CONFIG_MEMBARRIER')}
3255summary_info += {'debug stack usage': config_host.has_key('CONFIG_DEBUG_STACK_USAGE')}
3256summary_info += {'mutex debugging':   config_host.has_key('CONFIG_DEBUG_MUTEX')}
3257summary_info += {'memory allocator':  get_option('malloc')}
3258summary_info += {'avx2 optimization': config_host.has_key('CONFIG_AVX2_OPT')}
3259summary_info += {'avx512f optimization': config_host.has_key('CONFIG_AVX512F_OPT')}
3260summary_info += {'gprof enabled':     config_host.has_key('CONFIG_GPROF')}
3261summary_info += {'gcov':              get_option('b_coverage')}
3262summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
3263summary_info += {'CFI support':       get_option('cfi')}
3264if get_option('cfi')
3265  summary_info += {'CFI debug support': get_option('cfi_debug')}
3266endif
3267summary_info += {'strip binaries':    get_option('strip')}
3268summary_info += {'sparse':            sparse}
3269summary_info += {'mingw32 support':   targetos == 'windows'}
3270
3271# snarf the cross-compilation information for tests
3272foreach target: target_dirs
3273  tcg_mak = meson.current_build_dir() / 'tests/tcg' / 'config-' + target + '.mak'
3274  if fs.exists(tcg_mak)
3275    config_cross_tcg = keyval.load(tcg_mak)
3276    target = config_cross_tcg['TARGET_NAME']
3277    compiler = ''
3278    if 'DOCKER_CROSS_CC_GUEST' in config_cross_tcg
3279      summary_info += {target + ' tests': config_cross_tcg['DOCKER_CROSS_CC_GUEST'] +
3280                                          ' via ' + config_cross_tcg['DOCKER_IMAGE']}
3281    elif 'CROSS_CC_GUEST' in config_cross_tcg
3282      summary_info += {target + ' tests'
3283                                : config_cross_tcg['CROSS_CC_GUEST'] }
3284    endif
3285   endif
3286endforeach
3287
3288summary(summary_info, bool_yn: true, section: 'Compilation')
3289
3290# Targets and accelerators
3291summary_info = {}
3292if have_system
3293  summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
3294  summary_info += {'HAX support':       config_all.has_key('CONFIG_HAX')}
3295  summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
3296  summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
3297  summary_info += {'NVMM support':      config_all.has_key('CONFIG_NVMM')}
3298  summary_info += {'Xen support':       config_host.has_key('CONFIG_XEN_BACKEND')}
3299  if config_host.has_key('CONFIG_XEN_BACKEND')
3300    summary_info += {'xen ctrl version':  config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
3301  endif
3302endif
3303summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
3304if config_all.has_key('CONFIG_TCG')
3305  if get_option('tcg_interpreter')
3306    summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, experimental and slow)'}
3307  else
3308    summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
3309  endif
3310  summary_info += {'TCG plugins': config_host.has_key('CONFIG_PLUGIN')}
3311  summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
3312endif
3313summary_info += {'target list':       ' '.join(target_dirs)}
3314if have_system
3315  summary_info += {'default devices':   get_option('default_devices')}
3316  summary_info += {'out of process emulation': multiprocess_allowed}
3317endif
3318summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
3319
3320# Block layer
3321summary_info = {}
3322summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
3323summary_info += {'coroutine pool':    config_host['CONFIG_COROUTINE_POOL'] == '1'}
3324if have_block
3325  summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']}
3326  summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']}
3327  summary_info += {'Use block whitelist in tools': config_host.has_key('CONFIG_BDRV_WHITELIST_TOOLS')}
3328  summary_info += {'VirtFS support':    have_virtfs}
3329  summary_info += {'build virtiofs daemon': have_virtiofsd}
3330  summary_info += {'Live block migration': config_host.has_key('CONFIG_LIVE_BLOCK_MIGRATION')}
3331  summary_info += {'replication support': config_host.has_key('CONFIG_REPLICATION')}
3332  summary_info += {'bochs support':     config_host.has_key('CONFIG_BOCHS')}
3333  summary_info += {'cloop support':     config_host.has_key('CONFIG_CLOOP')}
3334  summary_info += {'dmg support':       config_host.has_key('CONFIG_DMG')}
3335  summary_info += {'qcow v1 support':   config_host.has_key('CONFIG_QCOW1')}
3336  summary_info += {'vdi support':       config_host.has_key('CONFIG_VDI')}
3337  summary_info += {'vvfat support':     config_host.has_key('CONFIG_VVFAT')}
3338  summary_info += {'qed support':       config_host.has_key('CONFIG_QED')}
3339  summary_info += {'parallels support': config_host.has_key('CONFIG_PARALLELS')}
3340  summary_info += {'FUSE exports':      fuse}
3341endif
3342summary(summary_info, bool_yn: true, section: 'Block layer support')
3343
3344# Crypto
3345summary_info = {}
3346summary_info += {'TLS priority':      config_host['CONFIG_TLS_PRIORITY']}
3347summary_info += {'GNUTLS support':    gnutls}
3348if gnutls.found()
3349  summary_info += {'  GNUTLS crypto':   gnutls_crypto.found()}
3350endif
3351summary_info += {'libgcrypt':         gcrypt}
3352summary_info += {'nettle':            nettle}
3353if nettle.found()
3354   summary_info += {'  XTS':             xts != 'private'}
3355endif
3356summary_info += {'crypto afalg':      config_host.has_key('CONFIG_AF_ALG')}
3357summary_info += {'rng-none':          config_host.has_key('CONFIG_RNG_NONE')}
3358summary_info += {'Linux keyring':     config_host.has_key('CONFIG_SECRET_KEYRING')}
3359summary(summary_info, bool_yn: true, section: 'Crypto')
3360
3361# Libraries
3362summary_info = {}
3363if targetos == 'darwin'
3364  summary_info += {'Cocoa support':   cocoa}
3365endif
3366summary_info += {'SDL support':       sdl}
3367summary_info += {'SDL image support': sdl_image}
3368summary_info += {'GTK support':       gtk}
3369summary_info += {'pixman':            pixman}
3370summary_info += {'VTE support':       vte}
3371summary_info += {'slirp support':     slirp_opt == 'internal' ? slirp_opt : slirp}
3372summary_info += {'libtasn1':          tasn1}
3373summary_info += {'PAM':               pam}
3374summary_info += {'iconv support':     iconv}
3375summary_info += {'curses support':    curses}
3376summary_info += {'virgl support':     virgl}
3377summary_info += {'curl support':      curl}
3378summary_info += {'Multipath support': mpathpersist}
3379summary_info += {'VNC support':       vnc}
3380if vnc.found()
3381  summary_info += {'VNC SASL support':  sasl}
3382  summary_info += {'VNC JPEG support':  jpeg}
3383  summary_info += {'VNC PNG support':   png}
3384endif
3385if targetos not in ['darwin', 'haiku', 'windows']
3386  summary_info += {'OSS support':     oss}
3387elif targetos == 'darwin'
3388  summary_info += {'CoreAudio support': coreaudio}
3389elif targetos == 'windows'
3390  summary_info += {'DirectSound support': dsound}
3391endif
3392if targetos == 'linux'
3393  summary_info += {'ALSA support':    alsa}
3394  summary_info += {'PulseAudio support': pulse}
3395endif
3396summary_info += {'JACK support':      jack}
3397summary_info += {'brlapi support':    brlapi}
3398summary_info += {'vde support':       vde}
3399summary_info += {'netmap support':    have_netmap}
3400summary_info += {'Linux AIO support': libaio}
3401summary_info += {'Linux io_uring support': linux_io_uring}
3402summary_info += {'ATTR/XATTR support': libattr}
3403summary_info += {'RDMA support':      config_host.has_key('CONFIG_RDMA')}
3404summary_info += {'PVRDMA support':    config_host.has_key('CONFIG_PVRDMA')}
3405summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
3406summary_info += {'libcap-ng support': libcap_ng}
3407summary_info += {'bpf support':       libbpf}
3408summary_info += {'spice protocol support': spice_protocol}
3409if spice_protocol.found()
3410  summary_info += {'  spice server support': spice}
3411endif
3412summary_info += {'rbd support':       rbd}
3413summary_info += {'xfsctl support':    config_host.has_key('CONFIG_XFS')}
3414summary_info += {'smartcard support': cacard}
3415summary_info += {'U2F support':       u2f}
3416summary_info += {'libusb':            libusb}
3417summary_info += {'usb net redir':     usbredir}
3418summary_info += {'OpenGL support':    config_host.has_key('CONFIG_OPENGL')}
3419summary_info += {'GBM':               gbm}
3420summary_info += {'libiscsi support':  libiscsi}
3421summary_info += {'libnfs support':    libnfs}
3422if targetos == 'windows'
3423  if config_host.has_key('CONFIG_GUEST_AGENT')
3424    summary_info += {'QGA VSS support':   config_host.has_key('CONFIG_QGA_VSS')}
3425    summary_info += {'QGA w32 disk info': config_host.has_key('CONFIG_QGA_NTDDSCSI')}
3426  endif
3427endif
3428summary_info += {'seccomp support':   seccomp}
3429summary_info += {'GlusterFS support': glusterfs}
3430summary_info += {'TPM support':       config_host.has_key('CONFIG_TPM')}
3431summary_info += {'libssh support':    config_host.has_key('CONFIG_LIBSSH')}
3432summary_info += {'lzo support':       lzo}
3433summary_info += {'snappy support':    snappy}
3434summary_info += {'bzip2 support':     libbzip2}
3435summary_info += {'lzfse support':     liblzfse}
3436summary_info += {'zstd support':      zstd}
3437summary_info += {'NUMA host support': config_host.has_key('CONFIG_NUMA')}
3438summary_info += {'libxml2':           libxml2}
3439summary_info += {'capstone':          capstone_opt == 'internal' ? capstone_opt : capstone}
3440summary_info += {'libpmem support':   libpmem}
3441summary_info += {'libdaxctl support': libdaxctl}
3442summary_info += {'libudev':           libudev}
3443# Dummy dependency, keep .found()
3444summary_info += {'FUSE lseek':        fuse_lseek.found()}
3445summary(summary_info, bool_yn: true, section: 'Dependencies')
3446
3447if not supported_cpus.contains(cpu)
3448  message()
3449  warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
3450  message()
3451  message('CPU host architecture ' + cpu + ' support is not currently maintained.')
3452  message('The QEMU project intends to remove support for this host CPU in')
3453  message('a future release if nobody volunteers to maintain it and to')
3454  message('provide a build host for our continuous integration setup.')
3455  message('configure has succeeded and you can continue to build, but')
3456  message('if you care about QEMU on this platform you should contact')
3457  message('us upstream at qemu-devel@nongnu.org.')
3458endif
3459
3460if not supported_oses.contains(targetos)
3461  message()
3462  warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
3463  message()
3464  message('Host OS ' + targetos + 'support is not currently maintained.')
3465  message('The QEMU project intends to remove support for this host OS in')
3466  message('a future release if nobody volunteers to maintain it and to')
3467  message('provide a build host for our continuous integration setup.')
3468  message('configure has succeeded and you can continue to build, but')
3469  message('if you care about QEMU on this platform you should contact')
3470  message('us upstream at qemu-devel@nongnu.org.')
3471endif
3472