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