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