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