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