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