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