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