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