xref: /openbmc/qemu/meson.build (revision effd60c8)
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
2387# has_header_symbol
2388config_host_data.set('CONFIG_BLKZONED',
2389                     cc.has_header_symbol('linux/blkzoned.h', 'BLKOPENZONE'))
2390config_host_data.set('CONFIG_EPOLL_CREATE1',
2391                     cc.has_header_symbol('sys/epoll.h', 'epoll_create1'))
2392config_host_data.set('CONFIG_FALLOCATE_PUNCH_HOLE',
2393                     cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_PUNCH_HOLE') and
2394                     cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_KEEP_SIZE'))
2395config_host_data.set('CONFIG_FALLOCATE_ZERO_RANGE',
2396                     cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_ZERO_RANGE'))
2397config_host_data.set('CONFIG_FIEMAP',
2398                     cc.has_header('linux/fiemap.h') and
2399                     cc.has_header_symbol('linux/fs.h', 'FS_IOC_FIEMAP'))
2400config_host_data.set('CONFIG_GETRANDOM',
2401                     cc.has_function('getrandom') and
2402                     cc.has_header_symbol('sys/random.h', 'GRND_NONBLOCK'))
2403config_host_data.set('CONFIG_INOTIFY',
2404                     cc.has_header_symbol('sys/inotify.h', 'inotify_init'))
2405config_host_data.set('CONFIG_INOTIFY1',
2406                     cc.has_header_symbol('sys/inotify.h', 'inotify_init1'))
2407config_host_data.set('CONFIG_PRCTL_PR_SET_TIMERSLACK',
2408                     cc.has_header_symbol('sys/prctl.h', 'PR_SET_TIMERSLACK'))
2409config_host_data.set('CONFIG_RTNETLINK',
2410                     cc.has_header_symbol('linux/rtnetlink.h', 'IFLA_PROTO_DOWN'))
2411config_host_data.set('CONFIG_SYSMACROS',
2412                     cc.has_header_symbol('sys/sysmacros.h', 'makedev'))
2413config_host_data.set('HAVE_OPTRESET',
2414                     cc.has_header_symbol('getopt.h', 'optreset'))
2415config_host_data.set('HAVE_IPPROTO_MPTCP',
2416                     cc.has_header_symbol('netinet/in.h', 'IPPROTO_MPTCP'))
2417
2418# has_member
2419config_host_data.set('HAVE_SIGEV_NOTIFY_THREAD_ID',
2420                     cc.has_member('struct sigevent', 'sigev_notify_thread_id',
2421                                   prefix: '#include <signal.h>'))
2422config_host_data.set('HAVE_STRUCT_STAT_ST_ATIM',
2423                     cc.has_member('struct stat', 'st_atim',
2424                                   prefix: '#include <sys/stat.h>'))
2425config_host_data.set('HAVE_BLK_ZONE_REP_CAPACITY',
2426                     cc.has_member('struct blk_zone', 'capacity',
2427                                   prefix: '#include <linux/blkzoned.h>'))
2428
2429# has_type
2430config_host_data.set('CONFIG_IOVEC',
2431                     cc.has_type('struct iovec',
2432                                 prefix: '#include <sys/uio.h>'))
2433config_host_data.set('HAVE_UTMPX',
2434                     cc.has_type('struct utmpx',
2435                                 prefix: '#include <utmpx.h>'))
2436
2437config_host_data.set('CONFIG_EVENTFD', cc.links('''
2438  #include <sys/eventfd.h>
2439  int main(void) { return eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); }'''))
2440config_host_data.set('CONFIG_FDATASYNC', cc.links(gnu_source_prefix + '''
2441  #include <unistd.h>
2442  int main(void) {
2443  #if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
2444  return fdatasync(0);
2445  #else
2446  #error Not supported
2447  #endif
2448  }'''))
2449
2450has_madvise = cc.links(gnu_source_prefix + '''
2451  #include <sys/types.h>
2452  #include <sys/mman.h>
2453  #include <stddef.h>
2454  int main(void) { return madvise(NULL, 0, MADV_DONTNEED); }''')
2455missing_madvise_proto = false
2456if has_madvise
2457  # Some platforms (illumos and Solaris before Solaris 11) provide madvise()
2458  # but forget to prototype it. In this case, has_madvise will be true (the
2459  # test program links despite a compile warning). To detect the
2460  # missing-prototype case, we try again with a definitely-bogus prototype.
2461  # This will only compile if the system headers don't provide the prototype;
2462  # otherwise the conflicting prototypes will cause a compiler error.
2463  missing_madvise_proto = cc.links(gnu_source_prefix + '''
2464    #include <sys/types.h>
2465    #include <sys/mman.h>
2466    #include <stddef.h>
2467    extern int madvise(int);
2468    int main(void) { return madvise(0); }''')
2469endif
2470config_host_data.set('CONFIG_MADVISE', has_madvise)
2471config_host_data.set('HAVE_MADVISE_WITHOUT_PROTOTYPE', missing_madvise_proto)
2472
2473config_host_data.set('CONFIG_MEMFD', cc.links(gnu_source_prefix + '''
2474  #include <sys/mman.h>
2475  int main(void) { return memfd_create("foo", MFD_ALLOW_SEALING); }'''))
2476config_host_data.set('CONFIG_OPEN_BY_HANDLE', cc.links(gnu_source_prefix + '''
2477  #include <fcntl.h>
2478  #if !defined(AT_EMPTY_PATH)
2479  # error missing definition
2480  #else
2481  int main(void) { struct file_handle fh; return open_by_handle_at(0, &fh, 0); }
2482  #endif'''))
2483config_host_data.set('CONFIG_POSIX_MADVISE', cc.links(gnu_source_prefix + '''
2484  #include <sys/mman.h>
2485  #include <stddef.h>
2486  int main(void) { return posix_madvise(NULL, 0, POSIX_MADV_DONTNEED); }'''))
2487
2488config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_W_TID', cc.links(gnu_source_prefix + '''
2489  #include <pthread.h>
2490
2491  static void *f(void *p) { return NULL; }
2492  int main(void)
2493  {
2494    pthread_t thread;
2495    pthread_create(&thread, 0, f, 0);
2496    pthread_setname_np(thread, "QEMU");
2497    return 0;
2498  }''', dependencies: threads))
2499config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_WO_TID', cc.links(gnu_source_prefix + '''
2500  #include <pthread.h>
2501
2502  static void *f(void *p) { pthread_setname_np("QEMU"); return NULL; }
2503  int main(void)
2504  {
2505    pthread_t thread;
2506    pthread_create(&thread, 0, f, 0);
2507    return 0;
2508  }''', dependencies: threads))
2509config_host_data.set('CONFIG_PTHREAD_SET_NAME_NP', cc.links(gnu_source_prefix + '''
2510  #include <pthread.h>
2511  #include <pthread_np.h>
2512
2513  static void *f(void *p) { return NULL; }
2514  int main(void)
2515  {
2516    pthread_t thread;
2517    pthread_create(&thread, 0, f, 0);
2518    pthread_set_name_np(thread, "QEMU");
2519    return 0;
2520  }''', dependencies: threads))
2521config_host_data.set('CONFIG_PTHREAD_CONDATTR_SETCLOCK', cc.links(gnu_source_prefix + '''
2522  #include <pthread.h>
2523  #include <time.h>
2524
2525  int main(void)
2526  {
2527    pthread_condattr_t attr
2528    pthread_condattr_init(&attr);
2529    pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
2530    return 0;
2531  }''', dependencies: threads))
2532config_host_data.set('CONFIG_PTHREAD_AFFINITY_NP', cc.links(gnu_source_prefix + '''
2533  #include <pthread.h>
2534
2535  static void *f(void *p) { return NULL; }
2536  int main(void)
2537  {
2538    int setsize = CPU_ALLOC_SIZE(64);
2539    pthread_t thread;
2540    cpu_set_t *cpuset;
2541    pthread_create(&thread, 0, f, 0);
2542    cpuset = CPU_ALLOC(64);
2543    CPU_ZERO_S(setsize, cpuset);
2544    pthread_setaffinity_np(thread, setsize, cpuset);
2545    pthread_getaffinity_np(thread, setsize, cpuset);
2546    CPU_FREE(cpuset);
2547    return 0;
2548  }''', dependencies: threads))
2549config_host_data.set('CONFIG_SIGNALFD', cc.links(gnu_source_prefix + '''
2550  #include <sys/signalfd.h>
2551  #include <stddef.h>
2552  int main(void) { return signalfd(-1, NULL, SFD_CLOEXEC); }'''))
2553config_host_data.set('CONFIG_SPLICE', cc.links(gnu_source_prefix + '''
2554  #include <unistd.h>
2555  #include <fcntl.h>
2556  #include <limits.h>
2557
2558  int main(void)
2559  {
2560    int len, fd = 0;
2561    len = tee(STDIN_FILENO, STDOUT_FILENO, INT_MAX, SPLICE_F_NONBLOCK);
2562    splice(STDIN_FILENO, NULL, fd, NULL, len, SPLICE_F_MOVE);
2563    return 0;
2564  }'''))
2565
2566config_host_data.set('HAVE_MLOCKALL', cc.links(gnu_source_prefix + '''
2567  #include <sys/mman.h>
2568  int main(void) {
2569    return mlockall(MCL_FUTURE);
2570  }'''))
2571
2572have_l2tpv3 = false
2573if get_option('l2tpv3').allowed() and have_system
2574  have_l2tpv3 = cc.has_type('struct mmsghdr',
2575    prefix: gnu_source_prefix + '''
2576      #include <sys/socket.h>
2577      #include <linux/ip.h>''')
2578endif
2579config_host_data.set('CONFIG_L2TPV3', have_l2tpv3)
2580
2581have_netmap = false
2582if get_option('netmap').allowed() and have_system
2583  have_netmap = cc.compiles('''
2584    #include <inttypes.h>
2585    #include <net/if.h>
2586    #include <net/netmap.h>
2587    #include <net/netmap_user.h>
2588    #if (NETMAP_API < 11) || (NETMAP_API > 15)
2589    #error
2590    #endif
2591    int main(void) { return 0; }''')
2592  if not have_netmap and get_option('netmap').enabled()
2593    error('Netmap headers not available')
2594  endif
2595endif
2596config_host_data.set('CONFIG_NETMAP', have_netmap)
2597
2598# Work around a system header bug with some kernel/XFS header
2599# versions where they both try to define 'struct fsxattr':
2600# xfs headers will not try to redefine structs from linux headers
2601# if this macro is set.
2602config_host_data.set('HAVE_FSXATTR', cc.links('''
2603  #include <linux/fs.h>
2604  struct fsxattr foo;
2605  int main(void) {
2606    return 0;
2607  }'''))
2608
2609# Some versions of Mac OS X incorrectly define SIZE_MAX
2610config_host_data.set('HAVE_BROKEN_SIZE_MAX', not cc.compiles('''
2611    #include <stdint.h>
2612    #include <stdio.h>
2613    int main(void) {
2614        return printf("%zu", SIZE_MAX);
2615    }''', args: ['-Werror']))
2616
2617# See if 64-bit atomic operations are supported.
2618# Note that without __atomic builtins, we can only
2619# assume atomic loads/stores max at pointer size.
2620config_host_data.set('CONFIG_ATOMIC64', cc.links('''
2621  #include <stdint.h>
2622  int main(void)
2623  {
2624    uint64_t x = 0, y = 0;
2625    y = __atomic_load_n(&x, __ATOMIC_RELAXED);
2626    __atomic_store_n(&x, y, __ATOMIC_RELAXED);
2627    __atomic_compare_exchange_n(&x, &y, x, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
2628    __atomic_exchange_n(&x, y, __ATOMIC_RELAXED);
2629    __atomic_fetch_add(&x, y, __ATOMIC_RELAXED);
2630    return 0;
2631  }'''))
2632
2633has_int128_type = cc.compiles('''
2634  __int128_t a;
2635  __uint128_t b;
2636  int main(void) { b = a; }''')
2637config_host_data.set('CONFIG_INT128_TYPE', has_int128_type)
2638
2639has_int128 = has_int128_type and cc.links('''
2640  __int128_t a;
2641  __uint128_t b;
2642  int main (void) {
2643    a = a + b;
2644    b = a * b;
2645    a = a * a;
2646    return 0;
2647  }''')
2648config_host_data.set('CONFIG_INT128', has_int128)
2649
2650if has_int128_type
2651  # "do we have 128-bit atomics which are handled inline and specifically not
2652  # via libatomic". The reason we can't use libatomic is documented in the
2653  # comment starting "GCC is a house divided" in include/qemu/atomic128.h.
2654  # We only care about these operations on 16-byte aligned pointers, so
2655  # force 16-byte alignment of the pointer, which may be greater than
2656  # __alignof(unsigned __int128) for the host.
2657  atomic_test_128 = '''
2658    int main(int ac, char **av) {
2659      __uint128_t *p = __builtin_assume_aligned(av[ac - 1], 16);
2660      p[1] = __atomic_load_n(&p[0], __ATOMIC_RELAXED);
2661      __atomic_store_n(&p[2], p[3], __ATOMIC_RELAXED);
2662      __atomic_compare_exchange_n(&p[4], &p[5], p[6], 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
2663      return 0;
2664    }'''
2665  has_atomic128 = cc.links(atomic_test_128)
2666
2667  config_host_data.set('CONFIG_ATOMIC128', has_atomic128)
2668
2669  if not has_atomic128
2670    # Even with __builtin_assume_aligned, the above test may have failed
2671    # without optimization enabled.  Try again with optimizations locally
2672    # enabled for the function.  See
2673    #   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107389
2674    has_atomic128_opt = cc.links('__attribute__((optimize("O1")))' + atomic_test_128)
2675    config_host_data.set('CONFIG_ATOMIC128_OPT', has_atomic128_opt)
2676
2677    if not has_atomic128_opt
2678      config_host_data.set('CONFIG_CMPXCHG128', cc.links('''
2679        int main(void)
2680        {
2681          __uint128_t x = 0, y = 0;
2682          __sync_val_compare_and_swap_16(&x, y, x);
2683          return 0;
2684        }
2685      '''))
2686    endif
2687  endif
2688endif
2689
2690config_host_data.set('CONFIG_GETAUXVAL', cc.links(gnu_source_prefix + '''
2691  #include <sys/auxv.h>
2692  int main(void) {
2693    return getauxval(AT_HWCAP) == 0;
2694  }'''))
2695
2696config_host_data.set('CONFIG_USBFS', have_linux_user and cc.compiles('''
2697  #include <linux/usbdevice_fs.h>
2698
2699  #ifndef USBDEVFS_GET_CAPABILITIES
2700  #error "USBDEVFS_GET_CAPABILITIES undefined"
2701  #endif
2702
2703  #ifndef USBDEVFS_DISCONNECT_CLAIM
2704  #error "USBDEVFS_DISCONNECT_CLAIM undefined"
2705  #endif
2706
2707  int main(void) { return 0; }'''))
2708
2709have_keyring = get_option('keyring') \
2710  .require(host_os == 'linux', error_message: 'keyring is only available on Linux') \
2711  .require(cc.compiles('''
2712    #include <errno.h>
2713    #include <asm/unistd.h>
2714    #include <linux/keyctl.h>
2715    #include <sys/syscall.h>
2716    #include <unistd.h>
2717    int main(void) {
2718        return syscall(__NR_keyctl, KEYCTL_READ, 0, NULL, NULL, 0);
2719    }'''), error_message: 'keyctl syscall not available on this system').allowed()
2720config_host_data.set('CONFIG_SECRET_KEYRING', have_keyring)
2721
2722have_cpuid_h = cc.links('''
2723  #include <cpuid.h>
2724  int main(void) {
2725    unsigned a, b, c, d;
2726    unsigned max = __get_cpuid_max(0, 0);
2727
2728    if (max >= 1) {
2729        __cpuid(1, a, b, c, d);
2730    }
2731
2732    if (max >= 7) {
2733        __cpuid_count(7, 0, a, b, c, d);
2734    }
2735
2736    return 0;
2737  }''')
2738config_host_data.set('CONFIG_CPUID_H', have_cpuid_h)
2739
2740config_host_data.set('CONFIG_AVX2_OPT', get_option('avx2') \
2741  .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX2') \
2742  .require(cc.links('''
2743    #include <cpuid.h>
2744    #include <immintrin.h>
2745    static int __attribute__((target("avx2"))) bar(void *a) {
2746      __m256i x = *(__m256i *)a;
2747      return _mm256_testz_si256(x, x);
2748    }
2749    int main(int argc, char *argv[]) { return bar(argv[argc - 1]); }
2750  '''), error_message: 'AVX2 not available').allowed())
2751
2752config_host_data.set('CONFIG_AVX512F_OPT', get_option('avx512f') \
2753  .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX512F') \
2754  .require(cc.links('''
2755    #include <cpuid.h>
2756    #include <immintrin.h>
2757    static int __attribute__((target("avx512f"))) bar(void *a) {
2758      __m512i x = *(__m512i *)a;
2759      return _mm512_test_epi64_mask(x, x);
2760    }
2761    int main(int argc, char *argv[]) { return bar(argv[argc - 1]); }
2762  '''), error_message: 'AVX512F not available').allowed())
2763
2764config_host_data.set('CONFIG_AVX512BW_OPT', get_option('avx512bw') \
2765  .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX512BW') \
2766  .require(cc.links('''
2767    #include <cpuid.h>
2768    #include <immintrin.h>
2769    static int __attribute__((target("avx512bw"))) bar(void *a) {
2770      __m512i *x = a;
2771      __m512i res= _mm512_abs_epi8(*x);
2772      return res[1];
2773    }
2774    int main(int argc, char *argv[]) { return bar(argv[0]); }
2775  '''), error_message: 'AVX512BW not available').allowed())
2776
2777# For both AArch64 and AArch32, detect if builtins are available.
2778config_host_data.set('CONFIG_ARM_AES_BUILTIN', cc.compiles('''
2779    #include <arm_neon.h>
2780    #ifndef __ARM_FEATURE_AES
2781    __attribute__((target("+crypto")))
2782    #endif
2783    void foo(uint8x16_t *p) { *p = vaesmcq_u8(*p); }
2784  '''))
2785
2786have_pvrdma = get_option('pvrdma') \
2787  .require(rdma.found(), error_message: 'PVRDMA requires OpenFabrics libraries') \
2788  .require(cc.compiles(gnu_source_prefix + '''
2789    #include <sys/mman.h>
2790    int main(void)
2791    {
2792      char buf = 0;
2793      void *addr = &buf;
2794      addr = mremap(addr, 0, 1, MREMAP_MAYMOVE | MREMAP_FIXED);
2795
2796      return 0;
2797    }'''), error_message: 'PVRDMA requires mremap').allowed()
2798
2799if have_pvrdma
2800  config_host_data.set('LEGACY_RDMA_REG_MR', not cc.links('''
2801    #include <infiniband/verbs.h>
2802    int main(void)
2803    {
2804      struct ibv_mr *mr;
2805      struct ibv_pd *pd = NULL;
2806      size_t length = 10;
2807      uint64_t iova = 0;
2808      int access = 0;
2809      void *addr = NULL;
2810
2811      mr = ibv_reg_mr_iova(pd, addr, length, iova, access);
2812      ibv_dereg_mr(mr);
2813      return 0;
2814    }'''))
2815endif
2816
2817if get_option('membarrier').disabled()
2818  have_membarrier = false
2819elif host_os == 'windows'
2820  have_membarrier = true
2821elif host_os == 'linux'
2822  have_membarrier = cc.compiles('''
2823    #include <linux/membarrier.h>
2824    #include <sys/syscall.h>
2825    #include <unistd.h>
2826    #include <stdlib.h>
2827    int main(void) {
2828        syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0);
2829        syscall(__NR_membarrier, MEMBARRIER_CMD_SHARED, 0);
2830        exit(0);
2831    }''')
2832endif
2833config_host_data.set('CONFIG_MEMBARRIER', get_option('membarrier') \
2834  .require(have_membarrier, error_message: 'membarrier system call not available') \
2835  .allowed())
2836
2837have_afalg = get_option('crypto_afalg') \
2838  .require(cc.compiles(gnu_source_prefix + '''
2839    #include <errno.h>
2840    #include <sys/types.h>
2841    #include <sys/socket.h>
2842    #include <linux/if_alg.h>
2843    int main(void) {
2844      int sock;
2845      sock = socket(AF_ALG, SOCK_SEQPACKET, 0);
2846      return sock;
2847    }
2848  '''), error_message: 'AF_ALG requested but could not be detected').allowed()
2849config_host_data.set('CONFIG_AF_ALG', have_afalg)
2850
2851config_host_data.set('CONFIG_AF_VSOCK', cc.has_header_symbol(
2852  'linux/vm_sockets.h', 'AF_VSOCK',
2853  prefix: '#include <sys/socket.h>',
2854))
2855
2856have_vss = false
2857have_vss_sdk = false # old xp/2003 SDK
2858if host_os == 'windows' and 'cpp' in all_languages
2859  have_vss = cxx.compiles('''
2860    #define __MIDL_user_allocate_free_DEFINED__
2861    #include <vss.h>
2862    int main(void) { return VSS_CTX_BACKUP; }''')
2863  have_vss_sdk = cxx.has_header('vscoordint.h')
2864endif
2865config_host_data.set('HAVE_VSS_SDK', have_vss_sdk)
2866
2867# Older versions of MinGW do not import _lock_file and _unlock_file properly.
2868# This was fixed for v6.0.0 with commit b48e3ac8969d.
2869if host_os == 'windows'
2870  config_host_data.set('HAVE__LOCK_FILE', cc.links('''
2871    #include <stdio.h>
2872    int main(void) {
2873      _lock_file(NULL);
2874      _unlock_file(NULL);
2875      return 0;
2876    }''', name: '_lock_file and _unlock_file'))
2877endif
2878
2879if host_os == 'windows'
2880  mingw_has_setjmp_longjmp = cc.links('''
2881    #include <setjmp.h>
2882    int main(void) {
2883      /*
2884       * These functions are not available in setjmp header, but may be
2885       * available at link time, from libmingwex.a.
2886       */
2887      extern int __mingw_setjmp(jmp_buf);
2888      extern void __attribute__((noreturn)) __mingw_longjmp(jmp_buf, int);
2889      jmp_buf env;
2890      __mingw_setjmp(env);
2891      __mingw_longjmp(env, 0);
2892    }
2893  ''', name: 'mingw setjmp and longjmp')
2894
2895  if cpu == 'aarch64' and not mingw_has_setjmp_longjmp
2896    error('mingw must provide setjmp/longjmp for windows-arm64')
2897  endif
2898endif
2899
2900########################
2901# Target configuration #
2902########################
2903
2904minikconf = find_program('scripts/minikconf.py')
2905
2906config_all_accel = {}
2907config_all_devices = {}
2908config_devices_mak_list = []
2909config_devices_h = {}
2910config_target_h = {}
2911config_target_mak = {}
2912
2913disassemblers = {
2914  'alpha' : ['CONFIG_ALPHA_DIS'],
2915  'avr' : ['CONFIG_AVR_DIS'],
2916  'cris' : ['CONFIG_CRIS_DIS'],
2917  'hexagon' : ['CONFIG_HEXAGON_DIS'],
2918  'hppa' : ['CONFIG_HPPA_DIS'],
2919  'i386' : ['CONFIG_I386_DIS'],
2920  'x86_64' : ['CONFIG_I386_DIS'],
2921  'm68k' : ['CONFIG_M68K_DIS'],
2922  'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
2923  'mips' : ['CONFIG_MIPS_DIS'],
2924  'nios2' : ['CONFIG_NIOS2_DIS'],
2925  'or1k' : ['CONFIG_OPENRISC_DIS'],
2926  'ppc' : ['CONFIG_PPC_DIS'],
2927  'riscv' : ['CONFIG_RISCV_DIS'],
2928  'rx' : ['CONFIG_RX_DIS'],
2929  's390' : ['CONFIG_S390_DIS'],
2930  'sh4' : ['CONFIG_SH4_DIS'],
2931  'sparc' : ['CONFIG_SPARC_DIS'],
2932  'xtensa' : ['CONFIG_XTENSA_DIS'],
2933  'loongarch' : ['CONFIG_LOONGARCH_DIS'],
2934}
2935
2936have_ivshmem = config_host_data.get('CONFIG_EVENTFD')
2937host_kconfig = \
2938  (get_option('fuzzing') ? ['CONFIG_FUZZ=y'] : []) + \
2939  (have_tpm ? ['CONFIG_TPM=y'] : []) + \
2940  (pixman.found() ? ['CONFIG_PIXMAN=y'] : []) + \
2941  (spice.found() ? ['CONFIG_SPICE=y'] : []) + \
2942  (have_ivshmem ? ['CONFIG_IVSHMEM=y'] : []) + \
2943  (opengl.found() ? ['CONFIG_OPENGL=y'] : []) + \
2944  (x11.found() ? ['CONFIG_X11=y'] : []) + \
2945  (have_vhost_user ? ['CONFIG_VHOST_USER=y'] : []) + \
2946  (have_vhost_vdpa ? ['CONFIG_VHOST_VDPA=y'] : []) + \
2947  (have_vhost_kernel ? ['CONFIG_VHOST_KERNEL=y'] : []) + \
2948  (have_virtfs ? ['CONFIG_VIRTFS=y'] : []) + \
2949  (host_os == 'linux' ? ['CONFIG_LINUX=y'] : []) + \
2950  (have_pvrdma ? ['CONFIG_PVRDMA=y'] : []) + \
2951  (multiprocess_allowed ? ['CONFIG_MULTIPROCESS_ALLOWED=y'] : []) + \
2952  (vfio_user_server_allowed ? ['CONFIG_VFIO_USER_SERVER_ALLOWED=y'] : []) + \
2953  (hv_balloon ? ['CONFIG_HV_BALLOON_POSSIBLE=y'] : [])
2954
2955ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ]
2956
2957default_targets = 'CONFIG_DEFAULT_TARGETS' in config_host
2958actual_target_dirs = []
2959fdt_required = []
2960foreach target : target_dirs
2961  config_target = { 'TARGET_NAME': target.split('-')[0] }
2962  if target.endswith('linux-user')
2963    if host_os != 'linux'
2964      if default_targets
2965        continue
2966      endif
2967      error('Target @0@ is only available on a Linux host'.format(target))
2968    endif
2969    config_target += { 'CONFIG_LINUX_USER': 'y' }
2970  elif target.endswith('bsd-user')
2971    if host_os not in bsd_oses
2972      if default_targets
2973        continue
2974      endif
2975      error('Target @0@ is only available on a BSD host'.format(target))
2976    endif
2977    config_target += { 'CONFIG_BSD_USER': 'y' }
2978  elif target.endswith('softmmu')
2979    config_target += { 'CONFIG_SYSTEM_ONLY': 'y' }
2980    config_target += { 'CONFIG_SOFTMMU': 'y' }
2981  endif
2982  if target.endswith('-user')
2983    config_target += {
2984      'CONFIG_USER_ONLY': 'y',
2985      'CONFIG_QEMU_INTERP_PREFIX':
2986        get_option('interp_prefix').replace('%M', config_target['TARGET_NAME'])
2987    }
2988  endif
2989
2990  accel_kconfig = []
2991  foreach sym: accelerators
2992    if sym == 'CONFIG_TCG' or target in accelerator_targets.get(sym, [])
2993      config_target += { sym: 'y' }
2994      config_all_accel += { sym: 'y' }
2995      if target in modular_tcg
2996        config_target += { 'CONFIG_TCG_MODULAR': 'y' }
2997      else
2998        config_target += { 'CONFIG_TCG_BUILTIN': 'y' }
2999      endif
3000      accel_kconfig += [ sym + '=y' ]
3001    endif
3002  endforeach
3003  if accel_kconfig.length() == 0
3004    if default_targets
3005      continue
3006    endif
3007    error('No accelerator available for target @0@'.format(target))
3008  endif
3009
3010  actual_target_dirs += target
3011  config_target += keyval.load('configs/targets' / target + '.mak')
3012  config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
3013
3014  if 'TARGET_NEED_FDT' in config_target
3015    fdt_required += target
3016  endif
3017
3018  # Add default keys
3019  if 'TARGET_BASE_ARCH' not in config_target
3020    config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
3021  endif
3022  if 'TARGET_ABI_DIR' not in config_target
3023    config_target += {'TARGET_ABI_DIR': config_target['TARGET_ARCH']}
3024  endif
3025  if 'TARGET_BIG_ENDIAN' not in config_target
3026    config_target += {'TARGET_BIG_ENDIAN': 'n'}
3027  endif
3028
3029  foreach k, v: disassemblers
3030    if host_arch.startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k)
3031      foreach sym: v
3032        config_target += { sym: 'y' }
3033      endforeach
3034    endif
3035  endforeach
3036
3037  config_target_data = configuration_data()
3038  foreach k, v: config_target
3039    if not k.startswith('TARGET_') and not k.startswith('CONFIG_')
3040      # do nothing
3041    elif ignored.contains(k)
3042      # do nothing
3043    elif k == 'TARGET_BASE_ARCH'
3044      # Note that TARGET_BASE_ARCH ends up in config-target.h but it is
3045      # not used to select files from sourcesets.
3046      config_target_data.set('TARGET_' + v.to_upper(), 1)
3047    elif k == 'TARGET_NAME' or k == 'CONFIG_QEMU_INTERP_PREFIX'
3048      config_target_data.set_quoted(k, v)
3049    elif v == 'y'
3050      config_target_data.set(k, 1)
3051    elif v == 'n'
3052      config_target_data.set(k, 0)
3053    else
3054      config_target_data.set(k, v)
3055    endif
3056  endforeach
3057  config_target_data.set('QEMU_ARCH',
3058                         'QEMU_ARCH_' + config_target['TARGET_BASE_ARCH'].to_upper())
3059  config_target_h += {target: configure_file(output: target + '-config-target.h',
3060                                               configuration: config_target_data)}
3061
3062  if target.endswith('-softmmu')
3063    config_input = meson.get_external_property(target, 'default')
3064    config_devices_mak = target + '-config-devices.mak'
3065    config_devices_mak = configure_file(
3066      input: ['configs/devices' / target / config_input + '.mak', 'Kconfig'],
3067      output: config_devices_mak,
3068      depfile: config_devices_mak + '.d',
3069      capture: true,
3070      command: [minikconf,
3071                get_option('default_devices') ? '--defconfig' : '--allnoconfig',
3072                config_devices_mak, '@DEPFILE@', '@INPUT@',
3073                host_kconfig, accel_kconfig,
3074                'CONFIG_' + config_target['TARGET_ARCH'].to_upper() + '=y'])
3075
3076    config_devices_data = configuration_data()
3077    config_devices = keyval.load(config_devices_mak)
3078    foreach k, v: config_devices
3079      config_devices_data.set(k, 1)
3080    endforeach
3081    config_devices_mak_list += config_devices_mak
3082    config_devices_h += {target: configure_file(output: target + '-config-devices.h',
3083                                                configuration: config_devices_data)}
3084    config_target += config_devices
3085    config_all_devices += config_devices
3086  endif
3087  config_target_mak += {target: config_target}
3088endforeach
3089target_dirs = actual_target_dirs
3090
3091target_configs_h = []
3092foreach target: target_dirs
3093  target_configs_h += config_target_h[target]
3094  target_configs_h += config_devices_h.get(target, [])
3095endforeach
3096genh += custom_target('config-poison.h',
3097                      input: [target_configs_h],
3098                      output: 'config-poison.h',
3099                      capture: true,
3100                      command: [find_program('scripts/make-config-poison.sh'),
3101                                target_configs_h])
3102
3103###############
3104# Subprojects #
3105###############
3106
3107libvfio_user_dep = not_found
3108if have_system and vfio_user_server_allowed
3109  libvfio_user_proj = subproject('libvfio-user', required: true)
3110  libvfio_user_dep = libvfio_user_proj.get_variable('libvfio_user_dep')
3111endif
3112
3113fdt = not_found
3114fdt_opt = get_option('fdt')
3115if fdt_required.length() > 0 or fdt_opt == 'enabled'
3116  if fdt_opt == 'disabled'
3117    error('fdt disabled but required by targets ' + ', '.join(fdt_required))
3118  endif
3119
3120  if fdt_opt in ['enabled', 'auto', 'system']
3121    if get_option('wrap_mode') == 'nodownload'
3122      fdt_opt = 'system'
3123    endif
3124    fdt = cc.find_library('fdt', required: fdt_opt == 'system')
3125    if fdt.found() and cc.links('''
3126       #include <libfdt.h>
3127       #include <libfdt_env.h>
3128       int main(void) { fdt_find_max_phandle(NULL, NULL); return 0; }''',
3129         dependencies: fdt)
3130      fdt_opt = 'system'
3131    elif fdt_opt == 'system'
3132       error('system libfdt requested, but it is too old (1.5.1 or newer required)')
3133    else
3134      fdt_opt = 'internal'
3135      fdt = not_found
3136    endif
3137  endif
3138  if not fdt.found()
3139    assert(fdt_opt == 'internal')
3140    libfdt_proj = subproject('dtc', required: true,
3141                             default_options: ['tools=false',  'yaml=disabled',
3142                                               'python=disabled', 'default_library=static'])
3143    fdt = libfdt_proj.get_variable('libfdt_dep')
3144  endif
3145else
3146  fdt_opt = 'disabled'
3147endif
3148
3149config_host_data.set('CONFIG_FDT', fdt.found())
3150
3151vhost_user = not_found
3152if host_os == 'linux' and have_vhost_user
3153  libvhost_user = subproject('libvhost-user')
3154  vhost_user = libvhost_user.get_variable('vhost_user_dep')
3155endif
3156
3157libvduse = not_found
3158if have_libvduse
3159  libvduse_proj = subproject('libvduse')
3160  libvduse = libvduse_proj.get_variable('libvduse_dep')
3161endif
3162
3163#####################
3164# Generated sources #
3165#####################
3166
3167genh += configure_file(output: 'config-host.h', configuration: config_host_data)
3168
3169hxtool = find_program('scripts/hxtool')
3170shaderinclude = find_program('scripts/shaderinclude.py')
3171qapi_gen = find_program('scripts/qapi-gen.py')
3172qapi_gen_depends = [ meson.current_source_dir() / 'scripts/qapi/__init__.py',
3173                     meson.current_source_dir() / 'scripts/qapi/commands.py',
3174                     meson.current_source_dir() / 'scripts/qapi/common.py',
3175                     meson.current_source_dir() / 'scripts/qapi/error.py',
3176                     meson.current_source_dir() / 'scripts/qapi/events.py',
3177                     meson.current_source_dir() / 'scripts/qapi/expr.py',
3178                     meson.current_source_dir() / 'scripts/qapi/gen.py',
3179                     meson.current_source_dir() / 'scripts/qapi/introspect.py',
3180                     meson.current_source_dir() / 'scripts/qapi/main.py',
3181                     meson.current_source_dir() / 'scripts/qapi/parser.py',
3182                     meson.current_source_dir() / 'scripts/qapi/schema.py',
3183                     meson.current_source_dir() / 'scripts/qapi/source.py',
3184                     meson.current_source_dir() / 'scripts/qapi/types.py',
3185                     meson.current_source_dir() / 'scripts/qapi/visit.py',
3186                     meson.current_source_dir() / 'scripts/qapi-gen.py'
3187]
3188
3189tracetool = [
3190  python, files('scripts/tracetool.py'),
3191   '--backend=' + ','.join(get_option('trace_backends'))
3192]
3193tracetool_depends = files(
3194  'scripts/tracetool/backend/log.py',
3195  'scripts/tracetool/backend/__init__.py',
3196  'scripts/tracetool/backend/dtrace.py',
3197  'scripts/tracetool/backend/ftrace.py',
3198  'scripts/tracetool/backend/simple.py',
3199  'scripts/tracetool/backend/syslog.py',
3200  'scripts/tracetool/backend/ust.py',
3201  'scripts/tracetool/format/ust_events_c.py',
3202  'scripts/tracetool/format/ust_events_h.py',
3203  'scripts/tracetool/format/__init__.py',
3204  'scripts/tracetool/format/d.py',
3205  'scripts/tracetool/format/simpletrace_stap.py',
3206  'scripts/tracetool/format/c.py',
3207  'scripts/tracetool/format/h.py',
3208  'scripts/tracetool/format/log_stap.py',
3209  'scripts/tracetool/format/stap.py',
3210  'scripts/tracetool/__init__.py',
3211  'scripts/tracetool/vcpu.py'
3212)
3213
3214qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
3215                    meson.current_source_dir(),
3216                    get_option('pkgversion'), meson.project_version()]
3217qemu_version = custom_target('qemu-version.h',
3218                             output: 'qemu-version.h',
3219                             command: qemu_version_cmd,
3220                             capture: true,
3221                             build_by_default: true,
3222                             build_always_stale: true)
3223genh += qemu_version
3224
3225hxdep = []
3226hx_headers = [
3227  ['qemu-options.hx', 'qemu-options.def'],
3228  ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
3229]
3230if have_system
3231  hx_headers += [
3232    ['hmp-commands.hx', 'hmp-commands.h'],
3233    ['hmp-commands-info.hx', 'hmp-commands-info.h'],
3234  ]
3235endif
3236foreach d : hx_headers
3237  hxdep += custom_target(d[1],
3238                input: files(d[0]),
3239                output: d[1],
3240                capture: true,
3241                command: [hxtool, '-h', '@INPUT0@'])
3242endforeach
3243genh += hxdep
3244
3245###############
3246# Trace files #
3247###############
3248
3249# TODO: add each directory to the subdirs from its own meson.build, once
3250# we have those
3251trace_events_subdirs = [
3252  'crypto',
3253  'qapi',
3254  'qom',
3255  'monitor',
3256  'util',
3257  'gdbstub',
3258]
3259if have_linux_user
3260  trace_events_subdirs += [ 'linux-user' ]
3261endif
3262if have_bsd_user
3263  trace_events_subdirs += [ 'bsd-user' ]
3264endif
3265if have_block
3266  trace_events_subdirs += [
3267    'authz',
3268    'block',
3269    'io',
3270    'nbd',
3271    'scsi',
3272  ]
3273endif
3274if have_system
3275  trace_events_subdirs += [
3276    'accel/kvm',
3277    'audio',
3278    'backends',
3279    'backends/tpm',
3280    'chardev',
3281    'ebpf',
3282    'hw/9pfs',
3283    'hw/acpi',
3284    'hw/adc',
3285    'hw/alpha',
3286    'hw/arm',
3287    'hw/audio',
3288    'hw/block',
3289    'hw/block/dataplane',
3290    'hw/char',
3291    'hw/display',
3292    'hw/dma',
3293    'hw/hyperv',
3294    'hw/i2c',
3295    'hw/i386',
3296    'hw/i386/xen',
3297    'hw/i386/kvm',
3298    'hw/ide',
3299    'hw/input',
3300    'hw/intc',
3301    'hw/isa',
3302    'hw/mem',
3303    'hw/mips',
3304    'hw/misc',
3305    'hw/misc/macio',
3306    'hw/net',
3307    'hw/net/can',
3308    'hw/nubus',
3309    'hw/nvme',
3310    'hw/nvram',
3311    'hw/pci',
3312    'hw/pci-host',
3313    'hw/ppc',
3314    'hw/rdma',
3315    'hw/rdma/vmw',
3316    'hw/rtc',
3317    'hw/s390x',
3318    'hw/scsi',
3319    'hw/sd',
3320    'hw/sh4',
3321    'hw/sparc',
3322    'hw/sparc64',
3323    'hw/ssi',
3324    'hw/timer',
3325    'hw/tpm',
3326    'hw/ufs',
3327    'hw/usb',
3328    'hw/vfio',
3329    'hw/virtio',
3330    'hw/watchdog',
3331    'hw/xen',
3332    'hw/gpio',
3333    'migration',
3334    'net',
3335    'system',
3336    'ui',
3337    'hw/remote',
3338  ]
3339endif
3340if have_system or have_user
3341  trace_events_subdirs += [
3342    'accel/tcg',
3343    'hw/core',
3344    'target/arm',
3345    'target/arm/hvf',
3346    'target/hppa',
3347    'target/i386',
3348    'target/i386/kvm',
3349    'target/loongarch',
3350    'target/mips/tcg',
3351    'target/nios2',
3352    'target/ppc',
3353    'target/riscv',
3354    'target/s390x',
3355    'target/s390x/kvm',
3356    'target/sparc',
3357  ]
3358endif
3359
3360###################
3361# Collect sources #
3362###################
3363
3364authz_ss = ss.source_set()
3365blockdev_ss = ss.source_set()
3366block_ss = ss.source_set()
3367chardev_ss = ss.source_set()
3368common_ss = ss.source_set()
3369crypto_ss = ss.source_set()
3370hwcore_ss = ss.source_set()
3371io_ss = ss.source_set()
3372qmp_ss = ss.source_set()
3373qom_ss = ss.source_set()
3374system_ss = ss.source_set()
3375specific_fuzz_ss = ss.source_set()
3376specific_ss = ss.source_set()
3377stub_ss = ss.source_set()
3378trace_ss = ss.source_set()
3379user_ss = ss.source_set()
3380util_ss = ss.source_set()
3381
3382# accel modules
3383qtest_module_ss = ss.source_set()
3384tcg_module_ss = ss.source_set()
3385
3386modules = {}
3387target_modules = {}
3388hw_arch = {}
3389target_arch = {}
3390target_system_arch = {}
3391target_user_arch = {}
3392
3393# NOTE: the trace/ subdirectory needs the qapi_trace_events variable
3394# that is filled in by qapi/.
3395subdir('qapi')
3396subdir('qobject')
3397subdir('stubs')
3398subdir('trace')
3399subdir('util')
3400subdir('qom')
3401subdir('authz')
3402subdir('crypto')
3403subdir('ui')
3404subdir('hw')
3405subdir('gdbstub')
3406
3407if enable_modules
3408  libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
3409  modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
3410endif
3411
3412qom_ss = qom_ss.apply({})
3413libqom = static_library('qom', qom_ss.sources() + genh,
3414                        dependencies: [qom_ss.dependencies()],
3415                        name_suffix: 'fa',
3416                        build_by_default: false)
3417qom = declare_dependency(link_whole: libqom)
3418
3419event_loop_base = files('event-loop-base.c')
3420event_loop_base = static_library('event-loop-base',
3421                                 sources: event_loop_base + genh,
3422                                 name_suffix: 'fa',
3423                                 build_by_default: false)
3424event_loop_base = declare_dependency(link_whole: event_loop_base,
3425                                     dependencies: [qom])
3426
3427stub_ss = stub_ss.apply({})
3428
3429util_ss.add_all(trace_ss)
3430util_ss = util_ss.apply({})
3431libqemuutil = static_library('qemuutil',
3432                             build_by_default: false,
3433                             sources: util_ss.sources() + stub_ss.sources() + genh,
3434                             dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc, pixman])
3435qemuutil = declare_dependency(link_with: libqemuutil,
3436                              sources: genh + version_res,
3437                              dependencies: [event_loop_base])
3438
3439if have_system or have_user
3440  decodetree = generator(find_program('scripts/decodetree.py'),
3441                         output: 'decode-@BASENAME@.c.inc',
3442                         arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
3443  subdir('libdecnumber')
3444  subdir('target')
3445endif
3446
3447subdir('audio')
3448subdir('io')
3449subdir('chardev')
3450subdir('fsdev')
3451subdir('dump')
3452
3453if have_block
3454  block_ss.add(files(
3455    'block.c',
3456    'blockjob.c',
3457    'job.c',
3458    'qemu-io-cmds.c',
3459  ))
3460  if config_host_data.get('CONFIG_REPLICATION')
3461    block_ss.add(files('replication.c'))
3462  endif
3463
3464  subdir('nbd')
3465  subdir('scsi')
3466  subdir('block')
3467
3468  blockdev_ss.add(files(
3469    'blockdev.c',
3470    'blockdev-nbd.c',
3471    'iothread.c',
3472    'job-qmp.c',
3473  ), gnutls)
3474
3475  # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
3476  # os-win32.c does not
3477  if host_os == 'windows'
3478    system_ss.add(files('os-win32.c'))
3479  else
3480    blockdev_ss.add(files('os-posix.c'))
3481  endif
3482endif
3483
3484common_ss.add(files('cpu-common.c'))
3485specific_ss.add(files('cpu-target.c'))
3486
3487subdir('system')
3488
3489# Work around a gcc bug/misfeature wherein constant propagation looks
3490# through an alias:
3491#   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99696
3492# to guess that a const variable is always zero.  Without lto, this is
3493# impossible, as the alias is restricted to page-vary-common.c.  Indeed,
3494# without lto, not even the alias is required -- we simply use different
3495# declarations in different compilation units.
3496pagevary = files('page-vary-common.c')
3497if get_option('b_lto')
3498  pagevary_flags = ['-fno-lto']
3499  if get_option('cfi')
3500    pagevary_flags += '-fno-sanitize=cfi-icall'
3501  endif
3502  pagevary = static_library('page-vary-common', sources: pagevary + genh,
3503                            c_args: pagevary_flags)
3504  pagevary = declare_dependency(link_with: pagevary)
3505endif
3506common_ss.add(pagevary)
3507specific_ss.add(files('page-vary-target.c'))
3508
3509subdir('backends')
3510subdir('disas')
3511subdir('migration')
3512subdir('monitor')
3513subdir('net')
3514subdir('replay')
3515subdir('semihosting')
3516subdir('stats')
3517subdir('tcg')
3518subdir('fpu')
3519subdir('accel')
3520subdir('plugins')
3521subdir('ebpf')
3522
3523common_user_inc = []
3524
3525subdir('common-user')
3526subdir('bsd-user')
3527subdir('linux-user')
3528
3529# needed for fuzzing binaries
3530subdir('tests/qtest/libqos')
3531subdir('tests/qtest/fuzz')
3532
3533# accel modules
3534tcg_real_module_ss = ss.source_set()
3535tcg_real_module_ss.add_all(when: 'CONFIG_TCG_MODULAR', if_true: tcg_module_ss)
3536specific_ss.add_all(when: 'CONFIG_TCG_BUILTIN', if_true: tcg_module_ss)
3537target_modules += { 'accel' : { 'qtest': qtest_module_ss,
3538                                'tcg': tcg_real_module_ss }}
3539
3540##############################################
3541# Internal static_libraries and dependencies #
3542##############################################
3543
3544modinfo_collect = find_program('scripts/modinfo-collect.py')
3545modinfo_generate = find_program('scripts/modinfo-generate.py')
3546modinfo_files = []
3547
3548block_mods = []
3549system_mods = []
3550foreach d, list : modules
3551  if not (d == 'block' ? have_block : have_system)
3552    continue
3553  endif
3554
3555  foreach m, module_ss : list
3556    if enable_modules
3557      module_ss = module_ss.apply(config_all_devices, strict: false)
3558      sl = static_library(d + '-' + m, [genh, module_ss.sources()],
3559                          dependencies: [modulecommon, module_ss.dependencies()], pic: true)
3560      if d == 'block'
3561        block_mods += sl
3562      else
3563        system_mods += sl
3564      endif
3565      if module_ss.sources() != []
3566        # FIXME: Should use sl.extract_all_objects(recursive: true) as
3567        # input. Sources can be used multiple times but objects are
3568        # unique when it comes to lookup in compile_commands.json.
3569        # Depnds on a mesion version with
3570        # https://github.com/mesonbuild/meson/pull/8900
3571        modinfo_files += custom_target(d + '-' + m + '.modinfo',
3572                                       output: d + '-' + m + '.modinfo',
3573                                       input: module_ss.sources() + genh,
3574                                       capture: true,
3575                                       command: [modinfo_collect, module_ss.sources()])
3576      endif
3577    else
3578      if d == 'block'
3579        block_ss.add_all(module_ss)
3580      else
3581        system_ss.add_all(module_ss)
3582      endif
3583    endif
3584  endforeach
3585endforeach
3586
3587foreach d, list : target_modules
3588  foreach m, module_ss : list
3589    if enable_modules
3590      foreach target : target_dirs
3591        if target.endswith('-softmmu')
3592          config_target = config_target_mak[target]
3593          target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3594          c_args = ['-DNEED_CPU_H',
3595                    '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3596                    '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3597          target_module_ss = module_ss.apply(config_target, strict: false)
3598          if target_module_ss.sources() != []
3599            module_name = d + '-' + m + '-' + config_target['TARGET_NAME']
3600            sl = static_library(module_name,
3601                                [genh, target_module_ss.sources()],
3602                                dependencies: [modulecommon, target_module_ss.dependencies()],
3603                                include_directories: target_inc,
3604                                c_args: c_args,
3605                                pic: true)
3606            system_mods += sl
3607            # FIXME: Should use sl.extract_all_objects(recursive: true) too.
3608            modinfo_files += custom_target(module_name + '.modinfo',
3609                                           output: module_name + '.modinfo',
3610                                           input: target_module_ss.sources() + genh,
3611                                           capture: true,
3612                                           command: [modinfo_collect, '--target', target, target_module_ss.sources()])
3613          endif
3614        endif
3615      endforeach
3616    else
3617      specific_ss.add_all(module_ss)
3618    endif
3619  endforeach
3620endforeach
3621
3622if enable_modules
3623  foreach target : target_dirs
3624    if target.endswith('-softmmu')
3625      config_target = config_target_mak[target]
3626      config_devices_mak = target + '-config-devices.mak'
3627      modinfo_src = custom_target('modinfo-' + target + '.c',
3628                                  output: 'modinfo-' + target + '.c',
3629                                  input: modinfo_files,
3630                                  command: [modinfo_generate, '--devices', config_devices_mak, '@INPUT@'],
3631                                  capture: true)
3632
3633      modinfo_lib = static_library('modinfo-' + target + '.c', modinfo_src)
3634      modinfo_dep = declare_dependency(link_with: modinfo_lib)
3635
3636      arch = config_target['TARGET_NAME'] == 'sparc64' ? 'sparc64' : config_target['TARGET_BASE_ARCH']
3637      hw_arch[arch].add(modinfo_dep)
3638    endif
3639  endforeach
3640endif
3641
3642nm = find_program('nm')
3643undefsym = find_program('scripts/undefsym.py')
3644block_syms = custom_target('block.syms', output: 'block.syms',
3645                             input: [libqemuutil, block_mods],
3646                             capture: true,
3647                             command: [undefsym, nm, '@INPUT@'])
3648qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
3649                             input: [libqemuutil, system_mods],
3650                             capture: true,
3651                             command: [undefsym, nm, '@INPUT@'])
3652
3653authz_ss = authz_ss.apply({})
3654libauthz = static_library('authz', authz_ss.sources() + genh,
3655                          dependencies: [authz_ss.dependencies()],
3656                          name_suffix: 'fa',
3657                          build_by_default: false)
3658
3659authz = declare_dependency(link_whole: libauthz,
3660                           dependencies: qom)
3661
3662crypto_ss = crypto_ss.apply({})
3663libcrypto = static_library('crypto', crypto_ss.sources() + genh,
3664                           dependencies: [crypto_ss.dependencies()],
3665                           name_suffix: 'fa',
3666                           build_by_default: false)
3667
3668crypto = declare_dependency(link_whole: libcrypto,
3669                            dependencies: [authz, qom])
3670
3671io_ss = io_ss.apply({})
3672libio = static_library('io', io_ss.sources() + genh,
3673                       dependencies: [io_ss.dependencies()],
3674                       link_with: libqemuutil,
3675                       name_suffix: 'fa',
3676                       build_by_default: false)
3677
3678io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
3679
3680libmigration = static_library('migration', sources: migration_files + genh,
3681                              name_suffix: 'fa',
3682                              build_by_default: false)
3683migration = declare_dependency(link_with: libmigration,
3684                               dependencies: [zlib, qom, io])
3685system_ss.add(migration)
3686
3687block_ss = block_ss.apply({})
3688libblock = static_library('block', block_ss.sources() + genh,
3689                          dependencies: block_ss.dependencies(),
3690                          link_depends: block_syms,
3691                          name_suffix: 'fa',
3692                          build_by_default: false)
3693
3694block = declare_dependency(link_whole: [libblock],
3695                           link_args: '@block.syms',
3696                           dependencies: [crypto, io])
3697
3698blockdev_ss = blockdev_ss.apply({})
3699libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
3700                             dependencies: blockdev_ss.dependencies(),
3701                             name_suffix: 'fa',
3702                             build_by_default: false)
3703
3704blockdev = declare_dependency(link_whole: [libblockdev],
3705                              dependencies: [block, event_loop_base])
3706
3707qmp_ss = qmp_ss.apply({})
3708libqmp = static_library('qmp', qmp_ss.sources() + genh,
3709                        dependencies: qmp_ss.dependencies(),
3710                        name_suffix: 'fa',
3711                        build_by_default: false)
3712
3713qmp = declare_dependency(link_whole: [libqmp])
3714
3715libchardev = static_library('chardev', chardev_ss.sources() + genh,
3716                            name_suffix: 'fa',
3717                            dependencies: chardev_ss.dependencies(),
3718                            build_by_default: false)
3719
3720chardev = declare_dependency(link_whole: libchardev)
3721
3722hwcore_ss = hwcore_ss.apply({})
3723libhwcore = static_library('hwcore', sources: hwcore_ss.sources() + genh,
3724                           name_suffix: 'fa',
3725                           build_by_default: false)
3726hwcore = declare_dependency(link_whole: libhwcore)
3727common_ss.add(hwcore)
3728
3729###########
3730# Targets #
3731###########
3732
3733emulator_modules = []
3734foreach m : block_mods + system_mods
3735  emulator_modules += shared_module(m.name(),
3736                build_by_default: true,
3737                name_prefix: '',
3738                link_whole: m,
3739                install: true,
3740                install_dir: qemu_moddir)
3741endforeach
3742if emulator_modules.length() > 0
3743  alias_target('modules', emulator_modules)
3744endif
3745
3746system_ss.add(authz, blockdev, chardev, crypto, io, qmp)
3747common_ss.add(qom, qemuutil)
3748
3749common_ss.add_all(when: 'CONFIG_SYSTEM_ONLY', if_true: [system_ss])
3750common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
3751
3752# Note that this library is never used directly (only through extract_objects)
3753# and is not built by default; therefore, source files not used by the build
3754# configuration will be in build.ninja, but are never built by default.
3755common_all = static_library('common',
3756                            build_by_default: false,
3757                            sources: common_ss.all_sources() + genh,
3758                            include_directories: common_user_inc,
3759                            implicit_include_directories: false,
3760                            dependencies: common_ss.all_dependencies(),
3761                            name_suffix: 'fa')
3762
3763feature_to_c = find_program('scripts/feature_to_c.py')
3764
3765if host_os == 'darwin'
3766  entitlement = find_program('scripts/entitlement.sh')
3767endif
3768
3769emulators = {}
3770foreach target : target_dirs
3771  config_target = config_target_mak[target]
3772  target_name = config_target['TARGET_NAME']
3773  target_base_arch = config_target['TARGET_BASE_ARCH']
3774  arch_srcs = [config_target_h[target]]
3775  arch_deps = []
3776  c_args = ['-DNEED_CPU_H',
3777            '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3778            '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3779  link_args = emulator_link_args
3780
3781  target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3782  if host_os == 'linux'
3783    target_inc += include_directories('linux-headers', is_system: true)
3784  endif
3785  if target.endswith('-softmmu')
3786    target_type='system'
3787    t = target_system_arch[target_base_arch].apply(config_target, strict: false)
3788    arch_srcs += t.sources()
3789    arch_deps += t.dependencies()
3790
3791    hw_dir = target_name == 'sparc64' ? 'sparc64' : target_base_arch
3792    if hw_arch.has_key(hw_dir)
3793      hw = hw_arch[hw_dir].apply(config_target, strict: false)
3794      arch_srcs += hw.sources()
3795      arch_deps += hw.dependencies()
3796    endif
3797
3798    arch_srcs += config_devices_h[target]
3799    link_args += ['@block.syms', '@qemu.syms']
3800  else
3801    abi = config_target['TARGET_ABI_DIR']
3802    target_type='user'
3803    target_inc += common_user_inc
3804    if target_base_arch in target_user_arch
3805      t = target_user_arch[target_base_arch].apply(config_target, strict: false)
3806      arch_srcs += t.sources()
3807      arch_deps += t.dependencies()
3808    endif
3809    if 'CONFIG_LINUX_USER' in config_target
3810      base_dir = 'linux-user'
3811    endif
3812    if 'CONFIG_BSD_USER' in config_target
3813      base_dir = 'bsd-user'
3814      target_inc += include_directories('bsd-user/' / host_os)
3815      target_inc += include_directories('bsd-user/host/' / host_arch)
3816      dir = base_dir / abi
3817      arch_srcs += files(dir / 'signal.c', dir / 'target_arch_cpu.c')
3818    endif
3819    target_inc += include_directories(
3820      base_dir,
3821      base_dir / abi,
3822    )
3823    if 'CONFIG_LINUX_USER' in config_target
3824      dir = base_dir / abi
3825      arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
3826      if config_target.has_key('TARGET_SYSTBL_ABI')
3827        arch_srcs += \
3828          syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
3829                                             extra_args : config_target['TARGET_SYSTBL_ABI'])
3830      endif
3831    endif
3832  endif
3833
3834  if 'TARGET_XML_FILES' in config_target
3835    gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
3836                                output: target + '-gdbstub-xml.c',
3837                                input: files(config_target['TARGET_XML_FILES'].split()),
3838                                command: [feature_to_c, '@INPUT@'],
3839                                capture: true)
3840    arch_srcs += gdbstub_xml
3841  endif
3842
3843  t = target_arch[target_base_arch].apply(config_target, strict: false)
3844  arch_srcs += t.sources()
3845  arch_deps += t.dependencies()
3846
3847  target_common = common_ss.apply(config_target, strict: false)
3848  objects = common_all.extract_objects(target_common.sources())
3849  deps = target_common.dependencies()
3850
3851  target_specific = specific_ss.apply(config_target, strict: false)
3852  arch_srcs += target_specific.sources()
3853  arch_deps += target_specific.dependencies()
3854
3855  lib = static_library('qemu-' + target,
3856                 sources: arch_srcs + genh,
3857                 dependencies: arch_deps,
3858                 objects: objects,
3859                 include_directories: target_inc,
3860                 c_args: c_args,
3861                 build_by_default: false,
3862                 name_suffix: 'fa')
3863
3864  if target.endswith('-softmmu')
3865    execs = [{
3866      'name': 'qemu-system-' + target_name,
3867      'win_subsystem': 'console',
3868      'sources': files('system/main.c'),
3869      'dependencies': []
3870    }]
3871    if host_os == 'windows' and (sdl.found() or gtk.found())
3872      execs += [{
3873        'name': 'qemu-system-' + target_name + 'w',
3874        'win_subsystem': 'windows',
3875        'sources': files('system/main.c'),
3876        'dependencies': []
3877      }]
3878    endif
3879    if get_option('fuzzing')
3880      specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
3881      execs += [{
3882        'name': 'qemu-fuzz-' + target_name,
3883        'win_subsystem': 'console',
3884        'sources': specific_fuzz.sources(),
3885        'dependencies': specific_fuzz.dependencies(),
3886      }]
3887    endif
3888  else
3889    execs = [{
3890      'name': 'qemu-' + target_name,
3891      'win_subsystem': 'console',
3892      'sources': [],
3893      'dependencies': []
3894    }]
3895  endif
3896  foreach exe: execs
3897    exe_name = exe['name']
3898    if host_os == 'darwin'
3899      exe_name += '-unsigned'
3900    endif
3901
3902    emulator = executable(exe_name, exe['sources'],
3903               install: true,
3904               c_args: c_args,
3905               dependencies: arch_deps + deps + exe['dependencies'],
3906               objects: lib.extract_all_objects(recursive: true),
3907               link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
3908               link_args: link_args,
3909               win_subsystem: exe['win_subsystem'])
3910
3911    if host_os == 'darwin'
3912      icon = 'pc-bios/qemu.rsrc'
3913      build_input = [emulator, files(icon)]
3914      install_input = [
3915        get_option('bindir') / exe_name,
3916        meson.current_source_dir() / icon
3917      ]
3918      if 'CONFIG_HVF' in config_target
3919        entitlements = 'accel/hvf/entitlements.plist'
3920        build_input += files(entitlements)
3921        install_input += meson.current_source_dir() / entitlements
3922      endif
3923
3924      emulators += {exe['name'] : custom_target(exe['name'],
3925                   input: build_input,
3926                   output: exe['name'],
3927                   command: [entitlement, '@OUTPUT@', '@INPUT@'])
3928      }
3929
3930      meson.add_install_script(entitlement, '--install',
3931                               get_option('bindir') / exe['name'],
3932                               install_input)
3933    else
3934      emulators += {exe['name']: emulator}
3935    endif
3936
3937    if stap.found()
3938      foreach stp: [
3939        {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
3940        {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
3941        {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
3942        {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
3943      ]
3944        custom_target(exe['name'] + stp['ext'],
3945                      input: trace_events_all,
3946                      output: exe['name'] + stp['ext'],
3947                      install: stp['install'],
3948                      install_dir: get_option('datadir') / 'systemtap/tapset',
3949                      command: [
3950                        tracetool, '--group=all', '--format=' + stp['fmt'],
3951                        '--binary=' + stp['bin'],
3952                        '--target-name=' + target_name,
3953                        '--target-type=' + target_type,
3954                        '--probe-prefix=qemu.' + target_type + '.' + target_name,
3955                        '@INPUT@', '@OUTPUT@'
3956                      ],
3957                      depend_files: tracetool_depends)
3958      endforeach
3959    endif
3960  endforeach
3961endforeach
3962
3963# Other build targets
3964
3965if get_option('plugins')
3966  install_headers('include/qemu/qemu-plugin.h')
3967  if host_os == 'windows'
3968    # On windows, we want to deliver the qemu_plugin_api.lib file in the qemu installer,
3969    # so that plugin authors can compile against it.
3970    install_data(win32_qemu_plugin_api_lib, install_dir: 'lib')
3971  endif
3972endif
3973
3974subdir('qga')
3975
3976# Don't build qemu-keymap if xkbcommon is not explicitly enabled
3977# when we don't build tools or system
3978if xkbcommon.found()
3979  # used for the update-keymaps target, so include rules even if !have_tools
3980  qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
3981                           dependencies: [qemuutil, xkbcommon], install: have_tools)
3982endif
3983
3984if have_tools
3985  qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
3986             dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
3987  qemu_io = executable('qemu-io', files('qemu-io.c'),
3988             dependencies: [block, qemuutil], install: true)
3989  qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
3990               dependencies: [blockdev, qemuutil, gnutls, selinux],
3991               install: true)
3992
3993  subdir('storage-daemon')
3994  subdir('contrib/rdmacm-mux')
3995  subdir('contrib/elf2dmp')
3996
3997  executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
3998             dependencies: qemuutil,
3999             install: true)
4000
4001  if have_vhost_user
4002    subdir('contrib/vhost-user-blk')
4003    subdir('contrib/vhost-user-gpu')
4004    subdir('contrib/vhost-user-input')
4005    subdir('contrib/vhost-user-scsi')
4006  endif
4007
4008  if host_os == 'linux'
4009    executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
4010               dependencies: [qemuutil, libcap_ng],
4011               install: true,
4012               install_dir: get_option('libexecdir'))
4013
4014    executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
4015               dependencies: [authz, crypto, io, qom, qemuutil,
4016                              libcap_ng, mpathpersist],
4017               install: true)
4018  endif
4019
4020  if have_ivshmem
4021    subdir('contrib/ivshmem-client')
4022    subdir('contrib/ivshmem-server')
4023  endif
4024endif
4025
4026subdir('scripts')
4027subdir('tools')
4028subdir('pc-bios')
4029subdir('docs')
4030subdir('tests')
4031if gtk.found()
4032  subdir('po')
4033endif
4034
4035if host_machine.system() == 'windows'
4036  nsis_cmd = [
4037    find_program('scripts/nsis.py'),
4038    '@OUTPUT@',
4039    get_option('prefix'),
4040    meson.current_source_dir(),
4041    glib_pc.get_variable('bindir'),
4042    host_machine.cpu(),
4043    '--',
4044    '-DDISPLAYVERSION=' + meson.project_version(),
4045  ]
4046  if build_docs
4047    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
4048  endif
4049  if gtk.found()
4050    nsis_cmd += '-DCONFIG_GTK=y'
4051  endif
4052
4053  nsis = custom_target('nsis',
4054                       output: 'qemu-setup-' + meson.project_version() + '.exe',
4055                       input: files('qemu.nsi'),
4056                       build_always_stale: true,
4057                       command: nsis_cmd + ['@INPUT@'])
4058  alias_target('installer', nsis)
4059endif
4060
4061#########################
4062# Configuration summary #
4063#########################
4064
4065# Build environment
4066summary_info = {}
4067summary_info += {'Build directory':   meson.current_build_dir()}
4068summary_info += {'Source path':       meson.current_source_dir()}
4069summary_info += {'Download dependencies': get_option('wrap_mode') != 'nodownload'}
4070summary(summary_info, bool_yn: true, section: 'Build environment')
4071
4072# Directories
4073summary_info += {'Install prefix':    get_option('prefix')}
4074summary_info += {'BIOS directory':    qemu_datadir}
4075pathsep = host_os == 'windows' ? ';' : ':'
4076summary_info += {'firmware path':     pathsep.join(get_option('qemu_firmwarepath'))}
4077summary_info += {'binary directory':  get_option('prefix') / get_option('bindir')}
4078summary_info += {'library directory': get_option('prefix') / get_option('libdir')}
4079summary_info += {'module directory':  qemu_moddir}
4080summary_info += {'libexec directory': get_option('prefix') / get_option('libexecdir')}
4081summary_info += {'include directory': get_option('prefix') / get_option('includedir')}
4082summary_info += {'config directory':  get_option('prefix') / get_option('sysconfdir')}
4083if host_os != 'windows'
4084  summary_info += {'local state directory': get_option('prefix') / get_option('localstatedir')}
4085  summary_info += {'Manual directory':      get_option('prefix') / get_option('mandir')}
4086else
4087  summary_info += {'local state directory': 'queried at runtime'}
4088endif
4089summary_info += {'Doc directory':     get_option('prefix') / get_option('docdir')}
4090summary(summary_info, bool_yn: true, section: 'Directories')
4091
4092# Host binaries
4093summary_info = {}
4094summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
4095summary_info += {'sphinx-build':      sphinx_build}
4096
4097# FIXME: the [binaries] section of machine files, which can be probed
4098# with find_program(), would be great for passing gdb and genisoimage
4099# paths from configure to Meson.  However, there seems to be no way to
4100# hide a program (for example if gdb is too old).
4101if config_host.has_key('GDB')
4102  summary_info += {'gdb':             config_host['GDB']}
4103endif
4104summary_info += {'iasl':              iasl}
4105summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
4106if host_os == 'windows' and have_ga
4107  summary_info += {'wixl':            wixl}
4108endif
4109if slirp.found() and have_system
4110  summary_info += {'smbd':            have_slirp_smbd ? smbd_path : false}
4111endif
4112summary(summary_info, bool_yn: true, section: 'Host binaries')
4113
4114# Configurable features
4115summary_info = {}
4116summary_info += {'Documentation':     build_docs}
4117summary_info += {'system-mode emulation': have_system}
4118summary_info += {'user-mode emulation': have_user}
4119summary_info += {'block layer':       have_block}
4120summary_info += {'Install blobs':     get_option('install_blobs')}
4121summary_info += {'module support':    enable_modules}
4122if enable_modules
4123  summary_info += {'alternative module path': get_option('module_upgrades')}
4124endif
4125summary_info += {'fuzzing support':   get_option('fuzzing')}
4126if have_system
4127  summary_info += {'Audio drivers':     ' '.join(audio_drivers_selected)}
4128endif
4129summary_info += {'Trace backends':    ','.join(get_option('trace_backends'))}
4130if 'simple' in get_option('trace_backends')
4131  summary_info += {'Trace output file': get_option('trace_file') + '-<pid>'}
4132endif
4133summary_info += {'D-Bus display':     dbus_display}
4134summary_info += {'QOM debugging':     get_option('qom_cast_debug')}
4135summary_info += {'Relocatable install': get_option('relocatable')}
4136summary_info += {'vhost-kernel support': have_vhost_kernel}
4137summary_info += {'vhost-net support': have_vhost_net}
4138summary_info += {'vhost-user support': have_vhost_user}
4139summary_info += {'vhost-user-crypto support': have_vhost_user_crypto}
4140summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
4141summary_info += {'vhost-vdpa support': have_vhost_vdpa}
4142summary_info += {'build guest agent': have_ga}
4143summary(summary_info, bool_yn: true, section: 'Configurable features')
4144
4145# Compilation information
4146summary_info = {}
4147summary_info += {'host CPU':          cpu}
4148summary_info += {'host endianness':   build_machine.endian()}
4149summary_info += {'C compiler':        ' '.join(meson.get_compiler('c').cmd_array())}
4150summary_info += {'Host C compiler':   ' '.join(meson.get_compiler('c', native: true).cmd_array())}
4151if 'cpp' in all_languages
4152  summary_info += {'C++ compiler':    ' '.join(meson.get_compiler('cpp').cmd_array())}
4153else
4154  summary_info += {'C++ compiler':      false}
4155endif
4156if 'objc' in all_languages
4157  summary_info += {'Objective-C compiler': ' '.join(meson.get_compiler('objc').cmd_array())}
4158else
4159  summary_info += {'Objective-C compiler': false}
4160endif
4161option_cflags = (get_option('debug') ? ['-g'] : [])
4162if get_option('optimization') != 'plain'
4163  option_cflags += ['-O' + get_option('optimization')]
4164endif
4165summary_info += {'CFLAGS':            ' '.join(get_option('c_args') + option_cflags)}
4166if 'cpp' in all_languages
4167  summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args') + option_cflags)}
4168endif
4169if 'objc' in all_languages
4170  summary_info += {'OBJCFLAGS':       ' '.join(get_option('objc_args') + option_cflags)}
4171endif
4172link_args = get_option('c_link_args')
4173if link_args.length() > 0
4174  summary_info += {'LDFLAGS':         ' '.join(link_args)}
4175endif
4176summary_info += {'QEMU_CFLAGS':       ' '.join(qemu_common_flags + qemu_cflags)}
4177if 'cpp' in all_languages
4178  summary_info += {'QEMU_CXXFLAGS':     ' '.join(qemu_common_flags + qemu_cxxflags)}
4179endif
4180if 'objc' in all_languages
4181  summary_info += {'QEMU_OBJCFLAGS':    ' '.join(qemu_common_flags)}
4182endif
4183summary_info += {'QEMU_LDFLAGS':      ' '.join(qemu_ldflags)}
4184summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
4185summary_info += {'PIE':               get_option('b_pie')}
4186summary_info += {'static build':      get_option('prefer_static')}
4187summary_info += {'malloc trim support': has_malloc_trim}
4188summary_info += {'membarrier':        have_membarrier}
4189summary_info += {'debug graph lock':  get_option('debug_graph_lock')}
4190summary_info += {'debug stack usage': get_option('debug_stack_usage')}
4191summary_info += {'mutex debugging':   get_option('debug_mutex')}
4192summary_info += {'memory allocator':  get_option('malloc')}
4193summary_info += {'avx2 optimization': config_host_data.get('CONFIG_AVX2_OPT')}
4194summary_info += {'avx512bw optimization': config_host_data.get('CONFIG_AVX512BW_OPT')}
4195summary_info += {'avx512f optimization': config_host_data.get('CONFIG_AVX512F_OPT')}
4196summary_info += {'gcov':              get_option('b_coverage')}
4197summary_info += {'thread sanitizer':  get_option('tsan')}
4198summary_info += {'CFI support':       get_option('cfi')}
4199if get_option('cfi')
4200  summary_info += {'CFI debug support': get_option('cfi_debug')}
4201endif
4202summary_info += {'strip binaries':    get_option('strip')}
4203summary_info += {'sparse':            sparse}
4204summary_info += {'mingw32 support':   host_os == 'windows'}
4205summary(summary_info, bool_yn: true, section: 'Compilation')
4206
4207# snarf the cross-compilation information for tests
4208summary_info = {}
4209have_cross = false
4210foreach target: target_dirs
4211  tcg_mak = meson.current_build_dir() / 'tests/tcg' / target / 'config-target.mak'
4212  if fs.exists(tcg_mak)
4213    config_cross_tcg = keyval.load(tcg_mak)
4214    if 'CC' in config_cross_tcg
4215      summary_info += {config_cross_tcg['TARGET_NAME']: config_cross_tcg['CC']}
4216      have_cross = true
4217    endif
4218  endif
4219endforeach
4220if have_cross
4221  summary(summary_info, bool_yn: true, section: 'Cross compilers')
4222endif
4223
4224# Targets and accelerators
4225summary_info = {}
4226if have_system
4227  summary_info += {'KVM support':       config_all_accel.has_key('CONFIG_KVM')}
4228  summary_info += {'HVF support':       config_all_accel.has_key('CONFIG_HVF')}
4229  summary_info += {'WHPX support':      config_all_accel.has_key('CONFIG_WHPX')}
4230  summary_info += {'NVMM support':      config_all_accel.has_key('CONFIG_NVMM')}
4231  summary_info += {'Xen support':       xen.found()}
4232  if xen.found()
4233    summary_info += {'xen ctrl version':  xen.version()}
4234  endif
4235  summary_info += {'Xen emulation':     config_all_devices.has_key('CONFIG_XEN_EMU')}
4236endif
4237summary_info += {'TCG support':       config_all_accel.has_key('CONFIG_TCG')}
4238if config_all_accel.has_key('CONFIG_TCG')
4239  if get_option('tcg_interpreter')
4240    summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, slow)'}
4241  else
4242    summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
4243  endif
4244  summary_info += {'TCG plugins':       get_option('plugins')}
4245  summary_info += {'TCG debug enabled': get_option('debug_tcg')}
4246endif
4247summary_info += {'target list':       ' '.join(target_dirs)}
4248if have_system
4249  summary_info += {'default devices':   get_option('default_devices')}
4250  summary_info += {'out of process emulation': multiprocess_allowed}
4251  summary_info += {'vfio-user server': vfio_user_server_allowed}
4252endif
4253summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
4254
4255# Block layer
4256summary_info = {}
4257summary_info += {'coroutine backend': coroutine_backend}
4258summary_info += {'coroutine pool':    have_coroutine_pool}
4259if have_block
4260  summary_info += {'Block whitelist (rw)': get_option('block_drv_rw_whitelist')}
4261  summary_info += {'Block whitelist (ro)': get_option('block_drv_ro_whitelist')}
4262  summary_info += {'Use block whitelist in tools': get_option('block_drv_whitelist_in_tools')}
4263  summary_info += {'VirtFS (9P) support':    have_virtfs}
4264  summary_info += {'VirtFS (9P) Proxy Helper support (deprecated)': have_virtfs_proxy_helper}
4265  summary_info += {'Live block migration': config_host_data.get('CONFIG_LIVE_BLOCK_MIGRATION')}
4266  summary_info += {'replication support': config_host_data.get('CONFIG_REPLICATION')}
4267  summary_info += {'bochs support':     get_option('bochs').allowed()}
4268  summary_info += {'cloop support':     get_option('cloop').allowed()}
4269  summary_info += {'dmg support':       get_option('dmg').allowed()}
4270  summary_info += {'qcow v1 support':   get_option('qcow1').allowed()}
4271  summary_info += {'vdi support':       get_option('vdi').allowed()}
4272  summary_info += {'vhdx support':      get_option('vhdx').allowed()}
4273  summary_info += {'vmdk support':      get_option('vmdk').allowed()}
4274  summary_info += {'vpc support':       get_option('vpc').allowed()}
4275  summary_info += {'vvfat support':     get_option('vvfat').allowed()}
4276  summary_info += {'qed support':       get_option('qed').allowed()}
4277  summary_info += {'parallels support': get_option('parallels').allowed()}
4278  summary_info += {'FUSE exports':      fuse}
4279  summary_info += {'VDUSE block exports': have_vduse_blk_export}
4280endif
4281summary(summary_info, bool_yn: true, section: 'Block layer support')
4282
4283# Crypto
4284summary_info = {}
4285summary_info += {'TLS priority':      get_option('tls_priority')}
4286summary_info += {'GNUTLS support':    gnutls}
4287if gnutls.found()
4288  summary_info += {'  GNUTLS crypto':   gnutls_crypto.found()}
4289endif
4290summary_info += {'libgcrypt':         gcrypt}
4291summary_info += {'nettle':            nettle}
4292if nettle.found()
4293   summary_info += {'  XTS':             xts != 'private'}
4294endif
4295summary_info += {'AF_ALG support':    have_afalg}
4296summary_info += {'rng-none':          get_option('rng_none')}
4297summary_info += {'Linux keyring':     have_keyring}
4298summary_info += {'Linux keyutils':    keyutils}
4299summary(summary_info, bool_yn: true, section: 'Crypto')
4300
4301# UI
4302summary_info = {}
4303if host_os == 'darwin'
4304  summary_info += {'Cocoa support':           cocoa}
4305endif
4306summary_info += {'SDL support':       sdl}
4307summary_info += {'SDL image support': sdl_image}
4308summary_info += {'GTK support':       gtk}
4309summary_info += {'pixman':            pixman}
4310summary_info += {'VTE support':       vte}
4311summary_info += {'PNG support':       png}
4312summary_info += {'VNC support':       vnc}
4313if vnc.found()
4314  summary_info += {'VNC SASL support':  sasl}
4315  summary_info += {'VNC JPEG support':  jpeg}
4316endif
4317summary_info += {'spice protocol support': spice_protocol}
4318if spice_protocol.found()
4319  summary_info += {'  spice server support': spice}
4320endif
4321summary_info += {'curses support':    curses}
4322summary_info += {'brlapi support':    brlapi}
4323summary(summary_info, bool_yn: true, section: 'User interface')
4324
4325# Graphics backends
4326summary_info = {}
4327summary_info += {'VirGL support':     virgl}
4328summary_info += {'Rutabaga support':  rutabaga}
4329summary(summary_info, bool_yn: true, section: 'Graphics backends')
4330
4331# Audio backends
4332summary_info = {}
4333if host_os not in ['darwin', 'haiku', 'windows']
4334  summary_info += {'OSS support':     oss}
4335  summary_info += {'sndio support':   sndio}
4336elif host_os == 'darwin'
4337  summary_info += {'CoreAudio support': coreaudio}
4338elif host_os == 'windows'
4339  summary_info += {'DirectSound support': dsound}
4340endif
4341if host_os == 'linux'
4342  summary_info += {'ALSA support':    alsa}
4343  summary_info += {'PulseAudio support': pulse}
4344endif
4345summary_info += {'PipeWire support':  pipewire}
4346summary_info += {'JACK support':      jack}
4347summary(summary_info, bool_yn: true, section: 'Audio backends')
4348
4349# Network backends
4350summary_info = {}
4351if host_os == 'darwin'
4352  summary_info += {'vmnet.framework support': vmnet}
4353endif
4354summary_info += {'AF_XDP support':    libxdp}
4355summary_info += {'slirp support':     slirp}
4356summary_info += {'vde support':       vde}
4357summary_info += {'netmap support':    have_netmap}
4358summary_info += {'l2tpv3 support':    have_l2tpv3}
4359summary(summary_info, bool_yn: true, section: 'Network backends')
4360
4361# Libraries
4362summary_info = {}
4363summary_info += {'libtasn1':          tasn1}
4364summary_info += {'PAM':               pam}
4365summary_info += {'iconv support':     iconv}
4366summary_info += {'blkio support':     blkio}
4367summary_info += {'curl support':      curl}
4368summary_info += {'Multipath support': mpathpersist}
4369summary_info += {'Linux AIO support': libaio}
4370summary_info += {'Linux io_uring support': linux_io_uring}
4371summary_info += {'ATTR/XATTR support': libattr}
4372summary_info += {'RDMA support':      rdma}
4373summary_info += {'PVRDMA support':    have_pvrdma}
4374summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
4375summary_info += {'libcap-ng support': libcap_ng}
4376summary_info += {'bpf support':       libbpf}
4377summary_info += {'rbd support':       rbd}
4378summary_info += {'smartcard support': cacard}
4379summary_info += {'U2F support':       u2f}
4380summary_info += {'libusb':            libusb}
4381summary_info += {'usb net redir':     usbredir}
4382summary_info += {'OpenGL support (epoxy)': opengl}
4383summary_info += {'GBM':               gbm}
4384summary_info += {'libiscsi support':  libiscsi}
4385summary_info += {'libnfs support':    libnfs}
4386if host_os == 'windows'
4387  if have_ga
4388    summary_info += {'QGA VSS support':   have_qga_vss}
4389  endif
4390endif
4391summary_info += {'seccomp support':   seccomp}
4392summary_info += {'GlusterFS support': glusterfs}
4393summary_info += {'hv-balloon support': hv_balloon}
4394summary_info += {'TPM support':       have_tpm}
4395summary_info += {'libssh support':    libssh}
4396summary_info += {'lzo support':       lzo}
4397summary_info += {'snappy support':    snappy}
4398summary_info += {'bzip2 support':     libbzip2}
4399summary_info += {'lzfse support':     liblzfse}
4400summary_info += {'zstd support':      zstd}
4401summary_info += {'NUMA host support': numa}
4402summary_info += {'capstone':          capstone}
4403summary_info += {'libpmem support':   libpmem}
4404summary_info += {'libdaxctl support': libdaxctl}
4405summary_info += {'libudev':           libudev}
4406# Dummy dependency, keep .found()
4407summary_info += {'FUSE lseek':        fuse_lseek.found()}
4408summary_info += {'selinux':           selinux}
4409summary_info += {'libdw':             libdw}
4410summary(summary_info, bool_yn: true, section: 'Dependencies')
4411
4412if host_arch == 'unknown'
4413  message()
4414  warning('UNSUPPORTED HOST CPU')
4415  message()
4416  message('Support for CPU host architecture ' + cpu + ' is not currently')
4417  message('maintained. The QEMU project does not guarantee that QEMU will')
4418  message('compile or work on this host CPU. You can help by volunteering')
4419  message('to maintain it and providing a build host for our continuous')
4420  message('integration setup.')
4421  if get_option('tcg').allowed() and target_dirs.length() > 0
4422    message()
4423    message('configure has succeeded and you can continue to build, but')
4424    message('QEMU will use a slow interpreter to emulate the target CPU.')
4425  endif
4426endif
4427
4428if not supported_oses.contains(host_os)
4429  message()
4430  warning('UNSUPPORTED HOST OS')
4431  message()
4432  message('Support for host OS ' + host_os + 'is not currently maintained.')
4433  message('configure has succeeded and you can continue to build, but')
4434  message('the QEMU project does not guarantee that QEMU will compile or')
4435  message('work on this operating system. You can help by volunteering')
4436  message('to maintain it and providing a build host for our continuous')
4437  message('integration setup. This will ensure that future versions of QEMU')
4438  message('will keep working on ' + host_os + '.')
4439endif
4440
4441if host_arch == 'unknown' or not supported_oses.contains(host_os)
4442  message()
4443  message('If you want to help supporting QEMU on this platform, please')
4444  message('contact the developers at qemu-devel@nongnu.org.')
4445endif
4446
4447actually_reloc = get_option('relocatable')
4448# check if get_relocated_path() is actually able to relocate paths
4449if get_option('relocatable') and \
4450  not (get_option('prefix') / get_option('bindir')).startswith(get_option('prefix') / '')
4451  message()
4452  warning('bindir not included within prefix, the installation will not be relocatable.')
4453  actually_reloc = false
4454endif
4455if not actually_reloc and (host_os == 'windows' or get_option('relocatable'))
4456  if host_os == 'windows'
4457    message()
4458    warning('Windows installs should usually be relocatable.')
4459  endif
4460  message()
4461  message('QEMU will have to be installed under ' + get_option('prefix') + '.')
4462  message('Use --disable-relocatable to remove this warning.')
4463endif
4464