xref: /qemu/meson.build (revision d201cf7a)
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/tcg_h.py',
2361  'scripts/tracetool/format/ust_events_c.py',
2362  'scripts/tracetool/format/ust_events_h.py',
2363  'scripts/tracetool/format/__init__.py',
2364  'scripts/tracetool/format/d.py',
2365  'scripts/tracetool/format/tcg_helper_c.py',
2366  'scripts/tracetool/format/simpletrace_stap.py',
2367  'scripts/tracetool/format/c.py',
2368  'scripts/tracetool/format/h.py',
2369  'scripts/tracetool/format/tcg_helper_h.py',
2370  'scripts/tracetool/format/log_stap.py',
2371  'scripts/tracetool/format/stap.py',
2372  'scripts/tracetool/format/tcg_helper_wrapper_h.py',
2373  'scripts/tracetool/__init__.py',
2374  'scripts/tracetool/transform.py',
2375  'scripts/tracetool/vcpu.py'
2376)
2377
2378qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
2379                    meson.current_source_dir(),
2380                    config_host['PKGVERSION'], meson.project_version()]
2381qemu_version = custom_target('qemu-version.h',
2382                             output: 'qemu-version.h',
2383                             command: qemu_version_cmd,
2384                             capture: true,
2385                             build_by_default: true,
2386                             build_always_stale: true)
2387genh += qemu_version
2388
2389hxdep = []
2390hx_headers = [
2391  ['qemu-options.hx', 'qemu-options.def'],
2392  ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
2393]
2394if have_system
2395  hx_headers += [
2396    ['hmp-commands.hx', 'hmp-commands.h'],
2397    ['hmp-commands-info.hx', 'hmp-commands-info.h'],
2398  ]
2399endif
2400foreach d : hx_headers
2401  hxdep += custom_target(d[1],
2402                input: files(d[0]),
2403                output: d[1],
2404                capture: true,
2405                build_by_default: true, # to be removed when added to a target
2406                command: [hxtool, '-h', '@INPUT0@'])
2407endforeach
2408genh += hxdep
2409
2410###################
2411# Collect sources #
2412###################
2413
2414authz_ss = ss.source_set()
2415blockdev_ss = ss.source_set()
2416block_ss = ss.source_set()
2417chardev_ss = ss.source_set()
2418common_ss = ss.source_set()
2419crypto_ss = ss.source_set()
2420hwcore_ss = ss.source_set()
2421io_ss = ss.source_set()
2422qmp_ss = ss.source_set()
2423qom_ss = ss.source_set()
2424softmmu_ss = ss.source_set()
2425specific_fuzz_ss = ss.source_set()
2426specific_ss = ss.source_set()
2427stub_ss = ss.source_set()
2428trace_ss = ss.source_set()
2429user_ss = ss.source_set()
2430util_ss = ss.source_set()
2431
2432# accel modules
2433qtest_module_ss = ss.source_set()
2434tcg_module_ss = ss.source_set()
2435
2436modules = {}
2437target_modules = {}
2438hw_arch = {}
2439target_arch = {}
2440target_softmmu_arch = {}
2441target_user_arch = {}
2442
2443###############
2444# Trace files #
2445###############
2446
2447# TODO: add each directory to the subdirs from its own meson.build, once
2448# we have those
2449trace_events_subdirs = [
2450  'crypto',
2451  'qapi',
2452  'qom',
2453  'monitor',
2454  'util',
2455]
2456if have_linux_user
2457  trace_events_subdirs += [ 'linux-user' ]
2458endif
2459if have_bsd_user
2460  trace_events_subdirs += [ 'bsd-user' ]
2461endif
2462if have_block
2463  trace_events_subdirs += [
2464    'authz',
2465    'block',
2466    'io',
2467    'nbd',
2468    'scsi',
2469  ]
2470endif
2471if have_system
2472  trace_events_subdirs += [
2473    'accel/kvm',
2474    'audio',
2475    'backends',
2476    'backends/tpm',
2477    'chardev',
2478    'ebpf',
2479    'hw/9pfs',
2480    'hw/acpi',
2481    'hw/adc',
2482    'hw/alpha',
2483    'hw/arm',
2484    'hw/audio',
2485    'hw/block',
2486    'hw/block/dataplane',
2487    'hw/char',
2488    'hw/display',
2489    'hw/dma',
2490    'hw/hppa',
2491    'hw/hyperv',
2492    'hw/i2c',
2493    'hw/i386',
2494    'hw/i386/xen',
2495    'hw/ide',
2496    'hw/input',
2497    'hw/intc',
2498    'hw/isa',
2499    'hw/mem',
2500    'hw/mips',
2501    'hw/misc',
2502    'hw/misc/macio',
2503    'hw/net',
2504    'hw/net/can',
2505    'hw/nubus',
2506    'hw/nvme',
2507    'hw/nvram',
2508    'hw/pci',
2509    'hw/pci-host',
2510    'hw/ppc',
2511    'hw/rdma',
2512    'hw/rdma/vmw',
2513    'hw/rtc',
2514    'hw/s390x',
2515    'hw/scsi',
2516    'hw/sd',
2517    'hw/sh4',
2518    'hw/sparc',
2519    'hw/sparc64',
2520    'hw/ssi',
2521    'hw/timer',
2522    'hw/tpm',
2523    'hw/usb',
2524    'hw/vfio',
2525    'hw/virtio',
2526    'hw/watchdog',
2527    'hw/xen',
2528    'hw/gpio',
2529    'migration',
2530    'net',
2531    'softmmu',
2532    'ui',
2533    'hw/remote',
2534  ]
2535endif
2536if have_system or have_user
2537  trace_events_subdirs += [
2538    'accel/tcg',
2539    'hw/core',
2540    'target/arm',
2541    'target/arm/hvf',
2542    'target/hppa',
2543    'target/i386',
2544    'target/i386/kvm',
2545    'target/mips/tcg',
2546    'target/ppc',
2547    'target/riscv',
2548    'target/s390x',
2549    'target/s390x/kvm',
2550    'target/sparc',
2551  ]
2552endif
2553
2554vhost_user = not_found
2555if 'CONFIG_VHOST_USER' in config_host
2556  libvhost_user = subproject('libvhost-user')
2557  vhost_user = libvhost_user.get_variable('vhost_user_dep')
2558endif
2559
2560# NOTE: the trace/ subdirectory needs the qapi_trace_events variable
2561# that is filled in by qapi/.
2562subdir('qapi')
2563subdir('qobject')
2564subdir('stubs')
2565subdir('trace')
2566subdir('util')
2567subdir('qom')
2568subdir('authz')
2569subdir('crypto')
2570subdir('ui')
2571
2572
2573if enable_modules
2574  libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
2575  modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
2576endif
2577
2578stub_ss = stub_ss.apply(config_all, strict: false)
2579
2580util_ss.add_all(trace_ss)
2581util_ss = util_ss.apply(config_all, strict: false)
2582libqemuutil = static_library('qemuutil',
2583                             sources: util_ss.sources() + stub_ss.sources() + genh,
2584                             dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc, pixman])
2585qemuutil = declare_dependency(link_with: libqemuutil,
2586                              sources: genh + version_res)
2587
2588if have_system or have_user
2589  decodetree = generator(find_program('scripts/decodetree.py'),
2590                         output: 'decode-@BASENAME@.c.inc',
2591                         arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
2592  subdir('libdecnumber')
2593  subdir('target')
2594endif
2595
2596subdir('audio')
2597subdir('io')
2598subdir('chardev')
2599subdir('fsdev')
2600subdir('dump')
2601
2602if have_block
2603  block_ss.add(files(
2604    'block.c',
2605    'blockjob.c',
2606    'job.c',
2607    'qemu-io-cmds.c',
2608  ))
2609  block_ss.add(when: 'CONFIG_REPLICATION', if_true: files('replication.c'))
2610
2611  subdir('nbd')
2612  subdir('scsi')
2613  subdir('block')
2614
2615  blockdev_ss.add(files(
2616    'blockdev.c',
2617    'blockdev-nbd.c',
2618    'iothread.c',
2619    'job-qmp.c',
2620  ), gnutls)
2621
2622  # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
2623  # os-win32.c does not
2624  blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
2625  softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
2626endif
2627
2628common_ss.add(files('cpus-common.c'))
2629
2630subdir('softmmu')
2631
2632common_ss.add(capstone)
2633specific_ss.add(files('cpu.c', 'disas.c', 'gdbstub.c'), capstone)
2634
2635# Work around a gcc bug/misfeature wherein constant propagation looks
2636# through an alias:
2637#   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99696
2638# to guess that a const variable is always zero.  Without lto, this is
2639# impossible, as the alias is restricted to page-vary-common.c.  Indeed,
2640# without lto, not even the alias is required -- we simply use different
2641# declarations in different compilation units.
2642pagevary = files('page-vary-common.c')
2643if get_option('b_lto')
2644  pagevary_flags = ['-fno-lto']
2645  if get_option('cfi')
2646    pagevary_flags += '-fno-sanitize=cfi-icall'
2647  endif
2648  pagevary = static_library('page-vary-common', sources: pagevary,
2649                            c_args: pagevary_flags)
2650  pagevary = declare_dependency(link_with: pagevary)
2651endif
2652common_ss.add(pagevary)
2653specific_ss.add(files('page-vary.c'))
2654
2655subdir('backends')
2656subdir('disas')
2657subdir('migration')
2658subdir('monitor')
2659subdir('net')
2660subdir('replay')
2661subdir('semihosting')
2662subdir('hw')
2663subdir('tcg')
2664subdir('fpu')
2665subdir('accel')
2666subdir('plugins')
2667subdir('ebpf')
2668
2669common_user_inc = []
2670
2671subdir('common-user')
2672subdir('bsd-user')
2673subdir('linux-user')
2674
2675# needed for fuzzing binaries
2676subdir('tests/qtest/libqos')
2677subdir('tests/qtest/fuzz')
2678
2679# accel modules
2680tcg_real_module_ss = ss.source_set()
2681tcg_real_module_ss.add_all(when: 'CONFIG_TCG_MODULAR', if_true: tcg_module_ss)
2682specific_ss.add_all(when: 'CONFIG_TCG_BUILTIN', if_true: tcg_module_ss)
2683target_modules += { 'accel' : { 'qtest': qtest_module_ss,
2684                                'tcg': tcg_real_module_ss }}
2685
2686########################
2687# Library dependencies #
2688########################
2689
2690modinfo_collect = find_program('scripts/modinfo-collect.py')
2691modinfo_generate = find_program('scripts/modinfo-generate.py')
2692modinfo_files = []
2693
2694block_mods = []
2695softmmu_mods = []
2696foreach d, list : modules
2697  foreach m, module_ss : list
2698    if enable_modules and targetos != 'windows'
2699      module_ss = module_ss.apply(config_all, strict: false)
2700      sl = static_library(d + '-' + m, [genh, module_ss.sources()],
2701                          dependencies: [modulecommon, module_ss.dependencies()], pic: true)
2702      if d == 'block'
2703        block_mods += sl
2704      else
2705        softmmu_mods += sl
2706      endif
2707      if module_ss.sources() != []
2708        # FIXME: Should use sl.extract_all_objects(recursive: true) as
2709        # input. Sources can be used multiple times but objects are
2710        # unique when it comes to lookup in compile_commands.json.
2711        # Depnds on a mesion version with
2712        # https://github.com/mesonbuild/meson/pull/8900
2713        modinfo_files += custom_target(d + '-' + m + '.modinfo',
2714                                       output: d + '-' + m + '.modinfo',
2715                                       input: module_ss.sources() + genh,
2716                                       capture: true,
2717                                       command: [modinfo_collect, module_ss.sources()])
2718      endif
2719    else
2720      if d == 'block'
2721        block_ss.add_all(module_ss)
2722      else
2723        softmmu_ss.add_all(module_ss)
2724      endif
2725    endif
2726  endforeach
2727endforeach
2728
2729foreach d, list : target_modules
2730  foreach m, module_ss : list
2731    if enable_modules and targetos != 'windows'
2732      foreach target : target_dirs
2733        if target.endswith('-softmmu')
2734          config_target = config_target_mak[target]
2735          config_target += config_host
2736          target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
2737          c_args = ['-DNEED_CPU_H',
2738                    '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
2739                    '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
2740          target_module_ss = module_ss.apply(config_target, strict: false)
2741          if target_module_ss.sources() != []
2742            module_name = d + '-' + m + '-' + config_target['TARGET_NAME']
2743            sl = static_library(module_name,
2744                                [genh, target_module_ss.sources()],
2745                                dependencies: [modulecommon, target_module_ss.dependencies()],
2746                                include_directories: target_inc,
2747                                c_args: c_args,
2748                                pic: true)
2749            softmmu_mods += sl
2750            # FIXME: Should use sl.extract_all_objects(recursive: true) too.
2751            modinfo_files += custom_target(module_name + '.modinfo',
2752                                           output: module_name + '.modinfo',
2753                                           input: target_module_ss.sources() + genh,
2754                                           capture: true,
2755                                           command: [modinfo_collect, '--target', target, target_module_ss.sources()])
2756          endif
2757        endif
2758      endforeach
2759    else
2760      specific_ss.add_all(module_ss)
2761    endif
2762  endforeach
2763endforeach
2764
2765if enable_modules
2766  modinfo_src = custom_target('modinfo.c',
2767                              output: 'modinfo.c',
2768                              input: modinfo_files,
2769                              command: [modinfo_generate, '@INPUT@'],
2770                              capture: true)
2771  modinfo_lib = static_library('modinfo', modinfo_src)
2772  modinfo_dep = declare_dependency(link_whole: modinfo_lib)
2773  softmmu_ss.add(modinfo_dep)
2774endif
2775
2776nm = find_program('nm')
2777undefsym = find_program('scripts/undefsym.py')
2778block_syms = custom_target('block.syms', output: 'block.syms',
2779                             input: [libqemuutil, block_mods],
2780                             capture: true,
2781                             command: [undefsym, nm, '@INPUT@'])
2782qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
2783                             input: [libqemuutil, softmmu_mods],
2784                             capture: true,
2785                             command: [undefsym, nm, '@INPUT@'])
2786
2787qom_ss = qom_ss.apply(config_host, strict: false)
2788libqom = static_library('qom', qom_ss.sources() + genh,
2789                        dependencies: [qom_ss.dependencies()],
2790                        name_suffix: 'fa')
2791
2792qom = declare_dependency(link_whole: libqom)
2793
2794authz_ss = authz_ss.apply(config_host, strict: false)
2795libauthz = static_library('authz', authz_ss.sources() + genh,
2796                          dependencies: [authz_ss.dependencies()],
2797                          name_suffix: 'fa',
2798                          build_by_default: false)
2799
2800authz = declare_dependency(link_whole: libauthz,
2801                           dependencies: qom)
2802
2803crypto_ss = crypto_ss.apply(config_host, strict: false)
2804libcrypto = static_library('crypto', crypto_ss.sources() + genh,
2805                           dependencies: [crypto_ss.dependencies()],
2806                           name_suffix: 'fa',
2807                           build_by_default: false)
2808
2809crypto = declare_dependency(link_whole: libcrypto,
2810                            dependencies: [authz, qom])
2811
2812io_ss = io_ss.apply(config_host, strict: false)
2813libio = static_library('io', io_ss.sources() + genh,
2814                       dependencies: [io_ss.dependencies()],
2815                       link_with: libqemuutil,
2816                       name_suffix: 'fa',
2817                       build_by_default: false)
2818
2819io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
2820
2821libmigration = static_library('migration', sources: migration_files + genh,
2822                              name_suffix: 'fa',
2823                              build_by_default: false)
2824migration = declare_dependency(link_with: libmigration,
2825                               dependencies: [zlib, qom, io])
2826softmmu_ss.add(migration)
2827
2828block_ss = block_ss.apply(config_host, strict: false)
2829libblock = static_library('block', block_ss.sources() + genh,
2830                          dependencies: block_ss.dependencies(),
2831                          link_depends: block_syms,
2832                          name_suffix: 'fa',
2833                          build_by_default: false)
2834
2835block = declare_dependency(link_whole: [libblock],
2836                           link_args: '@block.syms',
2837                           dependencies: [crypto, io])
2838
2839blockdev_ss = blockdev_ss.apply(config_host, strict: false)
2840libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
2841                             dependencies: blockdev_ss.dependencies(),
2842                             name_suffix: 'fa',
2843                             build_by_default: false)
2844
2845blockdev = declare_dependency(link_whole: [libblockdev],
2846                              dependencies: [block])
2847
2848qmp_ss = qmp_ss.apply(config_host, strict: false)
2849libqmp = static_library('qmp', qmp_ss.sources() + genh,
2850                        dependencies: qmp_ss.dependencies(),
2851                        name_suffix: 'fa',
2852                        build_by_default: false)
2853
2854qmp = declare_dependency(link_whole: [libqmp])
2855
2856libchardev = static_library('chardev', chardev_ss.sources() + genh,
2857                            name_suffix: 'fa',
2858                            dependencies: [gnutls],
2859                            build_by_default: false)
2860
2861chardev = declare_dependency(link_whole: libchardev)
2862
2863hwcore_ss = hwcore_ss.apply(config_host, strict: false)
2864libhwcore = static_library('hwcore', sources: hwcore_ss.sources() + genh,
2865                           name_suffix: 'fa',
2866                           build_by_default: false)
2867hwcore = declare_dependency(link_whole: libhwcore)
2868common_ss.add(hwcore)
2869
2870###########
2871# Targets #
2872###########
2873
2874emulator_modules = []
2875foreach m : block_mods + softmmu_mods
2876  emulator_modules += shared_module(m.name(),
2877                build_by_default: true,
2878                name_prefix: '',
2879                link_whole: m,
2880                install: true,
2881                install_dir: qemu_moddir)
2882endforeach
2883
2884softmmu_ss.add(authz, blockdev, chardev, crypto, io, qmp)
2885common_ss.add(qom, qemuutil)
2886
2887common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
2888common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
2889
2890common_all = common_ss.apply(config_all, strict: false)
2891common_all = static_library('common',
2892                            build_by_default: false,
2893                            sources: common_all.sources() + genh,
2894                            include_directories: common_user_inc,
2895                            implicit_include_directories: false,
2896                            dependencies: common_all.dependencies(),
2897                            name_suffix: 'fa')
2898
2899feature_to_c = find_program('scripts/feature_to_c.sh')
2900
2901emulators = {}
2902foreach target : target_dirs
2903  config_target = config_target_mak[target]
2904  target_name = config_target['TARGET_NAME']
2905  target_base_arch = config_target['TARGET_BASE_ARCH']
2906  arch_srcs = [config_target_h[target]]
2907  arch_deps = []
2908  c_args = ['-DNEED_CPU_H',
2909            '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
2910            '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
2911  link_args = emulator_link_args
2912
2913  config_target += config_host
2914  target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
2915  if targetos == 'linux'
2916    target_inc += include_directories('linux-headers', is_system: true)
2917  endif
2918  if target.endswith('-softmmu')
2919    qemu_target_name = 'qemu-system-' + target_name
2920    target_type='system'
2921    t = target_softmmu_arch[target_base_arch].apply(config_target, strict: false)
2922    arch_srcs += t.sources()
2923    arch_deps += t.dependencies()
2924
2925    hw_dir = target_name == 'sparc64' ? 'sparc64' : target_base_arch
2926    hw = hw_arch[hw_dir].apply(config_target, strict: false)
2927    arch_srcs += hw.sources()
2928    arch_deps += hw.dependencies()
2929
2930    arch_srcs += config_devices_h[target]
2931    link_args += ['@block.syms', '@qemu.syms']
2932  else
2933    abi = config_target['TARGET_ABI_DIR']
2934    target_type='user'
2935    target_inc += common_user_inc
2936    qemu_target_name = 'qemu-' + target_name
2937    if target_base_arch in target_user_arch
2938      t = target_user_arch[target_base_arch].apply(config_target, strict: false)
2939      arch_srcs += t.sources()
2940      arch_deps += t.dependencies()
2941    endif
2942    if 'CONFIG_LINUX_USER' in config_target
2943      base_dir = 'linux-user'
2944    endif
2945    if 'CONFIG_BSD_USER' in config_target
2946      base_dir = 'bsd-user'
2947      target_inc += include_directories('bsd-user/' / targetos)
2948      target_inc += include_directories('bsd-user/host/' / host_arch)
2949      dir = base_dir / abi
2950      arch_srcs += files(dir / 'signal.c', dir / 'target_arch_cpu.c')
2951    endif
2952    target_inc += include_directories(
2953      base_dir,
2954      base_dir / abi,
2955    )
2956    if 'CONFIG_LINUX_USER' in config_target
2957      dir = base_dir / abi
2958      arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
2959      if config_target.has_key('TARGET_SYSTBL_ABI')
2960        arch_srcs += \
2961          syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
2962                                             extra_args : config_target['TARGET_SYSTBL_ABI'])
2963      endif
2964    endif
2965  endif
2966
2967  if 'TARGET_XML_FILES' in config_target
2968    gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
2969                                output: target + '-gdbstub-xml.c',
2970                                input: files(config_target['TARGET_XML_FILES'].split()),
2971                                command: [feature_to_c, '@INPUT@'],
2972                                capture: true)
2973    arch_srcs += gdbstub_xml
2974  endif
2975
2976  t = target_arch[target_base_arch].apply(config_target, strict: false)
2977  arch_srcs += t.sources()
2978  arch_deps += t.dependencies()
2979
2980  target_common = common_ss.apply(config_target, strict: false)
2981  objects = common_all.extract_objects(target_common.sources())
2982  deps = target_common.dependencies()
2983
2984  target_specific = specific_ss.apply(config_target, strict: false)
2985  arch_srcs += target_specific.sources()
2986  arch_deps += target_specific.dependencies()
2987
2988  lib = static_library('qemu-' + target,
2989                 sources: arch_srcs + genh,
2990                 dependencies: arch_deps,
2991                 objects: objects,
2992                 include_directories: target_inc,
2993                 c_args: c_args,
2994                 build_by_default: false,
2995                 name_suffix: 'fa')
2996
2997  if target.endswith('-softmmu')
2998    execs = [{
2999      'name': 'qemu-system-' + target_name,
3000      'win_subsystem': 'console',
3001      'sources': files('softmmu/main.c'),
3002      'dependencies': []
3003    }]
3004    if targetos == 'windows' and (sdl.found() or gtk.found())
3005      execs += [{
3006        'name': 'qemu-system-' + target_name + 'w',
3007        'win_subsystem': 'windows',
3008        'sources': files('softmmu/main.c'),
3009        'dependencies': []
3010      }]
3011    endif
3012    if get_option('fuzzing')
3013      specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
3014      execs += [{
3015        'name': 'qemu-fuzz-' + target_name,
3016        'win_subsystem': 'console',
3017        'sources': specific_fuzz.sources(),
3018        'dependencies': specific_fuzz.dependencies(),
3019      }]
3020    endif
3021  else
3022    execs = [{
3023      'name': 'qemu-' + target_name,
3024      'win_subsystem': 'console',
3025      'sources': [],
3026      'dependencies': []
3027    }]
3028  endif
3029  foreach exe: execs
3030    exe_name = exe['name']
3031    if targetos == 'darwin'
3032      exe_name += '-unsigned'
3033    endif
3034
3035    emulator = executable(exe_name, exe['sources'],
3036               install: true,
3037               c_args: c_args,
3038               dependencies: arch_deps + deps + exe['dependencies'],
3039               objects: lib.extract_all_objects(recursive: true),
3040               link_language: link_language,
3041               link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
3042               link_args: link_args,
3043               win_subsystem: exe['win_subsystem'])
3044
3045    if targetos == 'darwin'
3046      icon = 'pc-bios/qemu.rsrc'
3047      build_input = [emulator, files(icon)]
3048      install_input = [
3049        get_option('bindir') / exe_name,
3050        meson.current_source_dir() / icon
3051      ]
3052      if 'CONFIG_HVF' in config_target
3053        entitlements = 'accel/hvf/entitlements.plist'
3054        build_input += files(entitlements)
3055        install_input += meson.current_source_dir() / entitlements
3056      endif
3057
3058      entitlement = find_program('scripts/entitlement.sh')
3059      emulators += {exe['name'] : custom_target(exe['name'],
3060                   input: build_input,
3061                   output: exe['name'],
3062                   command: [entitlement, '@OUTPUT@', '@INPUT@'])
3063      }
3064
3065      meson.add_install_script(entitlement, '--install',
3066                               get_option('bindir') / exe['name'],
3067                               install_input)
3068    else
3069      emulators += {exe['name']: emulator}
3070    endif
3071
3072    if stap.found()
3073      foreach stp: [
3074        {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
3075        {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
3076        {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
3077        {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
3078      ]
3079        custom_target(exe['name'] + stp['ext'],
3080                      input: trace_events_all,
3081                      output: exe['name'] + stp['ext'],
3082                      install: stp['install'],
3083                      install_dir: get_option('datadir') / 'systemtap/tapset',
3084                      command: [
3085                        tracetool, '--group=all', '--format=' + stp['fmt'],
3086                        '--binary=' + stp['bin'],
3087                        '--target-name=' + target_name,
3088                        '--target-type=' + target_type,
3089                        '--probe-prefix=qemu.' + target_type + '.' + target_name,
3090                        '@INPUT@', '@OUTPUT@'
3091                      ],
3092                      depend_files: tracetool_depends)
3093      endforeach
3094    endif
3095  endforeach
3096endforeach
3097
3098# Other build targets
3099
3100if 'CONFIG_PLUGIN' in config_host
3101  install_headers('include/qemu/qemu-plugin.h')
3102endif
3103
3104if 'CONFIG_GUEST_AGENT' in config_host
3105  subdir('qga')
3106elif get_option('guest_agent_msi').enabled()
3107  error('Guest agent MSI requested, but the guest agent is not being built')
3108endif
3109
3110# Don't build qemu-keymap if xkbcommon is not explicitly enabled
3111# when we don't build tools or system
3112if xkbcommon.found()
3113  # used for the update-keymaps target, so include rules even if !have_tools
3114  qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
3115                           dependencies: [qemuutil, xkbcommon], install: have_tools)
3116endif
3117
3118if have_tools
3119  qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
3120             dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
3121  qemu_io = executable('qemu-io', files('qemu-io.c'),
3122             dependencies: [block, qemuutil], install: true)
3123  qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
3124               dependencies: [blockdev, qemuutil, gnutls, selinux],
3125               install: true)
3126
3127  subdir('storage-daemon')
3128  subdir('contrib/rdmacm-mux')
3129  subdir('contrib/elf2dmp')
3130
3131  executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
3132             dependencies: qemuutil,
3133             install: true)
3134
3135  if 'CONFIG_VHOST_USER' in config_host
3136    subdir('contrib/vhost-user-blk')
3137    subdir('contrib/vhost-user-gpu')
3138    subdir('contrib/vhost-user-input')
3139    subdir('contrib/vhost-user-scsi')
3140  endif
3141
3142  if targetos == 'linux'
3143    executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
3144               dependencies: [qemuutil, libcap_ng],
3145               install: true,
3146               install_dir: get_option('libexecdir'))
3147
3148    executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
3149               dependencies: [authz, crypto, io, qom, qemuutil,
3150                              libcap_ng, mpathpersist],
3151               install: true)
3152  endif
3153
3154  if have_ivshmem
3155    subdir('contrib/ivshmem-client')
3156    subdir('contrib/ivshmem-server')
3157  endif
3158endif
3159
3160subdir('scripts')
3161subdir('tools')
3162subdir('pc-bios')
3163subdir('docs')
3164subdir('tests')
3165if gtk.found()
3166  subdir('po')
3167endif
3168
3169if host_machine.system() == 'windows'
3170  nsis_cmd = [
3171    find_program('scripts/nsis.py'),
3172    '@OUTPUT@',
3173    get_option('prefix'),
3174    meson.current_source_dir(),
3175    host_machine.cpu(),
3176    '--',
3177    '-DDISPLAYVERSION=' + meson.project_version(),
3178  ]
3179  if build_docs
3180    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
3181  endif
3182  if gtk.found()
3183    nsis_cmd += '-DCONFIG_GTK=y'
3184  endif
3185
3186  nsis = custom_target('nsis',
3187                       output: 'qemu-setup-' + meson.project_version() + '.exe',
3188                       input: files('qemu.nsi'),
3189                       build_always_stale: true,
3190                       command: nsis_cmd + ['@INPUT@'])
3191  alias_target('installer', nsis)
3192endif
3193
3194#########################
3195# Configuration summary #
3196#########################
3197
3198# Directories
3199summary_info = {}
3200summary_info += {'Install prefix':    get_option('prefix')}
3201summary_info += {'BIOS directory':    qemu_datadir}
3202summary_info += {'firmware path':     get_option('qemu_firmwarepath')}
3203summary_info += {'binary directory':  get_option('bindir')}
3204summary_info += {'library directory': get_option('libdir')}
3205summary_info += {'module directory':  qemu_moddir}
3206summary_info += {'libexec directory': get_option('libexecdir')}
3207summary_info += {'include directory': get_option('includedir')}
3208summary_info += {'config directory':  get_option('sysconfdir')}
3209if targetos != 'windows'
3210  summary_info += {'local state directory': get_option('localstatedir')}
3211  summary_info += {'Manual directory':      get_option('mandir')}
3212else
3213  summary_info += {'local state directory': 'queried at runtime'}
3214endif
3215summary_info += {'Doc directory':     get_option('docdir')}
3216summary_info += {'Build directory':   meson.current_build_dir()}
3217summary_info += {'Source path':       meson.current_source_dir()}
3218summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
3219summary(summary_info, bool_yn: true, section: 'Directories')
3220
3221# Host binaries
3222summary_info = {}
3223summary_info += {'git':               config_host['GIT']}
3224summary_info += {'make':              config_host['MAKE']}
3225summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
3226summary_info += {'sphinx-build':      sphinx_build}
3227if config_host.has_key('HAVE_GDB_BIN')
3228  summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
3229endif
3230summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
3231if targetos == 'windows' and config_host.has_key('CONFIG_GUEST_AGENT')
3232  summary_info += {'wixl':            wixl}
3233endif
3234if slirp_opt != 'disabled' and 'CONFIG_SLIRP_SMBD' in config_host
3235  summary_info += {'smbd':            config_host['CONFIG_SMBD_COMMAND']}
3236endif
3237summary(summary_info, bool_yn: true, section: 'Host binaries')
3238
3239# Configurable features
3240summary_info = {}
3241summary_info += {'Documentation':     build_docs}
3242summary_info += {'system-mode emulation': have_system}
3243summary_info += {'user-mode emulation': have_user}
3244summary_info += {'block layer':       have_block}
3245summary_info += {'Install blobs':     get_option('install_blobs')}
3246summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
3247if config_host.has_key('CONFIG_MODULES')
3248  summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')}
3249endif
3250summary_info += {'fuzzing support':   get_option('fuzzing')}
3251if have_system
3252  summary_info += {'Audio drivers':     ' '.join(audio_drivers_selected)}
3253endif
3254summary_info += {'Trace backends':    ','.join(get_option('trace_backends'))}
3255if 'simple' in get_option('trace_backends')
3256  summary_info += {'Trace output file': get_option('trace_file') + '-<pid>'}
3257endif
3258summary_info += {'D-Bus display':     dbus_display}
3259summary_info += {'QOM debugging':     config_host.has_key('CONFIG_QOM_CAST_DEBUG')}
3260summary_info += {'vhost-kernel support': config_host.has_key('CONFIG_VHOST_KERNEL')}
3261summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')}
3262summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')}
3263summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')}
3264summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')}
3265summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_USER')}
3266summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
3267summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')}
3268summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')}
3269summary_info += {'build guest agent': config_host.has_key('CONFIG_GUEST_AGENT')}
3270summary(summary_info, bool_yn: true, section: 'Configurable features')
3271
3272# Compilation information
3273summary_info = {}
3274summary_info += {'host CPU':          cpu}
3275summary_info += {'host endianness':   build_machine.endian()}
3276summary_info += {'C compiler':        ' '.join(meson.get_compiler('c').cmd_array())}
3277summary_info += {'Host C compiler':   ' '.join(meson.get_compiler('c', native: true).cmd_array())}
3278if link_language == 'cpp'
3279  summary_info += {'C++ compiler':    ' '.join(meson.get_compiler('cpp').cmd_array())}
3280else
3281  summary_info += {'C++ compiler':      false}
3282endif
3283if targetos == 'darwin'
3284  summary_info += {'Objective-C compiler': ' '.join(meson.get_compiler('objc').cmd_array())}
3285endif
3286if targetos == 'windows'
3287  if 'WIN_SDK' in config_host
3288    summary_info += {'Windows SDK':   config_host['WIN_SDK']}
3289  endif
3290endif
3291summary_info += {'CFLAGS':            ' '.join(get_option('c_args')
3292                                               + ['-O' + get_option('optimization')]
3293                                               + (get_option('debug') ? ['-g'] : []))}
3294if link_language == 'cpp'
3295  summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args')
3296                                               + ['-O' + get_option('optimization')]
3297                                               + (get_option('debug') ? ['-g'] : []))}
3298endif
3299link_args = get_option(link_language + '_link_args')
3300if link_args.length() > 0
3301  summary_info += {'LDFLAGS':         ' '.join(link_args)}
3302endif
3303summary_info += {'QEMU_CFLAGS':       config_host['QEMU_CFLAGS']}
3304summary_info += {'QEMU_LDFLAGS':      config_host['QEMU_LDFLAGS']}
3305summary_info += {'profiler':          config_host.has_key('CONFIG_PROFILER')}
3306summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
3307summary_info += {'PIE':               get_option('b_pie')}
3308summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
3309summary_info += {'malloc trim support': has_malloc_trim}
3310summary_info += {'membarrier':        config_host.has_key('CONFIG_MEMBARRIER')}
3311summary_info += {'debug stack usage': config_host.has_key('CONFIG_DEBUG_STACK_USAGE')}
3312summary_info += {'mutex debugging':   config_host.has_key('CONFIG_DEBUG_MUTEX')}
3313summary_info += {'memory allocator':  get_option('malloc')}
3314summary_info += {'avx2 optimization': config_host.has_key('CONFIG_AVX2_OPT')}
3315summary_info += {'avx512f optimization': config_host.has_key('CONFIG_AVX512F_OPT')}
3316summary_info += {'gprof enabled':     config_host.has_key('CONFIG_GPROF')}
3317summary_info += {'gcov':              get_option('b_coverage')}
3318summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
3319summary_info += {'CFI support':       get_option('cfi')}
3320if get_option('cfi')
3321  summary_info += {'CFI debug support': get_option('cfi_debug')}
3322endif
3323summary_info += {'strip binaries':    get_option('strip')}
3324summary_info += {'sparse':            sparse}
3325summary_info += {'mingw32 support':   targetos == 'windows'}
3326
3327# snarf the cross-compilation information for tests
3328foreach target: target_dirs
3329  tcg_mak = meson.current_build_dir() / 'tests/tcg' / 'config-' + target + '.mak'
3330  if fs.exists(tcg_mak)
3331    config_cross_tcg = keyval.load(tcg_mak)
3332    target = config_cross_tcg['TARGET_NAME']
3333    compiler = ''
3334    if 'DOCKER_CROSS_CC_GUEST' in config_cross_tcg
3335      summary_info += {target + ' tests': config_cross_tcg['DOCKER_CROSS_CC_GUEST'] +
3336                                          ' via ' + config_cross_tcg['DOCKER_IMAGE']}
3337    elif 'CROSS_CC_GUEST' in config_cross_tcg
3338      summary_info += {target + ' tests'
3339                                : config_cross_tcg['CROSS_CC_GUEST'] }
3340    endif
3341   endif
3342endforeach
3343
3344summary(summary_info, bool_yn: true, section: 'Compilation')
3345
3346# Targets and accelerators
3347summary_info = {}
3348if have_system
3349  summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
3350  summary_info += {'HAX support':       config_all.has_key('CONFIG_HAX')}
3351  summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
3352  summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
3353  summary_info += {'NVMM support':      config_all.has_key('CONFIG_NVMM')}
3354  summary_info += {'Xen support':       config_host.has_key('CONFIG_XEN_BACKEND')}
3355  if config_host.has_key('CONFIG_XEN_BACKEND')
3356    summary_info += {'xen ctrl version':  config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
3357  endif
3358endif
3359summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
3360if config_all.has_key('CONFIG_TCG')
3361  if get_option('tcg_interpreter')
3362    summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, slow)'}
3363  else
3364    summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
3365  endif
3366  summary_info += {'TCG plugins': config_host.has_key('CONFIG_PLUGIN')}
3367  summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
3368endif
3369summary_info += {'target list':       ' '.join(target_dirs)}
3370if have_system
3371  summary_info += {'default devices':   get_option('default_devices')}
3372  summary_info += {'out of process emulation': multiprocess_allowed}
3373endif
3374summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
3375
3376# Block layer
3377summary_info = {}
3378summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
3379summary_info += {'coroutine pool':    config_host['CONFIG_COROUTINE_POOL'] == '1'}
3380if have_block
3381  summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']}
3382  summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']}
3383  summary_info += {'Use block whitelist in tools': config_host.has_key('CONFIG_BDRV_WHITELIST_TOOLS')}
3384  summary_info += {'VirtFS support':    have_virtfs}
3385  summary_info += {'build virtiofs daemon': have_virtiofsd}
3386  summary_info += {'Live block migration': config_host.has_key('CONFIG_LIVE_BLOCK_MIGRATION')}
3387  summary_info += {'replication support': config_host.has_key('CONFIG_REPLICATION')}
3388  summary_info += {'bochs support':     config_host.has_key('CONFIG_BOCHS')}
3389  summary_info += {'cloop support':     config_host.has_key('CONFIG_CLOOP')}
3390  summary_info += {'dmg support':       config_host.has_key('CONFIG_DMG')}
3391  summary_info += {'qcow v1 support':   config_host.has_key('CONFIG_QCOW1')}
3392  summary_info += {'vdi support':       config_host.has_key('CONFIG_VDI')}
3393  summary_info += {'vvfat support':     config_host.has_key('CONFIG_VVFAT')}
3394  summary_info += {'qed support':       config_host.has_key('CONFIG_QED')}
3395  summary_info += {'parallels support': config_host.has_key('CONFIG_PARALLELS')}
3396  summary_info += {'FUSE exports':      fuse}
3397endif
3398summary(summary_info, bool_yn: true, section: 'Block layer support')
3399
3400# Crypto
3401summary_info = {}
3402summary_info += {'TLS priority':      config_host['CONFIG_TLS_PRIORITY']}
3403summary_info += {'GNUTLS support':    gnutls}
3404if gnutls.found()
3405  summary_info += {'  GNUTLS crypto':   gnutls_crypto.found()}
3406endif
3407summary_info += {'libgcrypt':         gcrypt}
3408summary_info += {'nettle':            nettle}
3409if nettle.found()
3410   summary_info += {'  XTS':             xts != 'private'}
3411endif
3412summary_info += {'crypto afalg':      config_host.has_key('CONFIG_AF_ALG')}
3413summary_info += {'rng-none':          config_host.has_key('CONFIG_RNG_NONE')}
3414summary_info += {'Linux keyring':     config_host.has_key('CONFIG_SECRET_KEYRING')}
3415summary(summary_info, bool_yn: true, section: 'Crypto')
3416
3417# Libraries
3418summary_info = {}
3419if targetos == 'darwin'
3420  summary_info += {'Cocoa support':   cocoa}
3421endif
3422summary_info += {'SDL support':       sdl}
3423summary_info += {'SDL image support': sdl_image}
3424summary_info += {'GTK support':       gtk}
3425summary_info += {'pixman':            pixman}
3426summary_info += {'VTE support':       vte}
3427summary_info += {'slirp support':     slirp_opt == 'internal' ? slirp_opt : slirp}
3428summary_info += {'libtasn1':          tasn1}
3429summary_info += {'PAM':               pam}
3430summary_info += {'iconv support':     iconv}
3431summary_info += {'curses support':    curses}
3432summary_info += {'virgl support':     virgl}
3433summary_info += {'curl support':      curl}
3434summary_info += {'Multipath support': mpathpersist}
3435summary_info += {'VNC support':       vnc}
3436if vnc.found()
3437  summary_info += {'VNC SASL support':  sasl}
3438  summary_info += {'VNC JPEG support':  jpeg}
3439  summary_info += {'VNC PNG support':   png}
3440endif
3441if targetos not in ['darwin', 'haiku', 'windows']
3442  summary_info += {'OSS support':     oss}
3443elif targetos == 'darwin'
3444  summary_info += {'CoreAudio support': coreaudio}
3445elif targetos == 'windows'
3446  summary_info += {'DirectSound support': dsound}
3447endif
3448if targetos == 'linux'
3449  summary_info += {'ALSA support':    alsa}
3450  summary_info += {'PulseAudio support': pulse}
3451endif
3452summary_info += {'JACK support':      jack}
3453summary_info += {'brlapi support':    brlapi}
3454summary_info += {'vde support':       vde}
3455summary_info += {'netmap support':    have_netmap}
3456summary_info += {'l2tpv3 support':    have_l2tpv3}
3457summary_info += {'Linux AIO support': libaio}
3458summary_info += {'Linux io_uring support': linux_io_uring}
3459summary_info += {'ATTR/XATTR support': libattr}
3460summary_info += {'RDMA support':      config_host.has_key('CONFIG_RDMA')}
3461summary_info += {'PVRDMA support':    config_host.has_key('CONFIG_PVRDMA')}
3462summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
3463summary_info += {'libcap-ng support': libcap_ng}
3464summary_info += {'bpf support':       libbpf}
3465summary_info += {'spice protocol support': spice_protocol}
3466if spice_protocol.found()
3467  summary_info += {'  spice server support': spice}
3468endif
3469summary_info += {'rbd support':       rbd}
3470summary_info += {'smartcard support': cacard}
3471summary_info += {'U2F support':       u2f}
3472summary_info += {'libusb':            libusb}
3473summary_info += {'usb net redir':     usbredir}
3474summary_info += {'OpenGL support':    config_host.has_key('CONFIG_OPENGL')}
3475summary_info += {'GBM':               gbm}
3476summary_info += {'libiscsi support':  libiscsi}
3477summary_info += {'libnfs support':    libnfs}
3478if targetos == 'windows'
3479  if config_host.has_key('CONFIG_GUEST_AGENT')
3480    summary_info += {'QGA VSS support':   config_host.has_key('CONFIG_QGA_VSS')}
3481    summary_info += {'QGA w32 disk info': config_host.has_key('CONFIG_QGA_NTDDSCSI')}
3482  endif
3483endif
3484summary_info += {'seccomp support':   seccomp}
3485summary_info += {'GlusterFS support': glusterfs}
3486summary_info += {'TPM support':       config_host.has_key('CONFIG_TPM')}
3487summary_info += {'libssh support':    libssh}
3488summary_info += {'lzo support':       lzo}
3489summary_info += {'snappy support':    snappy}
3490summary_info += {'bzip2 support':     libbzip2}
3491summary_info += {'lzfse support':     liblzfse}
3492summary_info += {'zstd support':      zstd}
3493summary_info += {'NUMA host support': config_host.has_key('CONFIG_NUMA')}
3494summary_info += {'capstone':          capstone_opt == 'internal' ? capstone_opt : capstone}
3495summary_info += {'libpmem support':   libpmem}
3496summary_info += {'libdaxctl support': libdaxctl}
3497summary_info += {'libudev':           libudev}
3498# Dummy dependency, keep .found()
3499summary_info += {'FUSE lseek':        fuse_lseek.found()}
3500summary_info += {'selinux':           selinux}
3501summary(summary_info, bool_yn: true, section: 'Dependencies')
3502
3503if not supported_cpus.contains(cpu)
3504  message()
3505  warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
3506  message()
3507  message('CPU host architecture ' + cpu + ' support is not currently maintained.')
3508  message('The QEMU project intends to remove support for this host CPU in')
3509  message('a future release if nobody volunteers to maintain it and to')
3510  message('provide a build host for our continuous integration setup.')
3511  message('configure has succeeded and you can continue to build, but')
3512  message('if you care about QEMU on this platform you should contact')
3513  message('us upstream at qemu-devel@nongnu.org.')
3514endif
3515
3516if not supported_oses.contains(targetos)
3517  message()
3518  warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
3519  message()
3520  message('Host OS ' + targetos + 'support is not currently maintained.')
3521  message('The QEMU project intends to remove support for this host OS in')
3522  message('a future release if nobody volunteers to maintain it and to')
3523  message('provide a build host for our continuous integration setup.')
3524  message('configure has succeeded and you can continue to build, but')
3525  message('if you care about QEMU on this platform you should contact')
3526  message('us upstream at qemu-devel@nongnu.org.')
3527endif
3528