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