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