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