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