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