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