xref: /openbmc/qemu/meson.build (revision 5df022cf)
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'))
1622# Note that we need to specify prefix: here to avoid incorrectly
1623# thinking that Windows has posix_memalign()
1624config_host_data.set('CONFIG_POSIX_MEMALIGN', cc.has_function('posix_memalign', prefix: '#include <stdlib.h>'))
1625config_host_data.set('CONFIG_ALIGNED_MALLOC', cc.has_function('_aligned_malloc'))
1626config_host_data.set('CONFIG_VALLOC', cc.has_function('valloc'))
1627config_host_data.set('CONFIG_MEMALIGN', cc.has_function('memalign'))
1628config_host_data.set('CONFIG_PPOLL', cc.has_function('ppoll'))
1629config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include <sys/uio.h>'))
1630config_host_data.set('CONFIG_SEM_TIMEDWAIT', cc.has_function('sem_timedwait', dependencies: threads))
1631config_host_data.set('CONFIG_SENDFILE', cc.has_function('sendfile'))
1632config_host_data.set('CONFIG_SETNS', cc.has_function('setns') and cc.has_function('unshare'))
1633config_host_data.set('CONFIG_SYNCFS', cc.has_function('syncfs'))
1634config_host_data.set('CONFIG_SYNC_FILE_RANGE', cc.has_function('sync_file_range'))
1635config_host_data.set('CONFIG_TIMERFD', cc.has_function('timerfd_create'))
1636config_host_data.set('HAVE_COPY_FILE_RANGE', cc.has_function('copy_file_range'))
1637config_host_data.set('HAVE_OPENPTY', cc.has_function('openpty', dependencies: util))
1638config_host_data.set('HAVE_STRCHRNUL', cc.has_function('strchrnul'))
1639config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: '#include <stdlib.h>'))
1640if rdma.found()
1641  config_host_data.set('HAVE_IBV_ADVISE_MR',
1642                       cc.has_function('ibv_advise_mr',
1643                                       args: config_host['RDMA_LIBS'].split(),
1644                                       prefix: '#include <infiniband/verbs.h>'))
1645endif
1646
1647# has_header_symbol
1648config_host_data.set('CONFIG_BYTESWAP_H',
1649                     cc.has_header_symbol('byteswap.h', 'bswap_32'))
1650config_host_data.set('CONFIG_EPOLL_CREATE1',
1651                     cc.has_header_symbol('sys/epoll.h', 'epoll_create1'))
1652config_host_data.set('CONFIG_HAS_ENVIRON',
1653                     cc.has_header_symbol('unistd.h', 'environ', prefix: gnu_source_prefix))
1654config_host_data.set('CONFIG_FALLOCATE_PUNCH_HOLE',
1655                     cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_PUNCH_HOLE') and
1656                     cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_KEEP_SIZE'))
1657config_host_data.set('CONFIG_FALLOCATE_ZERO_RANGE',
1658                     cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_ZERO_RANGE'))
1659config_host_data.set('CONFIG_FIEMAP',
1660                     cc.has_header('linux/fiemap.h') and
1661                     cc.has_header_symbol('linux/fs.h', 'FS_IOC_FIEMAP'))
1662config_host_data.set('CONFIG_GETRANDOM',
1663                     cc.has_function('getrandom') and
1664                     cc.has_header_symbol('sys/random.h', 'GRND_NONBLOCK'))
1665config_host_data.set('CONFIG_INOTIFY',
1666                     cc.has_header_symbol('sys/inotify.h', 'inotify_init'))
1667config_host_data.set('CONFIG_INOTIFY1',
1668                     cc.has_header_symbol('sys/inotify.h', 'inotify_init1'))
1669config_host_data.set('CONFIG_MACHINE_BSWAP_H',
1670                     cc.has_header_symbol('machine/bswap.h', 'bswap32',
1671                                          prefix: '''#include <sys/endian.h>
1672                                                     #include <sys/types.h>'''))
1673config_host_data.set('CONFIG_PRCTL_PR_SET_TIMERSLACK',
1674                     cc.has_header_symbol('sys/prctl.h', 'PR_SET_TIMERSLACK'))
1675config_host_data.set('CONFIG_RTNETLINK',
1676                     cc.has_header_symbol('linux/rtnetlink.h', 'IFLA_PROTO_DOWN'))
1677config_host_data.set('CONFIG_SYSMACROS',
1678                     cc.has_header_symbol('sys/sysmacros.h', 'makedev'))
1679config_host_data.set('HAVE_OPTRESET',
1680                     cc.has_header_symbol('getopt.h', 'optreset'))
1681config_host_data.set('HAVE_IPPROTO_MPTCP',
1682                     cc.has_header_symbol('netinet/in.h', 'IPPROTO_MPTCP'))
1683
1684# has_member
1685config_host_data.set('HAVE_SIGEV_NOTIFY_THREAD_ID',
1686                     cc.has_member('struct sigevent', 'sigev_notify_thread_id',
1687                                   prefix: '#include <signal.h>'))
1688config_host_data.set('HAVE_STRUCT_STAT_ST_ATIM',
1689                     cc.has_member('struct stat', 'st_atim',
1690                                   prefix: '#include <sys/stat.h>'))
1691
1692# has_type
1693config_host_data.set('CONFIG_IOVEC',
1694                     cc.has_type('struct iovec',
1695                                 prefix: '#include <sys/uio.h>'))
1696config_host_data.set('HAVE_UTMPX',
1697                     cc.has_type('struct utmpx',
1698                                 prefix: '#include <utmpx.h>'))
1699
1700config_host_data.set('CONFIG_EVENTFD', cc.links('''
1701  #include <sys/eventfd.h>
1702  int main(void) { return eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); }'''))
1703config_host_data.set('CONFIG_FDATASYNC', cc.links(gnu_source_prefix + '''
1704  #include <unistd.h>
1705  int main(void) {
1706  #if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
1707  return fdatasync(0);
1708  #else
1709  #error Not supported
1710  #endif
1711  }'''))
1712config_host_data.set('CONFIG_MADVISE', cc.links(gnu_source_prefix + '''
1713  #include <sys/types.h>
1714  #include <sys/mman.h>
1715  #include <stddef.h>
1716  int main(void) { return madvise(NULL, 0, MADV_DONTNEED); }'''))
1717config_host_data.set('CONFIG_MEMFD', cc.links(gnu_source_prefix + '''
1718  #include <sys/mman.h>
1719  int main(void) { return memfd_create("foo", MFD_ALLOW_SEALING); }'''))
1720config_host_data.set('CONFIG_OPEN_BY_HANDLE', cc.links(gnu_source_prefix + '''
1721  #include <fcntl.h>
1722  #if !defined(AT_EMPTY_PATH)
1723  # error missing definition
1724  #else
1725  int main(void) { struct file_handle fh; return open_by_handle_at(0, &fh, 0); }
1726  #endif'''))
1727config_host_data.set('CONFIG_PIPE2', cc.links(gnu_source_prefix + '''
1728  #include <unistd.h>
1729  #include <fcntl.h>
1730
1731  int main(void)
1732  {
1733      int pipefd[2];
1734      return pipe2(pipefd, O_CLOEXEC);
1735  }'''))
1736config_host_data.set('CONFIG_POSIX_MADVISE', cc.links(gnu_source_prefix + '''
1737  #include <sys/mman.h>
1738  #include <stddef.h>
1739  int main(void) { return posix_madvise(NULL, 0, POSIX_MADV_DONTNEED); }'''))
1740
1741config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_W_TID', cc.links(gnu_source_prefix + '''
1742  #include <pthread.h>
1743
1744  static void *f(void *p) { return NULL; }
1745  int main(void)
1746  {
1747    pthread_t thread;
1748    pthread_create(&thread, 0, f, 0);
1749    pthread_setname_np(thread, "QEMU");
1750    return 0;
1751  }''', dependencies: threads))
1752config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_WO_TID', cc.links(gnu_source_prefix + '''
1753  #include <pthread.h>
1754
1755  static void *f(void *p) { pthread_setname_np("QEMU"); return NULL; }
1756  int main(void)
1757  {
1758    pthread_t thread;
1759    pthread_create(&thread, 0, f, 0);
1760    return 0;
1761  }''', dependencies: threads))
1762
1763config_host_data.set('CONFIG_SIGNALFD', cc.links(gnu_source_prefix + '''
1764  #include <sys/signalfd.h>
1765  #include <stddef.h>
1766  int main(void) { return signalfd(-1, NULL, SFD_CLOEXEC); }'''))
1767config_host_data.set('CONFIG_SPLICE', cc.links(gnu_source_prefix + '''
1768  #include <unistd.h>
1769  #include <fcntl.h>
1770  #include <limits.h>
1771
1772  int main(void)
1773  {
1774    int len, fd = 0;
1775    len = tee(STDIN_FILENO, STDOUT_FILENO, INT_MAX, SPLICE_F_NONBLOCK);
1776    splice(STDIN_FILENO, NULL, fd, NULL, len, SPLICE_F_MOVE);
1777    return 0;
1778  }'''))
1779
1780config_host_data.set('HAVE_MLOCKALL', cc.links(gnu_source_prefix + '''
1781  #include <sys/mman.h>
1782  int main(int argc, char *argv[]) {
1783    return mlockall(MCL_FUTURE);
1784  }'''))
1785
1786have_l2tpv3 = false
1787if get_option('l2tpv3').allowed() and have_system
1788  have_l2tpv3 = cc.has_type('struct mmsghdr',
1789    prefix: gnu_source_prefix + '''
1790      #include <sys/socket.h>
1791      #include <linux/ip.h>''')
1792endif
1793config_host_data.set('CONFIG_L2TPV3', have_l2tpv3)
1794
1795have_netmap = false
1796if get_option('netmap').allowed() and have_system
1797  have_netmap = cc.compiles('''
1798    #include <inttypes.h>
1799    #include <net/if.h>
1800    #include <net/netmap.h>
1801    #include <net/netmap_user.h>
1802    #if (NETMAP_API < 11) || (NETMAP_API > 15)
1803    #error
1804    #endif
1805    int main(void) { return 0; }''')
1806  if not have_netmap and get_option('netmap').enabled()
1807    error('Netmap headers not available')
1808  endif
1809endif
1810config_host_data.set('CONFIG_NETMAP', have_netmap)
1811
1812# Work around a system header bug with some kernel/XFS header
1813# versions where they both try to define 'struct fsxattr':
1814# xfs headers will not try to redefine structs from linux headers
1815# if this macro is set.
1816config_host_data.set('HAVE_FSXATTR', cc.links('''
1817  #include <linux/fs.h>
1818  struct fsxattr foo;
1819  int main(void) {
1820    return 0;
1821  }'''))
1822
1823# Some versions of Mac OS X incorrectly define SIZE_MAX
1824config_host_data.set('HAVE_BROKEN_SIZE_MAX', not cc.compiles('''
1825    #include <stdint.h>
1826    #include <stdio.h>
1827    int main(int argc, char *argv[]) {
1828        return printf("%zu", SIZE_MAX);
1829    }''', args: ['-Werror']))
1830
1831# See if 64-bit atomic operations are supported.
1832# Note that without __atomic builtins, we can only
1833# assume atomic loads/stores max at pointer size.
1834config_host_data.set('CONFIG_ATOMIC64', cc.links('''
1835  #include <stdint.h>
1836  int main(void)
1837  {
1838    uint64_t x = 0, y = 0;
1839    y = __atomic_load_n(&x, __ATOMIC_RELAXED);
1840    __atomic_store_n(&x, y, __ATOMIC_RELAXED);
1841    __atomic_compare_exchange_n(&x, &y, x, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
1842    __atomic_exchange_n(&x, y, __ATOMIC_RELAXED);
1843    __atomic_fetch_add(&x, y, __ATOMIC_RELAXED);
1844    return 0;
1845  }'''))
1846
1847config_host_data.set('CONFIG_GETAUXVAL', cc.links(gnu_source_prefix + '''
1848  #include <sys/auxv.h>
1849  int main(void) {
1850    return getauxval(AT_HWCAP) == 0;
1851  }'''))
1852
1853have_cpuid_h = cc.links('''
1854  #include <cpuid.h>
1855  int main(void) {
1856    unsigned a, b, c, d;
1857    unsigned max = __get_cpuid_max(0, 0);
1858
1859    if (max >= 1) {
1860        __cpuid(1, a, b, c, d);
1861    }
1862
1863    if (max >= 7) {
1864        __cpuid_count(7, 0, a, b, c, d);
1865    }
1866
1867    return 0;
1868  }''')
1869config_host_data.set('CONFIG_CPUID_H', have_cpuid_h)
1870
1871config_host_data.set('CONFIG_AVX2_OPT', get_option('avx2') \
1872  .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX2') \
1873  .require(cc.links('''
1874    #pragma GCC push_options
1875    #pragma GCC target("avx2")
1876    #include <cpuid.h>
1877    #include <immintrin.h>
1878    static int bar(void *a) {
1879      __m256i x = *(__m256i *)a;
1880      return _mm256_testz_si256(x, x);
1881    }
1882    int main(int argc, char *argv[]) { return bar(argv[0]); }
1883  '''), error_message: 'AVX2 not available').allowed())
1884
1885config_host_data.set('CONFIG_AVX512F_OPT', get_option('avx512f') \
1886  .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX512F') \
1887  .require(cc.links('''
1888    #pragma GCC push_options
1889    #pragma GCC target("avx512f")
1890    #include <cpuid.h>
1891    #include <immintrin.h>
1892    static int bar(void *a) {
1893      __m512i x = *(__m512i *)a;
1894      return _mm512_test_epi64_mask(x, x);
1895    }
1896    int main(int argc, char *argv[]) { return bar(argv[0]); }
1897  '''), error_message: 'AVX512F not available').allowed())
1898
1899if get_option('membarrier').disabled()
1900  have_membarrier = false
1901elif targetos == 'windows'
1902  have_membarrier = true
1903elif targetos == 'linux'
1904  have_membarrier = cc.compiles('''
1905    #include <linux/membarrier.h>
1906    #include <sys/syscall.h>
1907    #include <unistd.h>
1908    #include <stdlib.h>
1909    int main(void) {
1910        syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0);
1911        syscall(__NR_membarrier, MEMBARRIER_CMD_SHARED, 0);
1912        exit(0);
1913    }''')
1914endif
1915config_host_data.set('CONFIG_MEMBARRIER', get_option('membarrier') \
1916  .require(have_membarrier, error_message: 'membarrier system call not available') \
1917  .allowed())
1918
1919have_afalg = get_option('crypto_afalg') \
1920  .require(cc.compiles(gnu_source_prefix + '''
1921    #include <errno.h>
1922    #include <sys/types.h>
1923    #include <sys/socket.h>
1924    #include <linux/if_alg.h>
1925    int main(void) {
1926      int sock;
1927      sock = socket(AF_ALG, SOCK_SEQPACKET, 0);
1928      return sock;
1929    }
1930  '''), error_message: 'AF_ALG requested but could not be detected').allowed()
1931config_host_data.set('CONFIG_AF_ALG', have_afalg)
1932
1933config_host_data.set('CONFIG_AF_VSOCK', cc.compiles(gnu_source_prefix + '''
1934  #include <errno.h>
1935  #include <sys/types.h>
1936  #include <sys/socket.h>
1937  #if !defined(AF_VSOCK)
1938  # error missing AF_VSOCK flag
1939  #endif
1940  #include <linux/vm_sockets.h>
1941  int main(void) {
1942    int sock, ret;
1943    struct sockaddr_vm svm;
1944    socklen_t len = sizeof(svm);
1945    sock = socket(AF_VSOCK, SOCK_STREAM, 0);
1946    ret = getpeername(sock, (struct sockaddr *)&svm, &len);
1947    if ((ret == -1) && (errno == ENOTCONN)) {
1948        return 0;
1949    }
1950    return -1;
1951  }'''))
1952
1953have_vss = false
1954if targetos == 'windows' and link_language == 'cpp'
1955  have_vss = cxx.compiles('''
1956    #define __MIDL_user_allocate_free_DEFINED__
1957    #include <inc/win2003/vss.h>
1958    int main(void) { return VSS_CTX_BACKUP; }''')
1959endif
1960
1961have_ntddscsi = false
1962if targetos == 'windows'
1963  have_ntddscsi = cc.compiles('''
1964    #include <windows.h>
1965    #include <ntddscsi.h>
1966    int main(void) {
1967    #if !defined(IOCTL_SCSI_GET_ADDRESS)
1968    #error Missing required ioctl definitions
1969    #endif
1970      SCSI_ADDRESS addr = { .Lun = 0, .TargetId = 0, .PathId = 0 };
1971      return addr.Lun;
1972    }
1973''')
1974endif
1975config_host_data.set('HAVE_NTDDSCSI', have_ntddscsi)
1976
1977ignored = ['CONFIG_QEMU_INTERP_PREFIX', # actually per-target
1978    'HAVE_GDB_BIN']
1979arrays = ['CONFIG_BDRV_RW_WHITELIST', 'CONFIG_BDRV_RO_WHITELIST']
1980foreach k, v: config_host
1981  if ignored.contains(k)
1982    # do nothing
1983  elif arrays.contains(k)
1984    if v != ''
1985      v = '"' + '", "'.join(v.split()) + '", '
1986    endif
1987    config_host_data.set(k, v)
1988  elif k.startswith('CONFIG_')
1989    config_host_data.set(k, v == 'y' ? 1 : v)
1990  endif
1991endforeach
1992
1993########################
1994# Target configuration #
1995########################
1996
1997minikconf = find_program('scripts/minikconf.py')
1998config_all = {}
1999config_all_devices = {}
2000config_all_disas = {}
2001config_devices_mak_list = []
2002config_devices_h = {}
2003config_target_h = {}
2004config_target_mak = {}
2005
2006disassemblers = {
2007  'alpha' : ['CONFIG_ALPHA_DIS'],
2008  'arm' : ['CONFIG_ARM_DIS'],
2009  'avr' : ['CONFIG_AVR_DIS'],
2010  'cris' : ['CONFIG_CRIS_DIS'],
2011  'hexagon' : ['CONFIG_HEXAGON_DIS'],
2012  'hppa' : ['CONFIG_HPPA_DIS'],
2013  'i386' : ['CONFIG_I386_DIS'],
2014  'x86_64' : ['CONFIG_I386_DIS'],
2015  'm68k' : ['CONFIG_M68K_DIS'],
2016  'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
2017  'mips' : ['CONFIG_MIPS_DIS'],
2018  'nios2' : ['CONFIG_NIOS2_DIS'],
2019  'or1k' : ['CONFIG_OPENRISC_DIS'],
2020  'ppc' : ['CONFIG_PPC_DIS'],
2021  'riscv' : ['CONFIG_RISCV_DIS'],
2022  'rx' : ['CONFIG_RX_DIS'],
2023  's390' : ['CONFIG_S390_DIS'],
2024  'sh4' : ['CONFIG_SH4_DIS'],
2025  'sparc' : ['CONFIG_SPARC_DIS'],
2026  'xtensa' : ['CONFIG_XTENSA_DIS'],
2027}
2028if link_language == 'cpp'
2029  disassemblers += {
2030    'aarch64' : [ 'CONFIG_ARM_A64_DIS'],
2031    'arm' : [ 'CONFIG_ARM_DIS', 'CONFIG_ARM_A64_DIS'],
2032    'mips' : [ 'CONFIG_MIPS_DIS', 'CONFIG_NANOMIPS_DIS'],
2033  }
2034endif
2035
2036have_ivshmem = config_host_data.get('CONFIG_EVENTFD')
2037host_kconfig = \
2038  (get_option('fuzzing') ? ['CONFIG_FUZZ=y'] : []) + \
2039  (have_tpm ? ['CONFIG_TPM=y'] : []) + \
2040  (spice.found() ? ['CONFIG_SPICE=y'] : []) + \
2041  (have_ivshmem ? ['CONFIG_IVSHMEM=y'] : []) + \
2042  ('CONFIG_OPENGL' in config_host ? ['CONFIG_OPENGL=y'] : []) + \
2043  (x11.found() ? ['CONFIG_X11=y'] : []) + \
2044  ('CONFIG_VHOST_USER' in config_host ? ['CONFIG_VHOST_USER=y'] : []) + \
2045  ('CONFIG_VHOST_VDPA' in config_host ? ['CONFIG_VHOST_VDPA=y'] : []) + \
2046  ('CONFIG_VHOST_KERNEL' in config_host ? ['CONFIG_VHOST_KERNEL=y'] : []) + \
2047  (have_virtfs ? ['CONFIG_VIRTFS=y'] : []) + \
2048  ('CONFIG_LINUX' in config_host ? ['CONFIG_LINUX=y'] : []) + \
2049  ('CONFIG_PVRDMA' in config_host ? ['CONFIG_PVRDMA=y'] : []) + \
2050  (multiprocess_allowed ? ['CONFIG_MULTIPROCESS_ALLOWED=y'] : [])
2051
2052ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ]
2053
2054default_targets = 'CONFIG_DEFAULT_TARGETS' in config_host
2055actual_target_dirs = []
2056fdt_required = []
2057foreach target : target_dirs
2058  config_target = { 'TARGET_NAME': target.split('-')[0] }
2059  if target.endswith('linux-user')
2060    if targetos != 'linux'
2061      if default_targets
2062        continue
2063      endif
2064      error('Target @0@ is only available on a Linux host'.format(target))
2065    endif
2066    config_target += { 'CONFIG_LINUX_USER': 'y' }
2067  elif target.endswith('bsd-user')
2068    if 'CONFIG_BSD' not in config_host
2069      if default_targets
2070        continue
2071      endif
2072      error('Target @0@ is only available on a BSD host'.format(target))
2073    endif
2074    config_target += { 'CONFIG_BSD_USER': 'y' }
2075  elif target.endswith('softmmu')
2076    config_target += { 'CONFIG_SOFTMMU': 'y' }
2077  endif
2078  if target.endswith('-user')
2079    config_target += {
2080      'CONFIG_USER_ONLY': 'y',
2081      'CONFIG_QEMU_INTERP_PREFIX':
2082        config_host['CONFIG_QEMU_INTERP_PREFIX'].format(config_target['TARGET_NAME'])
2083    }
2084  endif
2085
2086  accel_kconfig = []
2087  foreach sym: accelerators
2088    if sym == 'CONFIG_TCG' or target in accelerator_targets.get(sym, [])
2089      config_target += { sym: 'y' }
2090      config_all += { sym: 'y' }
2091      if sym == 'CONFIG_TCG' and tcg_arch == 'tci'
2092        config_target += { 'CONFIG_TCG_INTERPRETER': 'y' }
2093      elif sym == 'CONFIG_XEN' and have_xen_pci_passthrough
2094        config_target += { 'CONFIG_XEN_PCI_PASSTHROUGH': 'y' }
2095      endif
2096      if target in modular_tcg
2097        config_target += { 'CONFIG_TCG_MODULAR': 'y' }
2098      else
2099        config_target += { 'CONFIG_TCG_BUILTIN': 'y' }
2100      endif
2101      accel_kconfig += [ sym + '=y' ]
2102    endif
2103  endforeach
2104  if accel_kconfig.length() == 0
2105    if default_targets
2106      continue
2107    endif
2108    error('No accelerator available for target @0@'.format(target))
2109  endif
2110
2111  actual_target_dirs += target
2112  config_target += keyval.load('configs/targets' / target + '.mak')
2113  config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
2114
2115  if 'TARGET_NEED_FDT' in config_target
2116    fdt_required += target
2117  endif
2118
2119  # Add default keys
2120  if 'TARGET_BASE_ARCH' not in config_target
2121    config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
2122  endif
2123  if 'TARGET_ABI_DIR' not in config_target
2124    config_target += {'TARGET_ABI_DIR': config_target['TARGET_ARCH']}
2125  endif
2126
2127  foreach k, v: disassemblers
2128    if host_arch.startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k)
2129      foreach sym: v
2130        config_target += { sym: 'y' }
2131        config_all_disas += { sym: 'y' }
2132      endforeach
2133    endif
2134  endforeach
2135
2136  config_target_data = configuration_data()
2137  foreach k, v: config_target
2138    if not k.startswith('TARGET_') and not k.startswith('CONFIG_')
2139      # do nothing
2140    elif ignored.contains(k)
2141      # do nothing
2142    elif k == 'TARGET_BASE_ARCH'
2143      # Note that TARGET_BASE_ARCH ends up in config-target.h but it is
2144      # not used to select files from sourcesets.
2145      config_target_data.set('TARGET_' + v.to_upper(), 1)
2146    elif k == 'TARGET_NAME' or k == 'CONFIG_QEMU_INTERP_PREFIX'
2147      config_target_data.set_quoted(k, v)
2148    elif v == 'y'
2149      config_target_data.set(k, 1)
2150    else
2151      config_target_data.set(k, v)
2152    endif
2153  endforeach
2154  config_target_data.set('QEMU_ARCH',
2155                         'QEMU_ARCH_' + config_target['TARGET_BASE_ARCH'].to_upper())
2156  config_target_h += {target: configure_file(output: target + '-config-target.h',
2157                                               configuration: config_target_data)}
2158
2159  if target.endswith('-softmmu')
2160    config_input = meson.get_external_property(target, 'default')
2161    config_devices_mak = target + '-config-devices.mak'
2162    config_devices_mak = configure_file(
2163      input: ['configs/devices' / target / config_input + '.mak', 'Kconfig'],
2164      output: config_devices_mak,
2165      depfile: config_devices_mak + '.d',
2166      capture: true,
2167      command: [minikconf,
2168                get_option('default_devices') ? '--defconfig' : '--allnoconfig',
2169                config_devices_mak, '@DEPFILE@', '@INPUT@',
2170                host_kconfig, accel_kconfig,
2171                'CONFIG_' + config_target['TARGET_ARCH'].to_upper() + '=y'])
2172
2173    config_devices_data = configuration_data()
2174    config_devices = keyval.load(config_devices_mak)
2175    foreach k, v: config_devices
2176      config_devices_data.set(k, 1)
2177    endforeach
2178    config_devices_mak_list += config_devices_mak
2179    config_devices_h += {target: configure_file(output: target + '-config-devices.h',
2180                                                configuration: config_devices_data)}
2181    config_target += config_devices
2182    config_all_devices += config_devices
2183  endif
2184  config_target_mak += {target: config_target}
2185endforeach
2186target_dirs = actual_target_dirs
2187
2188# This configuration is used to build files that are shared by
2189# multiple binaries, and then extracted out of the "common"
2190# static_library target.
2191#
2192# We do not use all_sources()/all_dependencies(), because it would
2193# build literally all source files, including devices only used by
2194# targets that are not built for this compilation.  The CONFIG_ALL
2195# pseudo symbol replaces it.
2196
2197config_all += config_all_devices
2198config_all += config_host
2199config_all += config_all_disas
2200config_all += {
2201  'CONFIG_XEN': config_host.has_key('CONFIG_XEN_BACKEND'),
2202  'CONFIG_SOFTMMU': have_system,
2203  'CONFIG_USER_ONLY': have_user,
2204  'CONFIG_ALL': true,
2205}
2206
2207target_configs_h = []
2208foreach target: target_dirs
2209  target_configs_h += config_target_h[target]
2210  target_configs_h += config_devices_h.get(target, [])
2211endforeach
2212genh += custom_target('config-poison.h',
2213                      input: [target_configs_h],
2214                      output: 'config-poison.h',
2215                      capture: true,
2216                      command: [find_program('scripts/make-config-poison.sh'),
2217                                target_configs_h])
2218
2219##############
2220# Submodules #
2221##############
2222
2223capstone = not_found
2224capstone_opt = get_option('capstone')
2225if capstone_opt in ['enabled', 'auto', 'system']
2226  have_internal = fs.exists(meson.current_source_dir() / 'capstone/Makefile')
2227  capstone = dependency('capstone', version: '>=4.0',
2228                        kwargs: static_kwargs, method: 'pkg-config',
2229                        required: capstone_opt == 'system' or
2230                                  capstone_opt == 'enabled' and not have_internal)
2231
2232  # Some versions of capstone have broken pkg-config file
2233  # that reports a wrong -I path, causing the #include to
2234  # fail later. If the system has such a broken version
2235  # do not use it.
2236  if capstone.found() and not cc.compiles('#include <capstone.h>',
2237                                          dependencies: [capstone])
2238    capstone = not_found
2239    if capstone_opt == 'system'
2240      error('system capstone requested, it does not appear to work')
2241    endif
2242  endif
2243
2244  if capstone.found()
2245    capstone_opt = 'system'
2246  elif have_internal
2247    capstone_opt = 'internal'
2248  else
2249    capstone_opt = 'disabled'
2250  endif
2251endif
2252if capstone_opt == 'internal'
2253  capstone_data = configuration_data()
2254  capstone_data.set('CAPSTONE_USE_SYS_DYN_MEM', '1')
2255
2256  capstone_files = files(
2257    'capstone/cs.c',
2258    'capstone/MCInst.c',
2259    'capstone/MCInstrDesc.c',
2260    'capstone/MCRegisterInfo.c',
2261    'capstone/SStream.c',
2262    'capstone/utils.c'
2263  )
2264
2265  if 'CONFIG_ARM_DIS' in config_all_disas
2266    capstone_data.set('CAPSTONE_HAS_ARM', '1')
2267    capstone_files += files(
2268      'capstone/arch/ARM/ARMDisassembler.c',
2269      'capstone/arch/ARM/ARMInstPrinter.c',
2270      'capstone/arch/ARM/ARMMapping.c',
2271      'capstone/arch/ARM/ARMModule.c'
2272    )
2273  endif
2274
2275  # FIXME: This config entry currently depends on a c++ compiler.
2276  # Which is needed for building libvixl, but not for capstone.
2277  if 'CONFIG_ARM_A64_DIS' in config_all_disas
2278    capstone_data.set('CAPSTONE_HAS_ARM64', '1')
2279    capstone_files += files(
2280      'capstone/arch/AArch64/AArch64BaseInfo.c',
2281      'capstone/arch/AArch64/AArch64Disassembler.c',
2282      'capstone/arch/AArch64/AArch64InstPrinter.c',
2283      'capstone/arch/AArch64/AArch64Mapping.c',
2284      'capstone/arch/AArch64/AArch64Module.c'
2285    )
2286  endif
2287
2288  if 'CONFIG_PPC_DIS' in config_all_disas
2289    capstone_data.set('CAPSTONE_HAS_POWERPC', '1')
2290    capstone_files += files(
2291      'capstone/arch/PowerPC/PPCDisassembler.c',
2292      'capstone/arch/PowerPC/PPCInstPrinter.c',
2293      'capstone/arch/PowerPC/PPCMapping.c',
2294      'capstone/arch/PowerPC/PPCModule.c'
2295    )
2296  endif
2297
2298  if 'CONFIG_S390_DIS' in config_all_disas
2299    capstone_data.set('CAPSTONE_HAS_SYSZ', '1')
2300    capstone_files += files(
2301      'capstone/arch/SystemZ/SystemZDisassembler.c',
2302      'capstone/arch/SystemZ/SystemZInstPrinter.c',
2303      'capstone/arch/SystemZ/SystemZMapping.c',
2304      'capstone/arch/SystemZ/SystemZModule.c',
2305      'capstone/arch/SystemZ/SystemZMCTargetDesc.c'
2306    )
2307  endif
2308
2309  if 'CONFIG_I386_DIS' in config_all_disas
2310    capstone_data.set('CAPSTONE_HAS_X86', 1)
2311    capstone_files += files(
2312      'capstone/arch/X86/X86Disassembler.c',
2313      'capstone/arch/X86/X86DisassemblerDecoder.c',
2314      'capstone/arch/X86/X86ATTInstPrinter.c',
2315      'capstone/arch/X86/X86IntelInstPrinter.c',
2316      'capstone/arch/X86/X86InstPrinterCommon.c',
2317      'capstone/arch/X86/X86Mapping.c',
2318      'capstone/arch/X86/X86Module.c'
2319    )
2320  endif
2321
2322  configure_file(output: 'capstone-defs.h', configuration: capstone_data)
2323
2324  capstone_cargs = [
2325    # FIXME: There does not seem to be a way to completely replace the c_args
2326    # that come from add_project_arguments() -- we can only add to them.
2327    # So: disable all warnings with a big hammer.
2328    '-Wno-error', '-w',
2329
2330    # Include all configuration defines via a header file, which will wind up
2331    # as a dependency on the object file, and thus changes here will result
2332    # in a rebuild.
2333    '-include', 'capstone-defs.h'
2334  ]
2335
2336  libcapstone = static_library('capstone',
2337                               build_by_default: false,
2338                               sources: capstone_files,
2339                               c_args: capstone_cargs,
2340                               include_directories: 'capstone/include')
2341  capstone = declare_dependency(link_with: libcapstone,
2342                                include_directories: 'capstone/include/capstone')
2343endif
2344
2345slirp = not_found
2346slirp_opt = 'disabled'
2347if have_system
2348  slirp_opt = get_option('slirp')
2349  if slirp_opt in ['enabled', 'auto', 'system']
2350    have_internal = fs.exists(meson.current_source_dir() / 'slirp/meson.build')
2351    slirp = dependency('slirp', kwargs: static_kwargs,
2352                       method: 'pkg-config',
2353                       required: slirp_opt == 'system' or
2354                                 slirp_opt == 'enabled' and not have_internal)
2355    if slirp.found()
2356      slirp_opt = 'system'
2357    elif have_internal
2358      slirp_opt = 'internal'
2359    else
2360      slirp_opt = 'disabled'
2361    endif
2362  endif
2363  if slirp_opt == 'internal'
2364    slirp_deps = []
2365    if targetos == 'windows'
2366      slirp_deps = cc.find_library('iphlpapi')
2367    elif targetos == 'darwin'
2368      slirp_deps = cc.find_library('resolv')
2369    endif
2370    slirp_conf = configuration_data()
2371    slirp_conf.set('SLIRP_MAJOR_VERSION', meson.project_version().split('.')[0])
2372    slirp_conf.set('SLIRP_MINOR_VERSION', meson.project_version().split('.')[1])
2373    slirp_conf.set('SLIRP_MICRO_VERSION', meson.project_version().split('.')[2])
2374    slirp_conf.set_quoted('SLIRP_VERSION_STRING', meson.project_version())
2375    slirp_cargs = ['-DG_LOG_DOMAIN="Slirp"']
2376    slirp_files = [
2377      'slirp/src/arp_table.c',
2378      'slirp/src/bootp.c',
2379      'slirp/src/cksum.c',
2380      'slirp/src/dhcpv6.c',
2381      'slirp/src/dnssearch.c',
2382      'slirp/src/if.c',
2383      'slirp/src/ip6_icmp.c',
2384      'slirp/src/ip6_input.c',
2385      'slirp/src/ip6_output.c',
2386      'slirp/src/ip_icmp.c',
2387      'slirp/src/ip_input.c',
2388      'slirp/src/ip_output.c',
2389      'slirp/src/mbuf.c',
2390      'slirp/src/misc.c',
2391      'slirp/src/ncsi.c',
2392      'slirp/src/ndp_table.c',
2393      'slirp/src/sbuf.c',
2394      'slirp/src/slirp.c',
2395      'slirp/src/socket.c',
2396      'slirp/src/state.c',
2397      'slirp/src/stream.c',
2398      'slirp/src/tcp_input.c',
2399      'slirp/src/tcp_output.c',
2400      'slirp/src/tcp_subr.c',
2401      'slirp/src/tcp_timer.c',
2402      'slirp/src/tftp.c',
2403      'slirp/src/udp.c',
2404      'slirp/src/udp6.c',
2405      'slirp/src/util.c',
2406      'slirp/src/version.c',
2407      'slirp/src/vmstate.c',
2408    ]
2409
2410    configure_file(
2411      input : 'slirp/src/libslirp-version.h.in',
2412      output : 'libslirp-version.h',
2413      configuration: slirp_conf)
2414
2415    slirp_inc = include_directories('slirp', 'slirp/src')
2416    libslirp = static_library('slirp',
2417                              build_by_default: false,
2418                              sources: slirp_files,
2419                              c_args: slirp_cargs,
2420                              include_directories: slirp_inc)
2421    slirp = declare_dependency(link_with: libslirp,
2422                               dependencies: slirp_deps,
2423                               include_directories: slirp_inc)
2424  endif
2425endif
2426
2427# For CFI, we need to compile slirp as a static library together with qemu.
2428# This is because we register slirp functions as callbacks for QEMU Timers.
2429# When using a system-wide shared libslirp, the type information for the
2430# callback is missing and the timer call produces a false positive with CFI.
2431#
2432# Now that slirp_opt has been defined, check if the selected slirp is compatible
2433# with control-flow integrity.
2434if get_option('cfi') and slirp_opt == 'system'
2435  error('Control-Flow Integrity is not compatible with system-wide slirp.' \
2436         + ' Please configure with --enable-slirp=git')
2437endif
2438
2439fdt = not_found
2440fdt_opt = get_option('fdt')
2441if have_system
2442  if fdt_opt in ['enabled', 'auto', 'system']
2443    have_internal = fs.exists(meson.current_source_dir() / 'dtc/libfdt/Makefile.libfdt')
2444    fdt = cc.find_library('fdt', kwargs: static_kwargs,
2445                          required: fdt_opt == 'system' or
2446                                    fdt_opt == 'enabled' and not have_internal)
2447    if fdt.found() and cc.links('''
2448       #include <libfdt.h>
2449       #include <libfdt_env.h>
2450       int main(void) { fdt_find_max_phandle(NULL, NULL); return 0; }''',
2451         dependencies: fdt)
2452      fdt_opt = 'system'
2453    elif fdt_opt == 'system'
2454       error('system libfdt requested, but it is too old (1.5.1 or newer required)')
2455    elif have_internal
2456      fdt_opt = 'internal'
2457    else
2458      fdt_opt = 'disabled'
2459      fdt = not_found
2460    endif
2461  endif
2462  if fdt_opt == 'internal'
2463    fdt_files = files(
2464      'dtc/libfdt/fdt.c',
2465      'dtc/libfdt/fdt_ro.c',
2466      'dtc/libfdt/fdt_wip.c',
2467      'dtc/libfdt/fdt_sw.c',
2468      'dtc/libfdt/fdt_rw.c',
2469      'dtc/libfdt/fdt_strerror.c',
2470      'dtc/libfdt/fdt_empty_tree.c',
2471      'dtc/libfdt/fdt_addresses.c',
2472      'dtc/libfdt/fdt_overlay.c',
2473      'dtc/libfdt/fdt_check.c',
2474    )
2475
2476    fdt_inc = include_directories('dtc/libfdt')
2477    libfdt = static_library('fdt',
2478                            build_by_default: false,
2479                            sources: fdt_files,
2480                            include_directories: fdt_inc)
2481    fdt = declare_dependency(link_with: libfdt,
2482                             include_directories: fdt_inc)
2483  endif
2484endif
2485if not fdt.found() and fdt_required.length() > 0
2486  error('fdt not available but required by targets ' + ', '.join(fdt_required))
2487endif
2488
2489config_host_data.set('CONFIG_CAPSTONE', capstone.found())
2490config_host_data.set('CONFIG_FDT', fdt.found())
2491config_host_data.set('CONFIG_SLIRP', slirp.found())
2492
2493#####################
2494# Generated sources #
2495#####################
2496
2497genh += configure_file(output: 'config-host.h', configuration: config_host_data)
2498
2499hxtool = find_program('scripts/hxtool')
2500shaderinclude = find_program('scripts/shaderinclude.pl')
2501qapi_gen = find_program('scripts/qapi-gen.py')
2502qapi_gen_depends = [ meson.current_source_dir() / 'scripts/qapi/__init__.py',
2503                     meson.current_source_dir() / 'scripts/qapi/commands.py',
2504                     meson.current_source_dir() / 'scripts/qapi/common.py',
2505                     meson.current_source_dir() / 'scripts/qapi/error.py',
2506                     meson.current_source_dir() / 'scripts/qapi/events.py',
2507                     meson.current_source_dir() / 'scripts/qapi/expr.py',
2508                     meson.current_source_dir() / 'scripts/qapi/gen.py',
2509                     meson.current_source_dir() / 'scripts/qapi/introspect.py',
2510                     meson.current_source_dir() / 'scripts/qapi/parser.py',
2511                     meson.current_source_dir() / 'scripts/qapi/schema.py',
2512                     meson.current_source_dir() / 'scripts/qapi/source.py',
2513                     meson.current_source_dir() / 'scripts/qapi/types.py',
2514                     meson.current_source_dir() / 'scripts/qapi/visit.py',
2515                     meson.current_source_dir() / 'scripts/qapi/common.py',
2516                     meson.current_source_dir() / 'scripts/qapi-gen.py'
2517]
2518
2519tracetool = [
2520  python, files('scripts/tracetool.py'),
2521   '--backend=' + ','.join(get_option('trace_backends'))
2522]
2523tracetool_depends = files(
2524  'scripts/tracetool/backend/log.py',
2525  'scripts/tracetool/backend/__init__.py',
2526  'scripts/tracetool/backend/dtrace.py',
2527  'scripts/tracetool/backend/ftrace.py',
2528  'scripts/tracetool/backend/simple.py',
2529  'scripts/tracetool/backend/syslog.py',
2530  'scripts/tracetool/backend/ust.py',
2531  'scripts/tracetool/format/ust_events_c.py',
2532  'scripts/tracetool/format/ust_events_h.py',
2533  'scripts/tracetool/format/__init__.py',
2534  'scripts/tracetool/format/d.py',
2535  'scripts/tracetool/format/simpletrace_stap.py',
2536  'scripts/tracetool/format/c.py',
2537  'scripts/tracetool/format/h.py',
2538  'scripts/tracetool/format/log_stap.py',
2539  'scripts/tracetool/format/stap.py',
2540  'scripts/tracetool/__init__.py',
2541  'scripts/tracetool/transform.py',
2542  'scripts/tracetool/vcpu.py'
2543)
2544
2545qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
2546                    meson.current_source_dir(),
2547                    config_host['PKGVERSION'], meson.project_version()]
2548qemu_version = custom_target('qemu-version.h',
2549                             output: 'qemu-version.h',
2550                             command: qemu_version_cmd,
2551                             capture: true,
2552                             build_by_default: true,
2553                             build_always_stale: true)
2554genh += qemu_version
2555
2556hxdep = []
2557hx_headers = [
2558  ['qemu-options.hx', 'qemu-options.def'],
2559  ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
2560]
2561if have_system
2562  hx_headers += [
2563    ['hmp-commands.hx', 'hmp-commands.h'],
2564    ['hmp-commands-info.hx', 'hmp-commands-info.h'],
2565  ]
2566endif
2567foreach d : hx_headers
2568  hxdep += custom_target(d[1],
2569                input: files(d[0]),
2570                output: d[1],
2571                capture: true,
2572                build_by_default: true, # to be removed when added to a target
2573                command: [hxtool, '-h', '@INPUT0@'])
2574endforeach
2575genh += hxdep
2576
2577###################
2578# Collect sources #
2579###################
2580
2581authz_ss = ss.source_set()
2582blockdev_ss = ss.source_set()
2583block_ss = ss.source_set()
2584chardev_ss = ss.source_set()
2585common_ss = ss.source_set()
2586crypto_ss = ss.source_set()
2587hwcore_ss = ss.source_set()
2588io_ss = ss.source_set()
2589qmp_ss = ss.source_set()
2590qom_ss = ss.source_set()
2591softmmu_ss = ss.source_set()
2592specific_fuzz_ss = ss.source_set()
2593specific_ss = ss.source_set()
2594stub_ss = ss.source_set()
2595trace_ss = ss.source_set()
2596user_ss = ss.source_set()
2597util_ss = ss.source_set()
2598
2599# accel modules
2600qtest_module_ss = ss.source_set()
2601tcg_module_ss = ss.source_set()
2602
2603modules = {}
2604target_modules = {}
2605hw_arch = {}
2606target_arch = {}
2607target_softmmu_arch = {}
2608target_user_arch = {}
2609
2610###############
2611# Trace files #
2612###############
2613
2614# TODO: add each directory to the subdirs from its own meson.build, once
2615# we have those
2616trace_events_subdirs = [
2617  'crypto',
2618  'qapi',
2619  'qom',
2620  'monitor',
2621  'util',
2622]
2623if have_linux_user
2624  trace_events_subdirs += [ 'linux-user' ]
2625endif
2626if have_bsd_user
2627  trace_events_subdirs += [ 'bsd-user' ]
2628endif
2629if have_block
2630  trace_events_subdirs += [
2631    'authz',
2632    'block',
2633    'io',
2634    'nbd',
2635    'scsi',
2636  ]
2637endif
2638if have_system
2639  trace_events_subdirs += [
2640    'accel/kvm',
2641    'audio',
2642    'backends',
2643    'backends/tpm',
2644    'chardev',
2645    'ebpf',
2646    'hw/9pfs',
2647    'hw/acpi',
2648    'hw/adc',
2649    'hw/alpha',
2650    'hw/arm',
2651    'hw/audio',
2652    'hw/block',
2653    'hw/block/dataplane',
2654    'hw/char',
2655    'hw/display',
2656    'hw/dma',
2657    'hw/hppa',
2658    'hw/hyperv',
2659    'hw/i2c',
2660    'hw/i386',
2661    'hw/i386/xen',
2662    'hw/ide',
2663    'hw/input',
2664    'hw/intc',
2665    'hw/isa',
2666    'hw/mem',
2667    'hw/mips',
2668    'hw/misc',
2669    'hw/misc/macio',
2670    'hw/net',
2671    'hw/net/can',
2672    'hw/nubus',
2673    'hw/nvme',
2674    'hw/nvram',
2675    'hw/pci',
2676    'hw/pci-host',
2677    'hw/ppc',
2678    'hw/rdma',
2679    'hw/rdma/vmw',
2680    'hw/rtc',
2681    'hw/s390x',
2682    'hw/scsi',
2683    'hw/sd',
2684    'hw/sh4',
2685    'hw/sparc',
2686    'hw/sparc64',
2687    'hw/ssi',
2688    'hw/timer',
2689    'hw/tpm',
2690    'hw/usb',
2691    'hw/vfio',
2692    'hw/virtio',
2693    'hw/watchdog',
2694    'hw/xen',
2695    'hw/gpio',
2696    'migration',
2697    'net',
2698    'softmmu',
2699    'ui',
2700    'hw/remote',
2701  ]
2702endif
2703if have_system or have_user
2704  trace_events_subdirs += [
2705    'accel/tcg',
2706    'hw/core',
2707    'target/arm',
2708    'target/arm/hvf',
2709    'target/hppa',
2710    'target/i386',
2711    'target/i386/kvm',
2712    'target/mips/tcg',
2713    'target/nios2',
2714    'target/ppc',
2715    'target/riscv',
2716    'target/s390x',
2717    'target/s390x/kvm',
2718    'target/sparc',
2719  ]
2720endif
2721
2722vhost_user = not_found
2723if 'CONFIG_VHOST_USER' in config_host
2724  libvhost_user = subproject('libvhost-user')
2725  vhost_user = libvhost_user.get_variable('vhost_user_dep')
2726endif
2727
2728# NOTE: the trace/ subdirectory needs the qapi_trace_events variable
2729# that is filled in by qapi/.
2730subdir('qapi')
2731subdir('qobject')
2732subdir('stubs')
2733subdir('trace')
2734subdir('util')
2735subdir('qom')
2736subdir('authz')
2737subdir('crypto')
2738subdir('ui')
2739
2740
2741if enable_modules
2742  libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
2743  modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
2744endif
2745
2746stub_ss = stub_ss.apply(config_all, strict: false)
2747
2748util_ss.add_all(trace_ss)
2749util_ss = util_ss.apply(config_all, strict: false)
2750libqemuutil = static_library('qemuutil',
2751                             sources: util_ss.sources() + stub_ss.sources() + genh,
2752                             dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc, pixman])
2753qemuutil = declare_dependency(link_with: libqemuutil,
2754                              sources: genh + version_res)
2755
2756if have_system or have_user
2757  decodetree = generator(find_program('scripts/decodetree.py'),
2758                         output: 'decode-@BASENAME@.c.inc',
2759                         arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
2760  subdir('libdecnumber')
2761  subdir('target')
2762endif
2763
2764subdir('audio')
2765subdir('io')
2766subdir('chardev')
2767subdir('fsdev')
2768subdir('dump')
2769
2770if have_block
2771  block_ss.add(files(
2772    'block.c',
2773    'blockjob.c',
2774    'job.c',
2775    'qemu-io-cmds.c',
2776  ))
2777  if config_host_data.get('CONFIG_REPLICATION')
2778    block_ss.add(files('replication.c'))
2779  endif
2780
2781  subdir('nbd')
2782  subdir('scsi')
2783  subdir('block')
2784
2785  blockdev_ss.add(files(
2786    'blockdev.c',
2787    'blockdev-nbd.c',
2788    'iothread.c',
2789    'job-qmp.c',
2790  ), gnutls)
2791
2792  # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
2793  # os-win32.c does not
2794  blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
2795  softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
2796endif
2797
2798common_ss.add(files('cpus-common.c'))
2799
2800subdir('softmmu')
2801
2802common_ss.add(capstone)
2803specific_ss.add(files('cpu.c', 'disas.c', 'gdbstub.c'), capstone)
2804
2805# Work around a gcc bug/misfeature wherein constant propagation looks
2806# through an alias:
2807#   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99696
2808# to guess that a const variable is always zero.  Without lto, this is
2809# impossible, as the alias is restricted to page-vary-common.c.  Indeed,
2810# without lto, not even the alias is required -- we simply use different
2811# declarations in different compilation units.
2812pagevary = files('page-vary-common.c')
2813if get_option('b_lto')
2814  pagevary_flags = ['-fno-lto']
2815  if get_option('cfi')
2816    pagevary_flags += '-fno-sanitize=cfi-icall'
2817  endif
2818  pagevary = static_library('page-vary-common', sources: pagevary,
2819                            c_args: pagevary_flags)
2820  pagevary = declare_dependency(link_with: pagevary)
2821endif
2822common_ss.add(pagevary)
2823specific_ss.add(files('page-vary.c'))
2824
2825subdir('backends')
2826subdir('disas')
2827subdir('migration')
2828subdir('monitor')
2829subdir('net')
2830subdir('replay')
2831subdir('semihosting')
2832subdir('hw')
2833subdir('tcg')
2834subdir('fpu')
2835subdir('accel')
2836subdir('plugins')
2837subdir('ebpf')
2838
2839common_user_inc = []
2840
2841subdir('common-user')
2842subdir('bsd-user')
2843subdir('linux-user')
2844
2845# needed for fuzzing binaries
2846subdir('tests/qtest/libqos')
2847subdir('tests/qtest/fuzz')
2848
2849# accel modules
2850tcg_real_module_ss = ss.source_set()
2851tcg_real_module_ss.add_all(when: 'CONFIG_TCG_MODULAR', if_true: tcg_module_ss)
2852specific_ss.add_all(when: 'CONFIG_TCG_BUILTIN', if_true: tcg_module_ss)
2853target_modules += { 'accel' : { 'qtest': qtest_module_ss,
2854                                'tcg': tcg_real_module_ss }}
2855
2856########################
2857# Library dependencies #
2858########################
2859
2860modinfo_collect = find_program('scripts/modinfo-collect.py')
2861modinfo_generate = find_program('scripts/modinfo-generate.py')
2862modinfo_files = []
2863
2864block_mods = []
2865softmmu_mods = []
2866foreach d, list : modules
2867  foreach m, module_ss : list
2868    if enable_modules and targetos != 'windows'
2869      module_ss = module_ss.apply(config_all, strict: false)
2870      sl = static_library(d + '-' + m, [genh, module_ss.sources()],
2871                          dependencies: [modulecommon, module_ss.dependencies()], pic: true)
2872      if d == 'block'
2873        block_mods += sl
2874      else
2875        softmmu_mods += sl
2876      endif
2877      if module_ss.sources() != []
2878        # FIXME: Should use sl.extract_all_objects(recursive: true) as
2879        # input. Sources can be used multiple times but objects are
2880        # unique when it comes to lookup in compile_commands.json.
2881        # Depnds on a mesion version with
2882        # https://github.com/mesonbuild/meson/pull/8900
2883        modinfo_files += custom_target(d + '-' + m + '.modinfo',
2884                                       output: d + '-' + m + '.modinfo',
2885                                       input: module_ss.sources() + genh,
2886                                       capture: true,
2887                                       command: [modinfo_collect, module_ss.sources()])
2888      endif
2889    else
2890      if d == 'block'
2891        block_ss.add_all(module_ss)
2892      else
2893        softmmu_ss.add_all(module_ss)
2894      endif
2895    endif
2896  endforeach
2897endforeach
2898
2899foreach d, list : target_modules
2900  foreach m, module_ss : list
2901    if enable_modules and targetos != 'windows'
2902      foreach target : target_dirs
2903        if target.endswith('-softmmu')
2904          config_target = config_target_mak[target]
2905          config_target += config_host
2906          target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
2907          c_args = ['-DNEED_CPU_H',
2908                    '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
2909                    '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
2910          target_module_ss = module_ss.apply(config_target, strict: false)
2911          if target_module_ss.sources() != []
2912            module_name = d + '-' + m + '-' + config_target['TARGET_NAME']
2913            sl = static_library(module_name,
2914                                [genh, target_module_ss.sources()],
2915                                dependencies: [modulecommon, target_module_ss.dependencies()],
2916                                include_directories: target_inc,
2917                                c_args: c_args,
2918                                pic: true)
2919            softmmu_mods += sl
2920            # FIXME: Should use sl.extract_all_objects(recursive: true) too.
2921            modinfo_files += custom_target(module_name + '.modinfo',
2922                                           output: module_name + '.modinfo',
2923                                           input: target_module_ss.sources() + genh,
2924                                           capture: true,
2925                                           command: [modinfo_collect, '--target', target, target_module_ss.sources()])
2926          endif
2927        endif
2928      endforeach
2929    else
2930      specific_ss.add_all(module_ss)
2931    endif
2932  endforeach
2933endforeach
2934
2935if enable_modules
2936  modinfo_src = custom_target('modinfo.c',
2937                              output: 'modinfo.c',
2938                              input: modinfo_files,
2939                              command: [modinfo_generate, '@INPUT@'],
2940                              capture: true)
2941  modinfo_lib = static_library('modinfo', modinfo_src)
2942  modinfo_dep = declare_dependency(link_whole: modinfo_lib)
2943  softmmu_ss.add(modinfo_dep)
2944endif
2945
2946nm = find_program('nm')
2947undefsym = find_program('scripts/undefsym.py')
2948block_syms = custom_target('block.syms', output: 'block.syms',
2949                             input: [libqemuutil, block_mods],
2950                             capture: true,
2951                             command: [undefsym, nm, '@INPUT@'])
2952qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
2953                             input: [libqemuutil, softmmu_mods],
2954                             capture: true,
2955                             command: [undefsym, nm, '@INPUT@'])
2956
2957qom_ss = qom_ss.apply(config_host, strict: false)
2958libqom = static_library('qom', qom_ss.sources() + genh,
2959                        dependencies: [qom_ss.dependencies()],
2960                        name_suffix: 'fa')
2961
2962qom = declare_dependency(link_whole: libqom)
2963
2964authz_ss = authz_ss.apply(config_host, strict: false)
2965libauthz = static_library('authz', authz_ss.sources() + genh,
2966                          dependencies: [authz_ss.dependencies()],
2967                          name_suffix: 'fa',
2968                          build_by_default: false)
2969
2970authz = declare_dependency(link_whole: libauthz,
2971                           dependencies: qom)
2972
2973crypto_ss = crypto_ss.apply(config_host, strict: false)
2974libcrypto = static_library('crypto', crypto_ss.sources() + genh,
2975                           dependencies: [crypto_ss.dependencies()],
2976                           name_suffix: 'fa',
2977                           build_by_default: false)
2978
2979crypto = declare_dependency(link_whole: libcrypto,
2980                            dependencies: [authz, qom])
2981
2982io_ss = io_ss.apply(config_host, strict: false)
2983libio = static_library('io', io_ss.sources() + genh,
2984                       dependencies: [io_ss.dependencies()],
2985                       link_with: libqemuutil,
2986                       name_suffix: 'fa',
2987                       build_by_default: false)
2988
2989io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
2990
2991libmigration = static_library('migration', sources: migration_files + genh,
2992                              name_suffix: 'fa',
2993                              build_by_default: false)
2994migration = declare_dependency(link_with: libmigration,
2995                               dependencies: [zlib, qom, io])
2996softmmu_ss.add(migration)
2997
2998block_ss = block_ss.apply(config_host, strict: false)
2999libblock = static_library('block', block_ss.sources() + genh,
3000                          dependencies: block_ss.dependencies(),
3001                          link_depends: block_syms,
3002                          name_suffix: 'fa',
3003                          build_by_default: false)
3004
3005block = declare_dependency(link_whole: [libblock],
3006                           link_args: '@block.syms',
3007                           dependencies: [crypto, io])
3008
3009blockdev_ss = blockdev_ss.apply(config_host, strict: false)
3010libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
3011                             dependencies: blockdev_ss.dependencies(),
3012                             name_suffix: 'fa',
3013                             build_by_default: false)
3014
3015blockdev = declare_dependency(link_whole: [libblockdev],
3016                              dependencies: [block])
3017
3018qmp_ss = qmp_ss.apply(config_host, strict: false)
3019libqmp = static_library('qmp', qmp_ss.sources() + genh,
3020                        dependencies: qmp_ss.dependencies(),
3021                        name_suffix: 'fa',
3022                        build_by_default: false)
3023
3024qmp = declare_dependency(link_whole: [libqmp])
3025
3026libchardev = static_library('chardev', chardev_ss.sources() + genh,
3027                            name_suffix: 'fa',
3028                            dependencies: [gnutls],
3029                            build_by_default: false)
3030
3031chardev = declare_dependency(link_whole: libchardev)
3032
3033hwcore_ss = hwcore_ss.apply(config_host, strict: false)
3034libhwcore = static_library('hwcore', sources: hwcore_ss.sources() + genh,
3035                           name_suffix: 'fa',
3036                           build_by_default: false)
3037hwcore = declare_dependency(link_whole: libhwcore)
3038common_ss.add(hwcore)
3039
3040###########
3041# Targets #
3042###########
3043
3044emulator_modules = []
3045foreach m : block_mods + softmmu_mods
3046  emulator_modules += shared_module(m.name(),
3047                build_by_default: true,
3048                name_prefix: '',
3049                link_whole: m,
3050                install: true,
3051                install_dir: qemu_moddir)
3052endforeach
3053
3054softmmu_ss.add(authz, blockdev, chardev, crypto, io, qmp)
3055common_ss.add(qom, qemuutil)
3056
3057common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
3058common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
3059
3060common_all = common_ss.apply(config_all, strict: false)
3061common_all = static_library('common',
3062                            build_by_default: false,
3063                            sources: common_all.sources() + genh,
3064                            include_directories: common_user_inc,
3065                            implicit_include_directories: false,
3066                            dependencies: common_all.dependencies(),
3067                            name_suffix: 'fa')
3068
3069feature_to_c = find_program('scripts/feature_to_c.sh')
3070
3071emulators = {}
3072foreach target : target_dirs
3073  config_target = config_target_mak[target]
3074  target_name = config_target['TARGET_NAME']
3075  target_base_arch = config_target['TARGET_BASE_ARCH']
3076  arch_srcs = [config_target_h[target]]
3077  arch_deps = []
3078  c_args = ['-DNEED_CPU_H',
3079            '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3080            '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3081  link_args = emulator_link_args
3082
3083  config_target += config_host
3084  target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3085  if targetos == 'linux'
3086    target_inc += include_directories('linux-headers', is_system: true)
3087  endif
3088  if target.endswith('-softmmu')
3089    qemu_target_name = 'qemu-system-' + target_name
3090    target_type='system'
3091    t = target_softmmu_arch[target_base_arch].apply(config_target, strict: false)
3092    arch_srcs += t.sources()
3093    arch_deps += t.dependencies()
3094
3095    hw_dir = target_name == 'sparc64' ? 'sparc64' : target_base_arch
3096    hw = hw_arch[hw_dir].apply(config_target, strict: false)
3097    arch_srcs += hw.sources()
3098    arch_deps += hw.dependencies()
3099
3100    arch_srcs += config_devices_h[target]
3101    link_args += ['@block.syms', '@qemu.syms']
3102  else
3103    abi = config_target['TARGET_ABI_DIR']
3104    target_type='user'
3105    target_inc += common_user_inc
3106    qemu_target_name = 'qemu-' + target_name
3107    if target_base_arch in target_user_arch
3108      t = target_user_arch[target_base_arch].apply(config_target, strict: false)
3109      arch_srcs += t.sources()
3110      arch_deps += t.dependencies()
3111    endif
3112    if 'CONFIG_LINUX_USER' in config_target
3113      base_dir = 'linux-user'
3114    endif
3115    if 'CONFIG_BSD_USER' in config_target
3116      base_dir = 'bsd-user'
3117      target_inc += include_directories('bsd-user/' / targetos)
3118      target_inc += include_directories('bsd-user/host/' / host_arch)
3119      dir = base_dir / abi
3120      arch_srcs += files(dir / 'signal.c', dir / 'target_arch_cpu.c')
3121    endif
3122    target_inc += include_directories(
3123      base_dir,
3124      base_dir / abi,
3125    )
3126    if 'CONFIG_LINUX_USER' in config_target
3127      dir = base_dir / abi
3128      arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
3129      if config_target.has_key('TARGET_SYSTBL_ABI')
3130        arch_srcs += \
3131          syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
3132                                             extra_args : config_target['TARGET_SYSTBL_ABI'])
3133      endif
3134    endif
3135  endif
3136
3137  if 'TARGET_XML_FILES' in config_target
3138    gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
3139                                output: target + '-gdbstub-xml.c',
3140                                input: files(config_target['TARGET_XML_FILES'].split()),
3141                                command: [feature_to_c, '@INPUT@'],
3142                                capture: true)
3143    arch_srcs += gdbstub_xml
3144  endif
3145
3146  t = target_arch[target_base_arch].apply(config_target, strict: false)
3147  arch_srcs += t.sources()
3148  arch_deps += t.dependencies()
3149
3150  target_common = common_ss.apply(config_target, strict: false)
3151  objects = common_all.extract_objects(target_common.sources())
3152  deps = target_common.dependencies()
3153
3154  target_specific = specific_ss.apply(config_target, strict: false)
3155  arch_srcs += target_specific.sources()
3156  arch_deps += target_specific.dependencies()
3157
3158  lib = static_library('qemu-' + target,
3159                 sources: arch_srcs + genh,
3160                 dependencies: arch_deps,
3161                 objects: objects,
3162                 include_directories: target_inc,
3163                 c_args: c_args,
3164                 build_by_default: false,
3165                 name_suffix: 'fa')
3166
3167  if target.endswith('-softmmu')
3168    execs = [{
3169      'name': 'qemu-system-' + target_name,
3170      'win_subsystem': 'console',
3171      'sources': files('softmmu/main.c'),
3172      'dependencies': []
3173    }]
3174    if targetos == 'windows' and (sdl.found() or gtk.found())
3175      execs += [{
3176        'name': 'qemu-system-' + target_name + 'w',
3177        'win_subsystem': 'windows',
3178        'sources': files('softmmu/main.c'),
3179        'dependencies': []
3180      }]
3181    endif
3182    if get_option('fuzzing')
3183      specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
3184      execs += [{
3185        'name': 'qemu-fuzz-' + target_name,
3186        'win_subsystem': 'console',
3187        'sources': specific_fuzz.sources(),
3188        'dependencies': specific_fuzz.dependencies(),
3189      }]
3190    endif
3191  else
3192    execs = [{
3193      'name': 'qemu-' + target_name,
3194      'win_subsystem': 'console',
3195      'sources': [],
3196      'dependencies': []
3197    }]
3198  endif
3199  foreach exe: execs
3200    exe_name = exe['name']
3201    if targetos == 'darwin'
3202      exe_name += '-unsigned'
3203    endif
3204
3205    emulator = executable(exe_name, exe['sources'],
3206               install: true,
3207               c_args: c_args,
3208               dependencies: arch_deps + deps + exe['dependencies'],
3209               objects: lib.extract_all_objects(recursive: true),
3210               link_language: link_language,
3211               link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
3212               link_args: link_args,
3213               win_subsystem: exe['win_subsystem'])
3214
3215    if targetos == 'darwin'
3216      icon = 'pc-bios/qemu.rsrc'
3217      build_input = [emulator, files(icon)]
3218      install_input = [
3219        get_option('bindir') / exe_name,
3220        meson.current_source_dir() / icon
3221      ]
3222      if 'CONFIG_HVF' in config_target
3223        entitlements = 'accel/hvf/entitlements.plist'
3224        build_input += files(entitlements)
3225        install_input += meson.current_source_dir() / entitlements
3226      endif
3227
3228      entitlement = find_program('scripts/entitlement.sh')
3229      emulators += {exe['name'] : custom_target(exe['name'],
3230                   input: build_input,
3231                   output: exe['name'],
3232                   command: [entitlement, '@OUTPUT@', '@INPUT@'])
3233      }
3234
3235      meson.add_install_script(entitlement, '--install',
3236                               get_option('bindir') / exe['name'],
3237                               install_input)
3238    else
3239      emulators += {exe['name']: emulator}
3240    endif
3241
3242    if stap.found()
3243      foreach stp: [
3244        {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
3245        {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
3246        {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
3247        {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
3248      ]
3249        custom_target(exe['name'] + stp['ext'],
3250                      input: trace_events_all,
3251                      output: exe['name'] + stp['ext'],
3252                      install: stp['install'],
3253                      install_dir: get_option('datadir') / 'systemtap/tapset',
3254                      command: [
3255                        tracetool, '--group=all', '--format=' + stp['fmt'],
3256                        '--binary=' + stp['bin'],
3257                        '--target-name=' + target_name,
3258                        '--target-type=' + target_type,
3259                        '--probe-prefix=qemu.' + target_type + '.' + target_name,
3260                        '@INPUT@', '@OUTPUT@'
3261                      ],
3262                      depend_files: tracetool_depends)
3263      endforeach
3264    endif
3265  endforeach
3266endforeach
3267
3268# Other build targets
3269
3270if 'CONFIG_PLUGIN' in config_host
3271  install_headers('include/qemu/qemu-plugin.h')
3272endif
3273
3274subdir('qga')
3275
3276# Don't build qemu-keymap if xkbcommon is not explicitly enabled
3277# when we don't build tools or system
3278if xkbcommon.found()
3279  # used for the update-keymaps target, so include rules even if !have_tools
3280  qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
3281                           dependencies: [qemuutil, xkbcommon], install: have_tools)
3282endif
3283
3284if have_tools
3285  qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
3286             dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
3287  qemu_io = executable('qemu-io', files('qemu-io.c'),
3288             dependencies: [block, qemuutil], install: true)
3289  qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
3290               dependencies: [blockdev, qemuutil, gnutls, selinux],
3291               install: true)
3292
3293  subdir('storage-daemon')
3294  subdir('contrib/rdmacm-mux')
3295  subdir('contrib/elf2dmp')
3296
3297  executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
3298             dependencies: qemuutil,
3299             install: true)
3300
3301  if 'CONFIG_VHOST_USER' in config_host
3302    subdir('contrib/vhost-user-blk')
3303    subdir('contrib/vhost-user-gpu')
3304    subdir('contrib/vhost-user-input')
3305    subdir('contrib/vhost-user-scsi')
3306  endif
3307
3308  if targetos == 'linux'
3309    executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
3310               dependencies: [qemuutil, libcap_ng],
3311               install: true,
3312               install_dir: get_option('libexecdir'))
3313
3314    executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
3315               dependencies: [authz, crypto, io, qom, qemuutil,
3316                              libcap_ng, mpathpersist],
3317               install: true)
3318  endif
3319
3320  if have_ivshmem
3321    subdir('contrib/ivshmem-client')
3322    subdir('contrib/ivshmem-server')
3323  endif
3324endif
3325
3326subdir('scripts')
3327subdir('tools')
3328subdir('pc-bios')
3329subdir('docs')
3330subdir('tests')
3331if gtk.found()
3332  subdir('po')
3333endif
3334
3335if host_machine.system() == 'windows'
3336  nsis_cmd = [
3337    find_program('scripts/nsis.py'),
3338    '@OUTPUT@',
3339    get_option('prefix'),
3340    meson.current_source_dir(),
3341    host_machine.cpu(),
3342    '--',
3343    '-DDISPLAYVERSION=' + meson.project_version(),
3344  ]
3345  if build_docs
3346    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
3347  endif
3348  if gtk.found()
3349    nsis_cmd += '-DCONFIG_GTK=y'
3350  endif
3351
3352  nsis = custom_target('nsis',
3353                       output: 'qemu-setup-' + meson.project_version() + '.exe',
3354                       input: files('qemu.nsi'),
3355                       build_always_stale: true,
3356                       command: nsis_cmd + ['@INPUT@'])
3357  alias_target('installer', nsis)
3358endif
3359
3360#########################
3361# Configuration summary #
3362#########################
3363
3364# Directories
3365summary_info = {}
3366summary_info += {'Install prefix':    get_option('prefix')}
3367summary_info += {'BIOS directory':    qemu_datadir}
3368summary_info += {'firmware path':     get_option('qemu_firmwarepath')}
3369summary_info += {'binary directory':  get_option('bindir')}
3370summary_info += {'library directory': get_option('libdir')}
3371summary_info += {'module directory':  qemu_moddir}
3372summary_info += {'libexec directory': get_option('libexecdir')}
3373summary_info += {'include directory': get_option('includedir')}
3374summary_info += {'config directory':  get_option('sysconfdir')}
3375if targetos != 'windows'
3376  summary_info += {'local state directory': get_option('localstatedir')}
3377  summary_info += {'Manual directory':      get_option('mandir')}
3378else
3379  summary_info += {'local state directory': 'queried at runtime'}
3380endif
3381summary_info += {'Doc directory':     get_option('docdir')}
3382summary_info += {'Build directory':   meson.current_build_dir()}
3383summary_info += {'Source path':       meson.current_source_dir()}
3384summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
3385summary(summary_info, bool_yn: true, section: 'Directories')
3386
3387# Host binaries
3388summary_info = {}
3389summary_info += {'git':               config_host['GIT']}
3390summary_info += {'make':              config_host['MAKE']}
3391summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
3392summary_info += {'sphinx-build':      sphinx_build}
3393if config_host.has_key('HAVE_GDB_BIN')
3394  summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
3395endif
3396if get_option('iasl') != ''
3397  summary_info += {'iasl':            get_option('iasl')}
3398else
3399  summary_info += {'iasl':            false}
3400endif
3401summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
3402if targetos == 'windows' and have_ga
3403  summary_info += {'wixl':            wixl}
3404endif
3405if slirp_opt != 'disabled' and have_system
3406  summary_info += {'smbd':            have_slirp_smbd ? smbd_path : false}
3407endif
3408summary(summary_info, bool_yn: true, section: 'Host binaries')
3409
3410# Configurable features
3411summary_info = {}
3412summary_info += {'Documentation':     build_docs}
3413summary_info += {'system-mode emulation': have_system}
3414summary_info += {'user-mode emulation': have_user}
3415summary_info += {'block layer':       have_block}
3416summary_info += {'Install blobs':     get_option('install_blobs')}
3417summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
3418if config_host.has_key('CONFIG_MODULES')
3419  summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')}
3420endif
3421summary_info += {'fuzzing support':   get_option('fuzzing')}
3422if have_system
3423  summary_info += {'Audio drivers':     ' '.join(audio_drivers_selected)}
3424endif
3425summary_info += {'Trace backends':    ','.join(get_option('trace_backends'))}
3426if 'simple' in get_option('trace_backends')
3427  summary_info += {'Trace output file': get_option('trace_file') + '-<pid>'}
3428endif
3429summary_info += {'D-Bus display':     dbus_display}
3430summary_info += {'QOM debugging':     get_option('qom_cast_debug')}
3431summary_info += {'vhost-kernel support': config_host.has_key('CONFIG_VHOST_KERNEL')}
3432summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')}
3433summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')}
3434summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')}
3435summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')}
3436summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_USER')}
3437summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
3438summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')}
3439summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')}
3440summary_info += {'build guest agent': have_ga}
3441summary(summary_info, bool_yn: true, section: 'Configurable features')
3442
3443# Compilation information
3444summary_info = {}
3445summary_info += {'host CPU':          cpu}
3446summary_info += {'host endianness':   build_machine.endian()}
3447summary_info += {'C compiler':        ' '.join(meson.get_compiler('c').cmd_array())}
3448summary_info += {'Host C compiler':   ' '.join(meson.get_compiler('c', native: true).cmd_array())}
3449if link_language == 'cpp'
3450  summary_info += {'C++ compiler':    ' '.join(meson.get_compiler('cpp').cmd_array())}
3451else
3452  summary_info += {'C++ compiler':      false}
3453endif
3454if targetos == 'darwin'
3455  summary_info += {'Objective-C compiler': ' '.join(meson.get_compiler('objc').cmd_array())}
3456endif
3457summary_info += {'CFLAGS':            ' '.join(get_option('c_args')
3458                                               + ['-O' + get_option('optimization')]
3459                                               + (get_option('debug') ? ['-g'] : []))}
3460if link_language == 'cpp'
3461  summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args')
3462                                               + ['-O' + get_option('optimization')]
3463                                               + (get_option('debug') ? ['-g'] : []))}
3464endif
3465link_args = get_option(link_language + '_link_args')
3466if link_args.length() > 0
3467  summary_info += {'LDFLAGS':         ' '.join(link_args)}
3468endif
3469summary_info += {'QEMU_CFLAGS':       config_host['QEMU_CFLAGS']}
3470summary_info += {'QEMU_LDFLAGS':      config_host['QEMU_LDFLAGS']}
3471summary_info += {'profiler':          get_option('profiler')}
3472summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
3473summary_info += {'PIE':               get_option('b_pie')}
3474summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
3475summary_info += {'malloc trim support': has_malloc_trim}
3476summary_info += {'membarrier':        have_membarrier}
3477summary_info += {'debug stack usage': get_option('debug_stack_usage')}
3478summary_info += {'mutex debugging':   get_option('debug_mutex')}
3479summary_info += {'memory allocator':  get_option('malloc')}
3480summary_info += {'avx2 optimization': config_host_data.get('CONFIG_AVX2_OPT')}
3481summary_info += {'avx512f optimization': config_host_data.get('CONFIG_AVX512F_OPT')}
3482summary_info += {'gprof enabled':     get_option('gprof')}
3483summary_info += {'gcov':              get_option('b_coverage')}
3484summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
3485summary_info += {'CFI support':       get_option('cfi')}
3486if get_option('cfi')
3487  summary_info += {'CFI debug support': get_option('cfi_debug')}
3488endif
3489summary_info += {'strip binaries':    get_option('strip')}
3490summary_info += {'sparse':            sparse}
3491summary_info += {'mingw32 support':   targetos == 'windows'}
3492
3493# snarf the cross-compilation information for tests
3494foreach target: target_dirs
3495  tcg_mak = meson.current_build_dir() / 'tests/tcg' / 'config-' + target + '.mak'
3496  if fs.exists(tcg_mak)
3497    config_cross_tcg = keyval.load(tcg_mak)
3498    target = config_cross_tcg['TARGET_NAME']
3499    compiler = ''
3500    if 'DOCKER_CROSS_CC_GUEST' in config_cross_tcg
3501      summary_info += {target + ' tests': config_cross_tcg['DOCKER_CROSS_CC_GUEST'] +
3502                                          ' via ' + config_cross_tcg['DOCKER_IMAGE']}
3503    elif 'CROSS_CC_GUEST' in config_cross_tcg
3504      summary_info += {target + ' tests'
3505                                : config_cross_tcg['CROSS_CC_GUEST'] }
3506    endif
3507   endif
3508endforeach
3509
3510summary(summary_info, bool_yn: true, section: 'Compilation')
3511
3512# Targets and accelerators
3513summary_info = {}
3514if have_system
3515  summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
3516  summary_info += {'HAX support':       config_all.has_key('CONFIG_HAX')}
3517  summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
3518  summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
3519  summary_info += {'NVMM support':      config_all.has_key('CONFIG_NVMM')}
3520  summary_info += {'Xen support':       config_host.has_key('CONFIG_XEN_BACKEND')}
3521  if config_host.has_key('CONFIG_XEN_BACKEND')
3522    summary_info += {'xen ctrl version':  config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
3523  endif
3524endif
3525summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
3526if config_all.has_key('CONFIG_TCG')
3527  if get_option('tcg_interpreter')
3528    summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, slow)'}
3529  else
3530    summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
3531  endif
3532  summary_info += {'TCG plugins': config_host.has_key('CONFIG_PLUGIN')}
3533  summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
3534endif
3535summary_info += {'target list':       ' '.join(target_dirs)}
3536if have_system
3537  summary_info += {'default devices':   get_option('default_devices')}
3538  summary_info += {'out of process emulation': multiprocess_allowed}
3539endif
3540summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
3541
3542# Block layer
3543summary_info = {}
3544summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
3545summary_info += {'coroutine pool':    have_coroutine_pool}
3546if have_block
3547  summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']}
3548  summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']}
3549  summary_info += {'Use block whitelist in tools': get_option('block_drv_whitelist_in_tools')}
3550  summary_info += {'VirtFS support':    have_virtfs}
3551  summary_info += {'build virtiofs daemon': have_virtiofsd}
3552  summary_info += {'Live block migration': config_host_data.get('CONFIG_LIVE_BLOCK_MIGRATION')}
3553  summary_info += {'replication support': config_host_data.get('CONFIG_REPLICATION')}
3554  summary_info += {'bochs support':     get_option('bochs').allowed()}
3555  summary_info += {'cloop support':     get_option('cloop').allowed()}
3556  summary_info += {'dmg support':       get_option('dmg').allowed()}
3557  summary_info += {'qcow v1 support':   get_option('qcow1').allowed()}
3558  summary_info += {'vdi support':       get_option('vdi').allowed()}
3559  summary_info += {'vvfat support':     get_option('vvfat').allowed()}
3560  summary_info += {'qed support':       get_option('qed').allowed()}
3561  summary_info += {'parallels support': get_option('parallels').allowed()}
3562  summary_info += {'FUSE exports':      fuse}
3563endif
3564summary(summary_info, bool_yn: true, section: 'Block layer support')
3565
3566# Crypto
3567summary_info = {}
3568summary_info += {'TLS priority':      config_host['CONFIG_TLS_PRIORITY']}
3569summary_info += {'GNUTLS support':    gnutls}
3570if gnutls.found()
3571  summary_info += {'  GNUTLS crypto':   gnutls_crypto.found()}
3572endif
3573summary_info += {'libgcrypt':         gcrypt}
3574summary_info += {'nettle':            nettle}
3575if nettle.found()
3576   summary_info += {'  XTS':             xts != 'private'}
3577endif
3578summary_info += {'AF_ALG support':    have_afalg}
3579summary_info += {'rng-none':          get_option('rng_none')}
3580summary_info += {'Linux keyring':     config_host.has_key('CONFIG_SECRET_KEYRING')}
3581summary(summary_info, bool_yn: true, section: 'Crypto')
3582
3583# Libraries
3584summary_info = {}
3585if targetos == 'darwin'
3586  summary_info += {'Cocoa support':   cocoa}
3587endif
3588summary_info += {'SDL support':       sdl}
3589summary_info += {'SDL image support': sdl_image}
3590summary_info += {'GTK support':       gtk}
3591summary_info += {'pixman':            pixman}
3592summary_info += {'VTE support':       vte}
3593summary_info += {'slirp support':     slirp_opt == 'internal' ? slirp_opt : slirp}
3594summary_info += {'libtasn1':          tasn1}
3595summary_info += {'PAM':               pam}
3596summary_info += {'iconv support':     iconv}
3597summary_info += {'curses support':    curses}
3598summary_info += {'virgl support':     virgl}
3599summary_info += {'curl support':      curl}
3600summary_info += {'Multipath support': mpathpersist}
3601summary_info += {'VNC support':       vnc}
3602if vnc.found()
3603  summary_info += {'VNC SASL support':  sasl}
3604  summary_info += {'VNC JPEG support':  jpeg}
3605  summary_info += {'VNC PNG support':   png}
3606endif
3607if targetos not in ['darwin', 'haiku', 'windows']
3608  summary_info += {'OSS support':     oss}
3609elif targetos == 'darwin'
3610  summary_info += {'CoreAudio support': coreaudio}
3611elif targetos == 'windows'
3612  summary_info += {'DirectSound support': dsound}
3613endif
3614if targetos == 'linux'
3615  summary_info += {'ALSA support':    alsa}
3616  summary_info += {'PulseAudio support': pulse}
3617endif
3618summary_info += {'JACK support':      jack}
3619summary_info += {'brlapi support':    brlapi}
3620summary_info += {'vde support':       vde}
3621summary_info += {'netmap support':    have_netmap}
3622summary_info += {'l2tpv3 support':    have_l2tpv3}
3623summary_info += {'Linux AIO support': libaio}
3624summary_info += {'Linux io_uring support': linux_io_uring}
3625summary_info += {'ATTR/XATTR support': libattr}
3626summary_info += {'RDMA support':      config_host.has_key('CONFIG_RDMA')}
3627summary_info += {'PVRDMA support':    config_host.has_key('CONFIG_PVRDMA')}
3628summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
3629summary_info += {'libcap-ng support': libcap_ng}
3630summary_info += {'bpf support':       libbpf}
3631summary_info += {'spice protocol support': spice_protocol}
3632if spice_protocol.found()
3633  summary_info += {'  spice server support': spice}
3634endif
3635summary_info += {'rbd support':       rbd}
3636summary_info += {'smartcard support': cacard}
3637summary_info += {'U2F support':       u2f}
3638summary_info += {'libusb':            libusb}
3639summary_info += {'usb net redir':     usbredir}
3640summary_info += {'OpenGL support':    config_host.has_key('CONFIG_OPENGL')}
3641summary_info += {'GBM':               gbm}
3642summary_info += {'libiscsi support':  libiscsi}
3643summary_info += {'libnfs support':    libnfs}
3644if targetos == 'windows'
3645  if have_ga
3646    summary_info += {'QGA VSS support':   have_qga_vss}
3647    summary_info += {'QGA w32 disk info': have_ntddscsi}
3648  endif
3649endif
3650summary_info += {'seccomp support':   seccomp}
3651summary_info += {'GlusterFS support': glusterfs}
3652summary_info += {'TPM support':       have_tpm}
3653summary_info += {'libssh support':    libssh}
3654summary_info += {'lzo support':       lzo}
3655summary_info += {'snappy support':    snappy}
3656summary_info += {'bzip2 support':     libbzip2}
3657summary_info += {'lzfse support':     liblzfse}
3658summary_info += {'zstd support':      zstd}
3659summary_info += {'NUMA host support': numa}
3660summary_info += {'capstone':          capstone_opt == 'internal' ? capstone_opt : capstone}
3661summary_info += {'libpmem support':   libpmem}
3662summary_info += {'libdaxctl support': libdaxctl}
3663summary_info += {'libudev':           libudev}
3664# Dummy dependency, keep .found()
3665summary_info += {'FUSE lseek':        fuse_lseek.found()}
3666summary_info += {'selinux':           selinux}
3667summary(summary_info, bool_yn: true, section: 'Dependencies')
3668
3669if not supported_cpus.contains(cpu)
3670  message()
3671  warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
3672  message()
3673  message('CPU host architecture ' + cpu + ' support is not currently maintained.')
3674  message('The QEMU project intends to remove support for this host CPU in')
3675  message('a future release if nobody volunteers to maintain it and to')
3676  message('provide a build host for our continuous integration setup.')
3677  message('configure has succeeded and you can continue to build, but')
3678  message('if you care about QEMU on this platform you should contact')
3679  message('us upstream at qemu-devel@nongnu.org.')
3680endif
3681
3682if not supported_oses.contains(targetos)
3683  message()
3684  warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
3685  message()
3686  message('Host OS ' + targetos + 'support is not currently maintained.')
3687  message('The QEMU project intends to remove support for this host OS in')
3688  message('a future release if nobody volunteers to maintain it and to')
3689  message('provide a build host for our continuous integration setup.')
3690  message('configure has succeeded and you can continue to build, but')
3691  message('if you care about QEMU on this platform you should contact')
3692  message('us upstream at qemu-devel@nongnu.org.')
3693endif
3694