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