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