xref: /openbmc/qemu/meson.build (revision 90868c3dcec755f567426d1fad64e7611053778e)
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  rustfmt = find_program('rustfmt', required: false)
127
128  rustc_lint_args = run_command(rustc_args, '--lints',
129     capture: true, check: true).stdout().strip().splitlines()
130
131  # Occasionally, we may need to silence warnings and clippy lints that
132  # were only introduced in newer Rust compiler versions.  Do not croak
133  # in that case; a CI job with rust_strict_lints == true ensures that
134  # we do not have misspelled allow() attributes.
135  if not get_option('strict_rust_lints')
136    rustc_lint_args += ['-A', 'unknown_lints']
137  endif
138
139  # Apart from procedural macros, our Rust executables will often link
140  # with C code, so include all the libraries that C code needs.  This
141  # is safe; https://github.com/rust-lang/rust/pull/54675 says that
142  # passing -nodefaultlibs to the linker "was more ideological to
143  # start with than anything".
144  add_project_arguments(rustc_lint_args +
145      ['--cfg', 'MESON', '-C', 'default-linker-libraries'],
146      native: false, language: 'rust')
147  add_project_arguments(rustc_lint_args + ['--cfg', 'MESON'],
148      native: true, language: 'rust')
149endif
150
151dtrace = not_found
152stap = not_found
153if 'dtrace' in get_option('trace_backends')
154  dtrace = find_program('dtrace', required: true)
155  stap = find_program('stap', required: false)
156  if stap.found()
157    # Workaround to avoid dtrace(1) producing a file with 'hidden' symbol
158    # visibility. Define STAP_SDT_V2 to produce 'default' symbol visibility
159    # instead. QEMU --enable-modules depends on this because the SystemTap
160    # semaphores are linked into the main binary and not the module's shared
161    # object.
162    add_global_arguments('-DSTAP_SDT_V2',
163                         native: false, language: all_languages)
164  endif
165endif
166
167if get_option('iasl') == ''
168  iasl = find_program('iasl', required: false)
169else
170  iasl = find_program(get_option('iasl'), required: true)
171endif
172
173edk2_targets = [ 'arm-softmmu', 'aarch64-softmmu', 'i386-softmmu', 'x86_64-softmmu', 'riscv64-softmmu', 'loongarch64-softmmu' ]
174unpack_edk2_blobs = false
175foreach target : edk2_targets
176  if target in target_dirs
177    bzip2 = find_program('bzip2', required: get_option('install_blobs'))
178    unpack_edk2_blobs = bzip2.found()
179    break
180  endif
181endforeach
182
183#####################
184# Option validation #
185#####################
186
187# Fuzzing
188if get_option('fuzzing') and get_option('fuzzing_engine') == '' and \
189    not cc.links('''
190          #include <stdint.h>
191          #include <sys/types.h>
192          int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
193          int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { return 0; }
194        ''',
195        args: ['-Werror', '-fsanitize=fuzzer'])
196  error('Your compiler does not support -fsanitize=fuzzer')
197endif
198
199# Tracing backends
200if 'ftrace' in get_option('trace_backends') and host_os != 'linux'
201  error('ftrace is supported only on Linux')
202endif
203if 'syslog' in get_option('trace_backends') and not cc.compiles('''
204    #include <syslog.h>
205    int main(void) {
206        openlog("qemu", LOG_PID, LOG_DAEMON);
207        syslog(LOG_INFO, "configure");
208        return 0;
209    }''')
210  error('syslog is not supported on this system')
211endif
212
213# Miscellaneous Linux-only features
214get_option('mpath') \
215  .require(host_os == 'linux', error_message: 'Multipath is supported only on Linux')
216
217multiprocess_allowed = get_option('multiprocess') \
218  .require(host_os == 'linux', error_message: 'Multiprocess QEMU is supported only on Linux') \
219  .allowed()
220
221vfio_user_server_allowed = get_option('vfio_user_server') \
222  .require(host_os == 'linux', error_message: 'vfio-user server is supported only on Linux') \
223  .allowed()
224
225have_tpm = get_option('tpm') \
226  .require(host_os != 'windows', error_message: 'TPM emulation only available on POSIX systems') \
227  .allowed()
228
229# vhost
230have_vhost_user = get_option('vhost_user') \
231  .disable_auto_if(host_os != 'linux') \
232  .require(host_os != 'windows',
233           error_message: 'vhost-user is not available on Windows').allowed()
234have_vhost_vdpa = get_option('vhost_vdpa') \
235  .require(host_os == 'linux',
236           error_message: 'vhost-vdpa is only available on Linux').allowed()
237have_vhost_kernel = get_option('vhost_kernel') \
238  .require(host_os == 'linux',
239           error_message: 'vhost-kernel is only available on Linux').allowed()
240have_vhost_user_crypto = get_option('vhost_crypto') \
241  .require(have_vhost_user,
242           error_message: 'vhost-crypto requires vhost-user to be enabled').allowed()
243
244have_vhost = have_vhost_user or have_vhost_vdpa or have_vhost_kernel
245
246have_vhost_net_user = have_vhost_user and get_option('vhost_net').allowed()
247have_vhost_net_vdpa = have_vhost_vdpa and get_option('vhost_net').allowed()
248have_vhost_net_kernel = have_vhost_kernel and get_option('vhost_net').allowed()
249have_vhost_net = have_vhost_net_kernel or have_vhost_net_user or have_vhost_net_vdpa
250
251have_tools = get_option('tools') \
252  .disable_auto_if(not have_system) \
253  .allowed()
254have_ga = get_option('guest_agent') \
255  .disable_auto_if(not have_system and not have_tools) \
256  .require(host_os in ['sunos', 'linux', 'windows', 'freebsd', 'netbsd', 'openbsd'],
257           error_message: 'unsupported OS for QEMU guest agent') \
258  .allowed()
259have_block = have_system or have_tools
260
261enable_modules = get_option('modules') \
262  .require(host_os != 'windows',
263           error_message: 'Modules are not available for Windows') \
264  .require(not get_option('prefer_static'),
265           error_message: 'Modules are incompatible with static linking') \
266  .allowed()
267
268#######################################
269# Variables for host and accelerators #
270#######################################
271
272if cpu not in supported_cpus
273  host_arch = 'unknown'
274elif cpu == 'x86'
275  host_arch = 'i386'
276elif cpu == 'mips64'
277  host_arch = 'mips'
278elif cpu in ['riscv32', 'riscv64']
279  host_arch = 'riscv'
280else
281  host_arch = cpu
282endif
283
284if cpu in ['x86', 'x86_64']
285  kvm_targets = ['i386-softmmu', 'x86_64-softmmu']
286elif cpu == 'aarch64'
287  kvm_targets = ['aarch64-softmmu']
288elif cpu == 's390x'
289  kvm_targets = ['s390x-softmmu']
290elif cpu in ['ppc', 'ppc64']
291  kvm_targets = ['ppc-softmmu', 'ppc64-softmmu']
292elif cpu in ['mips', 'mips64']
293  kvm_targets = ['mips-softmmu', 'mipsel-softmmu', 'mips64-softmmu', 'mips64el-softmmu']
294elif cpu in ['riscv32']
295  kvm_targets = ['riscv32-softmmu']
296elif cpu in ['riscv64']
297  kvm_targets = ['riscv64-softmmu']
298elif cpu in ['loongarch64']
299  kvm_targets = ['loongarch64-softmmu']
300else
301  kvm_targets = []
302endif
303accelerator_targets = { 'CONFIG_KVM': kvm_targets }
304
305if cpu in ['x86', 'x86_64']
306  xen_targets = ['i386-softmmu', 'x86_64-softmmu']
307elif cpu in ['arm', 'aarch64']
308  # i386 emulator provides xenpv machine type for multiple architectures
309  xen_targets = ['i386-softmmu', 'x86_64-softmmu', 'aarch64-softmmu']
310else
311  xen_targets = []
312endif
313accelerator_targets += { 'CONFIG_XEN': xen_targets }
314
315if cpu in ['aarch64']
316  accelerator_targets += {
317    'CONFIG_HVF': ['aarch64-softmmu']
318  }
319endif
320
321if cpu in ['x86', 'x86_64']
322  accelerator_targets += {
323    'CONFIG_HVF': ['x86_64-softmmu'],
324    'CONFIG_NVMM': ['i386-softmmu', 'x86_64-softmmu'],
325    'CONFIG_WHPX': ['i386-softmmu', 'x86_64-softmmu'],
326  }
327endif
328
329modular_tcg = []
330# Darwin does not support references to thread-local variables in modules
331if host_os != 'darwin'
332  modular_tcg = ['i386-softmmu', 'x86_64-softmmu']
333endif
334
335##################
336# Compiler flags #
337##################
338
339foreach lang : all_languages
340  compiler = meson.get_compiler(lang)
341  if compiler.get_id() == 'gcc' and compiler.version().version_compare('>=7.4')
342    # ok
343  elif compiler.get_id() == 'clang' and compiler.compiles('''
344      #ifdef __apple_build_version__
345      # if __clang_major__ < 15 || (__clang_major__ == 15 && __clang_minor__ < 0)
346      #  error You need at least XCode Clang v15.0 to compile QEMU
347      # endif
348      #else
349      # if __clang_major__ < 10 || (__clang_major__ == 10 && __clang_minor__ < 0)
350      #  error You need at least Clang v10.0 to compile QEMU
351      # endif
352      #endif''')
353    # ok
354  else
355    error('You either need GCC v7.4 or Clang v10.0 (or XCode Clang v15.0) to compile QEMU')
356  endif
357endforeach
358
359# default flags for all hosts
360# We use -fwrapv to tell the compiler that we require a C dialect where
361# left shift of signed integers is well defined and has the expected
362# 2s-complement style results. (Both clang and gcc agree that it
363# provides these semantics.)
364
365qemu_common_flags = [
366  '-D_GNU_SOURCE', '-D_FILE_OFFSET_BITS=64', '-D_LARGEFILE_SOURCE',
367  '-fno-strict-aliasing', '-fno-common', '-fwrapv' ]
368qemu_cflags = []
369qemu_ldflags = []
370
371if host_os == 'darwin'
372  # Disable attempts to use ObjectiveC features in os/object.h since they
373  # won't work when we're compiling with gcc as a C compiler.
374  if compiler.get_id() == 'gcc'
375    qemu_common_flags += '-DOS_OBJECT_USE_OBJC=0'
376  endif
377elif host_os == 'sunos'
378  # needed for CMSG_ macros in sys/socket.h
379  qemu_common_flags += '-D_XOPEN_SOURCE=600'
380  # needed for TIOCWIN* defines in termios.h
381  qemu_common_flags += '-D__EXTENSIONS__'
382elif host_os == 'haiku'
383  qemu_common_flags += ['-DB_USE_POSITIVE_POSIX_ERRORS', '-D_BSD_SOURCE', '-fPIC']
384elif host_os == 'windows'
385  if not compiler.compiles('struct x { int y; } __attribute__((gcc_struct));',
386                           args: '-Werror')
387    error('Your compiler does not support __attribute__((gcc_struct)) - please use GCC instead of Clang')
388  endif
389endif
390
391# Choose instruction set (currently x86-only)
392
393qemu_isa_flags = []
394
395# __sync_fetch_and_and requires at least -march=i486. Many toolchains
396# use i686 as default anyway, but for those that don't, an explicit
397# specification is necessary
398if host_arch == 'i386' and not cc.links('''
399  static int sfaa(int *ptr)
400  {
401    return __sync_fetch_and_and(ptr, 0);
402  }
403
404  int main(void)
405  {
406    int val = 42;
407    val = __sync_val_compare_and_swap(&val, 0, 1);
408    sfaa(&val);
409    return val;
410  }''')
411  qemu_isa_flags += ['-march=i486']
412endif
413
414# Pick x86-64 baseline version
415if host_arch in ['i386', 'x86_64']
416  if get_option('x86_version') == '0' and host_arch == 'x86_64'
417    error('x86_64-v1 required for x86-64 hosts')
418  endif
419
420  # add flags for individual instruction set extensions
421  if get_option('x86_version') >= '1'
422    if host_arch == 'i386'
423      qemu_common_flags = ['-mfpmath=sse'] + qemu_common_flags
424    else
425      # present on basically all processors but technically not part of
426      # x86-64-v1, so only include -mneeded for x86-64 version 2 and above
427      qemu_isa_flags += ['-mcx16']
428    endif
429  endif
430  if get_option('x86_version') >= '2'
431    qemu_isa_flags += ['-mpopcnt']
432    qemu_isa_flags += cc.get_supported_arguments('-mneeded')
433  endif
434  if get_option('x86_version') >= '3'
435    qemu_isa_flags += ['-mmovbe', '-mabm', '-mbmi', '-mbmi2', '-mfma', '-mf16c']
436  endif
437
438  # add required vector instruction set (each level implies those below)
439  if get_option('x86_version') == '1'
440    qemu_isa_flags += ['-msse2']
441  elif get_option('x86_version') == '2'
442    qemu_isa_flags += ['-msse4.2']
443  elif get_option('x86_version') == '3'
444    qemu_isa_flags += ['-mavx2']
445  elif get_option('x86_version') == '4'
446    qemu_isa_flags += ['-mavx512f', '-mavx512bw', '-mavx512cd', '-mavx512dq', '-mavx512vl']
447  endif
448endif
449
450qemu_common_flags = qemu_isa_flags + qemu_common_flags
451
452if get_option('prefer_static')
453  qemu_ldflags += get_option('b_pie') ? '-static-pie' : '-static'
454endif
455
456# Meson currently only handles pie as a boolean for now, so if the user
457# has explicitly disabled PIE we need to extend our cflags.
458#
459# -no-pie is supposedly a linker flag that has no effect on the compiler
460# command line, but some distros, that didn't quite know what they were
461# doing, made local changes to gcc's specs file that turned it into
462# a compiler command-line flag.
463#
464# What about linker flags?  For a static build, no PIE is implied by -static
465# which we added above (and if it's not because of the same specs patching,
466# there's nothing we can do: compilation will fail, report a bug to your
467# distro and do not use --disable-pie in the meanwhile).  For dynamic linking,
468# instead, we can't add -no-pie because it overrides -shared: the linker then
469# tries to build an executable instead of a shared library and fails.  So
470# don't add -no-pie anywhere and cross fingers. :(
471if not get_option('b_pie')
472  qemu_common_flags += cc.get_supported_arguments('-fno-pie', '-no-pie')
473endif
474
475if not get_option('stack_protector').disabled()
476  stack_protector_probe = '''
477    int main(int argc, char *argv[])
478    {
479      char arr[64], *p = arr, *c = argv[argc - 1];
480      while (*c) {
481          *p++ = *c++;
482      }
483      return 0;
484    }'''
485  have_stack_protector = false
486  foreach arg : ['-fstack-protector-strong', '-fstack-protector-all']
487    # We need to check both a compile and a link, since some compiler
488    # setups fail only on a .c->.o compile and some only at link time
489    if cc.compiles(stack_protector_probe, args: ['-Werror', arg]) and \
490       cc.links(stack_protector_probe, args: ['-Werror', arg])
491      have_stack_protector = true
492      qemu_cflags += arg
493      qemu_ldflags += arg
494      break
495    endif
496  endforeach
497  get_option('stack_protector') \
498    .require(have_stack_protector, error_message: 'Stack protector not supported')
499endif
500
501coroutine_backend = get_option('coroutine_backend')
502ucontext_probe = '''
503  #include <ucontext.h>
504  #ifdef __stub_makecontext
505  #error Ignoring glibc stub makecontext which will always fail
506  #endif
507  int main(void) { makecontext(0, 0, 0); return 0; }'''
508
509# On Windows the only valid backend is the Windows specific one.
510# For POSIX prefer ucontext, but it's not always possible. The fallback
511# is sigcontext.
512supported_backends = []
513if host_os == 'windows'
514  supported_backends += ['windows']
515else
516  if host_os != 'darwin' and cc.links(ucontext_probe)
517    supported_backends += ['ucontext']
518  endif
519  supported_backends += ['sigaltstack']
520endif
521
522if coroutine_backend == 'auto'
523  coroutine_backend = supported_backends[0]
524elif coroutine_backend not in supported_backends
525  error('"@0@" backend requested but not available.  Available backends: @1@' \
526        .format(coroutine_backend, ', '.join(supported_backends)))
527endif
528
529# Compiles if SafeStack *not* enabled
530safe_stack_probe = '''
531  int main(void)
532  {
533  #if defined(__has_feature)
534  #if __has_feature(safe_stack)
535  #error SafeStack Enabled
536  #endif
537  #endif
538      return 0;
539  }'''
540if get_option('safe_stack') != not cc.compiles(safe_stack_probe)
541  safe_stack_arg = get_option('safe_stack') ? '-fsanitize=safe-stack' : '-fno-sanitize=safe-stack'
542  if get_option('safe_stack') != not cc.compiles(safe_stack_probe, args: safe_stack_arg)
543    error(get_option('safe_stack') \
544          ? 'SafeStack not supported by your compiler' \
545          : 'Cannot disable SafeStack')
546  endif
547  qemu_cflags += safe_stack_arg
548  qemu_ldflags += safe_stack_arg
549endif
550if get_option('safe_stack') and coroutine_backend != 'ucontext'
551  error('SafeStack is only supported with the ucontext coroutine backend')
552endif
553
554if get_option('asan')
555  if cc.has_argument('-fsanitize=address')
556    qemu_cflags = ['-fsanitize=address'] + qemu_cflags
557    qemu_ldflags = ['-fsanitize=address'] + qemu_ldflags
558  else
559    error('Your compiler does not support -fsanitize=address')
560  endif
561endif
562
563if get_option('ubsan')
564  # Detect static linking issue with ubsan:
565  # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84285
566  if cc.links('int main(int argc, char **argv) { return argc + 1; }',
567              args: [qemu_ldflags, '-fsanitize=undefined'])
568    qemu_cflags += ['-fsanitize=undefined']
569    qemu_ldflags += ['-fsanitize=undefined']
570
571    # Suppress undefined behaviour from function call to mismatched type.
572    # In addition, tcg prologue does not emit function type prefix
573    # required by function call sanitizer.
574    if cc.has_argument('-fno-sanitize=function')
575      qemu_cflags += ['-fno-sanitize=function']
576    endif
577  else
578    error('Your compiler does not support -fsanitize=undefined')
579  endif
580endif
581
582# Thread sanitizer is, for now, much noisier than the other sanitizers;
583# keep it separate until that is not the case.
584if get_option('tsan')
585  if get_option('asan') or get_option('ubsan')
586    error('TSAN is not supported with other sanitizers')
587  endif
588  if not cc.has_function('__tsan_create_fiber',
589                         args: '-fsanitize=thread',
590                         prefix: '#include <sanitizer/tsan_interface.h>')
591    error('Cannot enable TSAN due to missing fiber annotation interface')
592  endif
593  tsan_warn_suppress = []
594  # gcc (>=11) will report constructions not supported by tsan:
595  # "error: ‘atomic_thread_fence’ is not supported with ‘-fsanitize=thread’"
596  # https://gcc.gnu.org/gcc-11/changes.html
597  # However, clang does not support this warning and this triggers an error.
598  if cc.has_argument('-Wno-tsan')
599    tsan_warn_suppress = ['-Wno-tsan']
600  endif
601  qemu_cflags = ['-fsanitize=thread'] + tsan_warn_suppress + qemu_cflags
602  qemu_ldflags = ['-fsanitize=thread'] + qemu_ldflags
603endif
604
605# Detect support for PT_GNU_RELRO + DT_BIND_NOW.
606# The combination is known as "full relro", because .got.plt is read-only too.
607qemu_ldflags += cc.get_supported_link_arguments('-Wl,-z,relro', '-Wl,-z,now')
608
609if host_os == 'windows'
610  qemu_ldflags += cc.get_supported_link_arguments('-Wl,--no-seh', '-Wl,--nxcompat')
611  qemu_ldflags += cc.get_supported_link_arguments('-Wl,--dynamicbase', '-Wl,--high-entropy-va')
612endif
613
614if get_option('fuzzing')
615  # Specify a filter to only instrument code that is directly related to
616  # virtual-devices.
617  configure_file(output: 'instrumentation-filter',
618                 input: 'scripts/oss-fuzz/instrumentation-filter-template',
619                 copy: true)
620
621  if cc.compiles('int main () { return 0; }',
622                  name: '-fsanitize-coverage-allowlist=/dev/null',
623                 args: ['-fsanitize-coverage-allowlist=/dev/null',
624                        '-fsanitize-coverage=trace-pc'] )
625    qemu_common_flags += ['-fsanitize-coverage-allowlist=instrumentation-filter']
626  endif
627
628  if get_option('fuzzing_engine') == ''
629    # Add CFLAGS to tell clang to add fuzzer-related instrumentation to all the
630    # compiled code.  To build non-fuzzer binaries with --enable-fuzzing, link
631    # everything with fsanitize=fuzzer-no-link. Otherwise, the linker will be
632    # unable to bind the fuzzer-related callbacks added by instrumentation.
633    qemu_common_flags += ['-fsanitize=fuzzer-no-link']
634    qemu_ldflags += ['-fsanitize=fuzzer-no-link']
635    # For the actual fuzzer binaries, we need to link against the libfuzzer
636    # library. They need to be configurable, to support OSS-Fuzz
637    fuzz_exe_ldflags = ['-fsanitize=fuzzer']
638  else
639    # LIB_FUZZING_ENGINE was set; assume we are running on OSS-Fuzz, and
640    # the needed CFLAGS have already been provided
641    fuzz_exe_ldflags = get_option('fuzzing_engine').split()
642  endif
643endif
644
645if get_option('cfi')
646  cfi_flags=[]
647  # Check for dependency on LTO
648  if not get_option('b_lto')
649    error('Selected Control-Flow Integrity but LTO is disabled')
650  endif
651  if enable_modules
652    error('Selected Control-Flow Integrity is not compatible with modules')
653  endif
654  # Check for cfi flags. CFI requires LTO so we can't use
655  # get_supported_arguments, but need a more complex "compiles" which allows
656  # custom arguments
657  if cc.compiles('int main () { return 0; }', name: '-fsanitize=cfi-icall',
658                 args: ['-flto', '-fsanitize=cfi-icall'] )
659    cfi_flags += '-fsanitize=cfi-icall'
660  else
661    error('-fsanitize=cfi-icall is not supported by the compiler')
662  endif
663  if cc.compiles('int main () { return 0; }',
664                 name: '-fsanitize-cfi-icall-generalize-pointers',
665                 args: ['-flto', '-fsanitize=cfi-icall',
666                        '-fsanitize-cfi-icall-generalize-pointers'] )
667    cfi_flags += '-fsanitize-cfi-icall-generalize-pointers'
668  else
669    error('-fsanitize-cfi-icall-generalize-pointers is not supported by the compiler')
670  endif
671  if get_option('cfi_debug')
672    if cc.compiles('int main () { return 0; }',
673                   name: '-fno-sanitize-trap=cfi-icall',
674                   args: ['-flto', '-fsanitize=cfi-icall',
675                          '-fno-sanitize-trap=cfi-icall'] )
676      cfi_flags += '-fno-sanitize-trap=cfi-icall'
677    else
678      error('-fno-sanitize-trap=cfi-icall is not supported by the compiler')
679    endif
680  endif
681  add_global_arguments(cfi_flags, native: false, language: all_languages)
682  add_global_link_arguments(cfi_flags, native: false, language: all_languages)
683endif
684
685# Check further flags that make QEMU more robust against malicious parties
686
687hardening_flags = [
688    # Initialize all stack variables to zero. This makes
689    # it harder to take advantage of uninitialized stack
690    # data to drive exploits
691    '-ftrivial-auto-var-init=zero',
692]
693
694# Zero out registers used during a function call
695# upon its return. This makes it harder to assemble
696# ROP gadgets into something usable
697#
698# NB: Clang 17 is broken and SEGVs
699# https://github.com/llvm/llvm-project/issues/75168
700#
701# NB2: This clashes with the "retguard" extension of OpenBSD's Clang
702# https://gitlab.com/qemu-project/qemu/-/issues/2278
703if host_os != 'openbsd' and \
704   cc.compiles('extern struct { void (*cb)(void); } s; void f(void) { s.cb(); }',
705               name: '-fzero-call-used-regs=used-gpr',
706               args: ['-O2', '-fzero-call-used-regs=used-gpr'])
707    hardening_flags += '-fzero-call-used-regs=used-gpr'
708endif
709
710qemu_common_flags += cc.get_supported_arguments(hardening_flags)
711
712add_global_arguments(qemu_common_flags, native: false, language: all_languages)
713add_global_link_arguments(qemu_ldflags, native: false, language: all_languages)
714
715# Collect warning flags we want to set, sorted alphabetically
716warn_flags = [
717  # First enable interesting warnings
718  '-Wempty-body',
719  '-Wendif-labels',
720  '-Wexpansion-to-defined',
721  '-Wformat-security',
722  '-Wformat-y2k',
723  '-Wignored-qualifiers',
724  '-Wimplicit-fallthrough=2',
725  '-Winit-self',
726  '-Wmissing-format-attribute',
727  '-Wmissing-prototypes',
728  '-Wnested-externs',
729  '-Wold-style-declaration',
730  '-Wold-style-definition',
731  '-Wredundant-decls',
732  '-Wshadow=local',
733  '-Wstrict-prototypes',
734  '-Wtype-limits',
735  '-Wundef',
736  '-Wvla',
737  '-Wwrite-strings',
738
739  # Then disable some undesirable warnings
740  '-Wno-gnu-variable-sized-type-not-at-end',
741  '-Wno-initializer-overrides',
742  '-Wno-missing-include-dirs',
743  '-Wno-psabi',
744  '-Wno-shift-negative-value',
745  '-Wno-string-plus-int',
746  '-Wno-tautological-type-limit-compare',
747  '-Wno-typedef-redefinition',
748]
749
750if host_os != 'darwin'
751  tsa_has_cleanup = cc.compiles('''
752    struct __attribute__((capability("mutex"))) mutex {};
753    void lock(struct mutex *m) __attribute__((acquire_capability(m)));
754    void unlock(struct mutex *m) __attribute__((release_capability(m)));
755
756    void test(void) {
757      struct mutex __attribute__((cleanup(unlock))) m;
758      lock(&m);
759    }
760  ''', args: ['-Wthread-safety', '-Werror'])
761  if tsa_has_cleanup
762    warn_flags += ['-Wthread-safety']
763  endif
764endif
765
766# Set up C++ compiler flags
767qemu_cxxflags = []
768if 'cpp' in all_languages
769  qemu_cxxflags = ['-D__STDC_LIMIT_MACROS', '-D__STDC_CONSTANT_MACROS', '-D__STDC_FORMAT_MACROS'] + qemu_cflags
770endif
771
772add_project_arguments(qemu_cflags, native: false, language: 'c')
773add_project_arguments(cc.get_supported_arguments(warn_flags), native: false, language: 'c')
774if 'cpp' in all_languages
775  add_project_arguments(qemu_cxxflags, native: false, language: 'cpp')
776  add_project_arguments(cxx.get_supported_arguments(warn_flags), native: false, language: 'cpp')
777endif
778if 'objc' in all_languages
779  # Note sanitizer flags are not applied to Objective-C sources!
780  add_project_arguments(objc.get_supported_arguments(warn_flags), native: false, language: 'objc')
781endif
782if host_os == 'linux'
783  add_project_arguments('-isystem', meson.current_source_dir() / 'linux-headers',
784                        '-isystem', 'linux-headers',
785                        language: all_languages)
786endif
787
788add_project_arguments('-iquote', '.',
789                      '-iquote', meson.current_source_dir(),
790                      '-iquote', meson.current_source_dir() / 'include',
791                      language: all_languages)
792
793# If a host-specific include directory exists, list that first...
794host_include = meson.current_source_dir() / 'host/include/'
795if fs.is_dir(host_include / host_arch)
796  add_project_arguments('-iquote', host_include / host_arch,
797                        language: all_languages)
798endif
799# ... followed by the generic fallback.
800add_project_arguments('-iquote', host_include / 'generic',
801                      language: all_languages)
802
803sparse = find_program('cgcc', required: get_option('sparse'))
804if sparse.found()
805  run_target('sparse',
806             command: [find_program('scripts/check_sparse.py'),
807                       'compile_commands.json', sparse.full_path(), '-Wbitwise',
808                       '-Wno-transparent-union', '-Wno-old-initializer',
809                       '-Wno-non-pointer-null'])
810endif
811
812#####################################
813# Host-specific libraries and flags #
814#####################################
815
816libm = cc.find_library('m', required: false)
817threads = dependency('threads')
818util = cc.find_library('util', required: false)
819winmm = []
820socket = []
821version_res = []
822coref = []
823iokit = []
824emulator_link_args = []
825midl = not_found
826widl = not_found
827pathcch = not_found
828host_dsosuf = '.so'
829if host_os == 'windows'
830  midl = find_program('midl', required: false)
831  widl = find_program('widl', required: false)
832  pathcch = cc.find_library('pathcch')
833  socket = cc.find_library('ws2_32')
834  winmm = cc.find_library('winmm')
835
836  win = import('windows')
837  version_res = win.compile_resources('version.rc',
838                                      depend_files: files('pc-bios/qemu-nsis.ico'),
839                                      include_directories: include_directories('.'))
840  host_dsosuf = '.dll'
841elif host_os == 'darwin'
842  coref = dependency('appleframeworks', modules: 'CoreFoundation')
843  iokit = dependency('appleframeworks', modules: 'IOKit', required: false)
844  host_dsosuf = '.dylib'
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',
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            '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
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    arch_srcs += config_devices_h[target]
4138    link_args += ['@block.syms', '@qemu.syms']
4139  else
4140    abi = config_target['TARGET_ABI_DIR']
4141    target_type='user'
4142    target_inc += common_user_inc
4143    if target_base_arch in target_user_arch
4144      t = target_user_arch[target_base_arch].apply(config_target, strict: false)
4145      arch_srcs += t.sources()
4146      arch_deps += t.dependencies()
4147    endif
4148    if 'CONFIG_LINUX_USER' in config_target
4149      base_dir = 'linux-user'
4150    endif
4151    if 'CONFIG_BSD_USER' in config_target
4152      base_dir = 'bsd-user'
4153      target_inc += include_directories('bsd-user/' / host_os)
4154      target_inc += include_directories('bsd-user/host/' / host_arch)
4155      dir = base_dir / abi
4156      arch_srcs += files(dir / 'signal.c', dir / 'target_arch_cpu.c')
4157    endif
4158    target_inc += include_directories(
4159      base_dir,
4160      base_dir / abi,
4161    )
4162    if 'CONFIG_LINUX_USER' in config_target
4163      dir = base_dir / abi
4164      arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
4165      if config_target.has_key('TARGET_SYSTBL_ABI')
4166        arch_srcs += \
4167          syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
4168                                             extra_args : config_target['TARGET_SYSTBL_ABI'])
4169      endif
4170    endif
4171  endif
4172
4173  if 'TARGET_XML_FILES' in config_target
4174    gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
4175                                output: target + '-gdbstub-xml.c',
4176                                input: files(config_target['TARGET_XML_FILES'].split()),
4177                                command: [feature_to_c, '@INPUT@'],
4178                                capture: true)
4179    arch_srcs += gdbstub_xml
4180  endif
4181
4182  t = target_arch[target_base_arch].apply(config_target, strict: false)
4183  arch_srcs += t.sources()
4184  arch_deps += t.dependencies()
4185
4186  target_common = common_ss.apply(config_target, strict: false)
4187  objects = common_all.extract_objects(target_common.sources())
4188  arch_deps += target_common.dependencies()
4189
4190  target_specific = specific_ss.apply(config_target, strict: false)
4191  arch_srcs += target_specific.sources()
4192  arch_deps += target_specific.dependencies()
4193
4194  if have_rust and target_type == 'system'
4195    target_rust = rust_devices_ss.apply(config_target, strict: false)
4196    crates = []
4197    foreach dep : target_rust.dependencies()
4198      crates += dep.get_variable('crate')
4199    endforeach
4200    if crates.length() > 0
4201      rlib_rs = custom_target('rust_' + target.underscorify() + '.rs',
4202                              output: 'rust_' + target.underscorify() + '.rs',
4203                              command: [rust_root_crate, crates],
4204                              capture: true,
4205                              build_by_default: true,
4206                              build_always_stale: true)
4207      rlib = static_library('rust_' + target.underscorify(),
4208                            rlib_rs,
4209                            dependencies: target_rust.dependencies(),
4210                            override_options: ['rust_std=2021', 'build.rust_std=2021'],
4211                            rust_abi: 'c')
4212      arch_deps += declare_dependency(link_whole: [rlib])
4213    endif
4214  endif
4215
4216  # allow using headers from the dependencies but do not include the sources,
4217  # because this emulator only needs those in "objects".  For external
4218  # dependencies, the full dependency is included below in the executable.
4219  lib_deps = []
4220  foreach dep : arch_deps
4221    lib_deps += dep.partial_dependency(compile_args: true, includes: true)
4222  endforeach
4223
4224  lib = static_library('qemu-' + target,
4225                 sources: arch_srcs + genh,
4226                 dependencies: lib_deps,
4227                 objects: objects,
4228                 include_directories: target_inc,
4229                 c_args: c_args,
4230                 build_by_default: false)
4231
4232  if target.endswith('-softmmu')
4233    execs = [{
4234      'name': 'qemu-system-' + target_name,
4235      'win_subsystem': 'console',
4236      'sources': files('system/main.c'),
4237      'dependencies': [sdl]
4238    }]
4239    if host_os == 'windows' and (sdl.found() or gtk.found())
4240      execs += [{
4241        'name': 'qemu-system-' + target_name + 'w',
4242        'win_subsystem': 'windows',
4243        'sources': files('system/main.c'),
4244        'dependencies': [sdl]
4245      }]
4246    endif
4247    if get_option('fuzzing')
4248      specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
4249      execs += [{
4250        'name': 'qemu-fuzz-' + target_name,
4251        'win_subsystem': 'console',
4252        'sources': specific_fuzz.sources(),
4253        'dependencies': specific_fuzz.dependencies(),
4254      }]
4255    endif
4256  else
4257    execs = [{
4258      'name': 'qemu-' + target_name,
4259      'win_subsystem': 'console',
4260      'sources': [],
4261      'dependencies': []
4262    }]
4263  endif
4264  foreach exe: execs
4265    exe_name = exe['name']
4266    if host_os == 'darwin'
4267      exe_name += '-unsigned'
4268    endif
4269
4270    emulator = executable(exe_name, exe['sources'],
4271               install: true,
4272               c_args: c_args,
4273               dependencies: arch_deps + exe['dependencies'],
4274               objects: lib.extract_all_objects(recursive: true),
4275               link_depends: [block_syms, qemu_syms],
4276               link_args: link_args,
4277               win_subsystem: exe['win_subsystem'])
4278
4279    if host_os == 'darwin'
4280      icon = 'pc-bios/qemu.rsrc'
4281      build_input = [emulator, files(icon)]
4282      install_input = [
4283        get_option('bindir') / exe_name,
4284        meson.current_source_dir() / icon
4285      ]
4286      if 'CONFIG_HVF' in config_target
4287        entitlements = 'accel/hvf/entitlements.plist'
4288        build_input += files(entitlements)
4289        install_input += meson.current_source_dir() / entitlements
4290      endif
4291
4292      emulators += {exe['name'] : custom_target(exe['name'],
4293                   input: build_input,
4294                   output: exe['name'],
4295                   command: [entitlement, '@OUTPUT@', '@INPUT@'])
4296      }
4297
4298      meson.add_install_script(entitlement, '--install',
4299                               get_option('bindir') / exe['name'],
4300                               install_input)
4301    else
4302      emulators += {exe['name']: emulator}
4303    endif
4304
4305    traceable += [{
4306      'exe': exe['name'],
4307      'probe-prefix': 'qemu.' + target_type + '.' + target_name,
4308    }]
4309
4310  endforeach
4311endforeach
4312
4313# Other build targets
4314
4315if get_option('plugins')
4316  install_headers('include/qemu/qemu-plugin.h')
4317  if host_os == 'windows'
4318    # On windows, we want to deliver the qemu_plugin_api.lib file in the qemu installer,
4319    # so that plugin authors can compile against it.
4320    install_data(win32_qemu_plugin_api_lib, install_dir: 'lib')
4321  endif
4322endif
4323
4324subdir('qga')
4325
4326# Don't build qemu-keymap if xkbcommon is not explicitly enabled
4327# when we don't build tools or system
4328if xkbcommon.found()
4329  # used for the update-keymaps target, so include rules even if !have_tools
4330  qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
4331                           dependencies: [qemuutil, xkbcommon], install: have_tools)
4332endif
4333
4334if have_tools
4335  qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
4336             link_args: '@block.syms', link_depends: block_syms,
4337             dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
4338  qemu_io = executable('qemu-io', files('qemu-io.c'),
4339             link_args: '@block.syms', link_depends: block_syms,
4340             dependencies: [block, qemuutil], install: true)
4341  qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
4342               link_args: '@block.syms', link_depends: block_syms,
4343               dependencies: [blockdev, qemuutil, selinux],
4344               install: true)
4345
4346  subdir('storage-daemon')
4347
4348  foreach exe: [ 'qemu-img', 'qemu-io', 'qemu-nbd', 'qemu-storage-daemon']
4349    traceable += [{
4350      'exe': exe,
4351      'probe-prefix': 'qemu.' + exe.substring(5).replace('-', '_')
4352    }]
4353  endforeach
4354
4355  subdir('contrib/elf2dmp')
4356
4357  executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
4358             dependencies: qemuutil,
4359             install: true)
4360
4361  if have_vhost_user
4362    subdir('contrib/vhost-user-blk')
4363    subdir('contrib/vhost-user-gpu')
4364    subdir('contrib/vhost-user-input')
4365    subdir('contrib/vhost-user-scsi')
4366  endif
4367
4368  if host_os == 'linux'
4369    executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
4370               dependencies: [qemuutil, libcap_ng],
4371               install: true,
4372               install_dir: get_option('libexecdir'))
4373
4374    executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
4375               dependencies: [authz, crypto, io, qom, qemuutil,
4376                              libcap_ng, mpathpersist],
4377               install: true)
4378
4379    if cpu in ['x86', 'x86_64']
4380      executable('qemu-vmsr-helper', files('tools/i386/qemu-vmsr-helper.c'),
4381               dependencies: [authz, crypto, io, qom, qemuutil,
4382                              libcap_ng, mpathpersist],
4383               install: true)
4384    endif
4385  endif
4386
4387  if have_ivshmem
4388    subdir('contrib/ivshmem-client')
4389    subdir('contrib/ivshmem-server')
4390  endif
4391endif
4392
4393if stap.found()
4394  foreach t: traceable
4395    foreach stp: [
4396      {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / t['exe'], 'install': false},
4397      {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / t['exe'], 'install': true},
4398      {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
4399      {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
4400    ]
4401      cmd = [
4402        tracetool, '--group=all', '--format=' + stp['fmt'],
4403        '--binary=' + stp['bin'],
4404        '--probe-prefix=' + t['probe-prefix'],
4405        '@INPUT@', '@OUTPUT@'
4406      ]
4407
4408      custom_target(t['exe'] + stp['ext'],
4409                    input: trace_events_all,
4410                    output: t['exe'] + stp['ext'],
4411                    install: stp['install'],
4412                    install_dir: get_option('datadir') / 'systemtap/tapset',
4413                    command: cmd,
4414                    depend_files: tracetool_depends)
4415    endforeach
4416  endforeach
4417endif
4418
4419subdir('scripts')
4420subdir('tools')
4421subdir('pc-bios')
4422subdir('docs')
4423subdir('tests')
4424if gtk.found()
4425  subdir('po')
4426endif
4427
4428if host_machine.system() == 'windows'
4429  nsis_cmd = [
4430    find_program('scripts/nsis.py'),
4431    '@OUTPUT@',
4432    get_option('prefix'),
4433    meson.current_source_dir(),
4434    glib_pc.get_variable('bindir'),
4435    host_machine.cpu(),
4436    '--',
4437    '-DDISPLAYVERSION=' + meson.project_version(),
4438  ]
4439  if build_docs
4440    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
4441  endif
4442  if gtk.found()
4443    nsis_cmd += '-DCONFIG_GTK=y'
4444  endif
4445
4446  nsis = custom_target('nsis',
4447                       output: 'qemu-setup-' + meson.project_version() + '.exe',
4448                       input: files('qemu.nsi'),
4449                       build_always_stale: true,
4450                       command: nsis_cmd + ['@INPUT@'])
4451  alias_target('installer', nsis)
4452endif
4453
4454#########################
4455# Configuration summary #
4456#########################
4457
4458# Build environment
4459summary_info = {}
4460summary_info += {'Build directory':   meson.current_build_dir()}
4461summary_info += {'Source path':       meson.current_source_dir()}
4462summary_info += {'Download dependencies': get_option('wrap_mode') != 'nodownload'}
4463summary(summary_info, bool_yn: true, section: 'Build environment')
4464
4465# Directories
4466summary_info += {'Install prefix':    get_option('prefix')}
4467summary_info += {'BIOS directory':    qemu_datadir}
4468pathsep = host_os == 'windows' ? ';' : ':'
4469summary_info += {'firmware path':     pathsep.join(get_option('qemu_firmwarepath'))}
4470summary_info += {'binary directory':  get_option('prefix') / get_option('bindir')}
4471summary_info += {'library directory': get_option('prefix') / get_option('libdir')}
4472summary_info += {'module directory':  qemu_moddir}
4473summary_info += {'libexec directory': get_option('prefix') / get_option('libexecdir')}
4474summary_info += {'include directory': get_option('prefix') / get_option('includedir')}
4475summary_info += {'config directory':  get_option('prefix') / get_option('sysconfdir')}
4476if host_os != 'windows'
4477  summary_info += {'local state directory': get_option('prefix') / get_option('localstatedir')}
4478  summary_info += {'Manual directory':      get_option('prefix') / get_option('mandir')}
4479else
4480  summary_info += {'local state directory': 'queried at runtime'}
4481endif
4482summary_info += {'Doc directory':     get_option('prefix') / get_option('docdir')}
4483summary(summary_info, bool_yn: true, section: 'Directories')
4484
4485# Host binaries
4486summary_info = {}
4487summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
4488summary_info += {'sphinx-build':      sphinx_build}
4489
4490# FIXME: the [binaries] section of machine files, which can be probed
4491# with find_program(), would be great for passing gdb and genisoimage
4492# paths from configure to Meson.  However, there seems to be no way to
4493# hide a program (for example if gdb is too old).
4494if config_host.has_key('GDB')
4495  summary_info += {'gdb':             config_host['GDB']}
4496endif
4497summary_info += {'iasl':              iasl}
4498summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
4499if host_os == 'windows' and have_ga
4500  summary_info += {'wixl':            wixl}
4501endif
4502if slirp.found() and have_system
4503  summary_info += {'smbd':            have_slirp_smbd ? smbd_path : false}
4504endif
4505summary(summary_info, bool_yn: true, section: 'Host binaries')
4506
4507# Configurable features
4508summary_info = {}
4509summary_info += {'Documentation':     build_docs}
4510summary_info += {'system-mode emulation': have_system}
4511summary_info += {'user-mode emulation': have_user}
4512summary_info += {'block layer':       have_block}
4513summary_info += {'Install blobs':     get_option('install_blobs')}
4514summary_info += {'module support':    enable_modules}
4515if enable_modules
4516  summary_info += {'alternative module path': get_option('module_upgrades')}
4517endif
4518summary_info += {'fuzzing support':   get_option('fuzzing')}
4519if have_system
4520  summary_info += {'Audio drivers':     ' '.join(audio_drivers_selected)}
4521endif
4522summary_info += {'Trace backends':    ','.join(get_option('trace_backends'))}
4523if 'simple' in get_option('trace_backends')
4524  summary_info += {'Trace output file': get_option('trace_file') + '-<pid>'}
4525endif
4526summary_info += {'D-Bus display':     dbus_display}
4527summary_info += {'QOM debugging':     get_option('qom_cast_debug')}
4528summary_info += {'Relocatable install': get_option('relocatable')}
4529summary_info += {'vhost-kernel support': have_vhost_kernel}
4530summary_info += {'vhost-net support': have_vhost_net}
4531summary_info += {'vhost-user support': have_vhost_user}
4532summary_info += {'vhost-user-crypto support': have_vhost_user_crypto}
4533summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
4534summary_info += {'vhost-vdpa support': have_vhost_vdpa}
4535summary_info += {'build guest agent': have_ga}
4536summary(summary_info, bool_yn: true, section: 'Configurable features')
4537
4538# Compilation information
4539summary_info = {}
4540summary_info += {'host CPU':          cpu}
4541summary_info += {'host endianness':   build_machine.endian()}
4542summary_info += {'C compiler':        ' '.join(meson.get_compiler('c').cmd_array())}
4543summary_info += {'Host C compiler':   ' '.join(meson.get_compiler('c', native: true).cmd_array())}
4544if 'cpp' in all_languages
4545  summary_info += {'C++ compiler':    ' '.join(meson.get_compiler('cpp').cmd_array())}
4546else
4547  summary_info += {'C++ compiler':      false}
4548endif
4549if 'objc' in all_languages
4550  summary_info += {'Objective-C compiler': ' '.join(meson.get_compiler('objc').cmd_array())}
4551else
4552  summary_info += {'Objective-C compiler': false}
4553endif
4554summary_info += {'Rust support':      have_rust}
4555if have_rust
4556  summary_info += {'Rust target':     config_host['RUST_TARGET_TRIPLE']}
4557  summary_info += {'rustc':           ' '.join(rustc.cmd_array())}
4558  summary_info += {'rustc version':   rustc.version()}
4559  summary_info += {'bindgen':         bindgen.full_path()}
4560  summary_info += {'bindgen version': bindgen.version()}
4561endif
4562option_cflags = (get_option('debug') ? ['-g'] : [])
4563if get_option('optimization') != 'plain'
4564  option_cflags += ['-O' + get_option('optimization')]
4565endif
4566summary_info += {'CFLAGS':            ' '.join(get_option('c_args') + option_cflags)}
4567if 'cpp' in all_languages
4568  summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args') + option_cflags)}
4569endif
4570if 'objc' in all_languages
4571  summary_info += {'OBJCFLAGS':       ' '.join(get_option('objc_args') + option_cflags)}
4572endif
4573link_args = get_option('c_link_args')
4574if link_args.length() > 0
4575  summary_info += {'LDFLAGS':         ' '.join(link_args)}
4576endif
4577summary_info += {'QEMU_CFLAGS':       ' '.join(qemu_common_flags + qemu_cflags)}
4578if 'cpp' in all_languages
4579  summary_info += {'QEMU_CXXFLAGS':     ' '.join(qemu_common_flags + qemu_cxxflags)}
4580endif
4581if 'objc' in all_languages
4582  summary_info += {'QEMU_OBJCFLAGS':    ' '.join(qemu_common_flags)}
4583endif
4584summary_info += {'QEMU_LDFLAGS':      ' '.join(qemu_ldflags)}
4585summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
4586summary_info += {'PIE':               get_option('b_pie')}
4587summary_info += {'static build':      get_option('prefer_static')}
4588summary_info += {'malloc trim support': has_malloc_trim}
4589summary_info += {'membarrier':        have_membarrier}
4590summary_info += {'debug graph lock':  get_option('debug_graph_lock')}
4591summary_info += {'debug stack usage': get_option('debug_stack_usage')}
4592summary_info += {'mutex debugging':   get_option('debug_mutex')}
4593summary_info += {'memory allocator':  get_option('malloc')}
4594summary_info += {'avx2 optimization': config_host_data.get('CONFIG_AVX2_OPT')}
4595summary_info += {'avx512bw optimization': config_host_data.get('CONFIG_AVX512BW_OPT')}
4596summary_info += {'gcov':              get_option('b_coverage')}
4597summary_info += {'thread sanitizer':  get_option('tsan')}
4598summary_info += {'CFI support':       get_option('cfi')}
4599if get_option('cfi')
4600  summary_info += {'CFI debug support': get_option('cfi_debug')}
4601endif
4602summary_info += {'strip binaries':    get_option('strip')}
4603summary_info += {'sparse':            sparse}
4604summary_info += {'mingw32 support':   host_os == 'windows'}
4605summary(summary_info, bool_yn: true, section: 'Compilation')
4606
4607# snarf the cross-compilation information for tests
4608summary_info = {}
4609have_cross = false
4610foreach target: target_dirs
4611  tcg_mak = meson.current_build_dir() / 'tests/tcg' / target / 'config-target.mak'
4612  if fs.exists(tcg_mak)
4613    config_cross_tcg = keyval.load(tcg_mak)
4614    if 'CC' in config_cross_tcg
4615      summary_info += {config_cross_tcg['TARGET_NAME']: config_cross_tcg['CC']}
4616      have_cross = true
4617    endif
4618  endif
4619endforeach
4620if have_cross
4621  summary(summary_info, bool_yn: true, section: 'Cross compilers')
4622endif
4623
4624# Targets and accelerators
4625summary_info = {}
4626if have_system
4627  summary_info += {'KVM support':       config_all_accel.has_key('CONFIG_KVM')}
4628  summary_info += {'HVF support':       config_all_accel.has_key('CONFIG_HVF')}
4629  summary_info += {'WHPX support':      config_all_accel.has_key('CONFIG_WHPX')}
4630  summary_info += {'NVMM support':      config_all_accel.has_key('CONFIG_NVMM')}
4631  summary_info += {'Xen support':       xen.found()}
4632  if xen.found()
4633    summary_info += {'xen ctrl version':  xen.version()}
4634  endif
4635  summary_info += {'Xen emulation':     config_all_devices.has_key('CONFIG_XEN_EMU')}
4636endif
4637summary_info += {'TCG support':       config_all_accel.has_key('CONFIG_TCG')}
4638if config_all_accel.has_key('CONFIG_TCG')
4639  if get_option('tcg_interpreter')
4640    summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, slow)'}
4641  else
4642    summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
4643  endif
4644  summary_info += {'TCG plugins':       get_option('plugins')}
4645  summary_info += {'TCG debug enabled': get_option('debug_tcg')}
4646  if have_linux_user or have_bsd_user
4647    summary_info += {'syscall buffer debugging support': get_option('debug_remap')}
4648  endif
4649endif
4650summary_info += {'target list':       ' '.join(target_dirs)}
4651if have_system
4652  summary_info += {'default devices':   get_option('default_devices')}
4653  summary_info += {'out of process emulation': multiprocess_allowed}
4654  summary_info += {'vfio-user server': vfio_user_server_allowed}
4655endif
4656summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
4657
4658# Block layer
4659summary_info = {}
4660summary_info += {'coroutine backend': coroutine_backend}
4661summary_info += {'coroutine pool':    have_coroutine_pool}
4662if have_block
4663  summary_info += {'Block whitelist (rw)': get_option('block_drv_rw_whitelist')}
4664  summary_info += {'Block whitelist (ro)': get_option('block_drv_ro_whitelist')}
4665  summary_info += {'Use block whitelist in tools': get_option('block_drv_whitelist_in_tools')}
4666  summary_info += {'VirtFS (9P) support':    have_virtfs}
4667  summary_info += {'replication support': config_host_data.get('CONFIG_REPLICATION')}
4668  summary_info += {'bochs support':     get_option('bochs').allowed()}
4669  summary_info += {'cloop support':     get_option('cloop').allowed()}
4670  summary_info += {'dmg support':       get_option('dmg').allowed()}
4671  summary_info += {'qcow v1 support':   get_option('qcow1').allowed()}
4672  summary_info += {'vdi support':       get_option('vdi').allowed()}
4673  summary_info += {'vhdx support':      get_option('vhdx').allowed()}
4674  summary_info += {'vmdk support':      get_option('vmdk').allowed()}
4675  summary_info += {'vpc support':       get_option('vpc').allowed()}
4676  summary_info += {'vvfat support':     get_option('vvfat').allowed()}
4677  summary_info += {'qed support':       get_option('qed').allowed()}
4678  summary_info += {'parallels support': get_option('parallels').allowed()}
4679  summary_info += {'FUSE exports':      fuse}
4680  summary_info += {'VDUSE block exports': have_vduse_blk_export}
4681endif
4682summary(summary_info, bool_yn: true, section: 'Block layer support')
4683
4684# Crypto
4685summary_info = {}
4686summary_info += {'TLS priority':      get_option('tls_priority')}
4687summary_info += {'GNUTLS support':    gnutls}
4688if gnutls.found()
4689  summary_info += {'  GNUTLS crypto':   gnutls_crypto.found()}
4690endif
4691summary_info += {'libgcrypt':         gcrypt}
4692summary_info += {'nettle':            nettle}
4693if nettle.found()
4694   summary_info += {'  XTS':             xts != 'private'}
4695endif
4696summary_info += {'SM4 ALG support':   crypto_sm4}
4697summary_info += {'SM3 ALG support':   crypto_sm3}
4698summary_info += {'AF_ALG support':    have_afalg}
4699summary_info += {'rng-none':          get_option('rng_none')}
4700summary_info += {'Linux keyring':     have_keyring}
4701summary_info += {'Linux keyutils':    keyutils}
4702summary(summary_info, bool_yn: true, section: 'Crypto')
4703
4704# UI
4705summary_info = {}
4706if host_os == 'darwin'
4707  summary_info += {'Cocoa support':           cocoa}
4708endif
4709summary_info += {'SDL support':       sdl}
4710summary_info += {'SDL image support': sdl_image}
4711summary_info += {'GTK support':       gtk}
4712summary_info += {'pixman':            pixman}
4713summary_info += {'VTE support':       vte}
4714summary_info += {'PNG support':       png}
4715summary_info += {'VNC support':       vnc}
4716if vnc.found()
4717  summary_info += {'VNC SASL support':  sasl}
4718  summary_info += {'VNC JPEG support':  jpeg}
4719endif
4720summary_info += {'spice protocol support': spice_protocol}
4721if spice_protocol.found()
4722  summary_info += {'  spice server support': spice}
4723endif
4724summary_info += {'curses support':    curses}
4725summary_info += {'brlapi support':    brlapi}
4726summary(summary_info, bool_yn: true, section: 'User interface')
4727
4728# Graphics backends
4729summary_info = {}
4730summary_info += {'VirGL support':     virgl}
4731summary_info += {'Rutabaga support':  rutabaga}
4732summary(summary_info, bool_yn: true, section: 'Graphics backends')
4733
4734# Audio backends
4735summary_info = {}
4736if host_os not in ['darwin', 'haiku', 'windows']
4737  summary_info += {'OSS support':     oss}
4738  summary_info += {'sndio support':   sndio}
4739elif host_os == 'darwin'
4740  summary_info += {'CoreAudio support': coreaudio}
4741elif host_os == 'windows'
4742  summary_info += {'DirectSound support': dsound}
4743endif
4744if host_os == 'linux'
4745  summary_info += {'ALSA support':    alsa}
4746  summary_info += {'PulseAudio support': pulse}
4747endif
4748summary_info += {'PipeWire support':  pipewire}
4749summary_info += {'JACK support':      jack}
4750summary(summary_info, bool_yn: true, section: 'Audio backends')
4751
4752# Network backends
4753summary_info = {}
4754if host_os == 'darwin'
4755  summary_info += {'vmnet.framework support': vmnet}
4756endif
4757summary_info += {'AF_XDP support':    libxdp}
4758summary_info += {'slirp support':     slirp}
4759summary_info += {'vde support':       vde}
4760summary_info += {'netmap support':    have_netmap}
4761summary_info += {'l2tpv3 support':    have_l2tpv3}
4762summary(summary_info, bool_yn: true, section: 'Network backends')
4763
4764# Libraries
4765summary_info = {}
4766summary_info += {'libtasn1':          tasn1}
4767summary_info += {'PAM':               pam}
4768summary_info += {'iconv support':     iconv}
4769summary_info += {'blkio support':     blkio}
4770summary_info += {'curl support':      curl}
4771summary_info += {'Multipath support': mpathpersist}
4772summary_info += {'Linux AIO support': libaio}
4773summary_info += {'Linux io_uring support': linux_io_uring}
4774summary_info += {'ATTR/XATTR support': libattr}
4775summary_info += {'RDMA support':      rdma}
4776summary_info += {'fdt support':       fdt_opt == 'internal' ? 'internal' : fdt}
4777summary_info += {'libcap-ng support': libcap_ng}
4778summary_info += {'bpf support':       libbpf}
4779summary_info += {'rbd support':       rbd}
4780summary_info += {'smartcard support': cacard}
4781summary_info += {'U2F support':       u2f}
4782summary_info += {'libusb':            libusb}
4783summary_info += {'usb net redir':     usbredir}
4784summary_info += {'OpenGL support (epoxy)': opengl}
4785summary_info += {'GBM':               gbm}
4786summary_info += {'libiscsi support':  libiscsi}
4787summary_info += {'libnfs support':    libnfs}
4788if host_os == 'windows'
4789  if have_ga
4790    summary_info += {'QGA VSS support':   have_qga_vss}
4791  endif
4792endif
4793summary_info += {'seccomp support':   seccomp}
4794summary_info += {'GlusterFS support': glusterfs}
4795summary_info += {'hv-balloon support': hv_balloon}
4796summary_info += {'TPM support':       have_tpm}
4797summary_info += {'libssh support':    libssh}
4798summary_info += {'lzo support':       lzo}
4799summary_info += {'snappy support':    snappy}
4800summary_info += {'bzip2 support':     libbzip2}
4801summary_info += {'lzfse support':     liblzfse}
4802summary_info += {'zstd support':      zstd}
4803summary_info += {'Query Processing Library support': qpl}
4804summary_info += {'UADK Library support': uadk}
4805summary_info += {'qatzip support':    qatzip}
4806summary_info += {'NUMA host support': numa}
4807summary_info += {'capstone':          capstone}
4808summary_info += {'libpmem support':   libpmem}
4809summary_info += {'libdaxctl support': libdaxctl}
4810summary_info += {'libcbor support':   libcbor}
4811summary_info += {'libudev':           libudev}
4812# Dummy dependency, keep .found()
4813summary_info += {'FUSE lseek':        fuse_lseek.found()}
4814summary_info += {'selinux':           selinux}
4815summary_info += {'libdw':             libdw}
4816if host_os == 'freebsd'
4817  summary_info += {'libinotify-kqueue': inotify}
4818endif
4819summary(summary_info, bool_yn: true, section: 'Dependencies')
4820
4821if host_arch == 'unknown'
4822  message()
4823  warning('UNSUPPORTED HOST CPU')
4824  message()
4825  message('Support for CPU host architecture ' + cpu + ' is not currently')
4826  message('maintained. The QEMU project does not guarantee that QEMU will')
4827  message('compile or work on this host CPU. You can help by volunteering')
4828  message('to maintain it and providing a build host for our continuous')
4829  message('integration setup.')
4830  if get_option('tcg').allowed() and target_dirs.length() > 0
4831    message()
4832    message('configure has succeeded and you can continue to build, but')
4833    message('QEMU will use a slow interpreter to emulate the target CPU.')
4834  endif
4835elif host_arch == 'mips'
4836  message()
4837  warning('DEPRECATED HOST CPU')
4838  message()
4839  message('Support for CPU host architecture ' + cpu + ' is going to be')
4840  message('dropped as soon as the QEMU project stops supporting Debian 12')
4841  message('("Bookworm"). Going forward, the QEMU project will not guarantee')
4842  message('that QEMU will compile or work on this host CPU.')
4843endif
4844
4845if not supported_oses.contains(host_os)
4846  message()
4847  warning('UNSUPPORTED HOST OS')
4848  message()
4849  message('Support for host OS ' + host_os + 'is not currently maintained.')
4850  message('configure has succeeded and you can continue to build, but')
4851  message('the QEMU project does not guarantee that QEMU will compile or')
4852  message('work on this operating system. You can help by volunteering')
4853  message('to maintain it and providing a build host for our continuous')
4854  message('integration setup. This will ensure that future versions of QEMU')
4855  message('will keep working on ' + host_os + '.')
4856endif
4857
4858if host_arch == 'unknown' or not supported_oses.contains(host_os)
4859  message()
4860  message('If you want to help supporting QEMU on this platform, please')
4861  message('contact the developers at qemu-devel@nongnu.org.')
4862endif
4863
4864actually_reloc = get_option('relocatable')
4865# check if get_relocated_path() is actually able to relocate paths
4866if get_option('relocatable') and \
4867  not (get_option('prefix') / get_option('bindir')).startswith(get_option('prefix') / '')
4868  message()
4869  warning('bindir not included within prefix, the installation will not be relocatable.')
4870  actually_reloc = false
4871endif
4872if not actually_reloc and (host_os == 'windows' or get_option('relocatable'))
4873  if host_os == 'windows'
4874    message()
4875    warning('Windows installs should usually be relocatable.')
4876  endif
4877  message()
4878  message('QEMU will have to be installed under ' + get_option('prefix') + '.')
4879  message('Use --disable-relocatable to remove this warning.')
4880endif
4881