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