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