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