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