xref: /openbmc/qemu/meson.build (revision 7618fffd)
1project('qemu', ['c'], meson_version: '>=0.63.0',
2        default_options: ['warning_level=1', 'c_std=gnu11', 'cpp_std=gnu++11', 'b_colorout=auto',
3                          'b_staticpic=false', 'stdsplit=false', 'optimization=2', 'b_pie=true'],
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
10meson.add_postconf_script(find_program('scripts/symlink-install-tree.py'))
11
12####################
13# Global variables #
14####################
15
16not_found = dependency('', required: false)
17keyval = import('keyval')
18ss = import('sourceset')
19fs = import('fs')
20
21host_os = host_machine.system()
22config_host = keyval.load(meson.current_build_dir() / 'config-host.mak')
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
43genh = []
44qapi_trace_events = []
45
46bsd_oses = ['gnu/kfreebsd', 'freebsd', 'netbsd', 'openbsd', 'dragonfly', 'darwin']
47supported_oses = ['windows', 'freebsd', 'netbsd', 'openbsd', 'darwin', 'sunos', 'linux']
48supported_cpus = ['ppc', 'ppc64', 's390x', 'riscv32', 'riscv64', 'x86', 'x86_64',
49  'arm', 'aarch64', 'loongarch64', 'mips', 'mips64', 'sparc64']
50
51cpu = host_machine.cpu_family()
52
53target_dirs = config_host['TARGET_DIRS'].split()
54
55############
56# Programs #
57############
58
59sh = find_program('sh')
60python = import('python').find_installation()
61
62cc = meson.get_compiler('c')
63all_languages = ['c']
64if host_os == 'windows' and add_languages('cpp', required: false, native: false)
65  all_languages += ['cpp']
66  cxx = meson.get_compiler('cpp')
67endif
68if host_os == 'darwin' and \
69   add_languages('objc', required: get_option('cocoa'), native: false)
70  all_languages += ['objc']
71  objc = meson.get_compiler('objc')
72endif
73
74dtrace = not_found
75stap = not_found
76if 'dtrace' in get_option('trace_backends')
77  dtrace = find_program('dtrace', required: true)
78  stap = find_program('stap', required: false)
79  if stap.found()
80    # Workaround to avoid dtrace(1) producing a file with 'hidden' symbol
81    # visibility. Define STAP_SDT_V2 to produce 'default' symbol visibility
82    # instead. QEMU --enable-modules depends on this because the SystemTap
83    # semaphores are linked into the main binary and not the module's shared
84    # object.
85    add_global_arguments('-DSTAP_SDT_V2',
86                         native: false, language: all_languages)
87  endif
88endif
89
90if get_option('iasl') == ''
91  iasl = find_program('iasl', required: false)
92else
93  iasl = find_program(get_option('iasl'), required: true)
94endif
95
96edk2_targets = [ 'arm-softmmu', 'aarch64-softmmu', 'i386-softmmu', 'x86_64-softmmu' ]
97unpack_edk2_blobs = false
98foreach target : edk2_targets
99  if target in target_dirs
100    bzip2 = find_program('bzip2', required: get_option('install_blobs'))
101    unpack_edk2_blobs = bzip2.found()
102    break
103  endif
104endforeach
105
106#####################
107# Option validation #
108#####################
109
110# Fuzzing
111if get_option('fuzzing') and get_option('fuzzing_engine') == '' and \
112    not cc.links('''
113          #include <stdint.h>
114          #include <sys/types.h>
115          int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
116          int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { return 0; }
117        ''',
118        args: ['-Werror', '-fsanitize=fuzzer'])
119  error('Your compiler does not support -fsanitize=fuzzer')
120endif
121
122# Tracing backends
123if 'ftrace' in get_option('trace_backends') and host_os != 'linux'
124  error('ftrace is supported only on Linux')
125endif
126if 'syslog' in get_option('trace_backends') and not cc.compiles('''
127    #include <syslog.h>
128    int main(void) {
129        openlog("qemu", LOG_PID, LOG_DAEMON);
130        syslog(LOG_INFO, "configure");
131        return 0;
132    }''')
133  error('syslog is not supported on this system')
134endif
135
136# Miscellaneous Linux-only features
137get_option('mpath') \
138  .require(host_os == 'linux', error_message: 'Multipath is supported only on Linux')
139
140multiprocess_allowed = get_option('multiprocess') \
141  .require(host_os == 'linux', error_message: 'Multiprocess QEMU is supported only on Linux') \
142  .allowed()
143
144vfio_user_server_allowed = get_option('vfio_user_server') \
145  .require(host_os == 'linux', error_message: 'vfio-user server is supported only on Linux') \
146  .allowed()
147
148have_tpm = get_option('tpm') \
149  .require(host_os != 'windows', error_message: 'TPM emulation only available on POSIX systems') \
150  .allowed()
151
152# vhost
153have_vhost_user = get_option('vhost_user') \
154  .disable_auto_if(host_os != 'linux') \
155  .require(host_os != 'windows',
156           error_message: 'vhost-user is not available on Windows').allowed()
157have_vhost_vdpa = get_option('vhost_vdpa') \
158  .require(host_os == 'linux',
159           error_message: 'vhost-vdpa is only available on Linux').allowed()
160have_vhost_kernel = get_option('vhost_kernel') \
161  .require(host_os == 'linux',
162           error_message: 'vhost-kernel is only available on Linux').allowed()
163have_vhost_user_crypto = get_option('vhost_crypto') \
164  .require(have_vhost_user,
165           error_message: 'vhost-crypto requires vhost-user to be enabled').allowed()
166
167have_vhost = have_vhost_user or have_vhost_vdpa or have_vhost_kernel
168
169have_vhost_net_user = have_vhost_user and get_option('vhost_net').allowed()
170have_vhost_net_vdpa = have_vhost_vdpa and get_option('vhost_net').allowed()
171have_vhost_net_kernel = have_vhost_kernel and get_option('vhost_net').allowed()
172have_vhost_net = have_vhost_net_kernel or have_vhost_net_user or have_vhost_net_vdpa
173
174# type of binaries to build
175have_linux_user = false
176have_bsd_user = false
177have_system = false
178foreach target : target_dirs
179  have_linux_user = have_linux_user or target.endswith('linux-user')
180  have_bsd_user = have_bsd_user or target.endswith('bsd-user')
181  have_system = have_system or target.endswith('-softmmu')
182endforeach
183have_user = have_linux_user or have_bsd_user
184
185have_tools = get_option('tools') \
186  .disable_auto_if(not have_system) \
187  .allowed()
188have_ga = get_option('guest_agent') \
189  .disable_auto_if(not have_system and not have_tools) \
190  .require(host_os in ['sunos', 'linux', 'windows', 'freebsd', 'netbsd', 'openbsd'],
191           error_message: 'unsupported OS for QEMU guest agent') \
192  .allowed()
193have_block = have_system or have_tools
194
195enable_modules = get_option('modules') \
196  .require(host_os != 'windows',
197           error_message: 'Modules are not available for Windows') \
198  .require(not get_option('prefer_static'),
199           error_message: 'Modules are incompatible with static linking') \
200  .allowed()
201
202#######################################
203# Variables for host and accelerators #
204#######################################
205
206if cpu not in supported_cpus
207  host_arch = 'unknown'
208elif cpu == 'x86'
209  host_arch = 'i386'
210elif cpu == 'mips64'
211  host_arch = 'mips'
212elif cpu in ['riscv32', 'riscv64']
213  host_arch = 'riscv'
214else
215  host_arch = cpu
216endif
217
218if cpu in ['x86', 'x86_64']
219  kvm_targets = ['i386-softmmu', 'x86_64-softmmu']
220elif cpu == 'aarch64'
221  kvm_targets = ['aarch64-softmmu']
222elif cpu == 's390x'
223  kvm_targets = ['s390x-softmmu']
224elif cpu in ['ppc', 'ppc64']
225  kvm_targets = ['ppc-softmmu', 'ppc64-softmmu']
226elif cpu in ['mips', 'mips64']
227  kvm_targets = ['mips-softmmu', 'mipsel-softmmu', 'mips64-softmmu', 'mips64el-softmmu']
228elif cpu in ['riscv32']
229  kvm_targets = ['riscv32-softmmu']
230elif cpu in ['riscv64']
231  kvm_targets = ['riscv64-softmmu']
232elif cpu in ['loongarch64']
233  kvm_targets = ['loongarch64-softmmu']
234else
235  kvm_targets = []
236endif
237accelerator_targets = { 'CONFIG_KVM': kvm_targets }
238
239if cpu in ['x86', 'x86_64']
240  xen_targets = ['i386-softmmu', 'x86_64-softmmu']
241elif cpu in ['arm', 'aarch64']
242  # i386 emulator provides xenpv machine type for multiple architectures
243  xen_targets = ['i386-softmmu', 'x86_64-softmmu', 'aarch64-softmmu']
244else
245  xen_targets = []
246endif
247accelerator_targets += { 'CONFIG_XEN': xen_targets }
248
249if cpu in ['aarch64']
250  accelerator_targets += {
251    'CONFIG_HVF': ['aarch64-softmmu']
252  }
253endif
254
255if cpu in ['x86', 'x86_64']
256  accelerator_targets += {
257    'CONFIG_HVF': ['x86_64-softmmu'],
258    'CONFIG_NVMM': ['i386-softmmu', 'x86_64-softmmu'],
259    'CONFIG_WHPX': ['i386-softmmu', 'x86_64-softmmu'],
260  }
261endif
262
263modular_tcg = []
264# Darwin does not support references to thread-local variables in modules
265if host_os != 'darwin'
266  modular_tcg = ['i386-softmmu', 'x86_64-softmmu']
267endif
268
269##################
270# Compiler flags #
271##################
272
273foreach lang : all_languages
274  compiler = meson.get_compiler(lang)
275  if compiler.get_id() == 'gcc' and compiler.version().version_compare('>=7.4')
276    # ok
277  elif compiler.get_id() == 'clang' and compiler.compiles('''
278      #ifdef __apple_build_version__
279      # if __clang_major__ < 12 || (__clang_major__ == 12 && __clang_minor__ < 0)
280      #  error You need at least XCode Clang v12.0 to compile QEMU
281      # endif
282      #else
283      # if __clang_major__ < 10 || (__clang_major__ == 10 && __clang_minor__ < 0)
284      #  error You need at least Clang v10.0 to compile QEMU
285      # endif
286      #endif''')
287    # ok
288  else
289    error('You either need GCC v7.4 or Clang v10.0 (or XCode Clang v12.0) to compile QEMU')
290  endif
291endforeach
292
293# default flags for all hosts
294# We use -fwrapv to tell the compiler that we require a C dialect where
295# left shift of signed integers is well defined and has the expected
296# 2s-complement style results. (Both clang and gcc agree that it
297# provides these semantics.)
298
299qemu_common_flags = [
300  '-D_GNU_SOURCE', '-D_FILE_OFFSET_BITS=64', '-D_LARGEFILE_SOURCE',
301  '-fno-strict-aliasing', '-fno-common', '-fwrapv' ]
302qemu_cflags = []
303qemu_ldflags = []
304
305if host_os == 'darwin'
306  # Disable attempts to use ObjectiveC features in os/object.h since they
307  # won't work when we're compiling with gcc as a C compiler.
308  if compiler.get_id() == 'gcc'
309    qemu_common_flags += '-DOS_OBJECT_USE_OBJC=0'
310  endif
311elif host_os == 'sunos'
312  # needed for CMSG_ macros in sys/socket.h
313  qemu_common_flags += '-D_XOPEN_SOURCE=600'
314  # needed for TIOCWIN* defines in termios.h
315  qemu_common_flags += '-D__EXTENSIONS__'
316elif host_os == 'haiku'
317  qemu_common_flags += ['-DB_USE_POSITIVE_POSIX_ERRORS', '-D_BSD_SOURCE', '-fPIC']
318endif
319
320# __sync_fetch_and_and requires at least -march=i486. Many toolchains
321# use i686 as default anyway, but for those that don't, an explicit
322# specification is necessary
323if host_arch == 'i386' and not cc.links('''
324  static int sfaa(int *ptr)
325  {
326    return __sync_fetch_and_and(ptr, 0);
327  }
328
329  int main(void)
330  {
331    int val = 42;
332    val = __sync_val_compare_and_swap(&val, 0, 1);
333    sfaa(&val);
334    return val;
335  }''')
336  qemu_common_flags = ['-march=i486'] + qemu_common_flags
337endif
338
339if get_option('prefer_static')
340  qemu_ldflags += get_option('b_pie') ? '-static-pie' : '-static'
341endif
342
343# Meson currently only handles pie as a boolean for now, so if the user
344# has explicitly disabled PIE we need to extend our cflags.
345#
346# -no-pie is supposedly a linker flag that has no effect on the compiler
347# command line, but some distros, that didn't quite know what they were
348# doing, made local changes to gcc's specs file that turned it into
349# a compiler command-line flag.
350#
351# What about linker flags?  For a static build, no PIE is implied by -static
352# which we added above (and if it's not because of the same specs patching,
353# there's nothing we can do: compilation will fail, report a bug to your
354# distro and do not use --disable-pie in the meanwhile).  For dynamic linking,
355# instead, we can't add -no-pie because it overrides -shared: the linker then
356# tries to build an executable instead of a shared library and fails.  So
357# don't add -no-pie anywhere and cross fingers. :(
358if not get_option('b_pie')
359  qemu_common_flags += cc.get_supported_arguments('-fno-pie', '-no-pie')
360endif
361
362if not get_option('stack_protector').disabled()
363  stack_protector_probe = '''
364    int main(int argc, char *argv[])
365    {
366      char arr[64], *p = arr, *c = argv[argc - 1];
367      while (*c) {
368          *p++ = *c++;
369      }
370      return 0;
371    }'''
372  have_stack_protector = false
373  foreach arg : ['-fstack-protector-strong', '-fstack-protector-all']
374    # We need to check both a compile and a link, since some compiler
375    # setups fail only on a .c->.o compile and some only at link time
376    if cc.compiles(stack_protector_probe, args: ['-Werror', arg]) and \
377       cc.links(stack_protector_probe, args: ['-Werror', arg])
378      have_stack_protector = true
379      qemu_cflags += arg
380      qemu_ldflags += arg
381      break
382    endif
383  endforeach
384  get_option('stack_protector') \
385    .require(have_stack_protector, error_message: 'Stack protector not supported')
386endif
387
388coroutine_backend = get_option('coroutine_backend')
389ucontext_probe = '''
390  #include <ucontext.h>
391  #ifdef __stub_makecontext
392  #error Ignoring glibc stub makecontext which will always fail
393  #endif
394  int main(void) { makecontext(0, 0, 0); return 0; }'''
395
396# On Windows the only valid backend is the Windows specific one.
397# For POSIX prefer ucontext, but it's not always possible. The fallback
398# is sigcontext.
399supported_backends = []
400if host_os == 'windows'
401  supported_backends += ['windows']
402else
403  if host_os != 'darwin' and cc.links(ucontext_probe)
404    supported_backends += ['ucontext']
405  endif
406  supported_backends += ['sigaltstack']
407endif
408
409if coroutine_backend == 'auto'
410  coroutine_backend = supported_backends[0]
411elif coroutine_backend not in supported_backends
412  error('"@0@" backend requested but not available.  Available backends: @1@' \
413        .format(coroutine_backend, ', '.join(supported_backends)))
414endif
415
416# Compiles if SafeStack *not* enabled
417safe_stack_probe = '''
418  int main(void)
419  {
420  #if defined(__has_feature)
421  #if __has_feature(safe_stack)
422  #error SafeStack Enabled
423  #endif
424  #endif
425      return 0;
426  }'''
427if get_option('safe_stack') != not cc.compiles(safe_stack_probe)
428  safe_stack_arg = get_option('safe_stack') ? '-fsanitize=safe-stack' : '-fno-sanitize=safe-stack'
429  if get_option('safe_stack') != not cc.compiles(safe_stack_probe, args: safe_stack_arg)
430    error(get_option('safe_stack') \
431          ? 'SafeStack not supported by your compiler' \
432          : 'Cannot disable SafeStack')
433  endif
434  qemu_cflags += safe_stack_arg
435  qemu_ldflags += safe_stack_arg
436endif
437if get_option('safe_stack') and coroutine_backend != 'ucontext'
438  error('SafeStack is only supported with the ucontext coroutine backend')
439endif
440
441if get_option('sanitizers')
442  if cc.has_argument('-fsanitize=address')
443    qemu_cflags = ['-fsanitize=address'] + qemu_cflags
444    qemu_ldflags = ['-fsanitize=address'] + qemu_ldflags
445  endif
446
447  # Detect static linking issue with ubsan - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84285
448  if cc.links('int main(int argc, char **argv) { return argc + 1; }',
449              args: [qemu_ldflags, '-fsanitize=undefined'])
450    qemu_cflags = ['-fsanitize=undefined'] + qemu_cflags
451    qemu_ldflags = ['-fsanitize=undefined'] + qemu_ldflags
452  endif
453endif
454
455# Thread sanitizer is, for now, much noisier than the other sanitizers;
456# keep it separate until that is not the case.
457if get_option('tsan')
458  if get_option('sanitizers')
459    error('TSAN is not supported with other sanitizers')
460  endif
461  if not cc.has_function('__tsan_create_fiber',
462                         args: '-fsanitize=thread',
463                         prefix: '#include <sanitizer/tsan_interface.h>')
464    error('Cannot enable TSAN due to missing fiber annotation interface')
465  endif
466  qemu_cflags = ['-fsanitize=thread'] + qemu_cflags
467  qemu_ldflags = ['-fsanitize=thread'] + qemu_ldflags
468endif
469
470# Detect support for PT_GNU_RELRO + DT_BIND_NOW.
471# The combination is known as "full relro", because .got.plt is read-only too.
472qemu_ldflags += cc.get_supported_link_arguments('-Wl,-z,relro', '-Wl,-z,now')
473
474if host_os == 'windows'
475  qemu_ldflags += cc.get_supported_link_arguments('-Wl,--no-seh', '-Wl,--nxcompat')
476  qemu_ldflags += cc.get_supported_link_arguments('-Wl,--dynamicbase', '-Wl,--high-entropy-va')
477endif
478
479# Exclude --warn-common with TSan to suppress warnings from the TSan libraries.
480if host_os != 'sunos' and not get_option('tsan')
481  qemu_ldflags += cc.get_supported_link_arguments('-Wl,--warn-common')
482endif
483
484if get_option('fuzzing')
485  # Specify a filter to only instrument code that is directly related to
486  # virtual-devices.
487  configure_file(output: 'instrumentation-filter',
488                 input: 'scripts/oss-fuzz/instrumentation-filter-template',
489                 copy: true)
490
491  if cc.compiles('int main () { return 0; }',
492                  name: '-fsanitize-coverage-allowlist=/dev/null',
493                 args: ['-fsanitize-coverage-allowlist=/dev/null',
494                        '-fsanitize-coverage=trace-pc'] )
495    qemu_common_flags += ['-fsanitize-coverage-allowlist=instrumentation-filter']
496  endif
497
498  if get_option('fuzzing_engine') == ''
499    # Add CFLAGS to tell clang to add fuzzer-related instrumentation to all the
500    # compiled code.  To build non-fuzzer binaries with --enable-fuzzing, link
501    # everything with fsanitize=fuzzer-no-link. Otherwise, the linker will be
502    # unable to bind the fuzzer-related callbacks added by instrumentation.
503    qemu_common_flags += ['-fsanitize=fuzzer-no-link']
504    qemu_ldflags += ['-fsanitize=fuzzer-no-link']
505    # For the actual fuzzer binaries, we need to link against the libfuzzer
506    # library. They need to be configurable, to support OSS-Fuzz
507    fuzz_exe_ldflags = ['-fsanitize=fuzzer']
508  else
509    # LIB_FUZZING_ENGINE was set; assume we are running on OSS-Fuzz, and
510    # the needed CFLAGS have already been provided
511    fuzz_exe_ldflags = get_option('fuzzing_engine').split()
512  endif
513endif
514
515if get_option('cfi')
516  cfi_flags=[]
517  # Check for dependency on LTO
518  if not get_option('b_lto')
519    error('Selected Control-Flow Integrity but LTO is disabled')
520  endif
521  if enable_modules
522    error('Selected Control-Flow Integrity is not compatible with modules')
523  endif
524  # Check for cfi flags. CFI requires LTO so we can't use
525  # get_supported_arguments, but need a more complex "compiles" which allows
526  # custom arguments
527  if cc.compiles('int main () { return 0; }', name: '-fsanitize=cfi-icall',
528                 args: ['-flto', '-fsanitize=cfi-icall'] )
529    cfi_flags += '-fsanitize=cfi-icall'
530  else
531    error('-fsanitize=cfi-icall is not supported by the compiler')
532  endif
533  if cc.compiles('int main () { return 0; }',
534                 name: '-fsanitize-cfi-icall-generalize-pointers',
535                 args: ['-flto', '-fsanitize=cfi-icall',
536                        '-fsanitize-cfi-icall-generalize-pointers'] )
537    cfi_flags += '-fsanitize-cfi-icall-generalize-pointers'
538  else
539    error('-fsanitize-cfi-icall-generalize-pointers is not supported by the compiler')
540  endif
541  if get_option('cfi_debug')
542    if cc.compiles('int main () { return 0; }',
543                   name: '-fno-sanitize-trap=cfi-icall',
544                   args: ['-flto', '-fsanitize=cfi-icall',
545                          '-fno-sanitize-trap=cfi-icall'] )
546      cfi_flags += '-fno-sanitize-trap=cfi-icall'
547    else
548      error('-fno-sanitize-trap=cfi-icall is not supported by the compiler')
549    endif
550  endif
551  add_global_arguments(cfi_flags, native: false, language: all_languages)
552  add_global_link_arguments(cfi_flags, native: false, language: all_languages)
553endif
554
555# Check further flags that make QEMU more robust against malicious parties
556
557hardening_flags = [
558    # Zero out registers used during a function call
559    # upon its return. This makes it harder to assemble
560    # ROP gadgets into something usable
561    '-fzero-call-used-regs=used-gpr',
562
563    # Initialize all stack variables to zero. This makes
564    # it harder to take advantage of uninitialized stack
565    # data to drive exploits
566    '-ftrivial-auto-var-init=zero',
567]
568
569qemu_common_flags += cc.get_supported_arguments(hardening_flags)
570
571add_global_arguments(qemu_common_flags, native: false, language: all_languages)
572add_global_link_arguments(qemu_ldflags, native: false, language: all_languages)
573
574# Collect warnings that we want to enable
575
576warn_flags = [
577  '-Wundef',
578  '-Wwrite-strings',
579  '-Wmissing-prototypes',
580  '-Wstrict-prototypes',
581  '-Wredundant-decls',
582  '-Wold-style-declaration',
583  '-Wold-style-definition',
584  '-Wtype-limits',
585  '-Wformat-security',
586  '-Wformat-y2k',
587  '-Winit-self',
588  '-Wignored-qualifiers',
589  '-Wempty-body',
590  '-Wnested-externs',
591  '-Wendif-labels',
592  '-Wexpansion-to-defined',
593  '-Wimplicit-fallthrough=2',
594  '-Wmissing-format-attribute',
595  '-Wno-initializer-overrides',
596  '-Wno-missing-include-dirs',
597  '-Wno-shift-negative-value',
598  '-Wno-string-plus-int',
599  '-Wno-typedef-redefinition',
600  '-Wno-tautological-type-limit-compare',
601  '-Wno-psabi',
602  '-Wno-gnu-variable-sized-type-not-at-end',
603  '-Wshadow=local',
604]
605
606if host_os != 'darwin'
607  warn_flags += ['-Wthread-safety']
608endif
609
610# Set up C++ compiler flags
611qemu_cxxflags = []
612if 'cpp' in all_languages
613  qemu_cxxflags = ['-D__STDC_LIMIT_MACROS', '-D__STDC_CONSTANT_MACROS', '-D__STDC_FORMAT_MACROS'] + qemu_cflags
614endif
615
616add_project_arguments(qemu_cflags, native: false, language: 'c')
617add_project_arguments(cc.get_supported_arguments(warn_flags), native: false, language: 'c')
618if 'cpp' in all_languages
619  add_project_arguments(qemu_cxxflags, native: false, language: 'cpp')
620  add_project_arguments(cxx.get_supported_arguments(warn_flags), native: false, language: 'cpp')
621endif
622if 'objc' in all_languages
623  # Note sanitizer flags are not applied to Objective-C sources!
624  add_project_arguments(objc.get_supported_arguments(warn_flags), native: false, language: 'objc')
625endif
626if host_os == 'linux'
627  add_project_arguments('-isystem', meson.current_source_dir() / 'linux-headers',
628                        '-isystem', 'linux-headers',
629                        language: all_languages)
630endif
631
632add_project_arguments('-iquote', '.',
633                      '-iquote', meson.current_source_dir(),
634                      '-iquote', meson.current_source_dir() / 'include',
635                      language: all_languages)
636
637# If a host-specific include directory exists, list that first...
638host_include = meson.current_source_dir() / 'host/include/'
639if fs.is_dir(host_include / host_arch)
640  add_project_arguments('-iquote', host_include / host_arch,
641                        language: all_languages)
642endif
643# ... followed by the generic fallback.
644add_project_arguments('-iquote', host_include / 'generic',
645                      language: all_languages)
646
647sparse = find_program('cgcc', required: get_option('sparse'))
648if sparse.found()
649  run_target('sparse',
650             command: [find_program('scripts/check_sparse.py'),
651                       'compile_commands.json', sparse.full_path(), '-Wbitwise',
652                       '-Wno-transparent-union', '-Wno-old-initializer',
653                       '-Wno-non-pointer-null'])
654endif
655
656#####################################
657# Host-specific libraries and flags #
658#####################################
659
660libm = cc.find_library('m', required: false)
661threads = dependency('threads')
662util = cc.find_library('util', required: false)
663winmm = []
664socket = []
665version_res = []
666coref = []
667iokit = []
668emulator_link_args = []
669midl = not_found
670widl = not_found
671pathcch = not_found
672host_dsosuf = '.so'
673if host_os == 'windows'
674  midl = find_program('midl', required: false)
675  widl = find_program('widl', required: false)
676  pathcch = cc.find_library('pathcch')
677  socket = cc.find_library('ws2_32')
678  winmm = cc.find_library('winmm')
679
680  win = import('windows')
681  version_res = win.compile_resources('version.rc',
682                                      depend_files: files('pc-bios/qemu-nsis.ico'),
683                                      include_directories: include_directories('.'))
684  host_dsosuf = '.dll'
685elif host_os == 'darwin'
686  coref = dependency('appleframeworks', modules: 'CoreFoundation')
687  iokit = dependency('appleframeworks', modules: 'IOKit', required: false)
688  host_dsosuf = '.dylib'
689elif host_os == 'sunos'
690  socket = [cc.find_library('socket'),
691            cc.find_library('nsl'),
692            cc.find_library('resolv')]
693elif host_os == 'haiku'
694  socket = [cc.find_library('posix_error_mapper'),
695            cc.find_library('network'),
696            cc.find_library('bsd')]
697elif host_os == 'openbsd'
698  if get_option('tcg').allowed() and target_dirs.length() > 0
699    # Disable OpenBSD W^X if available
700    emulator_link_args = cc.get_supported_link_arguments('-Wl,-z,wxneeded')
701  endif
702endif
703
704###############################################
705# Host-specific configuration of accelerators #
706###############################################
707
708accelerators = []
709if get_option('kvm').allowed() and host_os == 'linux'
710  accelerators += 'CONFIG_KVM'
711endif
712if get_option('whpx').allowed() and host_os == 'windows'
713  if get_option('whpx').enabled() and host_machine.cpu() != 'x86_64'
714    error('WHPX requires 64-bit host')
715  elif cc.has_header('winhvplatform.h', required: get_option('whpx')) and \
716       cc.has_header('winhvemulation.h', required: get_option('whpx'))
717    accelerators += 'CONFIG_WHPX'
718  endif
719endif
720
721hvf = not_found
722if get_option('hvf').allowed()
723  hvf = dependency('appleframeworks', modules: 'Hypervisor',
724                   required: get_option('hvf'))
725  if hvf.found()
726    accelerators += 'CONFIG_HVF'
727  endif
728endif
729
730nvmm = not_found
731if host_os == 'netbsd'
732  nvmm = cc.find_library('nvmm', required: get_option('nvmm'))
733  if nvmm.found()
734    accelerators += 'CONFIG_NVMM'
735  endif
736endif
737
738tcg_arch = host_arch
739if get_option('tcg').allowed()
740  if host_arch == 'unknown'
741    if not get_option('tcg_interpreter')
742      error('Unsupported CPU @0@, try --enable-tcg-interpreter'.format(cpu))
743    endif
744  elif get_option('tcg_interpreter')
745    warning('Use of the TCG interpreter is not recommended on this host')
746    warning('architecture. There is a native TCG execution backend available')
747    warning('which provides substantially better performance and reliability.')
748    warning('It is strongly recommended to remove the --enable-tcg-interpreter')
749    warning('configuration option on this architecture to use the native')
750    warning('backend.')
751  endif
752  if get_option('tcg_interpreter')
753    tcg_arch = 'tci'
754  elif host_arch == 'x86_64'
755    tcg_arch = 'i386'
756  elif host_arch == 'ppc64'
757    tcg_arch = 'ppc'
758  endif
759  add_project_arguments('-iquote', meson.current_source_dir() / 'tcg' / tcg_arch,
760                        language: all_languages)
761
762  accelerators += 'CONFIG_TCG'
763endif
764
765if 'CONFIG_KVM' not in accelerators and get_option('kvm').enabled()
766  error('KVM not available on this platform')
767endif
768if 'CONFIG_HVF' not in accelerators and get_option('hvf').enabled()
769  error('HVF not available on this platform')
770endif
771if 'CONFIG_NVMM' not in accelerators and get_option('nvmm').enabled()
772  error('NVMM not available on this platform')
773endif
774if 'CONFIG_WHPX' not in accelerators and get_option('whpx').enabled()
775  error('WHPX not available on this platform')
776endif
777
778xen = not_found
779if get_option('xen').enabled() or (get_option('xen').auto() and have_system)
780  xencontrol = dependency('xencontrol', required: false,
781                          method: 'pkg-config')
782  if xencontrol.found()
783    xen_pc = declare_dependency(version: xencontrol.version(),
784      dependencies: [
785        xencontrol,
786        # disabler: true makes xen_pc.found() return false if any is not found
787        dependency('xenstore', required: false,
788                   method: 'pkg-config',
789                   disabler: true),
790        dependency('xenforeignmemory', required: false,
791                   method: 'pkg-config',
792                   disabler: true),
793        dependency('xengnttab', required: false,
794                   method: 'pkg-config',
795                   disabler: true),
796        dependency('xenevtchn', required: false,
797                   method: 'pkg-config',
798                   disabler: true),
799        dependency('xendevicemodel', required: false,
800                   method: 'pkg-config',
801                   disabler: true),
802        # optional, no "disabler: true"
803        dependency('xentoolcore', required: false,
804                   method: 'pkg-config')])
805    if xen_pc.found()
806      xen = xen_pc
807    endif
808  endif
809  if not xen.found()
810    xen_tests = [ '4.11.0', '4.10.0', '4.9.0', '4.8.0', '4.7.1' ]
811    xen_libs = {
812      '4.11.0': [ 'xenstore', 'xenctrl', 'xendevicemodel', 'xenforeignmemory', 'xengnttab', 'xenevtchn', 'xentoolcore' ],
813      '4.10.0': [ 'xenstore', 'xenctrl', 'xendevicemodel', 'xenforeignmemory', 'xengnttab', 'xenevtchn', 'xentoolcore' ],
814      '4.9.0': [ 'xenstore', 'xenctrl', 'xendevicemodel', 'xenforeignmemory', 'xengnttab', 'xenevtchn' ],
815      '4.8.0': [ 'xenstore', 'xenctrl', 'xenforeignmemory', 'xengnttab', 'xenevtchn' ],
816      '4.7.1': [ 'xenstore', 'xenctrl', 'xenforeignmemory', 'xengnttab', 'xenevtchn' ],
817    }
818    xen_deps = {}
819    foreach ver: xen_tests
820      # cache the various library tests to avoid polluting the logs
821      xen_test_deps = []
822      foreach l: xen_libs[ver]
823        if l not in xen_deps
824          xen_deps += { l: cc.find_library(l, required: false) }
825        endif
826        xen_test_deps += xen_deps[l]
827      endforeach
828
829      # Use -D to pick just one of the test programs in scripts/xen-detect.c
830      xen_version = ver.split('.')
831      xen_ctrl_version = xen_version[0] + \
832        ('0' + xen_version[1]).substring(-2) + \
833        ('0' + xen_version[2]).substring(-2)
834      if cc.links(files('scripts/xen-detect.c'),
835                  args: '-DCONFIG_XEN_CTRL_INTERFACE_VERSION=' + xen_ctrl_version,
836                  dependencies: xen_test_deps)
837        xen = declare_dependency(version: ver, dependencies: xen_test_deps)
838        break
839      endif
840    endforeach
841  endif
842  if xen.found()
843    accelerators += 'CONFIG_XEN'
844  elif get_option('xen').enabled()
845    error('could not compile and link Xen test program')
846  endif
847endif
848have_xen_pci_passthrough = get_option('xen_pci_passthrough') \
849  .require(xen.found(),
850           error_message: 'Xen PCI passthrough requested but Xen not enabled') \
851  .require(host_os == 'linux',
852           error_message: 'Xen PCI passthrough not available on this platform') \
853  .require(cpu == 'x86'  or cpu == 'x86_64',
854           error_message: 'Xen PCI passthrough not available on this platform') \
855  .allowed()
856
857################
858# Dependencies #
859################
860
861# When bumping glib minimum version, please check also whether to increase
862# the _WIN32_WINNT setting in osdep.h according to the value from glib
863glib_req_ver = '>=2.56.0'
864glib_pc = dependency('glib-2.0', version: glib_req_ver, required: true,
865                    method: 'pkg-config')
866glib_cflags = []
867if enable_modules
868  gmodule = dependency('gmodule-export-2.0', version: glib_req_ver, required: true,
869                       method: 'pkg-config')
870elif get_option('plugins')
871  gmodule = dependency('gmodule-no-export-2.0', version: glib_req_ver, required: true,
872                       method: 'pkg-config')
873else
874  gmodule = not_found
875endif
876
877# This workaround is required due to a bug in pkg-config file for glib as it
878# doesn't define GLIB_STATIC_COMPILATION for pkg-config --static
879if host_os == 'windows' and get_option('prefer_static')
880  glib_cflags += ['-DGLIB_STATIC_COMPILATION']
881endif
882
883# Sanity check that the current size_t matches the
884# size that glib thinks it should be. This catches
885# problems on multi-arch where people try to build
886# 32-bit QEMU while pointing at 64-bit glib headers
887
888if not cc.compiles('''
889  #include <glib.h>
890  #include <unistd.h>
891
892  #define QEMU_BUILD_BUG_ON(x) \
893  typedef char qemu_build_bug_on[(x)?-1:1] __attribute__((unused));
894
895  int main(void) {
896     QEMU_BUILD_BUG_ON(sizeof(size_t) != GLIB_SIZEOF_SIZE_T);
897     return 0;
898  }''', dependencies: glib_pc, args: glib_cflags)
899  error('''sizeof(size_t) doesn't match GLIB_SIZEOF_SIZE_T.
900        You probably need to set PKG_CONFIG_LIBDIR" to point
901        to the right pkg-config files for your build target.''')
902endif
903
904# Silence clang warnings triggered by glib < 2.57.2
905if not cc.compiles('''
906  #include <glib.h>
907  typedef struct Foo {
908    int i;
909  } Foo;
910  static void foo_free(Foo *f)
911  {
912    g_free(f);
913  }
914  G_DEFINE_AUTOPTR_CLEANUP_FUNC(Foo, foo_free)
915  int main(void) { return 0; }''', dependencies: glib_pc, args: ['-Wunused-function', '-Werror'])
916  glib_cflags += cc.get_supported_arguments('-Wno-unused-function')
917endif
918glib = declare_dependency(dependencies: [glib_pc, gmodule],
919                          compile_args: glib_cflags,
920                          version: glib_pc.version())
921
922# Check whether glib has gslice, which we have to avoid for correctness.
923# TODO: remove this check and the corresponding workaround (qtree) when
924# the minimum supported glib is >= 2.75.3
925glib_has_gslice = glib.version().version_compare('<2.75.3')
926
927# override glib dep to include the above refinements
928meson.override_dependency('glib-2.0', glib)
929
930# The path to glib.h is added to all compilation commands.
931add_project_dependencies(glib.partial_dependency(compile_args: true, includes: true),
932                         native: false, language: all_languages)
933
934gio = not_found
935gdbus_codegen = not_found
936gdbus_codegen_error = '@0@ requires gdbus-codegen, please install libgio'
937if not get_option('gio').auto() or have_system
938  gio = dependency('gio-2.0', required: get_option('gio'),
939                   method: 'pkg-config')
940  if gio.found() and not cc.links('''
941    #include <gio/gio.h>
942    int main(void)
943    {
944      g_dbus_proxy_new_sync(0, 0, 0, 0, 0, 0, 0, 0);
945      return 0;
946    }''', dependencies: [glib, gio])
947    if get_option('gio').enabled()
948      error('The installed libgio is broken for static linking')
949    endif
950    gio = not_found
951  endif
952  if gio.found()
953    gdbus_codegen = find_program(gio.get_variable('gdbus_codegen'),
954                                 required: get_option('gio'))
955    gio_unix = dependency('gio-unix-2.0', required: get_option('gio'),
956                          method: 'pkg-config')
957    gio = declare_dependency(dependencies: [gio, gio_unix],
958                             version: gio.version())
959  endif
960endif
961if gdbus_codegen.found() and get_option('cfi')
962  gdbus_codegen = not_found
963  gdbus_codegen_error = '@0@ uses gdbus-codegen, which does not support control flow integrity'
964endif
965
966xml_pp = find_program('scripts/xml-preprocess.py')
967
968lttng = not_found
969if 'ust' in get_option('trace_backends')
970  lttng = dependency('lttng-ust', required: true, version: '>= 2.1',
971                     method: 'pkg-config')
972endif
973pixman = not_found
974if not get_option('pixman').auto() or have_system or have_tools
975  pixman = dependency('pixman-1', required: get_option('pixman'), version:'>=0.21.8',
976                      method: 'pkg-config')
977endif
978
979zlib = dependency('zlib', required: true)
980
981libaio = not_found
982if not get_option('linux_aio').auto() or have_block
983  libaio = cc.find_library('aio', has_headers: ['libaio.h'],
984                           required: get_option('linux_aio'))
985endif
986
987linux_io_uring_test = '''
988  #include <liburing.h>
989  #include <linux/errqueue.h>
990
991  int main(void) { return 0; }'''
992
993linux_io_uring = not_found
994if not get_option('linux_io_uring').auto() or have_block
995  linux_io_uring = dependency('liburing', version: '>=0.3',
996                              required: get_option('linux_io_uring'),
997                              method: 'pkg-config')
998  if not cc.links(linux_io_uring_test)
999    linux_io_uring = not_found
1000  endif
1001endif
1002
1003libnfs = not_found
1004if not get_option('libnfs').auto() or have_block
1005  libnfs = dependency('libnfs', version: '>=1.9.3',
1006                      required: get_option('libnfs'),
1007                      method: 'pkg-config')
1008endif
1009
1010libattr_test = '''
1011  #include <stddef.h>
1012  #include <sys/types.h>
1013  #ifdef CONFIG_LIBATTR
1014  #include <attr/xattr.h>
1015  #else
1016  #include <sys/xattr.h>
1017  #endif
1018  int main(void) { getxattr(NULL, NULL, NULL, 0); setxattr(NULL, NULL, NULL, 0, 0); return 0; }'''
1019
1020libattr = not_found
1021have_old_libattr = false
1022if get_option('attr').allowed()
1023  if cc.links(libattr_test)
1024    libattr = declare_dependency()
1025  else
1026    libattr = cc.find_library('attr', has_headers: ['attr/xattr.h'],
1027                              required: get_option('attr'))
1028    if libattr.found() and not \
1029      cc.links(libattr_test, dependencies: libattr, args: '-DCONFIG_LIBATTR')
1030      libattr = not_found
1031      if get_option('attr').enabled()
1032        error('could not link libattr')
1033      else
1034        warning('could not link libattr, disabling')
1035      endif
1036    else
1037      have_old_libattr = libattr.found()
1038    endif
1039  endif
1040endif
1041
1042cocoa = dependency('appleframeworks', modules: ['Cocoa', 'CoreVideo'],
1043                   required: get_option('cocoa'))
1044
1045vmnet = dependency('appleframeworks', modules: 'vmnet', required: get_option('vmnet'))
1046if vmnet.found() and not cc.has_header_symbol('vmnet/vmnet.h',
1047                                              'VMNET_BRIDGED_MODE',
1048                                              dependencies: vmnet)
1049  vmnet = not_found
1050  if get_option('vmnet').enabled()
1051    error('vmnet.framework API is outdated')
1052  else
1053    warning('vmnet.framework API is outdated, disabling')
1054  endif
1055endif
1056
1057seccomp = not_found
1058seccomp_has_sysrawrc = false
1059if not get_option('seccomp').auto() or have_system or have_tools
1060  seccomp = dependency('libseccomp', version: '>=2.3.0',
1061                       required: get_option('seccomp'),
1062                       method: 'pkg-config')
1063  if seccomp.found()
1064    seccomp_has_sysrawrc = cc.has_header_symbol('seccomp.h',
1065                                                'SCMP_FLTATR_API_SYSRAWRC',
1066                                                dependencies: seccomp)
1067  endif
1068endif
1069
1070libcap_ng = not_found
1071if not get_option('cap_ng').auto() or have_system or have_tools
1072  libcap_ng = cc.find_library('cap-ng', has_headers: ['cap-ng.h'],
1073                              required: get_option('cap_ng'))
1074endif
1075if libcap_ng.found() and not cc.links('''
1076   #include <cap-ng.h>
1077   int main(void)
1078   {
1079     capng_capability_to_name(CAPNG_EFFECTIVE);
1080     return 0;
1081   }''', dependencies: libcap_ng)
1082  libcap_ng = not_found
1083  if get_option('cap_ng').enabled()
1084    error('could not link libcap-ng')
1085  else
1086    warning('could not link libcap-ng, disabling')
1087  endif
1088endif
1089
1090if get_option('xkbcommon').auto() and not have_system and not have_tools
1091  xkbcommon = not_found
1092else
1093  xkbcommon = dependency('xkbcommon', required: get_option('xkbcommon'),
1094                         method: 'pkg-config')
1095endif
1096
1097slirp = not_found
1098if not get_option('slirp').auto() or have_system
1099  slirp = dependency('slirp', required: get_option('slirp'),
1100                     method: 'pkg-config')
1101  # slirp < 4.7 is incompatible with CFI support in QEMU.  This is because
1102  # it passes function pointers within libslirp as callbacks for timers.
1103  # When using a system-wide shared libslirp, the type information for the
1104  # callback is missing and the timer call produces a false positive with CFI.
1105  # Do not use the "version" keyword argument to produce a better error.
1106  # with control-flow integrity.
1107  if get_option('cfi') and slirp.found() and slirp.version().version_compare('<4.7')
1108    if get_option('slirp').enabled()
1109      error('Control-Flow Integrity requires libslirp 4.7.')
1110    else
1111      warning('Cannot use libslirp since Control-Flow Integrity requires libslirp >= 4.7.')
1112      slirp = not_found
1113    endif
1114  endif
1115endif
1116
1117vde = not_found
1118if not get_option('vde').auto() or have_system or have_tools
1119  vde = cc.find_library('vdeplug', has_headers: ['libvdeplug.h'],
1120                           required: get_option('vde'))
1121endif
1122if vde.found() and not cc.links('''
1123   #include <libvdeplug.h>
1124   int main(void)
1125   {
1126     struct vde_open_args a = {0, 0, 0};
1127     char s[] = "";
1128     vde_open(s, s, &a);
1129     return 0;
1130   }''', dependencies: vde)
1131  vde = not_found
1132  if get_option('cap_ng').enabled()
1133    error('could not link libvdeplug')
1134  else
1135    warning('could not link libvdeplug, disabling')
1136  endif
1137endif
1138
1139pulse = not_found
1140if not get_option('pa').auto() or (host_os == 'linux' and have_system)
1141  pulse = dependency('libpulse', required: get_option('pa'),
1142                     method: 'pkg-config')
1143endif
1144alsa = not_found
1145if not get_option('alsa').auto() or (host_os == 'linux' and have_system)
1146  alsa = dependency('alsa', required: get_option('alsa'),
1147                    method: 'pkg-config')
1148endif
1149jack = not_found
1150if not get_option('jack').auto() or have_system
1151  jack = dependency('jack', required: get_option('jack'),
1152                    method: 'pkg-config')
1153endif
1154pipewire = not_found
1155if not get_option('pipewire').auto() or (host_os == 'linux' and have_system)
1156  pipewire = dependency('libpipewire-0.3', version: '>=0.3.60',
1157                    required: get_option('pipewire'),
1158                    method: 'pkg-config')
1159endif
1160sndio = not_found
1161if not get_option('sndio').auto() or have_system
1162  sndio = dependency('sndio', required: get_option('sndio'),
1163                    method: 'pkg-config')
1164endif
1165
1166spice_protocol = not_found
1167if not get_option('spice_protocol').auto() or have_system
1168  spice_protocol = dependency('spice-protocol', version: '>=0.14.0',
1169                              required: get_option('spice_protocol'),
1170                              method: 'pkg-config')
1171endif
1172spice = not_found
1173if get_option('spice') \
1174             .disable_auto_if(not have_system) \
1175             .require(pixman.found(),
1176                      error_message: 'cannot enable SPICE if pixman is not available') \
1177             .allowed()
1178  spice = dependency('spice-server', version: '>=0.14.0',
1179                     required: get_option('spice'),
1180                     method: 'pkg-config')
1181endif
1182spice_headers = spice.partial_dependency(compile_args: true, includes: true)
1183
1184rt = cc.find_library('rt', required: false)
1185
1186libiscsi = not_found
1187if not get_option('libiscsi').auto() or have_block
1188  libiscsi = dependency('libiscsi', version: '>=1.9.0',
1189                         required: get_option('libiscsi'),
1190                         method: 'pkg-config')
1191endif
1192zstd = not_found
1193if not get_option('zstd').auto() or have_block
1194  zstd = dependency('libzstd', version: '>=1.4.0',
1195                    required: get_option('zstd'),
1196                    method: 'pkg-config')
1197endif
1198virgl = not_found
1199
1200have_vhost_user_gpu = have_tools and host_os == 'linux' and pixman.found()
1201if not get_option('virglrenderer').auto() or have_system or have_vhost_user_gpu
1202  virgl = dependency('virglrenderer',
1203                     method: 'pkg-config',
1204                     required: get_option('virglrenderer'))
1205endif
1206rutabaga = not_found
1207if not get_option('rutabaga_gfx').auto() or have_system or have_vhost_user_gpu
1208  rutabaga = dependency('rutabaga_gfx_ffi',
1209                         method: 'pkg-config',
1210                         required: get_option('rutabaga_gfx'))
1211endif
1212blkio = not_found
1213if not get_option('blkio').auto() or have_block
1214  blkio = dependency('blkio',
1215                     method: 'pkg-config',
1216                     required: get_option('blkio'))
1217endif
1218curl = not_found
1219if not get_option('curl').auto() or have_block
1220  curl = dependency('libcurl', version: '>=7.29.0',
1221                    method: 'pkg-config',
1222                    required: get_option('curl'))
1223endif
1224libudev = not_found
1225if host_os == 'linux' and (have_system or have_tools)
1226  libudev = dependency('libudev',
1227                       method: 'pkg-config',
1228                       required: get_option('libudev'))
1229endif
1230
1231mpathlibs = [libudev]
1232mpathpersist = not_found
1233if host_os == 'linux' and have_tools and get_option('mpath').allowed()
1234  mpath_test_source = '''
1235    #include <libudev.h>
1236    #include <mpath_persist.h>
1237    unsigned mpath_mx_alloc_len = 1024;
1238    int logsink;
1239    static struct config *multipath_conf;
1240    extern struct udev *udev;
1241    extern struct config *get_multipath_config(void);
1242    extern void put_multipath_config(struct config *conf);
1243    struct udev *udev;
1244    struct config *get_multipath_config(void) { return multipath_conf; }
1245    void put_multipath_config(struct config *conf) { }
1246    int main(void) {
1247        udev = udev_new();
1248        multipath_conf = mpath_lib_init();
1249        return 0;
1250    }'''
1251  libmpathpersist = cc.find_library('mpathpersist',
1252                                    required: get_option('mpath'))
1253  if libmpathpersist.found()
1254    mpathlibs += libmpathpersist
1255    if get_option('prefer_static')
1256      mpathlibs += cc.find_library('devmapper',
1257                                     required: get_option('mpath'))
1258    endif
1259    mpathlibs += cc.find_library('multipath',
1260                                 required: get_option('mpath'))
1261    foreach lib: mpathlibs
1262      if not lib.found()
1263        mpathlibs = []
1264        break
1265      endif
1266    endforeach
1267    if mpathlibs.length() == 0
1268      msg = 'Dependencies missing for libmpathpersist'
1269    elif cc.links(mpath_test_source, dependencies: mpathlibs)
1270      mpathpersist = declare_dependency(dependencies: mpathlibs)
1271    else
1272      msg = 'Cannot detect libmpathpersist API'
1273    endif
1274    if not mpathpersist.found()
1275      if get_option('mpath').enabled()
1276        error(msg)
1277      else
1278        warning(msg + ', disabling')
1279      endif
1280    endif
1281  endif
1282endif
1283
1284iconv = not_found
1285curses = not_found
1286if have_system and get_option('curses').allowed()
1287  curses_test = '''
1288    #if defined(__APPLE__) || defined(__OpenBSD__)
1289    #define _XOPEN_SOURCE_EXTENDED 1
1290    #endif
1291    #include <locale.h>
1292    #include <curses.h>
1293    #include <wchar.h>
1294    int main(void) {
1295      wchar_t wch = L'w';
1296      setlocale(LC_ALL, "");
1297      resize_term(0, 0);
1298      addwstr(L"wide chars\n");
1299      addnwstr(&wch, 1);
1300      add_wch(WACS_DEGREE);
1301      return 0;
1302    }'''
1303
1304  curses_dep_list = host_os == 'windows' ? ['ncurses', 'ncursesw'] : ['ncursesw']
1305  curses = dependency(curses_dep_list,
1306                      required: false,
1307                      method: 'pkg-config')
1308  msg = get_option('curses').enabled() ? 'curses library not found' : ''
1309  curses_compile_args = ['-DNCURSES_WIDECHAR=1']
1310  if curses.found()
1311    if cc.links(curses_test, args: curses_compile_args, dependencies: [curses])
1312      curses = declare_dependency(compile_args: curses_compile_args, dependencies: [curses],
1313                                  version: curses.version())
1314    else
1315      msg = 'curses package not usable'
1316      curses = not_found
1317    endif
1318  endif
1319  if not curses.found()
1320    has_curses_h = cc.has_header('curses.h', args: curses_compile_args)
1321    if host_os != 'windows' and not has_curses_h
1322      message('Trying with /usr/include/ncursesw')
1323      curses_compile_args += ['-I/usr/include/ncursesw']
1324      has_curses_h = cc.has_header('curses.h', args: curses_compile_args)
1325    endif
1326    if has_curses_h
1327      curses_libname_list = (host_os == 'windows' ? ['pdcurses'] : ['ncursesw', 'cursesw'])
1328      foreach curses_libname : curses_libname_list
1329        libcurses = cc.find_library(curses_libname,
1330                                    required: false)
1331        if libcurses.found()
1332          if cc.links(curses_test, args: curses_compile_args, dependencies: libcurses)
1333            curses = declare_dependency(compile_args: curses_compile_args,
1334                                        dependencies: [libcurses])
1335            break
1336          else
1337            msg = 'curses library not usable'
1338          endif
1339        endif
1340      endforeach
1341    endif
1342  endif
1343  if get_option('iconv').allowed()
1344    foreach link_args : [ ['-liconv'], [] ]
1345      # Programs will be linked with glib and this will bring in libiconv on FreeBSD.
1346      # We need to use libiconv if available because mixing libiconv's headers with
1347      # the system libc does not work.
1348      # However, without adding glib to the dependencies -L/usr/local/lib will not be
1349      # included in the command line and libiconv will not be found.
1350      if cc.links('''
1351        #include <iconv.h>
1352        int main(void) {
1353          iconv_t conv = iconv_open("WCHAR_T", "UCS-2");
1354          return conv != (iconv_t) -1;
1355        }''', args: link_args, dependencies: glib)
1356        iconv = declare_dependency(link_args: link_args, dependencies: glib)
1357        break
1358      endif
1359    endforeach
1360  endif
1361  if curses.found() and not iconv.found()
1362    if get_option('iconv').enabled()
1363      error('iconv not available')
1364    endif
1365    msg = 'iconv required for curses UI but not available'
1366    curses = not_found
1367  endif
1368  if not curses.found() and msg != ''
1369    if get_option('curses').enabled()
1370      error(msg)
1371    else
1372      warning(msg + ', disabling')
1373    endif
1374  endif
1375endif
1376
1377brlapi = not_found
1378if not get_option('brlapi').auto() or have_system
1379  brlapi = cc.find_library('brlapi', has_headers: ['brlapi.h'],
1380                         required: get_option('brlapi'))
1381  if brlapi.found() and not cc.links('''
1382     #include <brlapi.h>
1383     #include <stddef.h>
1384     int main(void) { return brlapi__openConnection (NULL, NULL, NULL); }''', dependencies: brlapi)
1385    brlapi = not_found
1386    if get_option('brlapi').enabled()
1387      error('could not link brlapi')
1388    else
1389      warning('could not link brlapi, disabling')
1390    endif
1391  endif
1392endif
1393
1394sdl = not_found
1395if not get_option('sdl').auto() or have_system
1396  sdl = dependency('sdl2', required: get_option('sdl'))
1397  sdl_image = not_found
1398endif
1399if sdl.found()
1400  # Some versions of SDL have problems with -Wundef
1401  if not cc.compiles('''
1402                     #include <SDL.h>
1403                     #include <SDL_syswm.h>
1404                     int main(int argc, char *argv[]) { return 0; }
1405                     ''', dependencies: sdl, args: '-Werror=undef')
1406    sdl = declare_dependency(compile_args: '-Wno-undef',
1407                             dependencies: sdl,
1408                             version: sdl.version())
1409  endif
1410  sdl_image = dependency('SDL2_image', required: get_option('sdl_image'),
1411                         method: 'pkg-config')
1412else
1413  if get_option('sdl_image').enabled()
1414    error('sdl-image required, but SDL was @0@'.format(
1415          get_option('sdl').disabled() ? 'disabled' : 'not found'))
1416  endif
1417  sdl_image = not_found
1418endif
1419
1420rbd = not_found
1421if not get_option('rbd').auto() or have_block
1422  librados = cc.find_library('rados', required: get_option('rbd'))
1423  librbd = cc.find_library('rbd', has_headers: ['rbd/librbd.h'],
1424                           required: get_option('rbd'))
1425  if librados.found() and librbd.found()
1426    if cc.links('''
1427      #include <stdio.h>
1428      #include <rbd/librbd.h>
1429      int main(void) {
1430        rados_t cluster;
1431        rados_create(&cluster, NULL);
1432        #if LIBRBD_VERSION_CODE < LIBRBD_VERSION(1, 12, 0)
1433        #error
1434        #endif
1435        return 0;
1436      }''', dependencies: [librbd, librados])
1437      rbd = declare_dependency(dependencies: [librbd, librados])
1438    elif get_option('rbd').enabled()
1439      error('librbd >= 1.12.0 required')
1440    else
1441      warning('librbd >= 1.12.0 not found, disabling')
1442    endif
1443  endif
1444endif
1445
1446glusterfs = not_found
1447glusterfs_ftruncate_has_stat = false
1448glusterfs_iocb_has_stat = false
1449if not get_option('glusterfs').auto() or have_block
1450  glusterfs = dependency('glusterfs-api', version: '>=3',
1451                         required: get_option('glusterfs'),
1452                         method: 'pkg-config')
1453  if glusterfs.found()
1454    glusterfs_ftruncate_has_stat = cc.links('''
1455      #include <glusterfs/api/glfs.h>
1456
1457      int
1458      main(void)
1459      {
1460          /* new glfs_ftruncate() passes two additional args */
1461          return glfs_ftruncate(NULL, 0, NULL, NULL);
1462      }
1463    ''', dependencies: glusterfs)
1464    glusterfs_iocb_has_stat = cc.links('''
1465      #include <glusterfs/api/glfs.h>
1466
1467      /* new glfs_io_cbk() passes two additional glfs_stat structs */
1468      static void
1469      glusterfs_iocb(glfs_fd_t *fd, ssize_t ret, struct glfs_stat *prestat, struct glfs_stat *poststat, void *data)
1470      {}
1471
1472      int
1473      main(void)
1474      {
1475          glfs_io_cbk iocb = &glusterfs_iocb;
1476          iocb(NULL, 0 , NULL, NULL, NULL);
1477          return 0;
1478      }
1479    ''', dependencies: glusterfs)
1480  endif
1481endif
1482
1483hv_balloon = false
1484if get_option('hv_balloon').allowed() and have_system
1485  if cc.links('''
1486    #include <string.h>
1487    #include <gmodule.h>
1488    int main(void) {
1489        GTree *tree;
1490
1491        tree = g_tree_new((GCompareFunc)strcmp);
1492        (void)g_tree_node_first(tree);
1493        g_tree_destroy(tree);
1494        return 0;
1495    }
1496  ''', dependencies: glib)
1497    hv_balloon = true
1498  else
1499    if get_option('hv_balloon').enabled()
1500      error('could not enable hv-balloon, update your glib')
1501    else
1502      warning('could not find glib support for hv-balloon, disabling')
1503    endif
1504  endif
1505endif
1506
1507libssh = not_found
1508if not get_option('libssh').auto() or have_block
1509  libssh = dependency('libssh', version: '>=0.8.7',
1510                    method: 'pkg-config',
1511                    required: get_option('libssh'))
1512endif
1513
1514libbzip2 = not_found
1515if not get_option('bzip2').auto() or have_block
1516  libbzip2 = cc.find_library('bz2', has_headers: ['bzlib.h'],
1517                             required: get_option('bzip2'))
1518  if libbzip2.found() and not cc.links('''
1519     #include <bzlib.h>
1520     int main(void) { BZ2_bzlibVersion(); return 0; }''', dependencies: libbzip2)
1521    libbzip2 = not_found
1522    if get_option('bzip2').enabled()
1523      error('could not link libbzip2')
1524    else
1525      warning('could not link libbzip2, disabling')
1526    endif
1527  endif
1528endif
1529
1530liblzfse = not_found
1531if not get_option('lzfse').auto() or have_block
1532  liblzfse = cc.find_library('lzfse', has_headers: ['lzfse.h'],
1533                             required: get_option('lzfse'))
1534endif
1535if liblzfse.found() and not cc.links('''
1536   #include <lzfse.h>
1537   int main(void) { lzfse_decode_scratch_size(); return 0; }''', dependencies: liblzfse)
1538  liblzfse = not_found
1539  if get_option('lzfse').enabled()
1540    error('could not link liblzfse')
1541  else
1542    warning('could not link liblzfse, disabling')
1543  endif
1544endif
1545
1546oss = not_found
1547if get_option('oss').allowed() and have_system
1548  if not cc.has_header('sys/soundcard.h')
1549    # not found
1550  elif host_os == 'netbsd'
1551    oss = cc.find_library('ossaudio', required: get_option('oss'))
1552  else
1553    oss = declare_dependency()
1554  endif
1555
1556  if not oss.found()
1557    if get_option('oss').enabled()
1558      error('OSS not found')
1559    endif
1560  endif
1561endif
1562dsound = not_found
1563if not get_option('dsound').auto() or (host_os == 'windows' and have_system)
1564  if cc.has_header('dsound.h')
1565    dsound = declare_dependency(link_args: ['-lole32', '-ldxguid'])
1566  endif
1567
1568  if not dsound.found()
1569    if get_option('dsound').enabled()
1570      error('DirectSound not found')
1571    endif
1572  endif
1573endif
1574
1575coreaudio = not_found
1576if not get_option('coreaudio').auto() or (host_os == 'darwin' and have_system)
1577  coreaudio = dependency('appleframeworks', modules: 'CoreAudio',
1578                         required: get_option('coreaudio'))
1579endif
1580
1581opengl = not_found
1582if not get_option('opengl').auto() or have_system or have_vhost_user_gpu
1583  epoxy = dependency('epoxy', method: 'pkg-config',
1584                      required: get_option('opengl'))
1585  if cc.has_header('epoxy/egl.h', dependencies: epoxy)
1586    opengl = epoxy
1587  elif get_option('opengl').enabled()
1588    error('epoxy/egl.h not found')
1589  endif
1590endif
1591gbm = not_found
1592if (have_system or have_tools) and (virgl.found() or opengl.found())
1593  gbm = dependency('gbm', method: 'pkg-config', required: false)
1594endif
1595have_vhost_user_gpu = have_vhost_user_gpu and virgl.found() and opengl.found() and gbm.found()
1596
1597gnutls = not_found
1598gnutls_crypto = not_found
1599if get_option('gnutls').enabled() or (get_option('gnutls').auto() and have_system)
1600  # For general TLS support our min gnutls matches
1601  # that implied by our platform support matrix
1602  #
1603  # For the crypto backends, we look for a newer
1604  # gnutls:
1605  #
1606  #   Version 3.6.8  is needed to get XTS
1607  #   Version 3.6.13 is needed to get PBKDF
1608  #   Version 3.6.14 is needed to get HW accelerated XTS
1609  #
1610  # If newer enough gnutls isn't available, we can
1611  # still use a different crypto backend to satisfy
1612  # the platform support requirements
1613  gnutls_crypto = dependency('gnutls', version: '>=3.6.14',
1614                             method: 'pkg-config',
1615                             required: false)
1616  if gnutls_crypto.found()
1617    gnutls = gnutls_crypto
1618  else
1619    # Our min version if all we need is TLS
1620    gnutls = dependency('gnutls', version: '>=3.5.18',
1621                        method: 'pkg-config',
1622                        required: get_option('gnutls'))
1623  endif
1624endif
1625
1626# We prefer use of gnutls for crypto, unless the options
1627# explicitly asked for nettle or gcrypt.
1628#
1629# If gnutls isn't available for crypto, then we'll prefer
1630# gcrypt over nettle for performance reasons.
1631gcrypt = not_found
1632nettle = not_found
1633hogweed = not_found
1634xts = 'none'
1635
1636if get_option('nettle').enabled() and get_option('gcrypt').enabled()
1637  error('Only one of gcrypt & nettle can be enabled')
1638endif
1639
1640# Explicit nettle/gcrypt request, so ignore gnutls for crypto
1641if get_option('nettle').enabled() or get_option('gcrypt').enabled()
1642  gnutls_crypto = not_found
1643endif
1644
1645if not gnutls_crypto.found()
1646  if (not get_option('gcrypt').auto() or have_system) and not get_option('nettle').enabled()
1647    gcrypt = dependency('libgcrypt', version: '>=1.8',
1648                        method: 'config-tool',
1649                        required: get_option('gcrypt'))
1650    # Debian has removed -lgpg-error from libgcrypt-config
1651    # as it "spreads unnecessary dependencies" which in
1652    # turn breaks static builds...
1653    if gcrypt.found() and get_option('prefer_static')
1654      gcrypt = declare_dependency(dependencies:
1655        [gcrypt,
1656         cc.find_library('gpg-error', required: true)],
1657        version: gcrypt.version())
1658    endif
1659  endif
1660  if (not get_option('nettle').auto() or have_system) and not gcrypt.found()
1661    nettle = dependency('nettle', version: '>=3.4',
1662                        method: 'pkg-config',
1663                        required: get_option('nettle'))
1664    if nettle.found() and not cc.has_header('nettle/xts.h', dependencies: nettle)
1665      xts = 'private'
1666    endif
1667  endif
1668endif
1669
1670capstone = not_found
1671if not get_option('capstone').auto() or have_system or have_user
1672  capstone = dependency('capstone', version: '>=3.0.5',
1673                        method: 'pkg-config',
1674                        required: get_option('capstone'))
1675
1676  # Some versions of capstone have broken pkg-config file
1677  # that reports a wrong -I path, causing the #include to
1678  # fail later. If the system has such a broken version
1679  # do not use it.
1680  if capstone.found() and not cc.compiles('#include <capstone.h>',
1681                                          dependencies: [capstone])
1682    capstone = not_found
1683    if get_option('capstone').enabled()
1684      error('capstone requested, but it does not appear to work')
1685    endif
1686  endif
1687endif
1688
1689gmp = dependency('gmp', required: false, method: 'pkg-config')
1690if nettle.found() and gmp.found()
1691  hogweed = dependency('hogweed', version: '>=3.4',
1692                       method: 'pkg-config',
1693                       required: get_option('nettle'))
1694endif
1695
1696
1697gtk = not_found
1698gtkx11 = not_found
1699vte = not_found
1700have_gtk_clipboard = get_option('gtk_clipboard').enabled()
1701
1702if get_option('gtk') \
1703             .disable_auto_if(not have_system) \
1704             .require(pixman.found(),
1705                      error_message: 'cannot enable GTK if pixman is not available') \
1706             .allowed()
1707  gtk = dependency('gtk+-3.0', version: '>=3.22.0',
1708                   method: 'pkg-config',
1709                   required: get_option('gtk'))
1710  if gtk.found()
1711    gtkx11 = dependency('gtk+-x11-3.0', version: '>=3.22.0',
1712                        method: 'pkg-config',
1713                        required: false)
1714    gtk = declare_dependency(dependencies: [gtk, gtkx11],
1715                             version: gtk.version())
1716
1717    if not get_option('vte').auto() or have_system
1718      vte = dependency('vte-2.91',
1719                       method: 'pkg-config',
1720                       required: get_option('vte'))
1721    endif
1722  elif have_gtk_clipboard
1723    error('GTK clipboard requested, but GTK not found')
1724  endif
1725endif
1726
1727x11 = not_found
1728if gtkx11.found()
1729  x11 = dependency('x11', method: 'pkg-config', required: gtkx11.found())
1730endif
1731png = not_found
1732if get_option('png').allowed() and have_system
1733   png = dependency('libpng', version: '>=1.6.34', required: get_option('png'),
1734                    method: 'pkg-config')
1735endif
1736vnc = not_found
1737jpeg = not_found
1738sasl = not_found
1739if get_option('vnc') \
1740             .disable_auto_if(not have_system) \
1741             .require(pixman.found(),
1742                      error_message: 'cannot enable VNC if pixman is not available') \
1743             .allowed()
1744  vnc = declare_dependency() # dummy dependency
1745  jpeg = dependency('libjpeg', required: get_option('vnc_jpeg'),
1746                    method: 'pkg-config')
1747  sasl = cc.find_library('sasl2', has_headers: ['sasl/sasl.h'],
1748                         required: get_option('vnc_sasl'))
1749  if sasl.found()
1750    sasl = declare_dependency(dependencies: sasl,
1751                              compile_args: '-DSTRUCT_IOVEC_DEFINED')
1752  endif
1753endif
1754
1755pam = not_found
1756if not get_option('auth_pam').auto() or have_system
1757  pam = cc.find_library('pam', has_headers: ['security/pam_appl.h'],
1758                        required: get_option('auth_pam'))
1759endif
1760if pam.found() and not cc.links('''
1761   #include <stddef.h>
1762   #include <security/pam_appl.h>
1763   int main(void) {
1764     const char *service_name = "qemu";
1765     const char *user = "frank";
1766     const struct pam_conv pam_conv = { 0 };
1767     pam_handle_t *pamh = NULL;
1768     pam_start(service_name, user, &pam_conv, &pamh);
1769     return 0;
1770   }''', dependencies: pam)
1771  pam = not_found
1772  if get_option('auth_pam').enabled()
1773    error('could not link libpam')
1774  else
1775    warning('could not link libpam, disabling')
1776  endif
1777endif
1778
1779snappy = not_found
1780if not get_option('snappy').auto() or have_system
1781  snappy = cc.find_library('snappy', has_headers: ['snappy-c.h'],
1782                           required: get_option('snappy'))
1783endif
1784if snappy.found() and not cc.links('''
1785   #include <snappy-c.h>
1786   int main(void) { snappy_max_compressed_length(4096); return 0; }''', dependencies: snappy)
1787  snappy = not_found
1788  if get_option('snappy').enabled()
1789    error('could not link libsnappy')
1790  else
1791    warning('could not link libsnappy, disabling')
1792  endif
1793endif
1794
1795lzo = not_found
1796if not get_option('lzo').auto() or have_system
1797  lzo = cc.find_library('lzo2', has_headers: ['lzo/lzo1x.h'],
1798                        required: get_option('lzo'))
1799endif
1800if lzo.found() and not cc.links('''
1801   #include <lzo/lzo1x.h>
1802   int main(void) { lzo_version(); return 0; }''', dependencies: lzo)
1803  lzo = not_found
1804  if get_option('lzo').enabled()
1805    error('could not link liblzo2')
1806  else
1807    warning('could not link liblzo2, disabling')
1808  endif
1809endif
1810
1811numa = not_found
1812if not get_option('numa').auto() or have_system or have_tools
1813  numa = cc.find_library('numa', has_headers: ['numa.h'],
1814                              required: get_option('numa'))
1815endif
1816if numa.found() and not cc.links('''
1817   #include <numa.h>
1818   int main(void) { return numa_available(); }
1819   ''', dependencies: numa)
1820  numa = not_found
1821  if get_option('numa').enabled()
1822    error('could not link numa')
1823  else
1824    warning('could not link numa, disabling')
1825  endif
1826endif
1827
1828rdma = not_found
1829if not get_option('rdma').auto() or have_system
1830  libumad = cc.find_library('ibumad', required: get_option('rdma'))
1831  rdma_libs = [cc.find_library('rdmacm', has_headers: ['rdma/rdma_cma.h'],
1832                               required: get_option('rdma')),
1833               cc.find_library('ibverbs', required: get_option('rdma')),
1834               libumad]
1835  rdma = declare_dependency(dependencies: rdma_libs)
1836  foreach lib: rdma_libs
1837    if not lib.found()
1838      rdma = not_found
1839    endif
1840  endforeach
1841endif
1842
1843cacard = not_found
1844if not get_option('smartcard').auto() or have_system
1845  cacard = dependency('libcacard', required: get_option('smartcard'),
1846                      version: '>=2.5.1', method: 'pkg-config')
1847endif
1848u2f = not_found
1849if not get_option('u2f').auto() or have_system
1850  u2f = dependency('u2f-emu', required: get_option('u2f'),
1851                   method: 'pkg-config')
1852endif
1853canokey = not_found
1854if not get_option('canokey').auto() or have_system
1855  canokey = dependency('canokey-qemu', required: get_option('canokey'),
1856                   method: 'pkg-config')
1857endif
1858usbredir = not_found
1859if not get_option('usb_redir').auto() or have_system
1860  usbredir = dependency('libusbredirparser-0.5', required: get_option('usb_redir'),
1861                        version: '>=0.6', method: 'pkg-config')
1862endif
1863libusb = not_found
1864if not get_option('libusb').auto() or have_system
1865  libusb = dependency('libusb-1.0', required: get_option('libusb'),
1866                      version: '>=1.0.13', method: 'pkg-config')
1867endif
1868
1869libpmem = not_found
1870if not get_option('libpmem').auto() or have_system
1871  libpmem = dependency('libpmem', required: get_option('libpmem'),
1872                       method: 'pkg-config')
1873endif
1874libdaxctl = not_found
1875if not get_option('libdaxctl').auto() or have_system
1876  libdaxctl = dependency('libdaxctl', required: get_option('libdaxctl'),
1877                         version: '>=57', method: 'pkg-config')
1878endif
1879tasn1 = not_found
1880if gnutls.found()
1881  tasn1 = dependency('libtasn1',
1882                     method: 'pkg-config')
1883endif
1884keyutils = not_found
1885if not get_option('libkeyutils').auto() or have_block
1886  keyutils = dependency('libkeyutils', required: get_option('libkeyutils'),
1887                        method: 'pkg-config')
1888endif
1889
1890has_gettid = cc.has_function('gettid')
1891
1892# libselinux
1893selinux = dependency('libselinux',
1894                     required: get_option('selinux'),
1895                     method: 'pkg-config')
1896
1897# Malloc tests
1898
1899malloc = []
1900if get_option('malloc') == 'system'
1901  has_malloc_trim = \
1902    get_option('malloc_trim').allowed() and \
1903    cc.has_function('malloc_trim', prefix: '#include <malloc.h>')
1904else
1905  has_malloc_trim = false
1906  malloc = cc.find_library(get_option('malloc'), required: true)
1907endif
1908if not has_malloc_trim and get_option('malloc_trim').enabled()
1909  if get_option('malloc') == 'system'
1910    error('malloc_trim not available on this platform.')
1911  else
1912    error('malloc_trim not available with non-libc memory allocator')
1913  endif
1914endif
1915
1916gnu_source_prefix = '''
1917  #ifndef _GNU_SOURCE
1918  #define _GNU_SOURCE
1919  #endif
1920'''
1921
1922# Check whether the glibc provides STATX_BASIC_STATS
1923
1924has_statx = cc.has_header_symbol('sys/stat.h', 'STATX_BASIC_STATS', prefix: gnu_source_prefix)
1925
1926# Check whether statx() provides mount ID information
1927
1928has_statx_mnt_id = cc.has_header_symbol('sys/stat.h', 'STATX_MNT_ID', prefix: gnu_source_prefix)
1929
1930have_vhost_user_blk_server = get_option('vhost_user_blk_server') \
1931  .require(host_os == 'linux',
1932           error_message: 'vhost_user_blk_server requires linux') \
1933  .require(have_vhost_user,
1934           error_message: 'vhost_user_blk_server requires vhost-user support') \
1935  .disable_auto_if(not have_tools and not have_system) \
1936  .allowed()
1937
1938if get_option('fuse').disabled() and get_option('fuse_lseek').enabled()
1939  error('Cannot enable fuse-lseek while fuse is disabled')
1940endif
1941
1942fuse = dependency('fuse3', required: get_option('fuse'),
1943                  version: '>=3.1', method: 'pkg-config')
1944
1945fuse_lseek = not_found
1946if get_option('fuse_lseek').allowed()
1947  if fuse.version().version_compare('>=3.8')
1948    # Dummy dependency
1949    fuse_lseek = declare_dependency()
1950  elif get_option('fuse_lseek').enabled()
1951    if fuse.found()
1952      error('fuse-lseek requires libfuse >=3.8, found ' + fuse.version())
1953    else
1954      error('fuse-lseek requires libfuse, which was not found')
1955    endif
1956  endif
1957endif
1958
1959have_libvduse = (host_os == 'linux')
1960if get_option('libvduse').enabled()
1961    if host_os != 'linux'
1962        error('libvduse requires linux')
1963    endif
1964elif get_option('libvduse').disabled()
1965    have_libvduse = false
1966endif
1967
1968have_vduse_blk_export = (have_libvduse and host_os == 'linux')
1969if get_option('vduse_blk_export').enabled()
1970    if host_os != 'linux'
1971        error('vduse_blk_export requires linux')
1972    elif not have_libvduse
1973        error('vduse_blk_export requires libvduse support')
1974    endif
1975elif get_option('vduse_blk_export').disabled()
1976    have_vduse_blk_export = false
1977endif
1978
1979# libbpf
1980libbpf = dependency('libbpf', required: get_option('bpf'), method: 'pkg-config')
1981if libbpf.found() and not cc.links('''
1982   #include <bpf/libbpf.h>
1983   int main(void)
1984   {
1985     bpf_object__destroy_skeleton(NULL);
1986     return 0;
1987   }''', dependencies: libbpf)
1988  libbpf = not_found
1989  if get_option('bpf').enabled()
1990    error('libbpf skeleton test failed')
1991  else
1992    warning('libbpf skeleton test failed, disabling')
1993  endif
1994endif
1995
1996# libxdp
1997libxdp = not_found
1998if not get_option('af_xdp').auto() or have_system
1999    libxdp = dependency('libxdp', required: get_option('af_xdp'),
2000                        version: '>=1.4.0', method: 'pkg-config')
2001endif
2002
2003# libdw
2004libdw = not_found
2005if not get_option('libdw').auto() or \
2006        (not get_option('prefer_static') and (have_system or have_user))
2007    libdw = dependency('libdw',
2008                       method: 'pkg-config',
2009                       required: get_option('libdw'))
2010endif
2011
2012#################
2013# config-host.h #
2014#################
2015
2016config_host_data = configuration_data()
2017
2018audio_drivers_selected = []
2019if have_system
2020  audio_drivers_available = {
2021    'alsa': alsa.found(),
2022    'coreaudio': coreaudio.found(),
2023    'dsound': dsound.found(),
2024    'jack': jack.found(),
2025    'oss': oss.found(),
2026    'pa': pulse.found(),
2027    'pipewire': pipewire.found(),
2028    'sdl': sdl.found(),
2029    'sndio': sndio.found(),
2030  }
2031  foreach k, v: audio_drivers_available
2032    config_host_data.set('CONFIG_AUDIO_' + k.to_upper(), v)
2033  endforeach
2034
2035  # Default to native drivers first, OSS second, SDL third
2036  audio_drivers_priority = \
2037    [ 'pa', 'coreaudio', 'dsound', 'sndio', 'oss' ] + \
2038    (host_os == 'linux' ? [] : [ 'sdl' ])
2039  audio_drivers_default = []
2040  foreach k: audio_drivers_priority
2041    if audio_drivers_available[k]
2042      audio_drivers_default += k
2043    endif
2044  endforeach
2045
2046  foreach k: get_option('audio_drv_list')
2047    if k == 'default'
2048      audio_drivers_selected += audio_drivers_default
2049    elif not audio_drivers_available[k]
2050      error('Audio driver "@0@" not available.'.format(k))
2051    else
2052      audio_drivers_selected += k
2053    endif
2054  endforeach
2055endif
2056config_host_data.set('CONFIG_AUDIO_DRIVERS',
2057                     '"' + '", "'.join(audio_drivers_selected) + '", ')
2058
2059have_host_block_device = (host_os != 'darwin' or
2060    cc.has_header('IOKit/storage/IOMedia.h'))
2061
2062dbus_display = get_option('dbus_display') \
2063  .require(gio.version().version_compare('>=2.64'),
2064           error_message: '-display dbus requires glib>=2.64') \
2065  .require(gdbus_codegen.found(),
2066           error_message: gdbus_codegen_error.format('-display dbus')) \
2067  .allowed()
2068
2069have_virtfs = get_option('virtfs') \
2070    .require(host_os == 'linux' or host_os == 'darwin',
2071             error_message: 'virtio-9p (virtfs) requires Linux or macOS') \
2072    .require(host_os == 'linux' or cc.has_function('pthread_fchdir_np'),
2073             error_message: 'virtio-9p (virtfs) on macOS requires the presence of pthread_fchdir_np') \
2074    .require(host_os == 'darwin' or libattr.found(),
2075             error_message: 'virtio-9p (virtfs) on Linux requires libattr-devel') \
2076    .disable_auto_if(not have_tools and not have_system) \
2077    .allowed()
2078
2079have_virtfs_proxy_helper = get_option('virtfs_proxy_helper') \
2080    .require(host_os != 'darwin', error_message: 'the virtfs proxy helper is incompatible with macOS') \
2081    .require(have_virtfs, error_message: 'the virtfs proxy helper requires that virtfs is enabled') \
2082    .disable_auto_if(not have_tools) \
2083    .require(libcap_ng.found(), error_message: 'the virtfs proxy helper requires libcap-ng') \
2084    .allowed()
2085
2086if get_option('block_drv_ro_whitelist') == ''
2087  config_host_data.set('CONFIG_BDRV_RO_WHITELIST', '')
2088else
2089  config_host_data.set('CONFIG_BDRV_RO_WHITELIST',
2090        '"' + get_option('block_drv_ro_whitelist').replace(',', '", "') + '", ')
2091endif
2092if get_option('block_drv_rw_whitelist') == ''
2093  config_host_data.set('CONFIG_BDRV_RW_WHITELIST', '')
2094else
2095  config_host_data.set('CONFIG_BDRV_RW_WHITELIST',
2096        '"' + get_option('block_drv_rw_whitelist').replace(',', '", "') + '", ')
2097endif
2098
2099foreach k : get_option('trace_backends')
2100  config_host_data.set('CONFIG_TRACE_' + k.to_upper(), true)
2101endforeach
2102config_host_data.set_quoted('CONFIG_TRACE_FILE', get_option('trace_file'))
2103config_host_data.set_quoted('CONFIG_TLS_PRIORITY', get_option('tls_priority'))
2104if iasl.found()
2105  config_host_data.set_quoted('CONFIG_IASL', iasl.full_path())
2106endif
2107config_host_data.set_quoted('CONFIG_BINDIR', get_option('prefix') / get_option('bindir'))
2108config_host_data.set_quoted('CONFIG_PREFIX', get_option('prefix'))
2109config_host_data.set_quoted('CONFIG_QEMU_CONFDIR', get_option('prefix') / qemu_confdir)
2110config_host_data.set_quoted('CONFIG_QEMU_DATADIR', get_option('prefix') / qemu_datadir)
2111config_host_data.set_quoted('CONFIG_QEMU_DESKTOPDIR', get_option('prefix') / qemu_desktopdir)
2112
2113qemu_firmwarepath = ''
2114foreach k : get_option('qemu_firmwarepath')
2115  qemu_firmwarepath += '"' + get_option('prefix') / k + '", '
2116endforeach
2117config_host_data.set('CONFIG_QEMU_FIRMWAREPATH', qemu_firmwarepath)
2118
2119config_host_data.set_quoted('CONFIG_QEMU_HELPERDIR', get_option('prefix') / get_option('libexecdir'))
2120config_host_data.set_quoted('CONFIG_QEMU_ICONDIR', get_option('prefix') / qemu_icondir)
2121config_host_data.set_quoted('CONFIG_QEMU_LOCALEDIR', get_option('prefix') / get_option('localedir'))
2122config_host_data.set_quoted('CONFIG_QEMU_LOCALSTATEDIR', get_option('prefix') / get_option('localstatedir'))
2123config_host_data.set_quoted('CONFIG_QEMU_MODDIR', get_option('prefix') / qemu_moddir)
2124config_host_data.set_quoted('CONFIG_SYSCONFDIR', get_option('prefix') / get_option('sysconfdir'))
2125
2126if enable_modules
2127  config_host_data.set('CONFIG_STAMP', run_command(
2128      meson.current_source_dir() / 'scripts/qemu-stamp.py',
2129      meson.project_version(), get_option('pkgversion'), '--',
2130      meson.current_source_dir() / 'configure',
2131      capture: true, check: true).stdout().strip())
2132endif
2133
2134have_slirp_smbd = get_option('slirp_smbd') \
2135  .require(host_os != 'windows', error_message: 'Host smbd not supported on this platform.') \
2136  .allowed()
2137if have_slirp_smbd
2138  smbd_path = get_option('smbd')
2139  if smbd_path == ''
2140    smbd_path = (host_os == 'sunos' ? '/usr/sfw/sbin/smbd' : '/usr/sbin/smbd')
2141  endif
2142  config_host_data.set_quoted('CONFIG_SMBD_COMMAND', smbd_path)
2143endif
2144
2145config_host_data.set('HOST_' + host_arch.to_upper(), 1)
2146
2147kvm_targets_c = '""'
2148if get_option('kvm').allowed() and host_os == 'linux'
2149  kvm_targets_c = '"' + '" ,"'.join(kvm_targets) + '"'
2150endif
2151config_host_data.set('CONFIG_KVM_TARGETS', kvm_targets_c)
2152
2153if get_option('module_upgrades') and not enable_modules
2154  error('Cannot enable module-upgrades as modules are not enabled')
2155endif
2156config_host_data.set('CONFIG_MODULE_UPGRADES', get_option('module_upgrades'))
2157
2158config_host_data.set('CONFIG_ATTR', libattr.found())
2159config_host_data.set('CONFIG_BDRV_WHITELIST_TOOLS', get_option('block_drv_whitelist_in_tools'))
2160config_host_data.set('CONFIG_BRLAPI', brlapi.found())
2161config_host_data.set('CONFIG_BSD', host_os in bsd_oses)
2162config_host_data.set('CONFIG_CAPSTONE', capstone.found())
2163config_host_data.set('CONFIG_COCOA', cocoa.found())
2164config_host_data.set('CONFIG_DARWIN', host_os == 'darwin')
2165config_host_data.set('CONFIG_FUZZ', get_option('fuzzing'))
2166config_host_data.set('CONFIG_GCOV', get_option('b_coverage'))
2167config_host_data.set('CONFIG_LIBUDEV', libudev.found())
2168config_host_data.set('CONFIG_LINUX', host_os == 'linux')
2169config_host_data.set('CONFIG_POSIX', host_os != 'windows')
2170config_host_data.set('CONFIG_WIN32', host_os == 'windows')
2171config_host_data.set('CONFIG_LZO', lzo.found())
2172config_host_data.set('CONFIG_MPATH', mpathpersist.found())
2173config_host_data.set('CONFIG_BLKIO', blkio.found())
2174if blkio.found()
2175  config_host_data.set('CONFIG_BLKIO_VHOST_VDPA_FD',
2176                       blkio.version().version_compare('>=1.3.0'))
2177endif
2178config_host_data.set('CONFIG_CURL', curl.found())
2179config_host_data.set('CONFIG_CURSES', curses.found())
2180config_host_data.set('CONFIG_GBM', gbm.found())
2181config_host_data.set('CONFIG_GIO', gio.found())
2182config_host_data.set('CONFIG_GLUSTERFS', glusterfs.found())
2183if glusterfs.found()
2184  config_host_data.set('CONFIG_GLUSTERFS_XLATOR_OPT', glusterfs.version().version_compare('>=4'))
2185  config_host_data.set('CONFIG_GLUSTERFS_DISCARD', glusterfs.version().version_compare('>=5'))
2186  config_host_data.set('CONFIG_GLUSTERFS_FALLOCATE', glusterfs.version().version_compare('>=6'))
2187  config_host_data.set('CONFIG_GLUSTERFS_ZEROFILL', glusterfs.version().version_compare('>=6'))
2188  config_host_data.set('CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT', glusterfs_ftruncate_has_stat)
2189  config_host_data.set('CONFIG_GLUSTERFS_IOCB_HAS_STAT', glusterfs_iocb_has_stat)
2190endif
2191config_host_data.set('CONFIG_GTK', gtk.found())
2192config_host_data.set('CONFIG_VTE', vte.found())
2193config_host_data.set('CONFIG_GTK_CLIPBOARD', have_gtk_clipboard)
2194config_host_data.set('CONFIG_HEXAGON_IDEF_PARSER', get_option('hexagon_idef_parser'))
2195config_host_data.set('CONFIG_LIBATTR', have_old_libattr)
2196config_host_data.set('CONFIG_LIBCAP_NG', libcap_ng.found())
2197config_host_data.set('CONFIG_EBPF', libbpf.found())
2198config_host_data.set('CONFIG_AF_XDP', libxdp.found())
2199config_host_data.set('CONFIG_LIBDAXCTL', libdaxctl.found())
2200config_host_data.set('CONFIG_LIBISCSI', libiscsi.found())
2201config_host_data.set('CONFIG_LIBNFS', libnfs.found())
2202config_host_data.set('CONFIG_LIBSSH', libssh.found())
2203config_host_data.set('CONFIG_LINUX_AIO', libaio.found())
2204config_host_data.set('CONFIG_LINUX_IO_URING', linux_io_uring.found())
2205config_host_data.set('CONFIG_LIBPMEM', libpmem.found())
2206config_host_data.set('CONFIG_MODULES', enable_modules)
2207config_host_data.set('CONFIG_NUMA', numa.found())
2208if numa.found()
2209  config_host_data.set('HAVE_NUMA_HAS_PREFERRED_MANY',
2210                       cc.has_function('numa_has_preferred_many',
2211                                       dependencies: numa))
2212endif
2213config_host_data.set('CONFIG_OPENGL', opengl.found())
2214config_host_data.set('CONFIG_PLUGIN', get_option('plugins'))
2215config_host_data.set('CONFIG_RBD', rbd.found())
2216config_host_data.set('CONFIG_RDMA', rdma.found())
2217config_host_data.set('CONFIG_RELOCATABLE', get_option('relocatable'))
2218config_host_data.set('CONFIG_SAFESTACK', get_option('safe_stack'))
2219config_host_data.set('CONFIG_SDL', sdl.found())
2220config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found())
2221config_host_data.set('CONFIG_SECCOMP', seccomp.found())
2222if seccomp.found()
2223  config_host_data.set('CONFIG_SECCOMP_SYSRAWRC', seccomp_has_sysrawrc)
2224endif
2225config_host_data.set('CONFIG_PIXMAN', pixman.found())
2226config_host_data.set('CONFIG_SLIRP', slirp.found())
2227config_host_data.set('CONFIG_SNAPPY', snappy.found())
2228config_host_data.set('CONFIG_SOLARIS', host_os == 'sunos')
2229if get_option('tcg').allowed()
2230  config_host_data.set('CONFIG_TCG', 1)
2231  config_host_data.set('CONFIG_TCG_INTERPRETER', tcg_arch == 'tci')
2232endif
2233config_host_data.set('CONFIG_TPM', have_tpm)
2234config_host_data.set('CONFIG_TSAN', get_option('tsan'))
2235config_host_data.set('CONFIG_USB_LIBUSB', libusb.found())
2236config_host_data.set('CONFIG_VDE', vde.found())
2237config_host_data.set('CONFIG_VHOST', have_vhost)
2238config_host_data.set('CONFIG_VHOST_NET', have_vhost_net)
2239config_host_data.set('CONFIG_VHOST_NET_USER', have_vhost_net_user)
2240config_host_data.set('CONFIG_VHOST_NET_VDPA', have_vhost_net_vdpa)
2241config_host_data.set('CONFIG_VHOST_KERNEL', have_vhost_kernel)
2242config_host_data.set('CONFIG_VHOST_USER', have_vhost_user)
2243config_host_data.set('CONFIG_VHOST_CRYPTO', have_vhost_user_crypto)
2244config_host_data.set('CONFIG_VHOST_VDPA', have_vhost_vdpa)
2245config_host_data.set('CONFIG_VMNET', vmnet.found())
2246config_host_data.set('CONFIG_VHOST_USER_BLK_SERVER', have_vhost_user_blk_server)
2247config_host_data.set('CONFIG_VDUSE_BLK_EXPORT', have_vduse_blk_export)
2248config_host_data.set('CONFIG_PNG', png.found())
2249config_host_data.set('CONFIG_VNC', vnc.found())
2250config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
2251config_host_data.set('CONFIG_VNC_SASL', sasl.found())
2252if virgl.found()
2253  config_host_data.set('HAVE_VIRGL_D3D_INFO_EXT',
2254                       cc.has_member('struct virgl_renderer_resource_info_ext', 'd3d_tex2d',
2255                                     prefix: '#include <virglrenderer.h>',
2256                                     dependencies: virgl))
2257endif
2258config_host_data.set('CONFIG_VIRTFS', have_virtfs)
2259config_host_data.set('CONFIG_VTE', vte.found())
2260config_host_data.set('CONFIG_XKBCOMMON', xkbcommon.found())
2261config_host_data.set('CONFIG_KEYUTILS', keyutils.found())
2262config_host_data.set('CONFIG_GETTID', has_gettid)
2263config_host_data.set('CONFIG_GNUTLS', gnutls.found())
2264config_host_data.set('CONFIG_GNUTLS_CRYPTO', gnutls_crypto.found())
2265config_host_data.set('CONFIG_TASN1', tasn1.found())
2266config_host_data.set('CONFIG_GCRYPT', gcrypt.found())
2267config_host_data.set('CONFIG_NETTLE', nettle.found())
2268config_host_data.set('CONFIG_HOGWEED', hogweed.found())
2269config_host_data.set('CONFIG_QEMU_PRIVATE_XTS', xts == 'private')
2270config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim)
2271config_host_data.set('CONFIG_STATX', has_statx)
2272config_host_data.set('CONFIG_STATX_MNT_ID', has_statx_mnt_id)
2273config_host_data.set('CONFIG_ZSTD', zstd.found())
2274config_host_data.set('CONFIG_FUSE', fuse.found())
2275config_host_data.set('CONFIG_FUSE_LSEEK', fuse_lseek.found())
2276config_host_data.set('CONFIG_SPICE_PROTOCOL', spice_protocol.found())
2277if spice_protocol.found()
2278config_host_data.set('CONFIG_SPICE_PROTOCOL_MAJOR', spice_protocol.version().split('.')[0])
2279config_host_data.set('CONFIG_SPICE_PROTOCOL_MINOR', spice_protocol.version().split('.')[1])
2280config_host_data.set('CONFIG_SPICE_PROTOCOL_MICRO', spice_protocol.version().split('.')[2])
2281endif
2282config_host_data.set('CONFIG_SPICE', spice.found())
2283config_host_data.set('CONFIG_X11', x11.found())
2284config_host_data.set('CONFIG_DBUS_DISPLAY', dbus_display)
2285config_host_data.set('CONFIG_CFI', get_option('cfi'))
2286config_host_data.set('CONFIG_SELINUX', selinux.found())
2287config_host_data.set('CONFIG_XEN_BACKEND', xen.found())
2288config_host_data.set('CONFIG_LIBDW', libdw.found())
2289if xen.found()
2290  # protect from xen.version() having less than three components
2291  xen_version = xen.version().split('.') + ['0', '0']
2292  xen_ctrl_version = xen_version[0] + \
2293    ('0' + xen_version[1]).substring(-2) + \
2294    ('0' + xen_version[2]).substring(-2)
2295  config_host_data.set('CONFIG_XEN_CTRL_INTERFACE_VERSION', xen_ctrl_version)
2296endif
2297config_host_data.set('QEMU_VERSION', '"@0@"'.format(meson.project_version()))
2298config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0])
2299config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1])
2300config_host_data.set('QEMU_VERSION_MICRO', meson.project_version().split('.')[2])
2301
2302config_host_data.set_quoted('CONFIG_HOST_DSOSUF', host_dsosuf)
2303config_host_data.set('HAVE_HOST_BLOCK_DEVICE', have_host_block_device)
2304
2305have_coroutine_pool = get_option('coroutine_pool')
2306if get_option('debug_stack_usage') and have_coroutine_pool
2307  message('Disabling coroutine pool to measure stack usage')
2308  have_coroutine_pool = false
2309endif
2310config_host_data.set('CONFIG_COROUTINE_POOL', have_coroutine_pool)
2311config_host_data.set('CONFIG_DEBUG_GRAPH_LOCK', get_option('debug_graph_lock'))
2312config_host_data.set('CONFIG_DEBUG_MUTEX', get_option('debug_mutex'))
2313config_host_data.set('CONFIG_DEBUG_STACK_USAGE', get_option('debug_stack_usage'))
2314config_host_data.set('CONFIG_DEBUG_TCG', get_option('debug_tcg'))
2315config_host_data.set('CONFIG_LIVE_BLOCK_MIGRATION', get_option('live_block_migration').allowed())
2316config_host_data.set('CONFIG_QOM_CAST_DEBUG', get_option('qom_cast_debug'))
2317config_host_data.set('CONFIG_REPLICATION', get_option('replication').allowed())
2318
2319# has_header
2320config_host_data.set('CONFIG_EPOLL', cc.has_header('sys/epoll.h'))
2321config_host_data.set('CONFIG_LINUX_MAGIC_H', cc.has_header('linux/magic.h'))
2322config_host_data.set('CONFIG_VALGRIND_H', cc.has_header('valgrind/valgrind.h'))
2323config_host_data.set('HAVE_BTRFS_H', cc.has_header('linux/btrfs.h'))
2324config_host_data.set('HAVE_DRM_H', cc.has_header('libdrm/drm.h'))
2325config_host_data.set('HAVE_PTY_H', cc.has_header('pty.h'))
2326config_host_data.set('HAVE_SYS_DISK_H', cc.has_header('sys/disk.h'))
2327config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h'))
2328config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h'))
2329if host_os == 'windows'
2330  config_host_data.set('HAVE_AFUNIX_H', cc.has_header('afunix.h'))
2331endif
2332
2333# has_function
2334config_host_data.set('CONFIG_CLOSE_RANGE', cc.has_function('close_range'))
2335config_host_data.set('CONFIG_ACCEPT4', cc.has_function('accept4'))
2336config_host_data.set('CONFIG_CLOCK_ADJTIME', cc.has_function('clock_adjtime'))
2337config_host_data.set('CONFIG_DUP3', cc.has_function('dup3'))
2338config_host_data.set('CONFIG_FALLOCATE', cc.has_function('fallocate'))
2339config_host_data.set('CONFIG_POSIX_FALLOCATE', cc.has_function('posix_fallocate'))
2340config_host_data.set('CONFIG_GETCPU', cc.has_function('getcpu', prefix: gnu_source_prefix))
2341config_host_data.set('CONFIG_SCHED_GETCPU', cc.has_function('sched_getcpu', prefix: '#include <sched.h>'))
2342# Note that we need to specify prefix: here to avoid incorrectly
2343# thinking that Windows has posix_memalign()
2344config_host_data.set('CONFIG_POSIX_MEMALIGN', cc.has_function('posix_memalign', prefix: '#include <stdlib.h>'))
2345config_host_data.set('CONFIG_ALIGNED_MALLOC', cc.has_function('_aligned_malloc'))
2346config_host_data.set('CONFIG_VALLOC', cc.has_function('valloc'))
2347config_host_data.set('CONFIG_MEMALIGN', cc.has_function('memalign'))
2348config_host_data.set('CONFIG_PPOLL', cc.has_function('ppoll'))
2349config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include <sys/uio.h>'))
2350config_host_data.set('CONFIG_PTHREAD_FCHDIR_NP', cc.has_function('pthread_fchdir_np'))
2351config_host_data.set('CONFIG_SENDFILE', cc.has_function('sendfile'))
2352config_host_data.set('CONFIG_SETNS', cc.has_function('setns') and cc.has_function('unshare'))
2353config_host_data.set('CONFIG_SYNCFS', cc.has_function('syncfs'))
2354config_host_data.set('CONFIG_SYNC_FILE_RANGE', cc.has_function('sync_file_range'))
2355config_host_data.set('CONFIG_TIMERFD', cc.has_function('timerfd_create'))
2356config_host_data.set('HAVE_COPY_FILE_RANGE', cc.has_function('copy_file_range'))
2357config_host_data.set('HAVE_GETIFADDRS', cc.has_function('getifaddrs'))
2358config_host_data.set('HAVE_GLIB_WITH_SLICE_ALLOCATOR', glib_has_gslice)
2359config_host_data.set('HAVE_OPENPTY', cc.has_function('openpty', dependencies: util))
2360config_host_data.set('HAVE_STRCHRNUL', cc.has_function('strchrnul'))
2361config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: '#include <stdlib.h>'))
2362if rbd.found()
2363  config_host_data.set('HAVE_RBD_NAMESPACE_EXISTS',
2364                       cc.has_function('rbd_namespace_exists',
2365                                       dependencies: rbd,
2366                                       prefix: '#include <rbd/librbd.h>'))
2367endif
2368if rdma.found()
2369  config_host_data.set('HAVE_IBV_ADVISE_MR',
2370                       cc.has_function('ibv_advise_mr',
2371                                       dependencies: rdma,
2372                                       prefix: '#include <infiniband/verbs.h>'))
2373endif
2374
2375have_asan_fiber = false
2376if get_option('sanitizers') and \
2377   not cc.has_function('__sanitizer_start_switch_fiber',
2378                         args: '-fsanitize=address',
2379                         prefix: '#include <sanitizer/asan_interface.h>')
2380  warning('Missing ASAN due to missing fiber annotation interface')
2381  warning('Without code annotation, the report may be inferior.')
2382else
2383  have_asan_fiber = true
2384endif
2385config_host_data.set('CONFIG_ASAN_IFACE_FIBER', have_asan_fiber)
2386
2387have_inotify_init = cc.has_header_symbol('sys/inotify.h', 'inotify_init')
2388have_inotify_init1 = cc.has_header_symbol('sys/inotify.h', 'inotify_init1')
2389inotify = not_found
2390if (have_inotify_init or have_inotify_init1) and host_os == 'freebsd'
2391  # libinotify-kqueue
2392  inotify = cc.find_library('inotify')
2393  if have_inotify_init
2394    have_inotify_init = inotify.found()
2395  endif
2396  if have_inotify_init1
2397    have_inotify_init1 = inotify.found()
2398  endif
2399endif
2400config_host_data.set('CONFIG_INOTIFY', have_inotify_init)
2401config_host_data.set('CONFIG_INOTIFY1', have_inotify_init1)
2402
2403# has_header_symbol
2404config_host_data.set('CONFIG_BLKZONED',
2405                     cc.has_header_symbol('linux/blkzoned.h', 'BLKOPENZONE'))
2406config_host_data.set('CONFIG_EPOLL_CREATE1',
2407                     cc.has_header_symbol('sys/epoll.h', 'epoll_create1'))
2408config_host_data.set('CONFIG_FALLOCATE_PUNCH_HOLE',
2409                     cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_PUNCH_HOLE') and
2410                     cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_KEEP_SIZE'))
2411config_host_data.set('CONFIG_FALLOCATE_ZERO_RANGE',
2412                     cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_ZERO_RANGE'))
2413config_host_data.set('CONFIG_FIEMAP',
2414                     cc.has_header('linux/fiemap.h') and
2415                     cc.has_header_symbol('linux/fs.h', 'FS_IOC_FIEMAP'))
2416config_host_data.set('CONFIG_GETRANDOM',
2417                     cc.has_function('getrandom') and
2418                     cc.has_header_symbol('sys/random.h', 'GRND_NONBLOCK'))
2419config_host_data.set('CONFIG_PRCTL_PR_SET_TIMERSLACK',
2420                     cc.has_header_symbol('sys/prctl.h', 'PR_SET_TIMERSLACK'))
2421config_host_data.set('CONFIG_RTNETLINK',
2422                     cc.has_header_symbol('linux/rtnetlink.h', 'IFLA_PROTO_DOWN'))
2423config_host_data.set('CONFIG_SYSMACROS',
2424                     cc.has_header_symbol('sys/sysmacros.h', 'makedev'))
2425config_host_data.set('HAVE_OPTRESET',
2426                     cc.has_header_symbol('getopt.h', 'optreset'))
2427config_host_data.set('HAVE_IPPROTO_MPTCP',
2428                     cc.has_header_symbol('netinet/in.h', 'IPPROTO_MPTCP'))
2429
2430# has_member
2431config_host_data.set('HAVE_SIGEV_NOTIFY_THREAD_ID',
2432                     cc.has_member('struct sigevent', 'sigev_notify_thread_id',
2433                                   prefix: '#include <signal.h>'))
2434config_host_data.set('HAVE_STRUCT_STAT_ST_ATIM',
2435                     cc.has_member('struct stat', 'st_atim',
2436                                   prefix: '#include <sys/stat.h>'))
2437config_host_data.set('HAVE_BLK_ZONE_REP_CAPACITY',
2438                     cc.has_member('struct blk_zone', 'capacity',
2439                                   prefix: '#include <linux/blkzoned.h>'))
2440
2441# has_type
2442config_host_data.set('CONFIG_IOVEC',
2443                     cc.has_type('struct iovec',
2444                                 prefix: '#include <sys/uio.h>'))
2445config_host_data.set('HAVE_UTMPX',
2446                     cc.has_type('struct utmpx',
2447                                 prefix: '#include <utmpx.h>'))
2448
2449config_host_data.set('CONFIG_EVENTFD', cc.links('''
2450  #include <sys/eventfd.h>
2451  int main(void) { return eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); }'''))
2452config_host_data.set('CONFIG_FDATASYNC', cc.links(gnu_source_prefix + '''
2453  #include <unistd.h>
2454  int main(void) {
2455  #if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
2456  return fdatasync(0);
2457  #else
2458  #error Not supported
2459  #endif
2460  }'''))
2461
2462has_madvise = cc.links(gnu_source_prefix + '''
2463  #include <sys/types.h>
2464  #include <sys/mman.h>
2465  #include <stddef.h>
2466  int main(void) { return madvise(NULL, 0, MADV_DONTNEED); }''')
2467missing_madvise_proto = false
2468if has_madvise
2469  # Some platforms (illumos and Solaris before Solaris 11) provide madvise()
2470  # but forget to prototype it. In this case, has_madvise will be true (the
2471  # test program links despite a compile warning). To detect the
2472  # missing-prototype case, we try again with a definitely-bogus prototype.
2473  # This will only compile if the system headers don't provide the prototype;
2474  # otherwise the conflicting prototypes will cause a compiler error.
2475  missing_madvise_proto = cc.links(gnu_source_prefix + '''
2476    #include <sys/types.h>
2477    #include <sys/mman.h>
2478    #include <stddef.h>
2479    extern int madvise(int);
2480    int main(void) { return madvise(0); }''')
2481endif
2482config_host_data.set('CONFIG_MADVISE', has_madvise)
2483config_host_data.set('HAVE_MADVISE_WITHOUT_PROTOTYPE', missing_madvise_proto)
2484
2485config_host_data.set('CONFIG_MEMFD', cc.links(gnu_source_prefix + '''
2486  #include <sys/mman.h>
2487  int main(void) { return memfd_create("foo", MFD_ALLOW_SEALING); }'''))
2488config_host_data.set('CONFIG_OPEN_BY_HANDLE', cc.links(gnu_source_prefix + '''
2489  #include <fcntl.h>
2490  #if !defined(AT_EMPTY_PATH)
2491  # error missing definition
2492  #else
2493  int main(void) { struct file_handle fh; return open_by_handle_at(0, &fh, 0); }
2494  #endif'''))
2495config_host_data.set('CONFIG_POSIX_MADVISE', cc.links(gnu_source_prefix + '''
2496  #include <sys/mman.h>
2497  #include <stddef.h>
2498  int main(void) { return posix_madvise(NULL, 0, POSIX_MADV_DONTNEED); }'''))
2499
2500config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_W_TID', cc.links(gnu_source_prefix + '''
2501  #include <pthread.h>
2502
2503  static void *f(void *p) { return NULL; }
2504  int main(void)
2505  {
2506    pthread_t thread;
2507    pthread_create(&thread, 0, f, 0);
2508    pthread_setname_np(thread, "QEMU");
2509    return 0;
2510  }''', dependencies: threads))
2511config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_WO_TID', cc.links(gnu_source_prefix + '''
2512  #include <pthread.h>
2513
2514  static void *f(void *p) { pthread_setname_np("QEMU"); return NULL; }
2515  int main(void)
2516  {
2517    pthread_t thread;
2518    pthread_create(&thread, 0, f, 0);
2519    return 0;
2520  }''', dependencies: threads))
2521config_host_data.set('CONFIG_PTHREAD_SET_NAME_NP', cc.links(gnu_source_prefix + '''
2522  #include <pthread.h>
2523  #include <pthread_np.h>
2524
2525  static void *f(void *p) { return NULL; }
2526  int main(void)
2527  {
2528    pthread_t thread;
2529    pthread_create(&thread, 0, f, 0);
2530    pthread_set_name_np(thread, "QEMU");
2531    return 0;
2532  }''', dependencies: threads))
2533config_host_data.set('CONFIG_PTHREAD_CONDATTR_SETCLOCK', cc.links(gnu_source_prefix + '''
2534  #include <pthread.h>
2535  #include <time.h>
2536
2537  int main(void)
2538  {
2539    pthread_condattr_t attr
2540    pthread_condattr_init(&attr);
2541    pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
2542    return 0;
2543  }''', dependencies: threads))
2544config_host_data.set('CONFIG_PTHREAD_AFFINITY_NP', cc.links(gnu_source_prefix + '''
2545  #include <pthread.h>
2546
2547  static void *f(void *p) { return NULL; }
2548  int main(void)
2549  {
2550    int setsize = CPU_ALLOC_SIZE(64);
2551    pthread_t thread;
2552    cpu_set_t *cpuset;
2553    pthread_create(&thread, 0, f, 0);
2554    cpuset = CPU_ALLOC(64);
2555    CPU_ZERO_S(setsize, cpuset);
2556    pthread_setaffinity_np(thread, setsize, cpuset);
2557    pthread_getaffinity_np(thread, setsize, cpuset);
2558    CPU_FREE(cpuset);
2559    return 0;
2560  }''', dependencies: threads))
2561config_host_data.set('CONFIG_SIGNALFD', cc.links(gnu_source_prefix + '''
2562  #include <sys/signalfd.h>
2563  #include <stddef.h>
2564  int main(void) { return signalfd(-1, NULL, SFD_CLOEXEC); }'''))
2565config_host_data.set('CONFIG_SPLICE', cc.links(gnu_source_prefix + '''
2566  #include <unistd.h>
2567  #include <fcntl.h>
2568  #include <limits.h>
2569
2570  int main(void)
2571  {
2572    int len, fd = 0;
2573    len = tee(STDIN_FILENO, STDOUT_FILENO, INT_MAX, SPLICE_F_NONBLOCK);
2574    splice(STDIN_FILENO, NULL, fd, NULL, len, SPLICE_F_MOVE);
2575    return 0;
2576  }'''))
2577
2578config_host_data.set('HAVE_MLOCKALL', cc.links(gnu_source_prefix + '''
2579  #include <sys/mman.h>
2580  int main(void) {
2581    return mlockall(MCL_FUTURE);
2582  }'''))
2583
2584have_l2tpv3 = false
2585if get_option('l2tpv3').allowed() and have_system
2586  have_l2tpv3 = cc.has_type('struct mmsghdr',
2587    prefix: gnu_source_prefix + '''
2588      #include <sys/socket.h>
2589      #include <linux/ip.h>''')
2590endif
2591config_host_data.set('CONFIG_L2TPV3', have_l2tpv3)
2592
2593have_netmap = false
2594if get_option('netmap').allowed() and have_system
2595  have_netmap = cc.compiles('''
2596    #include <inttypes.h>
2597    #include <net/if.h>
2598    #include <net/netmap.h>
2599    #include <net/netmap_user.h>
2600    #if (NETMAP_API < 11) || (NETMAP_API > 15)
2601    #error
2602    #endif
2603    int main(void) { return 0; }''')
2604  if not have_netmap and get_option('netmap').enabled()
2605    error('Netmap headers not available')
2606  endif
2607endif
2608config_host_data.set('CONFIG_NETMAP', have_netmap)
2609
2610# Work around a system header bug with some kernel/XFS header
2611# versions where they both try to define 'struct fsxattr':
2612# xfs headers will not try to redefine structs from linux headers
2613# if this macro is set.
2614config_host_data.set('HAVE_FSXATTR', cc.links('''
2615  #include <linux/fs.h>
2616  struct fsxattr foo;
2617  int main(void) {
2618    return 0;
2619  }'''))
2620
2621# Some versions of Mac OS X incorrectly define SIZE_MAX
2622config_host_data.set('HAVE_BROKEN_SIZE_MAX', not cc.compiles('''
2623    #include <stdint.h>
2624    #include <stdio.h>
2625    int main(void) {
2626        return printf("%zu", SIZE_MAX);
2627    }''', args: ['-Werror']))
2628
2629# See if 64-bit atomic operations are supported.
2630# Note that without __atomic builtins, we can only
2631# assume atomic loads/stores max at pointer size.
2632config_host_data.set('CONFIG_ATOMIC64', cc.links('''
2633  #include <stdint.h>
2634  int main(void)
2635  {
2636    uint64_t x = 0, y = 0;
2637    y = __atomic_load_n(&x, __ATOMIC_RELAXED);
2638    __atomic_store_n(&x, y, __ATOMIC_RELAXED);
2639    __atomic_compare_exchange_n(&x, &y, x, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
2640    __atomic_exchange_n(&x, y, __ATOMIC_RELAXED);
2641    __atomic_fetch_add(&x, y, __ATOMIC_RELAXED);
2642    return 0;
2643  }'''))
2644
2645has_int128_type = cc.compiles('''
2646  __int128_t a;
2647  __uint128_t b;
2648  int main(void) { b = a; }''')
2649config_host_data.set('CONFIG_INT128_TYPE', has_int128_type)
2650
2651has_int128 = has_int128_type and cc.links('''
2652  __int128_t a;
2653  __uint128_t b;
2654  int main (void) {
2655    a = a + b;
2656    b = a * b;
2657    a = a * a;
2658    return 0;
2659  }''')
2660config_host_data.set('CONFIG_INT128', has_int128)
2661
2662if has_int128_type
2663  # "do we have 128-bit atomics which are handled inline and specifically not
2664  # via libatomic". The reason we can't use libatomic is documented in the
2665  # comment starting "GCC is a house divided" in include/qemu/atomic128.h.
2666  # We only care about these operations on 16-byte aligned pointers, so
2667  # force 16-byte alignment of the pointer, which may be greater than
2668  # __alignof(unsigned __int128) for the host.
2669  atomic_test_128 = '''
2670    int main(int ac, char **av) {
2671      __uint128_t *p = __builtin_assume_aligned(av[ac - 1], 16);
2672      p[1] = __atomic_load_n(&p[0], __ATOMIC_RELAXED);
2673      __atomic_store_n(&p[2], p[3], __ATOMIC_RELAXED);
2674      __atomic_compare_exchange_n(&p[4], &p[5], p[6], 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
2675      return 0;
2676    }'''
2677  has_atomic128 = cc.links(atomic_test_128)
2678
2679  config_host_data.set('CONFIG_ATOMIC128', has_atomic128)
2680
2681  if not has_atomic128
2682    # Even with __builtin_assume_aligned, the above test may have failed
2683    # without optimization enabled.  Try again with optimizations locally
2684    # enabled for the function.  See
2685    #   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107389
2686    has_atomic128_opt = cc.links('__attribute__((optimize("O1")))' + atomic_test_128)
2687    config_host_data.set('CONFIG_ATOMIC128_OPT', has_atomic128_opt)
2688
2689    if not has_atomic128_opt
2690      config_host_data.set('CONFIG_CMPXCHG128', cc.links('''
2691        int main(void)
2692        {
2693          __uint128_t x = 0, y = 0;
2694          __sync_val_compare_and_swap_16(&x, y, x);
2695          return 0;
2696        }
2697      '''))
2698    endif
2699  endif
2700endif
2701
2702config_host_data.set('CONFIG_GETAUXVAL', cc.links(gnu_source_prefix + '''
2703  #include <sys/auxv.h>
2704  int main(void) {
2705    return getauxval(AT_HWCAP) == 0;
2706  }'''))
2707
2708config_host_data.set('CONFIG_USBFS', have_linux_user and cc.compiles('''
2709  #include <linux/usbdevice_fs.h>
2710
2711  #ifndef USBDEVFS_GET_CAPABILITIES
2712  #error "USBDEVFS_GET_CAPABILITIES undefined"
2713  #endif
2714
2715  #ifndef USBDEVFS_DISCONNECT_CLAIM
2716  #error "USBDEVFS_DISCONNECT_CLAIM undefined"
2717  #endif
2718
2719  int main(void) { return 0; }'''))
2720
2721have_keyring = get_option('keyring') \
2722  .require(host_os == 'linux', error_message: 'keyring is only available on Linux') \
2723  .require(cc.compiles('''
2724    #include <errno.h>
2725    #include <asm/unistd.h>
2726    #include <linux/keyctl.h>
2727    #include <sys/syscall.h>
2728    #include <unistd.h>
2729    int main(void) {
2730        return syscall(__NR_keyctl, KEYCTL_READ, 0, NULL, NULL, 0);
2731    }'''), error_message: 'keyctl syscall not available on this system').allowed()
2732config_host_data.set('CONFIG_SECRET_KEYRING', have_keyring)
2733
2734have_cpuid_h = cc.links('''
2735  #include <cpuid.h>
2736  int main(void) {
2737    unsigned a, b, c, d;
2738    unsigned max = __get_cpuid_max(0, 0);
2739
2740    if (max >= 1) {
2741        __cpuid(1, a, b, c, d);
2742    }
2743
2744    if (max >= 7) {
2745        __cpuid_count(7, 0, a, b, c, d);
2746    }
2747
2748    return 0;
2749  }''')
2750config_host_data.set('CONFIG_CPUID_H', have_cpuid_h)
2751
2752config_host_data.set('CONFIG_AVX2_OPT', get_option('avx2') \
2753  .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX2') \
2754  .require(cc.links('''
2755    #include <cpuid.h>
2756    #include <immintrin.h>
2757    static int __attribute__((target("avx2"))) bar(void *a) {
2758      __m256i x = *(__m256i *)a;
2759      return _mm256_testz_si256(x, x);
2760    }
2761    int main(int argc, char *argv[]) { return bar(argv[argc - 1]); }
2762  '''), error_message: 'AVX2 not available').allowed())
2763
2764config_host_data.set('CONFIG_AVX512F_OPT', get_option('avx512f') \
2765  .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX512F') \
2766  .require(cc.links('''
2767    #include <cpuid.h>
2768    #include <immintrin.h>
2769    static int __attribute__((target("avx512f"))) bar(void *a) {
2770      __m512i x = *(__m512i *)a;
2771      return _mm512_test_epi64_mask(x, x);
2772    }
2773    int main(int argc, char *argv[]) { return bar(argv[argc - 1]); }
2774  '''), error_message: 'AVX512F not available').allowed())
2775
2776config_host_data.set('CONFIG_AVX512BW_OPT', get_option('avx512bw') \
2777  .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX512BW') \
2778  .require(cc.links('''
2779    #include <cpuid.h>
2780    #include <immintrin.h>
2781    static int __attribute__((target("avx512bw"))) bar(void *a) {
2782      __m512i *x = a;
2783      __m512i res= _mm512_abs_epi8(*x);
2784      return res[1];
2785    }
2786    int main(int argc, char *argv[]) { return bar(argv[0]); }
2787  '''), error_message: 'AVX512BW not available').allowed())
2788
2789# For both AArch64 and AArch32, detect if builtins are available.
2790config_host_data.set('CONFIG_ARM_AES_BUILTIN', cc.compiles('''
2791    #include <arm_neon.h>
2792    #ifndef __ARM_FEATURE_AES
2793    __attribute__((target("+crypto")))
2794    #endif
2795    void foo(uint8x16_t *p) { *p = vaesmcq_u8(*p); }
2796  '''))
2797
2798have_pvrdma = get_option('pvrdma') \
2799  .require(rdma.found(), error_message: 'PVRDMA requires OpenFabrics libraries') \
2800  .require(cc.compiles(gnu_source_prefix + '''
2801    #include <sys/mman.h>
2802    int main(void)
2803    {
2804      char buf = 0;
2805      void *addr = &buf;
2806      addr = mremap(addr, 0, 1, MREMAP_MAYMOVE | MREMAP_FIXED);
2807
2808      return 0;
2809    }'''), error_message: 'PVRDMA requires mremap').allowed()
2810
2811if have_pvrdma
2812  config_host_data.set('LEGACY_RDMA_REG_MR', not cc.links('''
2813    #include <infiniband/verbs.h>
2814    int main(void)
2815    {
2816      struct ibv_mr *mr;
2817      struct ibv_pd *pd = NULL;
2818      size_t length = 10;
2819      uint64_t iova = 0;
2820      int access = 0;
2821      void *addr = NULL;
2822
2823      mr = ibv_reg_mr_iova(pd, addr, length, iova, access);
2824      ibv_dereg_mr(mr);
2825      return 0;
2826    }'''))
2827endif
2828
2829if get_option('membarrier').disabled()
2830  have_membarrier = false
2831elif host_os == 'windows'
2832  have_membarrier = true
2833elif host_os == 'linux'
2834  have_membarrier = cc.compiles('''
2835    #include <linux/membarrier.h>
2836    #include <sys/syscall.h>
2837    #include <unistd.h>
2838    #include <stdlib.h>
2839    int main(void) {
2840        syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0);
2841        syscall(__NR_membarrier, MEMBARRIER_CMD_SHARED, 0);
2842        exit(0);
2843    }''')
2844endif
2845config_host_data.set('CONFIG_MEMBARRIER', get_option('membarrier') \
2846  .require(have_membarrier, error_message: 'membarrier system call not available') \
2847  .allowed())
2848
2849have_afalg = get_option('crypto_afalg') \
2850  .require(cc.compiles(gnu_source_prefix + '''
2851    #include <errno.h>
2852    #include <sys/types.h>
2853    #include <sys/socket.h>
2854    #include <linux/if_alg.h>
2855    int main(void) {
2856      int sock;
2857      sock = socket(AF_ALG, SOCK_SEQPACKET, 0);
2858      return sock;
2859    }
2860  '''), error_message: 'AF_ALG requested but could not be detected').allowed()
2861config_host_data.set('CONFIG_AF_ALG', have_afalg)
2862
2863config_host_data.set('CONFIG_AF_VSOCK', cc.has_header_symbol(
2864  'linux/vm_sockets.h', 'AF_VSOCK',
2865  prefix: '#include <sys/socket.h>',
2866))
2867
2868have_vss = false
2869have_vss_sdk = false # old xp/2003 SDK
2870if host_os == 'windows' and 'cpp' in all_languages
2871  have_vss = cxx.compiles('''
2872    #define __MIDL_user_allocate_free_DEFINED__
2873    #include <vss.h>
2874    int main(void) { return VSS_CTX_BACKUP; }''')
2875  have_vss_sdk = cxx.has_header('vscoordint.h')
2876endif
2877config_host_data.set('HAVE_VSS_SDK', have_vss_sdk)
2878
2879# Older versions of MinGW do not import _lock_file and _unlock_file properly.
2880# This was fixed for v6.0.0 with commit b48e3ac8969d.
2881if host_os == 'windows'
2882  config_host_data.set('HAVE__LOCK_FILE', cc.links('''
2883    #include <stdio.h>
2884    int main(void) {
2885      _lock_file(NULL);
2886      _unlock_file(NULL);
2887      return 0;
2888    }''', name: '_lock_file and _unlock_file'))
2889endif
2890
2891if host_os == 'windows'
2892  mingw_has_setjmp_longjmp = cc.links('''
2893    #include <setjmp.h>
2894    int main(void) {
2895      /*
2896       * These functions are not available in setjmp header, but may be
2897       * available at link time, from libmingwex.a.
2898       */
2899      extern int __mingw_setjmp(jmp_buf);
2900      extern void __attribute__((noreturn)) __mingw_longjmp(jmp_buf, int);
2901      jmp_buf env;
2902      __mingw_setjmp(env);
2903      __mingw_longjmp(env, 0);
2904    }
2905  ''', name: 'mingw setjmp and longjmp')
2906
2907  if cpu == 'aarch64' and not mingw_has_setjmp_longjmp
2908    error('mingw must provide setjmp/longjmp for windows-arm64')
2909  endif
2910endif
2911
2912########################
2913# Target configuration #
2914########################
2915
2916minikconf = find_program('scripts/minikconf.py')
2917
2918config_all_accel = {}
2919config_all_devices = {}
2920config_devices_mak_list = []
2921config_devices_h = {}
2922config_target_h = {}
2923config_target_mak = {}
2924
2925disassemblers = {
2926  'alpha' : ['CONFIG_ALPHA_DIS'],
2927  'avr' : ['CONFIG_AVR_DIS'],
2928  'cris' : ['CONFIG_CRIS_DIS'],
2929  'hexagon' : ['CONFIG_HEXAGON_DIS'],
2930  'hppa' : ['CONFIG_HPPA_DIS'],
2931  'i386' : ['CONFIG_I386_DIS'],
2932  'x86_64' : ['CONFIG_I386_DIS'],
2933  'm68k' : ['CONFIG_M68K_DIS'],
2934  'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
2935  'mips' : ['CONFIG_MIPS_DIS'],
2936  'nios2' : ['CONFIG_NIOS2_DIS'],
2937  'or1k' : ['CONFIG_OPENRISC_DIS'],
2938  'ppc' : ['CONFIG_PPC_DIS'],
2939  'riscv' : ['CONFIG_RISCV_DIS'],
2940  'rx' : ['CONFIG_RX_DIS'],
2941  's390' : ['CONFIG_S390_DIS'],
2942  'sh4' : ['CONFIG_SH4_DIS'],
2943  'sparc' : ['CONFIG_SPARC_DIS'],
2944  'xtensa' : ['CONFIG_XTENSA_DIS'],
2945  'loongarch' : ['CONFIG_LOONGARCH_DIS'],
2946}
2947
2948have_ivshmem = config_host_data.get('CONFIG_EVENTFD')
2949host_kconfig = \
2950  (get_option('fuzzing') ? ['CONFIG_FUZZ=y'] : []) + \
2951  (have_tpm ? ['CONFIG_TPM=y'] : []) + \
2952  (pixman.found() ? ['CONFIG_PIXMAN=y'] : []) + \
2953  (spice.found() ? ['CONFIG_SPICE=y'] : []) + \
2954  (have_ivshmem ? ['CONFIG_IVSHMEM=y'] : []) + \
2955  (opengl.found() ? ['CONFIG_OPENGL=y'] : []) + \
2956  (x11.found() ? ['CONFIG_X11=y'] : []) + \
2957  (have_vhost_user ? ['CONFIG_VHOST_USER=y'] : []) + \
2958  (have_vhost_vdpa ? ['CONFIG_VHOST_VDPA=y'] : []) + \
2959  (have_vhost_kernel ? ['CONFIG_VHOST_KERNEL=y'] : []) + \
2960  (have_virtfs ? ['CONFIG_VIRTFS=y'] : []) + \
2961  (host_os == 'linux' ? ['CONFIG_LINUX=y'] : []) + \
2962  (have_pvrdma ? ['CONFIG_PVRDMA=y'] : []) + \
2963  (multiprocess_allowed ? ['CONFIG_MULTIPROCESS_ALLOWED=y'] : []) + \
2964  (vfio_user_server_allowed ? ['CONFIG_VFIO_USER_SERVER_ALLOWED=y'] : []) + \
2965  (hv_balloon ? ['CONFIG_HV_BALLOON_POSSIBLE=y'] : [])
2966
2967ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ]
2968
2969default_targets = 'CONFIG_DEFAULT_TARGETS' in config_host
2970actual_target_dirs = []
2971fdt_required = []
2972foreach target : target_dirs
2973  config_target = { 'TARGET_NAME': target.split('-')[0] }
2974  if target.endswith('linux-user')
2975    if host_os != 'linux'
2976      if default_targets
2977        continue
2978      endif
2979      error('Target @0@ is only available on a Linux host'.format(target))
2980    endif
2981    config_target += { 'CONFIG_LINUX_USER': 'y' }
2982  elif target.endswith('bsd-user')
2983    if host_os not in bsd_oses
2984      if default_targets
2985        continue
2986      endif
2987      error('Target @0@ is only available on a BSD host'.format(target))
2988    endif
2989    config_target += { 'CONFIG_BSD_USER': 'y' }
2990  elif target.endswith('softmmu')
2991    config_target += { 'CONFIG_SYSTEM_ONLY': 'y' }
2992    config_target += { 'CONFIG_SOFTMMU': 'y' }
2993  endif
2994  if target.endswith('-user')
2995    config_target += {
2996      'CONFIG_USER_ONLY': 'y',
2997      'CONFIG_QEMU_INTERP_PREFIX':
2998        get_option('interp_prefix').replace('%M', config_target['TARGET_NAME'])
2999    }
3000  endif
3001
3002  accel_kconfig = []
3003  foreach sym: accelerators
3004    if sym == 'CONFIG_TCG' or target in accelerator_targets.get(sym, [])
3005      config_target += { sym: 'y' }
3006      config_all_accel += { sym: 'y' }
3007      if target in modular_tcg
3008        config_target += { 'CONFIG_TCG_MODULAR': 'y' }
3009      else
3010        config_target += { 'CONFIG_TCG_BUILTIN': 'y' }
3011      endif
3012      accel_kconfig += [ sym + '=y' ]
3013    endif
3014  endforeach
3015  if accel_kconfig.length() == 0
3016    if default_targets
3017      continue
3018    endif
3019    error('No accelerator available for target @0@'.format(target))
3020  endif
3021
3022  actual_target_dirs += target
3023  config_target += keyval.load('configs/targets' / target + '.mak')
3024  config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
3025
3026  if 'TARGET_NEED_FDT' in config_target
3027    fdt_required += target
3028  endif
3029
3030  # Add default keys
3031  if 'TARGET_BASE_ARCH' not in config_target
3032    config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
3033  endif
3034  if 'TARGET_ABI_DIR' not in config_target
3035    config_target += {'TARGET_ABI_DIR': config_target['TARGET_ARCH']}
3036  endif
3037  if 'TARGET_BIG_ENDIAN' not in config_target
3038    config_target += {'TARGET_BIG_ENDIAN': 'n'}
3039  endif
3040
3041  foreach k, v: disassemblers
3042    if host_arch.startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k)
3043      foreach sym: v
3044        config_target += { sym: 'y' }
3045      endforeach
3046    endif
3047  endforeach
3048
3049  config_target_data = configuration_data()
3050  foreach k, v: config_target
3051    if not k.startswith('TARGET_') and not k.startswith('CONFIG_')
3052      # do nothing
3053    elif ignored.contains(k)
3054      # do nothing
3055    elif k == 'TARGET_BASE_ARCH'
3056      # Note that TARGET_BASE_ARCH ends up in config-target.h but it is
3057      # not used to select files from sourcesets.
3058      config_target_data.set('TARGET_' + v.to_upper(), 1)
3059    elif k == 'TARGET_NAME' or k == 'CONFIG_QEMU_INTERP_PREFIX'
3060      config_target_data.set_quoted(k, v)
3061    elif v == 'y'
3062      config_target_data.set(k, 1)
3063    elif v == 'n'
3064      config_target_data.set(k, 0)
3065    else
3066      config_target_data.set(k, v)
3067    endif
3068  endforeach
3069  config_target_data.set('QEMU_ARCH',
3070                         'QEMU_ARCH_' + config_target['TARGET_BASE_ARCH'].to_upper())
3071  config_target_h += {target: configure_file(output: target + '-config-target.h',
3072                                               configuration: config_target_data)}
3073
3074  if target.endswith('-softmmu')
3075    config_input = meson.get_external_property(target, 'default')
3076    config_devices_mak = target + '-config-devices.mak'
3077    config_devices_mak = configure_file(
3078      input: ['configs/devices' / target / config_input + '.mak', 'Kconfig'],
3079      output: config_devices_mak,
3080      depfile: config_devices_mak + '.d',
3081      capture: true,
3082      command: [minikconf,
3083                get_option('default_devices') ? '--defconfig' : '--allnoconfig',
3084                config_devices_mak, '@DEPFILE@', '@INPUT@',
3085                host_kconfig, accel_kconfig,
3086                'CONFIG_' + config_target['TARGET_ARCH'].to_upper() + '=y'])
3087
3088    config_devices_data = configuration_data()
3089    config_devices = keyval.load(config_devices_mak)
3090    foreach k, v: config_devices
3091      config_devices_data.set(k, 1)
3092    endforeach
3093    config_devices_mak_list += config_devices_mak
3094    config_devices_h += {target: configure_file(output: target + '-config-devices.h',
3095                                                configuration: config_devices_data)}
3096    config_target += config_devices
3097    config_all_devices += config_devices
3098  endif
3099  config_target_mak += {target: config_target}
3100endforeach
3101target_dirs = actual_target_dirs
3102
3103target_configs_h = []
3104foreach target: target_dirs
3105  target_configs_h += config_target_h[target]
3106  target_configs_h += config_devices_h.get(target, [])
3107endforeach
3108genh += custom_target('config-poison.h',
3109                      input: [target_configs_h],
3110                      output: 'config-poison.h',
3111                      capture: true,
3112                      command: [find_program('scripts/make-config-poison.sh'),
3113                                target_configs_h])
3114
3115###############
3116# Subprojects #
3117###############
3118
3119libvfio_user_dep = not_found
3120if have_system and vfio_user_server_allowed
3121  libvfio_user_proj = subproject('libvfio-user', required: true)
3122  libvfio_user_dep = libvfio_user_proj.get_variable('libvfio_user_dep')
3123endif
3124
3125fdt = not_found
3126fdt_opt = get_option('fdt')
3127if fdt_required.length() > 0 or fdt_opt == 'enabled'
3128  if fdt_opt == 'disabled'
3129    error('fdt disabled but required by targets ' + ', '.join(fdt_required))
3130  endif
3131
3132  if fdt_opt in ['enabled', 'auto', 'system']
3133    if get_option('wrap_mode') == 'nodownload'
3134      fdt_opt = 'system'
3135    endif
3136    fdt = cc.find_library('fdt', required: fdt_opt == 'system')
3137    if fdt.found() and cc.links('''
3138       #include <libfdt.h>
3139       #include <libfdt_env.h>
3140       int main(void) { fdt_find_max_phandle(NULL, NULL); return 0; }''',
3141         dependencies: fdt)
3142      fdt_opt = 'system'
3143    elif fdt_opt == 'system'
3144       error('system libfdt requested, but it is too old (1.5.1 or newer required)')
3145    else
3146      fdt_opt = 'internal'
3147      fdt = not_found
3148    endif
3149  endif
3150  if not fdt.found()
3151    assert(fdt_opt == 'internal')
3152    libfdt_proj = subproject('dtc', required: true,
3153                             default_options: ['tools=false',  'yaml=disabled',
3154                                               'python=disabled', 'default_library=static'])
3155    fdt = libfdt_proj.get_variable('libfdt_dep')
3156  endif
3157else
3158  fdt_opt = 'disabled'
3159endif
3160
3161config_host_data.set('CONFIG_FDT', fdt.found())
3162
3163vhost_user = not_found
3164if host_os == 'linux' and have_vhost_user
3165  libvhost_user = subproject('libvhost-user')
3166  vhost_user = libvhost_user.get_variable('vhost_user_dep')
3167endif
3168
3169libvduse = not_found
3170if have_libvduse
3171  libvduse_proj = subproject('libvduse')
3172  libvduse = libvduse_proj.get_variable('libvduse_dep')
3173endif
3174
3175#####################
3176# Generated sources #
3177#####################
3178
3179genh += configure_file(output: 'config-host.h', configuration: config_host_data)
3180
3181hxtool = find_program('scripts/hxtool')
3182shaderinclude = find_program('scripts/shaderinclude.py')
3183qapi_gen = find_program('scripts/qapi-gen.py')
3184qapi_gen_depends = [ meson.current_source_dir() / 'scripts/qapi/__init__.py',
3185                     meson.current_source_dir() / 'scripts/qapi/commands.py',
3186                     meson.current_source_dir() / 'scripts/qapi/common.py',
3187                     meson.current_source_dir() / 'scripts/qapi/error.py',
3188                     meson.current_source_dir() / 'scripts/qapi/events.py',
3189                     meson.current_source_dir() / 'scripts/qapi/expr.py',
3190                     meson.current_source_dir() / 'scripts/qapi/gen.py',
3191                     meson.current_source_dir() / 'scripts/qapi/introspect.py',
3192                     meson.current_source_dir() / 'scripts/qapi/main.py',
3193                     meson.current_source_dir() / 'scripts/qapi/parser.py',
3194                     meson.current_source_dir() / 'scripts/qapi/schema.py',
3195                     meson.current_source_dir() / 'scripts/qapi/source.py',
3196                     meson.current_source_dir() / 'scripts/qapi/types.py',
3197                     meson.current_source_dir() / 'scripts/qapi/visit.py',
3198                     meson.current_source_dir() / 'scripts/qapi-gen.py'
3199]
3200
3201tracetool = [
3202  python, files('scripts/tracetool.py'),
3203   '--backend=' + ','.join(get_option('trace_backends'))
3204]
3205tracetool_depends = files(
3206  'scripts/tracetool/backend/log.py',
3207  'scripts/tracetool/backend/__init__.py',
3208  'scripts/tracetool/backend/dtrace.py',
3209  'scripts/tracetool/backend/ftrace.py',
3210  'scripts/tracetool/backend/simple.py',
3211  'scripts/tracetool/backend/syslog.py',
3212  'scripts/tracetool/backend/ust.py',
3213  'scripts/tracetool/format/ust_events_c.py',
3214  'scripts/tracetool/format/ust_events_h.py',
3215  'scripts/tracetool/format/__init__.py',
3216  'scripts/tracetool/format/d.py',
3217  'scripts/tracetool/format/simpletrace_stap.py',
3218  'scripts/tracetool/format/c.py',
3219  'scripts/tracetool/format/h.py',
3220  'scripts/tracetool/format/log_stap.py',
3221  'scripts/tracetool/format/stap.py',
3222  'scripts/tracetool/__init__.py',
3223  'scripts/tracetool/vcpu.py'
3224)
3225
3226qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
3227                    meson.current_source_dir(),
3228                    get_option('pkgversion'), meson.project_version()]
3229qemu_version = custom_target('qemu-version.h',
3230                             output: 'qemu-version.h',
3231                             command: qemu_version_cmd,
3232                             capture: true,
3233                             build_by_default: true,
3234                             build_always_stale: true)
3235genh += qemu_version
3236
3237hxdep = []
3238hx_headers = [
3239  ['qemu-options.hx', 'qemu-options.def'],
3240  ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
3241]
3242if have_system
3243  hx_headers += [
3244    ['hmp-commands.hx', 'hmp-commands.h'],
3245    ['hmp-commands-info.hx', 'hmp-commands-info.h'],
3246  ]
3247endif
3248foreach d : hx_headers
3249  hxdep += custom_target(d[1],
3250                input: files(d[0]),
3251                output: d[1],
3252                capture: true,
3253                command: [hxtool, '-h', '@INPUT0@'])
3254endforeach
3255genh += hxdep
3256
3257###############
3258# Trace files #
3259###############
3260
3261# TODO: add each directory to the subdirs from its own meson.build, once
3262# we have those
3263trace_events_subdirs = [
3264  'crypto',
3265  'qapi',
3266  'qom',
3267  'monitor',
3268  'util',
3269  'gdbstub',
3270]
3271if have_linux_user
3272  trace_events_subdirs += [ 'linux-user' ]
3273endif
3274if have_bsd_user
3275  trace_events_subdirs += [ 'bsd-user' ]
3276endif
3277if have_block
3278  trace_events_subdirs += [
3279    'authz',
3280    'block',
3281    'io',
3282    'nbd',
3283    'scsi',
3284  ]
3285endif
3286if have_system
3287  trace_events_subdirs += [
3288    'accel/kvm',
3289    'audio',
3290    'backends',
3291    'backends/tpm',
3292    'chardev',
3293    'ebpf',
3294    'hw/9pfs',
3295    'hw/acpi',
3296    'hw/adc',
3297    'hw/alpha',
3298    'hw/arm',
3299    'hw/audio',
3300    'hw/block',
3301    'hw/char',
3302    'hw/display',
3303    'hw/dma',
3304    'hw/fsi',
3305    'hw/hyperv',
3306    'hw/i2c',
3307    'hw/i386',
3308    'hw/i386/xen',
3309    'hw/i386/kvm',
3310    'hw/ide',
3311    'hw/input',
3312    'hw/intc',
3313    'hw/isa',
3314    'hw/mem',
3315    'hw/mips',
3316    'hw/misc',
3317    'hw/misc/macio',
3318    'hw/net',
3319    'hw/net/can',
3320    'hw/nubus',
3321    'hw/nvme',
3322    'hw/nvram',
3323    'hw/pci',
3324    'hw/pci-host',
3325    'hw/ppc',
3326    'hw/rdma',
3327    'hw/rdma/vmw',
3328    'hw/rtc',
3329    'hw/s390x',
3330    'hw/scsi',
3331    'hw/sd',
3332    'hw/sh4',
3333    'hw/sparc',
3334    'hw/sparc64',
3335    'hw/ssi',
3336    'hw/timer',
3337    'hw/tpm',
3338    'hw/ufs',
3339    'hw/usb',
3340    'hw/vfio',
3341    'hw/virtio',
3342    'hw/watchdog',
3343    'hw/xen',
3344    'hw/gpio',
3345    'migration',
3346    'net',
3347    'system',
3348    'ui',
3349    'hw/remote',
3350  ]
3351endif
3352if have_system or have_user
3353  trace_events_subdirs += [
3354    'accel/tcg',
3355    'hw/core',
3356    'target/arm',
3357    'target/arm/hvf',
3358    'target/hppa',
3359    'target/i386',
3360    'target/i386/kvm',
3361    'target/loongarch',
3362    'target/mips/tcg',
3363    'target/nios2',
3364    'target/ppc',
3365    'target/riscv',
3366    'target/s390x',
3367    'target/s390x/kvm',
3368    'target/sparc',
3369  ]
3370endif
3371
3372###################
3373# Collect sources #
3374###################
3375
3376authz_ss = ss.source_set()
3377blockdev_ss = ss.source_set()
3378block_ss = ss.source_set()
3379chardev_ss = ss.source_set()
3380common_ss = ss.source_set()
3381crypto_ss = ss.source_set()
3382hwcore_ss = ss.source_set()
3383io_ss = ss.source_set()
3384qmp_ss = ss.source_set()
3385qom_ss = ss.source_set()
3386system_ss = ss.source_set()
3387specific_fuzz_ss = ss.source_set()
3388specific_ss = ss.source_set()
3389stub_ss = ss.source_set()
3390trace_ss = ss.source_set()
3391user_ss = ss.source_set()
3392util_ss = ss.source_set()
3393
3394# accel modules
3395qtest_module_ss = ss.source_set()
3396tcg_module_ss = ss.source_set()
3397
3398modules = {}
3399target_modules = {}
3400hw_arch = {}
3401target_arch = {}
3402target_system_arch = {}
3403target_user_arch = {}
3404
3405# NOTE: the trace/ subdirectory needs the qapi_trace_events variable
3406# that is filled in by qapi/.
3407subdir('qapi')
3408subdir('qobject')
3409subdir('stubs')
3410subdir('trace')
3411subdir('util')
3412subdir('qom')
3413subdir('authz')
3414subdir('crypto')
3415subdir('ui')
3416subdir('hw')
3417subdir('gdbstub')
3418
3419if enable_modules
3420  libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
3421  modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
3422endif
3423
3424qom_ss = qom_ss.apply({})
3425libqom = static_library('qom', qom_ss.sources() + genh,
3426                        dependencies: [qom_ss.dependencies()],
3427                        name_suffix: 'fa',
3428                        build_by_default: false)
3429qom = declare_dependency(link_whole: libqom)
3430
3431event_loop_base = files('event-loop-base.c')
3432event_loop_base = static_library('event-loop-base',
3433                                 sources: event_loop_base + genh,
3434                                 name_suffix: 'fa',
3435                                 build_by_default: false)
3436event_loop_base = declare_dependency(link_whole: event_loop_base,
3437                                     dependencies: [qom])
3438
3439stub_ss = stub_ss.apply({})
3440
3441util_ss.add_all(trace_ss)
3442util_ss = util_ss.apply({})
3443libqemuutil = static_library('qemuutil',
3444                             build_by_default: false,
3445                             sources: util_ss.sources() + stub_ss.sources() + genh,
3446                             dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc, pixman])
3447qemuutil = declare_dependency(link_with: libqemuutil,
3448                              sources: genh + version_res,
3449                              dependencies: [event_loop_base])
3450
3451if have_system or have_user
3452  decodetree = generator(find_program('scripts/decodetree.py'),
3453                         output: 'decode-@BASENAME@.c.inc',
3454                         arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
3455  subdir('libdecnumber')
3456  subdir('target')
3457endif
3458
3459subdir('audio')
3460subdir('io')
3461subdir('chardev')
3462subdir('fsdev')
3463subdir('dump')
3464
3465if have_block
3466  block_ss.add(files(
3467    'block.c',
3468    'blockjob.c',
3469    'job.c',
3470    'qemu-io-cmds.c',
3471  ))
3472  if config_host_data.get('CONFIG_REPLICATION')
3473    block_ss.add(files('replication.c'))
3474  endif
3475
3476  subdir('nbd')
3477  subdir('scsi')
3478  subdir('block')
3479
3480  blockdev_ss.add(files(
3481    'blockdev.c',
3482    'blockdev-nbd.c',
3483    'iothread.c',
3484    'job-qmp.c',
3485  ), gnutls)
3486
3487  # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
3488  # os-win32.c does not
3489  if host_os == 'windows'
3490    system_ss.add(files('os-win32.c'))
3491  else
3492    blockdev_ss.add(files('os-posix.c'))
3493  endif
3494endif
3495
3496common_ss.add(files('cpu-common.c'))
3497specific_ss.add(files('cpu-target.c'))
3498
3499subdir('system')
3500
3501# Work around a gcc bug/misfeature wherein constant propagation looks
3502# through an alias:
3503#   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99696
3504# to guess that a const variable is always zero.  Without lto, this is
3505# impossible, as the alias is restricted to page-vary-common.c.  Indeed,
3506# without lto, not even the alias is required -- we simply use different
3507# declarations in different compilation units.
3508pagevary = files('page-vary-common.c')
3509if get_option('b_lto')
3510  pagevary_flags = ['-fno-lto']
3511  if get_option('cfi')
3512    pagevary_flags += '-fno-sanitize=cfi-icall'
3513  endif
3514  pagevary = static_library('page-vary-common', sources: pagevary + genh,
3515                            c_args: pagevary_flags)
3516  pagevary = declare_dependency(link_with: pagevary)
3517endif
3518common_ss.add(pagevary)
3519specific_ss.add(files('page-vary-target.c'))
3520
3521subdir('backends')
3522subdir('disas')
3523subdir('migration')
3524subdir('monitor')
3525subdir('net')
3526subdir('replay')
3527subdir('semihosting')
3528subdir('stats')
3529subdir('tcg')
3530subdir('fpu')
3531subdir('accel')
3532subdir('plugins')
3533subdir('ebpf')
3534
3535common_user_inc = []
3536
3537subdir('common-user')
3538subdir('bsd-user')
3539subdir('linux-user')
3540
3541# needed for fuzzing binaries
3542subdir('tests/qtest/libqos')
3543subdir('tests/qtest/fuzz')
3544
3545# accel modules
3546tcg_real_module_ss = ss.source_set()
3547tcg_real_module_ss.add_all(when: 'CONFIG_TCG_MODULAR', if_true: tcg_module_ss)
3548specific_ss.add_all(when: 'CONFIG_TCG_BUILTIN', if_true: tcg_module_ss)
3549target_modules += { 'accel' : { 'qtest': qtest_module_ss,
3550                                'tcg': tcg_real_module_ss }}
3551
3552##############################################
3553# Internal static_libraries and dependencies #
3554##############################################
3555
3556modinfo_collect = find_program('scripts/modinfo-collect.py')
3557modinfo_generate = find_program('scripts/modinfo-generate.py')
3558modinfo_files = []
3559
3560block_mods = []
3561system_mods = []
3562foreach d, list : modules
3563  if not (d == 'block' ? have_block : have_system)
3564    continue
3565  endif
3566
3567  foreach m, module_ss : list
3568    if enable_modules
3569      module_ss = module_ss.apply(config_all_devices, strict: false)
3570      sl = static_library(d + '-' + m, [genh, module_ss.sources()],
3571                          dependencies: [modulecommon, module_ss.dependencies()], pic: true)
3572      if d == 'block'
3573        block_mods += sl
3574      else
3575        system_mods += sl
3576      endif
3577      if module_ss.sources() != []
3578        # FIXME: Should use sl.extract_all_objects(recursive: true) as
3579        # input. Sources can be used multiple times but objects are
3580        # unique when it comes to lookup in compile_commands.json.
3581        # Depnds on a mesion version with
3582        # https://github.com/mesonbuild/meson/pull/8900
3583        modinfo_files += custom_target(d + '-' + m + '.modinfo',
3584                                       output: d + '-' + m + '.modinfo',
3585                                       input: module_ss.sources() + genh,
3586                                       capture: true,
3587                                       command: [modinfo_collect, module_ss.sources()])
3588      endif
3589    else
3590      if d == 'block'
3591        block_ss.add_all(module_ss)
3592      else
3593        system_ss.add_all(module_ss)
3594      endif
3595    endif
3596  endforeach
3597endforeach
3598
3599foreach d, list : target_modules
3600  foreach m, module_ss : list
3601    if enable_modules
3602      foreach target : target_dirs
3603        if target.endswith('-softmmu')
3604          config_target = config_target_mak[target]
3605          target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3606          c_args = ['-DNEED_CPU_H',
3607                    '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3608                    '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3609          target_module_ss = module_ss.apply(config_target, strict: false)
3610          if target_module_ss.sources() != []
3611            module_name = d + '-' + m + '-' + config_target['TARGET_NAME']
3612            sl = static_library(module_name,
3613                                [genh, target_module_ss.sources()],
3614                                dependencies: [modulecommon, target_module_ss.dependencies()],
3615                                include_directories: target_inc,
3616                                c_args: c_args,
3617                                pic: true)
3618            system_mods += sl
3619            # FIXME: Should use sl.extract_all_objects(recursive: true) too.
3620            modinfo_files += custom_target(module_name + '.modinfo',
3621                                           output: module_name + '.modinfo',
3622                                           input: target_module_ss.sources() + genh,
3623                                           capture: true,
3624                                           command: [modinfo_collect, '--target', target, target_module_ss.sources()])
3625          endif
3626        endif
3627      endforeach
3628    else
3629      specific_ss.add_all(module_ss)
3630    endif
3631  endforeach
3632endforeach
3633
3634if enable_modules
3635  foreach target : target_dirs
3636    if target.endswith('-softmmu')
3637      config_target = config_target_mak[target]
3638      config_devices_mak = target + '-config-devices.mak'
3639      modinfo_src = custom_target('modinfo-' + target + '.c',
3640                                  output: 'modinfo-' + target + '.c',
3641                                  input: modinfo_files,
3642                                  command: [modinfo_generate, '--devices', config_devices_mak, '@INPUT@'],
3643                                  capture: true)
3644
3645      modinfo_lib = static_library('modinfo-' + target + '.c', modinfo_src)
3646      modinfo_dep = declare_dependency(link_with: modinfo_lib)
3647
3648      arch = config_target['TARGET_NAME'] == 'sparc64' ? 'sparc64' : config_target['TARGET_BASE_ARCH']
3649      hw_arch[arch].add(modinfo_dep)
3650    endif
3651  endforeach
3652endif
3653
3654nm = find_program('nm')
3655undefsym = find_program('scripts/undefsym.py')
3656block_syms = custom_target('block.syms', output: 'block.syms',
3657                             input: [libqemuutil, block_mods],
3658                             capture: true,
3659                             command: [undefsym, nm, '@INPUT@'])
3660qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
3661                             input: [libqemuutil, system_mods],
3662                             capture: true,
3663                             command: [undefsym, nm, '@INPUT@'])
3664
3665authz_ss = authz_ss.apply({})
3666libauthz = static_library('authz', authz_ss.sources() + genh,
3667                          dependencies: [authz_ss.dependencies()],
3668                          name_suffix: 'fa',
3669                          build_by_default: false)
3670
3671authz = declare_dependency(link_whole: libauthz,
3672                           dependencies: qom)
3673
3674crypto_ss = crypto_ss.apply({})
3675libcrypto = static_library('crypto', crypto_ss.sources() + genh,
3676                           dependencies: [crypto_ss.dependencies()],
3677                           name_suffix: 'fa',
3678                           build_by_default: false)
3679
3680crypto = declare_dependency(link_whole: libcrypto,
3681                            dependencies: [authz, qom])
3682
3683io_ss = io_ss.apply({})
3684libio = static_library('io', io_ss.sources() + genh,
3685                       dependencies: [io_ss.dependencies()],
3686                       link_with: libqemuutil,
3687                       name_suffix: 'fa',
3688                       build_by_default: false)
3689
3690io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
3691
3692libmigration = static_library('migration', sources: migration_files + genh,
3693                              name_suffix: 'fa',
3694                              build_by_default: false)
3695migration = declare_dependency(link_with: libmigration,
3696                               dependencies: [zlib, qom, io])
3697system_ss.add(migration)
3698
3699block_ss = block_ss.apply({})
3700libblock = static_library('block', block_ss.sources() + genh,
3701                          dependencies: block_ss.dependencies(),
3702                          link_depends: block_syms,
3703                          name_suffix: 'fa',
3704                          build_by_default: false)
3705
3706block = declare_dependency(link_whole: [libblock],
3707                           link_args: '@block.syms',
3708                           dependencies: [crypto, io])
3709
3710blockdev_ss = blockdev_ss.apply({})
3711libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
3712                             dependencies: blockdev_ss.dependencies(),
3713                             name_suffix: 'fa',
3714                             build_by_default: false)
3715
3716blockdev = declare_dependency(link_whole: [libblockdev],
3717                              dependencies: [block, event_loop_base])
3718
3719qmp_ss = qmp_ss.apply({})
3720libqmp = static_library('qmp', qmp_ss.sources() + genh,
3721                        dependencies: qmp_ss.dependencies(),
3722                        name_suffix: 'fa',
3723                        build_by_default: false)
3724
3725qmp = declare_dependency(link_whole: [libqmp])
3726
3727libchardev = static_library('chardev', chardev_ss.sources() + genh,
3728                            name_suffix: 'fa',
3729                            dependencies: chardev_ss.dependencies(),
3730                            build_by_default: false)
3731
3732chardev = declare_dependency(link_whole: libchardev)
3733
3734hwcore_ss = hwcore_ss.apply({})
3735libhwcore = static_library('hwcore', sources: hwcore_ss.sources() + genh,
3736                           name_suffix: 'fa',
3737                           build_by_default: false)
3738hwcore = declare_dependency(link_whole: libhwcore)
3739common_ss.add(hwcore)
3740
3741###########
3742# Targets #
3743###########
3744
3745emulator_modules = []
3746foreach m : block_mods + system_mods
3747  emulator_modules += shared_module(m.name(),
3748                build_by_default: true,
3749                name_prefix: '',
3750                link_whole: m,
3751                install: true,
3752                install_dir: qemu_moddir)
3753endforeach
3754if emulator_modules.length() > 0
3755  alias_target('modules', emulator_modules)
3756endif
3757
3758system_ss.add(authz, blockdev, chardev, crypto, io, qmp)
3759common_ss.add(qom, qemuutil)
3760
3761common_ss.add_all(when: 'CONFIG_SYSTEM_ONLY', if_true: [system_ss])
3762common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
3763
3764# Note that this library is never used directly (only through extract_objects)
3765# and is not built by default; therefore, source files not used by the build
3766# configuration will be in build.ninja, but are never built by default.
3767common_all = static_library('common',
3768                            build_by_default: false,
3769                            sources: common_ss.all_sources() + genh,
3770                            include_directories: common_user_inc,
3771                            implicit_include_directories: false,
3772                            dependencies: common_ss.all_dependencies(),
3773                            name_suffix: 'fa')
3774
3775feature_to_c = find_program('scripts/feature_to_c.py')
3776
3777if host_os == 'darwin'
3778  entitlement = find_program('scripts/entitlement.sh')
3779endif
3780
3781emulators = {}
3782foreach target : target_dirs
3783  config_target = config_target_mak[target]
3784  target_name = config_target['TARGET_NAME']
3785  target_base_arch = config_target['TARGET_BASE_ARCH']
3786  arch_srcs = [config_target_h[target]]
3787  arch_deps = []
3788  c_args = ['-DNEED_CPU_H',
3789            '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3790            '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3791  link_args = emulator_link_args
3792
3793  target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3794  if host_os == 'linux'
3795    target_inc += include_directories('linux-headers', is_system: true)
3796  endif
3797  if target.endswith('-softmmu')
3798    target_type='system'
3799    t = target_system_arch[target_base_arch].apply(config_target, strict: false)
3800    arch_srcs += t.sources()
3801    arch_deps += t.dependencies()
3802
3803    hw_dir = target_name == 'sparc64' ? 'sparc64' : target_base_arch
3804    if hw_arch.has_key(hw_dir)
3805      hw = hw_arch[hw_dir].apply(config_target, strict: false)
3806      arch_srcs += hw.sources()
3807      arch_deps += hw.dependencies()
3808    endif
3809
3810    arch_srcs += config_devices_h[target]
3811    link_args += ['@block.syms', '@qemu.syms']
3812  else
3813    abi = config_target['TARGET_ABI_DIR']
3814    target_type='user'
3815    target_inc += common_user_inc
3816    if target_base_arch in target_user_arch
3817      t = target_user_arch[target_base_arch].apply(config_target, strict: false)
3818      arch_srcs += t.sources()
3819      arch_deps += t.dependencies()
3820    endif
3821    if 'CONFIG_LINUX_USER' in config_target
3822      base_dir = 'linux-user'
3823    endif
3824    if 'CONFIG_BSD_USER' in config_target
3825      base_dir = 'bsd-user'
3826      target_inc += include_directories('bsd-user/' / host_os)
3827      target_inc += include_directories('bsd-user/host/' / host_arch)
3828      dir = base_dir / abi
3829      arch_srcs += files(dir / 'signal.c', dir / 'target_arch_cpu.c')
3830    endif
3831    target_inc += include_directories(
3832      base_dir,
3833      base_dir / abi,
3834    )
3835    if 'CONFIG_LINUX_USER' in config_target
3836      dir = base_dir / abi
3837      arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
3838      if config_target.has_key('TARGET_SYSTBL_ABI')
3839        arch_srcs += \
3840          syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
3841                                             extra_args : config_target['TARGET_SYSTBL_ABI'])
3842      endif
3843    endif
3844  endif
3845
3846  if 'TARGET_XML_FILES' in config_target
3847    gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
3848                                output: target + '-gdbstub-xml.c',
3849                                input: files(config_target['TARGET_XML_FILES'].split()),
3850                                command: [feature_to_c, '@INPUT@'],
3851                                capture: true)
3852    arch_srcs += gdbstub_xml
3853  endif
3854
3855  t = target_arch[target_base_arch].apply(config_target, strict: false)
3856  arch_srcs += t.sources()
3857  arch_deps += t.dependencies()
3858
3859  target_common = common_ss.apply(config_target, strict: false)
3860  objects = common_all.extract_objects(target_common.sources())
3861  deps = target_common.dependencies()
3862
3863  target_specific = specific_ss.apply(config_target, strict: false)
3864  arch_srcs += target_specific.sources()
3865  arch_deps += target_specific.dependencies()
3866
3867  lib = static_library('qemu-' + target,
3868                 sources: arch_srcs + genh,
3869                 dependencies: arch_deps,
3870                 objects: objects,
3871                 include_directories: target_inc,
3872                 c_args: c_args,
3873                 build_by_default: false,
3874                 name_suffix: 'fa')
3875
3876  if target.endswith('-softmmu')
3877    execs = [{
3878      'name': 'qemu-system-' + target_name,
3879      'win_subsystem': 'console',
3880      'sources': files('system/main.c'),
3881      'dependencies': []
3882    }]
3883    if host_os == 'windows' and (sdl.found() or gtk.found())
3884      execs += [{
3885        'name': 'qemu-system-' + target_name + 'w',
3886        'win_subsystem': 'windows',
3887        'sources': files('system/main.c'),
3888        'dependencies': []
3889      }]
3890    endif
3891    if get_option('fuzzing')
3892      specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
3893      execs += [{
3894        'name': 'qemu-fuzz-' + target_name,
3895        'win_subsystem': 'console',
3896        'sources': specific_fuzz.sources(),
3897        'dependencies': specific_fuzz.dependencies(),
3898      }]
3899    endif
3900  else
3901    execs = [{
3902      'name': 'qemu-' + target_name,
3903      'win_subsystem': 'console',
3904      'sources': [],
3905      'dependencies': []
3906    }]
3907  endif
3908  foreach exe: execs
3909    exe_name = exe['name']
3910    if host_os == 'darwin'
3911      exe_name += '-unsigned'
3912    endif
3913
3914    emulator = executable(exe_name, exe['sources'],
3915               install: true,
3916               c_args: c_args,
3917               dependencies: arch_deps + deps + exe['dependencies'],
3918               objects: lib.extract_all_objects(recursive: true),
3919               link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
3920               link_args: link_args,
3921               win_subsystem: exe['win_subsystem'])
3922
3923    if host_os == 'darwin'
3924      icon = 'pc-bios/qemu.rsrc'
3925      build_input = [emulator, files(icon)]
3926      install_input = [
3927        get_option('bindir') / exe_name,
3928        meson.current_source_dir() / icon
3929      ]
3930      if 'CONFIG_HVF' in config_target
3931        entitlements = 'accel/hvf/entitlements.plist'
3932        build_input += files(entitlements)
3933        install_input += meson.current_source_dir() / entitlements
3934      endif
3935
3936      emulators += {exe['name'] : custom_target(exe['name'],
3937                   input: build_input,
3938                   output: exe['name'],
3939                   command: [entitlement, '@OUTPUT@', '@INPUT@'])
3940      }
3941
3942      meson.add_install_script(entitlement, '--install',
3943                               get_option('bindir') / exe['name'],
3944                               install_input)
3945    else
3946      emulators += {exe['name']: emulator}
3947    endif
3948
3949    if stap.found()
3950      foreach stp: [
3951        {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
3952        {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
3953        {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
3954        {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
3955      ]
3956        custom_target(exe['name'] + stp['ext'],
3957                      input: trace_events_all,
3958                      output: exe['name'] + stp['ext'],
3959                      install: stp['install'],
3960                      install_dir: get_option('datadir') / 'systemtap/tapset',
3961                      command: [
3962                        tracetool, '--group=all', '--format=' + stp['fmt'],
3963                        '--binary=' + stp['bin'],
3964                        '--target-name=' + target_name,
3965                        '--target-type=' + target_type,
3966                        '--probe-prefix=qemu.' + target_type + '.' + target_name,
3967                        '@INPUT@', '@OUTPUT@'
3968                      ],
3969                      depend_files: tracetool_depends)
3970      endforeach
3971    endif
3972  endforeach
3973endforeach
3974
3975# Other build targets
3976
3977if get_option('plugins')
3978  install_headers('include/qemu/qemu-plugin.h')
3979  if host_os == 'windows'
3980    # On windows, we want to deliver the qemu_plugin_api.lib file in the qemu installer,
3981    # so that plugin authors can compile against it.
3982    install_data(win32_qemu_plugin_api_lib, install_dir: 'lib')
3983  endif
3984endif
3985
3986subdir('qga')
3987
3988# Don't build qemu-keymap if xkbcommon is not explicitly enabled
3989# when we don't build tools or system
3990if xkbcommon.found()
3991  # used for the update-keymaps target, so include rules even if !have_tools
3992  qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
3993                           dependencies: [qemuutil, xkbcommon], install: have_tools)
3994endif
3995
3996if have_tools
3997  qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
3998             dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
3999  qemu_io = executable('qemu-io', files('qemu-io.c'),
4000             dependencies: [block, qemuutil], install: true)
4001  qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
4002               dependencies: [blockdev, qemuutil, gnutls, selinux],
4003               install: true)
4004
4005  subdir('storage-daemon')
4006  subdir('contrib/rdmacm-mux')
4007  subdir('contrib/elf2dmp')
4008
4009  executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
4010             dependencies: qemuutil,
4011             install: true)
4012
4013  if have_vhost_user
4014    subdir('contrib/vhost-user-blk')
4015    subdir('contrib/vhost-user-gpu')
4016    subdir('contrib/vhost-user-input')
4017    subdir('contrib/vhost-user-scsi')
4018  endif
4019
4020  if host_os == 'linux'
4021    executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
4022               dependencies: [qemuutil, libcap_ng],
4023               install: true,
4024               install_dir: get_option('libexecdir'))
4025
4026    executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
4027               dependencies: [authz, crypto, io, qom, qemuutil,
4028                              libcap_ng, mpathpersist],
4029               install: true)
4030  endif
4031
4032  if have_ivshmem
4033    subdir('contrib/ivshmem-client')
4034    subdir('contrib/ivshmem-server')
4035  endif
4036endif
4037
4038subdir('scripts')
4039subdir('tools')
4040subdir('pc-bios')
4041subdir('docs')
4042subdir('tests')
4043if gtk.found()
4044  subdir('po')
4045endif
4046
4047if host_machine.system() == 'windows'
4048  nsis_cmd = [
4049    find_program('scripts/nsis.py'),
4050    '@OUTPUT@',
4051    get_option('prefix'),
4052    meson.current_source_dir(),
4053    glib_pc.get_variable('bindir'),
4054    host_machine.cpu(),
4055    '--',
4056    '-DDISPLAYVERSION=' + meson.project_version(),
4057  ]
4058  if build_docs
4059    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
4060  endif
4061  if gtk.found()
4062    nsis_cmd += '-DCONFIG_GTK=y'
4063  endif
4064
4065  nsis = custom_target('nsis',
4066                       output: 'qemu-setup-' + meson.project_version() + '.exe',
4067                       input: files('qemu.nsi'),
4068                       build_always_stale: true,
4069                       command: nsis_cmd + ['@INPUT@'])
4070  alias_target('installer', nsis)
4071endif
4072
4073#########################
4074# Configuration summary #
4075#########################
4076
4077# Build environment
4078summary_info = {}
4079summary_info += {'Build directory':   meson.current_build_dir()}
4080summary_info += {'Source path':       meson.current_source_dir()}
4081summary_info += {'Download dependencies': get_option('wrap_mode') != 'nodownload'}
4082summary(summary_info, bool_yn: true, section: 'Build environment')
4083
4084# Directories
4085summary_info += {'Install prefix':    get_option('prefix')}
4086summary_info += {'BIOS directory':    qemu_datadir}
4087pathsep = host_os == 'windows' ? ';' : ':'
4088summary_info += {'firmware path':     pathsep.join(get_option('qemu_firmwarepath'))}
4089summary_info += {'binary directory':  get_option('prefix') / get_option('bindir')}
4090summary_info += {'library directory': get_option('prefix') / get_option('libdir')}
4091summary_info += {'module directory':  qemu_moddir}
4092summary_info += {'libexec directory': get_option('prefix') / get_option('libexecdir')}
4093summary_info += {'include directory': get_option('prefix') / get_option('includedir')}
4094summary_info += {'config directory':  get_option('prefix') / get_option('sysconfdir')}
4095if host_os != 'windows'
4096  summary_info += {'local state directory': get_option('prefix') / get_option('localstatedir')}
4097  summary_info += {'Manual directory':      get_option('prefix') / get_option('mandir')}
4098else
4099  summary_info += {'local state directory': 'queried at runtime'}
4100endif
4101summary_info += {'Doc directory':     get_option('prefix') / get_option('docdir')}
4102summary(summary_info, bool_yn: true, section: 'Directories')
4103
4104# Host binaries
4105summary_info = {}
4106summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
4107summary_info += {'sphinx-build':      sphinx_build}
4108
4109# FIXME: the [binaries] section of machine files, which can be probed
4110# with find_program(), would be great for passing gdb and genisoimage
4111# paths from configure to Meson.  However, there seems to be no way to
4112# hide a program (for example if gdb is too old).
4113if config_host.has_key('GDB')
4114  summary_info += {'gdb':             config_host['GDB']}
4115endif
4116summary_info += {'iasl':              iasl}
4117summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
4118if host_os == 'windows' and have_ga
4119  summary_info += {'wixl':            wixl}
4120endif
4121if slirp.found() and have_system
4122  summary_info += {'smbd':            have_slirp_smbd ? smbd_path : false}
4123endif
4124summary(summary_info, bool_yn: true, section: 'Host binaries')
4125
4126# Configurable features
4127summary_info = {}
4128summary_info += {'Documentation':     build_docs}
4129summary_info += {'system-mode emulation': have_system}
4130summary_info += {'user-mode emulation': have_user}
4131summary_info += {'block layer':       have_block}
4132summary_info += {'Install blobs':     get_option('install_blobs')}
4133summary_info += {'module support':    enable_modules}
4134if enable_modules
4135  summary_info += {'alternative module path': get_option('module_upgrades')}
4136endif
4137summary_info += {'fuzzing support':   get_option('fuzzing')}
4138if have_system
4139  summary_info += {'Audio drivers':     ' '.join(audio_drivers_selected)}
4140endif
4141summary_info += {'Trace backends':    ','.join(get_option('trace_backends'))}
4142if 'simple' in get_option('trace_backends')
4143  summary_info += {'Trace output file': get_option('trace_file') + '-<pid>'}
4144endif
4145summary_info += {'D-Bus display':     dbus_display}
4146summary_info += {'QOM debugging':     get_option('qom_cast_debug')}
4147summary_info += {'Relocatable install': get_option('relocatable')}
4148summary_info += {'vhost-kernel support': have_vhost_kernel}
4149summary_info += {'vhost-net support': have_vhost_net}
4150summary_info += {'vhost-user support': have_vhost_user}
4151summary_info += {'vhost-user-crypto support': have_vhost_user_crypto}
4152summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
4153summary_info += {'vhost-vdpa support': have_vhost_vdpa}
4154summary_info += {'build guest agent': have_ga}
4155summary(summary_info, bool_yn: true, section: 'Configurable features')
4156
4157# Compilation information
4158summary_info = {}
4159summary_info += {'host CPU':          cpu}
4160summary_info += {'host endianness':   build_machine.endian()}
4161summary_info += {'C compiler':        ' '.join(meson.get_compiler('c').cmd_array())}
4162summary_info += {'Host C compiler':   ' '.join(meson.get_compiler('c', native: true).cmd_array())}
4163if 'cpp' in all_languages
4164  summary_info += {'C++ compiler':    ' '.join(meson.get_compiler('cpp').cmd_array())}
4165else
4166  summary_info += {'C++ compiler':      false}
4167endif
4168if 'objc' in all_languages
4169  summary_info += {'Objective-C compiler': ' '.join(meson.get_compiler('objc').cmd_array())}
4170else
4171  summary_info += {'Objective-C compiler': false}
4172endif
4173option_cflags = (get_option('debug') ? ['-g'] : [])
4174if get_option('optimization') != 'plain'
4175  option_cflags += ['-O' + get_option('optimization')]
4176endif
4177summary_info += {'CFLAGS':            ' '.join(get_option('c_args') + option_cflags)}
4178if 'cpp' in all_languages
4179  summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args') + option_cflags)}
4180endif
4181if 'objc' in all_languages
4182  summary_info += {'OBJCFLAGS':       ' '.join(get_option('objc_args') + option_cflags)}
4183endif
4184link_args = get_option('c_link_args')
4185if link_args.length() > 0
4186  summary_info += {'LDFLAGS':         ' '.join(link_args)}
4187endif
4188summary_info += {'QEMU_CFLAGS':       ' '.join(qemu_common_flags + qemu_cflags)}
4189if 'cpp' in all_languages
4190  summary_info += {'QEMU_CXXFLAGS':     ' '.join(qemu_common_flags + qemu_cxxflags)}
4191endif
4192if 'objc' in all_languages
4193  summary_info += {'QEMU_OBJCFLAGS':    ' '.join(qemu_common_flags)}
4194endif
4195summary_info += {'QEMU_LDFLAGS':      ' '.join(qemu_ldflags)}
4196summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
4197summary_info += {'PIE':               get_option('b_pie')}
4198summary_info += {'static build':      get_option('prefer_static')}
4199summary_info += {'malloc trim support': has_malloc_trim}
4200summary_info += {'membarrier':        have_membarrier}
4201summary_info += {'debug graph lock':  get_option('debug_graph_lock')}
4202summary_info += {'debug stack usage': get_option('debug_stack_usage')}
4203summary_info += {'mutex debugging':   get_option('debug_mutex')}
4204summary_info += {'memory allocator':  get_option('malloc')}
4205summary_info += {'avx2 optimization': config_host_data.get('CONFIG_AVX2_OPT')}
4206summary_info += {'avx512bw optimization': config_host_data.get('CONFIG_AVX512BW_OPT')}
4207summary_info += {'avx512f optimization': config_host_data.get('CONFIG_AVX512F_OPT')}
4208summary_info += {'gcov':              get_option('b_coverage')}
4209summary_info += {'thread sanitizer':  get_option('tsan')}
4210summary_info += {'CFI support':       get_option('cfi')}
4211if get_option('cfi')
4212  summary_info += {'CFI debug support': get_option('cfi_debug')}
4213endif
4214summary_info += {'strip binaries':    get_option('strip')}
4215summary_info += {'sparse':            sparse}
4216summary_info += {'mingw32 support':   host_os == 'windows'}
4217summary(summary_info, bool_yn: true, section: 'Compilation')
4218
4219# snarf the cross-compilation information for tests
4220summary_info = {}
4221have_cross = false
4222foreach target: target_dirs
4223  tcg_mak = meson.current_build_dir() / 'tests/tcg' / target / 'config-target.mak'
4224  if fs.exists(tcg_mak)
4225    config_cross_tcg = keyval.load(tcg_mak)
4226    if 'CC' in config_cross_tcg
4227      summary_info += {config_cross_tcg['TARGET_NAME']: config_cross_tcg['CC']}
4228      have_cross = true
4229    endif
4230  endif
4231endforeach
4232if have_cross
4233  summary(summary_info, bool_yn: true, section: 'Cross compilers')
4234endif
4235
4236# Targets and accelerators
4237summary_info = {}
4238if have_system
4239  summary_info += {'KVM support':       config_all_accel.has_key('CONFIG_KVM')}
4240  summary_info += {'HVF support':       config_all_accel.has_key('CONFIG_HVF')}
4241  summary_info += {'WHPX support':      config_all_accel.has_key('CONFIG_WHPX')}
4242  summary_info += {'NVMM support':      config_all_accel.has_key('CONFIG_NVMM')}
4243  summary_info += {'Xen support':       xen.found()}
4244  if xen.found()
4245    summary_info += {'xen ctrl version':  xen.version()}
4246  endif
4247  summary_info += {'Xen emulation':     config_all_devices.has_key('CONFIG_XEN_EMU')}
4248endif
4249summary_info += {'TCG support':       config_all_accel.has_key('CONFIG_TCG')}
4250if config_all_accel.has_key('CONFIG_TCG')
4251  if get_option('tcg_interpreter')
4252    summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, slow)'}
4253  else
4254    summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
4255  endif
4256  summary_info += {'TCG plugins':       get_option('plugins')}
4257  summary_info += {'TCG debug enabled': get_option('debug_tcg')}
4258endif
4259summary_info += {'target list':       ' '.join(target_dirs)}
4260if have_system
4261  summary_info += {'default devices':   get_option('default_devices')}
4262  summary_info += {'out of process emulation': multiprocess_allowed}
4263  summary_info += {'vfio-user server': vfio_user_server_allowed}
4264endif
4265summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
4266
4267# Block layer
4268summary_info = {}
4269summary_info += {'coroutine backend': coroutine_backend}
4270summary_info += {'coroutine pool':    have_coroutine_pool}
4271if have_block
4272  summary_info += {'Block whitelist (rw)': get_option('block_drv_rw_whitelist')}
4273  summary_info += {'Block whitelist (ro)': get_option('block_drv_ro_whitelist')}
4274  summary_info += {'Use block whitelist in tools': get_option('block_drv_whitelist_in_tools')}
4275  summary_info += {'VirtFS (9P) support':    have_virtfs}
4276  summary_info += {'VirtFS (9P) Proxy Helper support (deprecated)': have_virtfs_proxy_helper}
4277  summary_info += {'Live block migration': config_host_data.get('CONFIG_LIVE_BLOCK_MIGRATION')}
4278  summary_info += {'replication support': config_host_data.get('CONFIG_REPLICATION')}
4279  summary_info += {'bochs support':     get_option('bochs').allowed()}
4280  summary_info += {'cloop support':     get_option('cloop').allowed()}
4281  summary_info += {'dmg support':       get_option('dmg').allowed()}
4282  summary_info += {'qcow v1 support':   get_option('qcow1').allowed()}
4283  summary_info += {'vdi support':       get_option('vdi').allowed()}
4284  summary_info += {'vhdx support':      get_option('vhdx').allowed()}
4285  summary_info += {'vmdk support':      get_option('vmdk').allowed()}
4286  summary_info += {'vpc support':       get_option('vpc').allowed()}
4287  summary_info += {'vvfat support':     get_option('vvfat').allowed()}
4288  summary_info += {'qed support':       get_option('qed').allowed()}
4289  summary_info += {'parallels support': get_option('parallels').allowed()}
4290  summary_info += {'FUSE exports':      fuse}
4291  summary_info += {'VDUSE block exports': have_vduse_blk_export}
4292endif
4293summary(summary_info, bool_yn: true, section: 'Block layer support')
4294
4295# Crypto
4296summary_info = {}
4297summary_info += {'TLS priority':      get_option('tls_priority')}
4298summary_info += {'GNUTLS support':    gnutls}
4299if gnutls.found()
4300  summary_info += {'  GNUTLS crypto':   gnutls_crypto.found()}
4301endif
4302summary_info += {'libgcrypt':         gcrypt}
4303summary_info += {'nettle':            nettle}
4304if nettle.found()
4305   summary_info += {'  XTS':             xts != 'private'}
4306endif
4307summary_info += {'AF_ALG support':    have_afalg}
4308summary_info += {'rng-none':          get_option('rng_none')}
4309summary_info += {'Linux keyring':     have_keyring}
4310summary_info += {'Linux keyutils':    keyutils}
4311summary(summary_info, bool_yn: true, section: 'Crypto')
4312
4313# UI
4314summary_info = {}
4315if host_os == 'darwin'
4316  summary_info += {'Cocoa support':           cocoa}
4317endif
4318summary_info += {'SDL support':       sdl}
4319summary_info += {'SDL image support': sdl_image}
4320summary_info += {'GTK support':       gtk}
4321summary_info += {'pixman':            pixman}
4322summary_info += {'VTE support':       vte}
4323summary_info += {'PNG support':       png}
4324summary_info += {'VNC support':       vnc}
4325if vnc.found()
4326  summary_info += {'VNC SASL support':  sasl}
4327  summary_info += {'VNC JPEG support':  jpeg}
4328endif
4329summary_info += {'spice protocol support': spice_protocol}
4330if spice_protocol.found()
4331  summary_info += {'  spice server support': spice}
4332endif
4333summary_info += {'curses support':    curses}
4334summary_info += {'brlapi support':    brlapi}
4335summary(summary_info, bool_yn: true, section: 'User interface')
4336
4337# Graphics backends
4338summary_info = {}
4339summary_info += {'VirGL support':     virgl}
4340summary_info += {'Rutabaga support':  rutabaga}
4341summary(summary_info, bool_yn: true, section: 'Graphics backends')
4342
4343# Audio backends
4344summary_info = {}
4345if host_os not in ['darwin', 'haiku', 'windows']
4346  summary_info += {'OSS support':     oss}
4347  summary_info += {'sndio support':   sndio}
4348elif host_os == 'darwin'
4349  summary_info += {'CoreAudio support': coreaudio}
4350elif host_os == 'windows'
4351  summary_info += {'DirectSound support': dsound}
4352endif
4353if host_os == 'linux'
4354  summary_info += {'ALSA support':    alsa}
4355  summary_info += {'PulseAudio support': pulse}
4356endif
4357summary_info += {'PipeWire support':  pipewire}
4358summary_info += {'JACK support':      jack}
4359summary(summary_info, bool_yn: true, section: 'Audio backends')
4360
4361# Network backends
4362summary_info = {}
4363if host_os == 'darwin'
4364  summary_info += {'vmnet.framework support': vmnet}
4365endif
4366summary_info += {'AF_XDP support':    libxdp}
4367summary_info += {'slirp support':     slirp}
4368summary_info += {'vde support':       vde}
4369summary_info += {'netmap support':    have_netmap}
4370summary_info += {'l2tpv3 support':    have_l2tpv3}
4371summary(summary_info, bool_yn: true, section: 'Network backends')
4372
4373# Libraries
4374summary_info = {}
4375summary_info += {'libtasn1':          tasn1}
4376summary_info += {'PAM':               pam}
4377summary_info += {'iconv support':     iconv}
4378summary_info += {'blkio support':     blkio}
4379summary_info += {'curl support':      curl}
4380summary_info += {'Multipath support': mpathpersist}
4381summary_info += {'Linux AIO support': libaio}
4382summary_info += {'Linux io_uring support': linux_io_uring}
4383summary_info += {'ATTR/XATTR support': libattr}
4384summary_info += {'RDMA support':      rdma}
4385summary_info += {'PVRDMA support':    have_pvrdma}
4386summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
4387summary_info += {'libcap-ng support': libcap_ng}
4388summary_info += {'bpf support':       libbpf}
4389summary_info += {'rbd support':       rbd}
4390summary_info += {'smartcard support': cacard}
4391summary_info += {'U2F support':       u2f}
4392summary_info += {'libusb':            libusb}
4393summary_info += {'usb net redir':     usbredir}
4394summary_info += {'OpenGL support (epoxy)': opengl}
4395summary_info += {'GBM':               gbm}
4396summary_info += {'libiscsi support':  libiscsi}
4397summary_info += {'libnfs support':    libnfs}
4398if host_os == 'windows'
4399  if have_ga
4400    summary_info += {'QGA VSS support':   have_qga_vss}
4401  endif
4402endif
4403summary_info += {'seccomp support':   seccomp}
4404summary_info += {'GlusterFS support': glusterfs}
4405summary_info += {'hv-balloon support': hv_balloon}
4406summary_info += {'TPM support':       have_tpm}
4407summary_info += {'libssh support':    libssh}
4408summary_info += {'lzo support':       lzo}
4409summary_info += {'snappy support':    snappy}
4410summary_info += {'bzip2 support':     libbzip2}
4411summary_info += {'lzfse support':     liblzfse}
4412summary_info += {'zstd support':      zstd}
4413summary_info += {'NUMA host support': numa}
4414summary_info += {'capstone':          capstone}
4415summary_info += {'libpmem support':   libpmem}
4416summary_info += {'libdaxctl support': libdaxctl}
4417summary_info += {'libudev':           libudev}
4418# Dummy dependency, keep .found()
4419summary_info += {'FUSE lseek':        fuse_lseek.found()}
4420summary_info += {'selinux':           selinux}
4421summary_info += {'libdw':             libdw}
4422if host_os == 'freebsd'
4423  summary_info += {'libinotify-kqueue': inotify}
4424endif
4425summary(summary_info, bool_yn: true, section: 'Dependencies')
4426
4427if host_arch == 'unknown'
4428  message()
4429  warning('UNSUPPORTED HOST CPU')
4430  message()
4431  message('Support for CPU host architecture ' + cpu + ' is not currently')
4432  message('maintained. The QEMU project does not guarantee that QEMU will')
4433  message('compile or work on this host CPU. You can help by volunteering')
4434  message('to maintain it and providing a build host for our continuous')
4435  message('integration setup.')
4436  if get_option('tcg').allowed() and target_dirs.length() > 0
4437    message()
4438    message('configure has succeeded and you can continue to build, but')
4439    message('QEMU will use a slow interpreter to emulate the target CPU.')
4440  endif
4441endif
4442
4443if not supported_oses.contains(host_os)
4444  message()
4445  warning('UNSUPPORTED HOST OS')
4446  message()
4447  message('Support for host OS ' + host_os + 'is not currently maintained.')
4448  message('configure has succeeded and you can continue to build, but')
4449  message('the QEMU project does not guarantee that QEMU will compile or')
4450  message('work on this operating system. You can help by volunteering')
4451  message('to maintain it and providing a build host for our continuous')
4452  message('integration setup. This will ensure that future versions of QEMU')
4453  message('will keep working on ' + host_os + '.')
4454endif
4455
4456if host_arch == 'unknown' or not supported_oses.contains(host_os)
4457  message()
4458  message('If you want to help supporting QEMU on this platform, please')
4459  message('contact the developers at qemu-devel@nongnu.org.')
4460endif
4461
4462actually_reloc = get_option('relocatable')
4463# check if get_relocated_path() is actually able to relocate paths
4464if get_option('relocatable') and \
4465  not (get_option('prefix') / get_option('bindir')).startswith(get_option('prefix') / '')
4466  message()
4467  warning('bindir not included within prefix, the installation will not be relocatable.')
4468  actually_reloc = false
4469endif
4470if not actually_reloc and (host_os == 'windows' or get_option('relocatable'))
4471  if host_os == 'windows'
4472    message()
4473    warning('Windows installs should usually be relocatable.')
4474  endif
4475  message()
4476  message('QEMU will have to be installed under ' + get_option('prefix') + '.')
4477  message('Use --disable-relocatable to remove this warning.')
4478endif
4479