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