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