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