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