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