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