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