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