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