xref: /openbmc/qemu/meson.build (revision 0d70c5aa1bbfb0f5099d53d6e084337a8246cc0c)
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
1288enable_passt = get_option('passt') \
1289  .require(host_os == 'linux', error_message: 'passt is supported only on Linux') \
1290  .allowed()
1291
1292vde = not_found
1293if not get_option('vde').auto() or have_system or have_tools
1294  vde = cc.find_library('vdeplug', has_headers: ['libvdeplug.h'],
1295                           required: get_option('vde'))
1296endif
1297if vde.found() and not cc.links('''
1298   #include <libvdeplug.h>
1299   int main(void)
1300   {
1301     struct vde_open_args a = {0, 0, 0};
1302     char s[] = "";
1303     vde_open(s, s, &a);
1304     return 0;
1305   }''', dependencies: vde)
1306  vde = not_found
1307  if get_option('cap_ng').enabled()
1308    error('could not link libvdeplug')
1309  else
1310    warning('could not link libvdeplug, disabling')
1311  endif
1312endif
1313
1314pulse = not_found
1315if not get_option('pa').auto() or (host_os == 'linux' and have_system)
1316  pulse = dependency('libpulse', required: get_option('pa'),
1317                     method: 'pkg-config')
1318endif
1319alsa = not_found
1320if not get_option('alsa').auto() or (host_os == 'linux' and have_system)
1321  alsa = dependency('alsa', required: get_option('alsa'),
1322                    method: 'pkg-config')
1323endif
1324jack = not_found
1325if not get_option('jack').auto() or have_system
1326  jack = dependency('jack', required: get_option('jack'),
1327                    method: 'pkg-config')
1328endif
1329pipewire = not_found
1330if not get_option('pipewire').auto() or (host_os == 'linux' and have_system)
1331  pipewire = dependency('libpipewire-0.3', version: '>=0.3.60',
1332                    required: get_option('pipewire'),
1333                    method: 'pkg-config')
1334endif
1335sndio = not_found
1336if not get_option('sndio').auto() or have_system
1337  sndio = dependency('sndio', required: get_option('sndio'),
1338                    method: 'pkg-config')
1339endif
1340
1341spice_protocol = not_found
1342if not get_option('spice_protocol').auto() or have_system
1343  spice_protocol = dependency('spice-protocol', version: '>=0.14.0',
1344                              required: get_option('spice_protocol'),
1345                              method: 'pkg-config')
1346endif
1347spice = not_found
1348if get_option('spice') \
1349             .disable_auto_if(not have_system) \
1350             .require(pixman.found(),
1351                      error_message: 'cannot enable SPICE if pixman is not available') \
1352             .allowed()
1353  spice = dependency('spice-server', version: '>=0.14.0',
1354                     required: get_option('spice'),
1355                     method: 'pkg-config')
1356endif
1357spice_headers = spice.partial_dependency(compile_args: true, includes: true)
1358
1359rt = cc.find_library('rt', required: false)
1360
1361libiscsi = not_found
1362if not get_option('libiscsi').auto() or have_block
1363  libiscsi = dependency('libiscsi', version: '>=1.9.0',
1364                         required: get_option('libiscsi'),
1365                         method: 'pkg-config')
1366endif
1367zstd = not_found
1368if not get_option('zstd').auto() or have_block
1369  zstd = dependency('libzstd', version: '>=1.4.0',
1370                    required: get_option('zstd'),
1371                    method: 'pkg-config')
1372endif
1373qpl = not_found
1374if not get_option('qpl').auto() or have_system
1375  qpl = dependency('qpl', version: '>=1.5.0',
1376                    required: get_option('qpl'),
1377                    method: 'pkg-config')
1378endif
1379uadk = not_found
1380if not get_option('uadk').auto() or have_system
1381  libwd = dependency('libwd', version: '>=2.6',
1382                      required: get_option('uadk'),
1383                      method: 'pkg-config')
1384  libwd_comp = dependency('libwd_comp', version: '>=2.6',
1385                           required: get_option('uadk'),
1386                           method: 'pkg-config')
1387  if libwd.found() and libwd_comp.found()
1388     uadk = declare_dependency(dependencies: [libwd, libwd_comp])
1389  endif
1390endif
1391
1392qatzip = not_found
1393if not get_option('qatzip').auto() or have_system
1394  qatzip = dependency('qatzip', version: '>=1.1.2',
1395                      required: get_option('qatzip'),
1396                      method: 'pkg-config')
1397endif
1398
1399virgl = not_found
1400
1401have_vhost_user_gpu = have_tools and host_os == 'linux' and pixman.found()
1402if not get_option('virglrenderer').auto() or have_system or have_vhost_user_gpu
1403  virgl = dependency('virglrenderer',
1404                     method: 'pkg-config',
1405                     required: get_option('virglrenderer'))
1406endif
1407rutabaga = not_found
1408if not get_option('rutabaga_gfx').auto() or have_system or have_vhost_user_gpu
1409  rutabaga = dependency('rutabaga_gfx_ffi',
1410                         method: 'pkg-config',
1411                         required: get_option('rutabaga_gfx'))
1412endif
1413blkio = not_found
1414if not get_option('blkio').auto() or have_block
1415  blkio = dependency('blkio',
1416                     method: 'pkg-config',
1417                     required: get_option('blkio'))
1418endif
1419curl = not_found
1420if not get_option('curl').auto() or have_block
1421  curl = dependency('libcurl', version: '>=7.29.0',
1422                    method: 'pkg-config',
1423                    required: get_option('curl'))
1424endif
1425libudev = not_found
1426if host_os == 'linux' and (have_system or have_tools)
1427  libudev = dependency('libudev',
1428                       method: 'pkg-config',
1429                       required: get_option('libudev'))
1430endif
1431igvm = not_found
1432if not get_option('igvm').auto() or have_system
1433  igvm = dependency('igvm', version: '>= 0.3.0',
1434                    method: 'pkg-config',
1435                    required: get_option('igvm'))
1436endif
1437
1438mpathlibs = [libudev]
1439mpathpersist = not_found
1440if host_os == 'linux' and have_tools and get_option('mpath').allowed()
1441  mpath_test_source = '''
1442    #include <libudev.h>
1443    #include <mpath_persist.h>
1444    unsigned mpath_mx_alloc_len = 1024;
1445    int logsink;
1446    static struct config *multipath_conf;
1447    extern struct udev *udev;
1448    extern struct config *get_multipath_config(void);
1449    extern void put_multipath_config(struct config *conf);
1450    struct udev *udev;
1451    struct config *get_multipath_config(void) { return multipath_conf; }
1452    void put_multipath_config(struct config *conf) { }
1453    int main(void) {
1454        udev = udev_new();
1455        multipath_conf = mpath_lib_init();
1456        return 0;
1457    }'''
1458  libmpathpersist = cc.find_library('mpathpersist',
1459                                    required: get_option('mpath'))
1460  if libmpathpersist.found()
1461    mpathlibs += libmpathpersist
1462    if get_option('prefer_static')
1463      mpathlibs += cc.find_library('devmapper',
1464                                     required: get_option('mpath'))
1465    endif
1466    mpathlibs += cc.find_library('multipath',
1467                                 required: get_option('mpath'))
1468    foreach lib: mpathlibs
1469      if not lib.found()
1470        mpathlibs = []
1471        break
1472      endif
1473    endforeach
1474    if mpathlibs.length() == 0
1475      msg = 'Dependencies missing for libmpathpersist'
1476    elif cc.links(mpath_test_source, dependencies: mpathlibs)
1477      mpathpersist = declare_dependency(dependencies: mpathlibs)
1478    else
1479      msg = 'Cannot detect libmpathpersist API'
1480    endif
1481    if not mpathpersist.found()
1482      if get_option('mpath').enabled()
1483        error(msg)
1484      else
1485        warning(msg + ', disabling')
1486      endif
1487    endif
1488  endif
1489endif
1490
1491iconv = not_found
1492curses = not_found
1493if have_system and get_option('curses').allowed()
1494  curses_test = '''
1495    #ifdef __APPLE__
1496    #define _XOPEN_SOURCE_EXTENDED 1
1497    #endif
1498    #include <locale.h>
1499    #include <curses.h>
1500    #include <wchar.h>
1501    int main(void) {
1502      wchar_t wch = L'w';
1503      setlocale(LC_ALL, "");
1504      resize_term(0, 0);
1505      addwstr(L"wide chars\n");
1506      addnwstr(&wch, 1);
1507      add_wch(WACS_DEGREE);
1508      return 0;
1509    }'''
1510
1511  curses_dep_list = host_os == 'windows' ? ['ncurses', 'ncursesw'] : ['ncursesw']
1512  curses = dependency(curses_dep_list,
1513                      required: false,
1514                      method: 'pkg-config')
1515  msg = get_option('curses').enabled() ? 'curses library not found' : ''
1516  curses_compile_args = ['-DNCURSES_WIDECHAR=1']
1517  if curses.found()
1518    if cc.links(curses_test, args: curses_compile_args, dependencies: [curses])
1519      curses = declare_dependency(compile_args: curses_compile_args, dependencies: [curses],
1520                                  version: curses.version())
1521    else
1522      msg = 'curses package not usable'
1523      curses = not_found
1524    endif
1525  endif
1526  if not curses.found()
1527    has_curses_h = cc.has_header('curses.h', args: curses_compile_args)
1528    if host_os != 'windows' and not has_curses_h
1529      message('Trying with /usr/include/ncursesw')
1530      curses_compile_args += ['-I/usr/include/ncursesw']
1531      has_curses_h = cc.has_header('curses.h', args: curses_compile_args)
1532    endif
1533    if has_curses_h
1534      curses_libname_list = (host_os == 'windows' ? ['pdcurses'] : ['ncursesw', 'cursesw'])
1535      foreach curses_libname : curses_libname_list
1536        libcurses = cc.find_library(curses_libname,
1537                                    required: false)
1538        if libcurses.found()
1539          if cc.links(curses_test, args: curses_compile_args, dependencies: libcurses)
1540            curses = declare_dependency(compile_args: curses_compile_args,
1541                                        dependencies: [libcurses])
1542            break
1543          else
1544            msg = 'curses library not usable'
1545          endif
1546        endif
1547      endforeach
1548    endif
1549  endif
1550  if get_option('iconv').allowed()
1551    foreach link_args : [ ['-liconv'], [] ]
1552      # Programs will be linked with glib and this will bring in libiconv on FreeBSD.
1553      # We need to use libiconv if available because mixing libiconv's headers with
1554      # the system libc does not work.
1555      # However, without adding glib to the dependencies -L/usr/local/lib will not be
1556      # included in the command line and libiconv will not be found.
1557      if cc.links('''
1558        #include <iconv.h>
1559        int main(void) {
1560          iconv_t conv = iconv_open("WCHAR_T", "UCS-2");
1561          return conv != (iconv_t) -1;
1562        }''', args: link_args, dependencies: glib)
1563        iconv = declare_dependency(link_args: link_args, dependencies: glib)
1564        break
1565      endif
1566    endforeach
1567  endif
1568  if curses.found() and not iconv.found()
1569    if get_option('iconv').enabled()
1570      error('iconv not available')
1571    endif
1572    msg = 'iconv required for curses UI but not available'
1573    curses = not_found
1574  endif
1575  if not curses.found() and msg != ''
1576    if get_option('curses').enabled()
1577      error(msg)
1578    else
1579      warning(msg + ', disabling')
1580    endif
1581  endif
1582endif
1583
1584brlapi = not_found
1585if not get_option('brlapi').auto() or have_system
1586  brlapi = cc.find_library('brlapi', has_headers: ['brlapi.h'],
1587                         required: get_option('brlapi'))
1588  if brlapi.found() and not cc.links('''
1589     #include <brlapi.h>
1590     #include <stddef.h>
1591     int main(void) { return brlapi__openConnection (NULL, NULL, NULL); }''', dependencies: brlapi)
1592    brlapi = not_found
1593    if get_option('brlapi').enabled()
1594      error('could not link brlapi')
1595    else
1596      warning('could not link brlapi, disabling')
1597    endif
1598  endif
1599endif
1600
1601sdl = not_found
1602if not get_option('sdl').auto() or have_system
1603  sdl = dependency('sdl2', required: get_option('sdl'))
1604  sdl_image = not_found
1605endif
1606if sdl.found()
1607  # Some versions of SDL have problems with -Wundef
1608  if not cc.compiles('''
1609                     #include <SDL.h>
1610                     #include <SDL_syswm.h>
1611                     int main(int argc, char *argv[]) { return 0; }
1612                     ''', dependencies: sdl, args: '-Werror=undef')
1613    sdl = declare_dependency(compile_args: '-Wno-undef',
1614                             dependencies: sdl,
1615                             version: sdl.version())
1616  endif
1617  sdl_image = dependency('SDL2_image', required: get_option('sdl_image'),
1618                         method: 'pkg-config')
1619else
1620  if get_option('sdl_image').enabled()
1621    error('sdl-image required, but SDL was @0@'.format(
1622          get_option('sdl').disabled() ? 'disabled' : 'not found'))
1623  endif
1624  sdl_image = not_found
1625endif
1626
1627rbd = not_found
1628if not get_option('rbd').auto() or have_block
1629  librados = cc.find_library('rados', required: get_option('rbd'))
1630  librbd = cc.find_library('rbd', has_headers: ['rbd/librbd.h'],
1631                           required: get_option('rbd'))
1632  if librados.found() and librbd.found()
1633    if cc.links('''
1634      #include <stdio.h>
1635      #include <rbd/librbd.h>
1636      int main(void) {
1637        rados_t cluster;
1638        rados_create(&cluster, NULL);
1639        #if LIBRBD_VERSION_CODE < LIBRBD_VERSION(1, 12, 0)
1640        #error
1641        #endif
1642        return 0;
1643      }''', dependencies: [librbd, librados])
1644      rbd = declare_dependency(dependencies: [librbd, librados])
1645    elif get_option('rbd').enabled()
1646      error('librbd >= 1.12.0 required')
1647    else
1648      warning('librbd >= 1.12.0 not found, disabling')
1649    endif
1650  endif
1651endif
1652
1653glusterfs = not_found
1654glusterfs_ftruncate_has_stat = false
1655glusterfs_iocb_has_stat = false
1656if not get_option('glusterfs').auto() or have_block
1657  glusterfs = dependency('glusterfs-api', version: '>=3',
1658                         required: get_option('glusterfs'),
1659                         method: 'pkg-config')
1660  if glusterfs.found()
1661    glusterfs_ftruncate_has_stat = cc.links('''
1662      #include <glusterfs/api/glfs.h>
1663
1664      int
1665      main(void)
1666      {
1667          /* new glfs_ftruncate() passes two additional args */
1668          return glfs_ftruncate(NULL, 0, NULL, NULL);
1669      }
1670    ''', dependencies: glusterfs)
1671    glusterfs_iocb_has_stat = cc.links('''
1672      #include <glusterfs/api/glfs.h>
1673
1674      /* new glfs_io_cbk() passes two additional glfs_stat structs */
1675      static void
1676      glusterfs_iocb(glfs_fd_t *fd, ssize_t ret, struct glfs_stat *prestat, struct glfs_stat *poststat, void *data)
1677      {}
1678
1679      int
1680      main(void)
1681      {
1682          glfs_io_cbk iocb = &glusterfs_iocb;
1683          iocb(NULL, 0 , NULL, NULL, NULL);
1684          return 0;
1685      }
1686    ''', dependencies: glusterfs)
1687  endif
1688endif
1689
1690hv_balloon = false
1691if get_option('hv_balloon').allowed() and have_system
1692  if cc.links('''
1693    #include <string.h>
1694    #include <gmodule.h>
1695    int main(void) {
1696        GTree *tree;
1697
1698        tree = g_tree_new((GCompareFunc)strcmp);
1699        (void)g_tree_node_first(tree);
1700        g_tree_destroy(tree);
1701        return 0;
1702    }
1703  ''', dependencies: glib)
1704    hv_balloon = true
1705  else
1706    if get_option('hv_balloon').enabled()
1707      error('could not enable hv-balloon, update your glib')
1708    else
1709      warning('could not find glib support for hv-balloon, disabling')
1710    endif
1711  endif
1712endif
1713
1714libssh = not_found
1715if not get_option('libssh').auto() or have_block
1716  libssh = dependency('libssh', version: '>=0.8.7',
1717                    method: 'pkg-config',
1718                    required: get_option('libssh'))
1719endif
1720
1721libbzip2 = not_found
1722if not get_option('bzip2').auto() or have_block
1723  libbzip2 = cc.find_library('bz2', has_headers: ['bzlib.h'],
1724                             required: get_option('bzip2'))
1725  if libbzip2.found() and not cc.links('''
1726     #include <bzlib.h>
1727     int main(void) { BZ2_bzlibVersion(); return 0; }''', dependencies: libbzip2)
1728    libbzip2 = not_found
1729    if get_option('bzip2').enabled()
1730      error('could not link libbzip2')
1731    else
1732      warning('could not link libbzip2, disabling')
1733    endif
1734  endif
1735endif
1736
1737liblzfse = not_found
1738if not get_option('lzfse').auto() or have_block
1739  liblzfse = cc.find_library('lzfse', has_headers: ['lzfse.h'],
1740                             required: get_option('lzfse'))
1741endif
1742if liblzfse.found() and not cc.links('''
1743   #include <lzfse.h>
1744   int main(void) { lzfse_decode_scratch_size(); return 0; }''', dependencies: liblzfse)
1745  liblzfse = not_found
1746  if get_option('lzfse').enabled()
1747    error('could not link liblzfse')
1748  else
1749    warning('could not link liblzfse, disabling')
1750  endif
1751endif
1752
1753oss = not_found
1754if get_option('oss').allowed() and have_system
1755  if not cc.has_header('sys/soundcard.h')
1756    # not found
1757  elif host_os == 'netbsd'
1758    oss = cc.find_library('ossaudio', required: get_option('oss'))
1759  else
1760    oss = declare_dependency()
1761  endif
1762
1763  if not oss.found()
1764    if get_option('oss').enabled()
1765      error('OSS not found')
1766    endif
1767  endif
1768endif
1769dsound = not_found
1770if not get_option('dsound').auto() or (host_os == 'windows' and have_system)
1771  if cc.has_header('dsound.h')
1772    dsound = declare_dependency(link_args: ['-lole32', '-ldxguid'])
1773  endif
1774
1775  if not dsound.found()
1776    if get_option('dsound').enabled()
1777      error('DirectSound not found')
1778    endif
1779  endif
1780endif
1781
1782coreaudio = not_found
1783if not get_option('coreaudio').auto() or (host_os == 'darwin' and have_system)
1784  coreaudio = dependency('appleframeworks', modules: 'CoreAudio',
1785                         required: get_option('coreaudio'))
1786endif
1787
1788opengl = not_found
1789if not get_option('opengl').auto() or have_system or have_vhost_user_gpu
1790  epoxy = dependency('epoxy', method: 'pkg-config',
1791                      required: get_option('opengl'))
1792  if cc.has_header('epoxy/egl.h', dependencies: epoxy)
1793    opengl = epoxy
1794  elif get_option('opengl').enabled()
1795    error('epoxy/egl.h not found')
1796  endif
1797endif
1798gbm = not_found
1799if (have_system or have_tools) and (virgl.found() or opengl.found())
1800  gbm = dependency('gbm', method: 'pkg-config', required: false)
1801endif
1802have_vhost_user_gpu = have_vhost_user_gpu and virgl.found() and opengl.found() and gbm.found()
1803
1804libcbor = not_found
1805if not get_option('libcbor').auto() or have_system
1806  libcbor = dependency('libcbor', version: '>=0.7.0',
1807                       required: get_option('libcbor'))
1808endif
1809
1810gnutls = not_found
1811gnutls_crypto = not_found
1812if get_option('gnutls').enabled() or (get_option('gnutls').auto() and have_system)
1813  # For general TLS support our min gnutls matches
1814  # that implied by our platform support matrix
1815  #
1816  # For the crypto backends, we look for a newer
1817  # gnutls:
1818  #
1819  #   Version 3.6.8  is needed to get XTS
1820  #   Version 3.6.13 is needed to get PBKDF
1821  #   Version 3.6.14 is needed to get HW accelerated XTS
1822  #
1823  # If newer enough gnutls isn't available, we can
1824  # still use a different crypto backend to satisfy
1825  # the platform support requirements
1826  gnutls_crypto = dependency('gnutls', version: '>=3.6.14',
1827                             method: 'pkg-config',
1828                             required: false)
1829  if gnutls_crypto.found()
1830    gnutls = gnutls_crypto
1831  else
1832    # Our min version if all we need is TLS
1833    gnutls = dependency('gnutls', version: '>=3.5.18',
1834                        method: 'pkg-config',
1835                        required: get_option('gnutls'))
1836  endif
1837endif
1838
1839# We prefer use of gnutls for crypto, unless the options
1840# explicitly asked for nettle or gcrypt.
1841#
1842# If gnutls isn't available for crypto, then we'll prefer
1843# gcrypt over nettle for performance reasons.
1844gcrypt = not_found
1845nettle = not_found
1846hogweed = not_found
1847crypto_sm4 = not_found
1848crypto_sm3 = not_found
1849xts = 'none'
1850
1851if get_option('nettle').enabled() and get_option('gcrypt').enabled()
1852  error('Only one of gcrypt & nettle can be enabled')
1853endif
1854
1855# Explicit nettle/gcrypt request, so ignore gnutls for crypto
1856if get_option('nettle').enabled() or get_option('gcrypt').enabled()
1857  gnutls_crypto = not_found
1858endif
1859
1860if not gnutls_crypto.found()
1861  if (not get_option('gcrypt').auto() or have_system) and not get_option('nettle').enabled()
1862    gcrypt = dependency('libgcrypt', version: '>=1.8',
1863                        required: get_option('gcrypt'))
1864    # Debian has removed -lgpg-error from libgcrypt-config
1865    # as it "spreads unnecessary dependencies" which in
1866    # turn breaks static builds...
1867    if gcrypt.found() and get_option('prefer_static')
1868      gcrypt = declare_dependency(dependencies:
1869        [gcrypt,
1870         cc.find_library('gpg-error', required: true)],
1871        version: gcrypt.version())
1872    endif
1873    crypto_sm4 = gcrypt
1874    # SM4 ALG is available in libgcrypt >= 1.9
1875    if gcrypt.found() and not cc.links('''
1876      #include <gcrypt.h>
1877      int main(void) {
1878        gcry_cipher_hd_t handler;
1879        gcry_cipher_open(&handler, GCRY_CIPHER_SM4, GCRY_CIPHER_MODE_ECB, 0);
1880        return 0;
1881      }''', dependencies: gcrypt)
1882      crypto_sm4 = not_found
1883    endif
1884    crypto_sm3 = gcrypt
1885    # SM3 ALG is available in libgcrypt >= 1.9
1886    if gcrypt.found() and not cc.links('''
1887      #include <gcrypt.h>
1888      int main(void) {
1889        gcry_md_hd_t handler;
1890        gcry_md_open(&handler, GCRY_MD_SM3, 0);
1891        return 0;
1892      }''', dependencies: gcrypt)
1893      crypto_sm3 = not_found
1894    endif
1895  endif
1896  if (not get_option('nettle').auto() or have_system) and not gcrypt.found()
1897    nettle = dependency('nettle', version: '>=3.4',
1898                        method: 'pkg-config',
1899                        required: get_option('nettle'))
1900    if nettle.found() and not cc.has_header('nettle/xts.h', dependencies: nettle)
1901      xts = 'private'
1902    endif
1903    crypto_sm4 = nettle
1904    # SM4 ALG is available in nettle >= 3.9
1905    if nettle.found() and not cc.links('''
1906      #include <nettle/sm4.h>
1907      int main(void) {
1908        struct sm4_ctx ctx;
1909        unsigned char key[16] = {0};
1910        sm4_set_encrypt_key(&ctx, key);
1911        return 0;
1912      }''', dependencies: nettle)
1913      crypto_sm4 = not_found
1914    endif
1915    crypto_sm3 = nettle
1916    # SM3 ALG is available in nettle >= 3.8
1917    if nettle.found() and not cc.links('''
1918      #include <nettle/sm3.h>
1919      #include <nettle/hmac.h>
1920      int main(void) {
1921      struct sm3_ctx ctx;
1922      struct hmac_sm3_ctx hmac_ctx;
1923      unsigned char data[64] = {0};
1924      unsigned char output[32];
1925
1926      // SM3 hash function test
1927      sm3_init(&ctx);
1928      sm3_update(&ctx, 64, data);
1929      sm3_digest(&ctx, 32, data);
1930
1931      // HMAC-SM3 test
1932      hmac_sm3_set_key(&hmac_ctx, 32, data);
1933      hmac_sm3_update(&hmac_ctx, 64, data);
1934      hmac_sm3_digest(&hmac_ctx, 32, output);
1935
1936      return 0;
1937      }''', dependencies: nettle)
1938      crypto_sm3 = not_found
1939    endif
1940  endif
1941endif
1942
1943capstone = not_found
1944if not get_option('capstone').auto() or have_system or have_user
1945  capstone = dependency('capstone', version: '>=3.0.5',
1946                        method: 'pkg-config',
1947                        required: get_option('capstone'))
1948
1949  # Some versions of capstone have broken pkg-config file
1950  # that reports a wrong -I path, causing the #include to
1951  # fail later. If the system has such a broken version
1952  # do not use it.
1953  if capstone.found() and not cc.compiles('#include <capstone.h>',
1954                                          dependencies: [capstone])
1955    capstone = not_found
1956    if get_option('capstone').enabled()
1957      error('capstone requested, but it does not appear to work')
1958    endif
1959  endif
1960endif
1961
1962gmp = dependency('gmp', required: false, method: 'pkg-config')
1963if nettle.found() and gmp.found()
1964  hogweed = dependency('hogweed', version: '>=3.4',
1965                       method: 'pkg-config',
1966                       required: get_option('nettle'))
1967endif
1968
1969
1970gtk = not_found
1971gtkx11 = not_found
1972vte = not_found
1973have_gtk_clipboard = get_option('gtk_clipboard').enabled()
1974
1975if get_option('gtk') \
1976             .disable_auto_if(not have_system) \
1977             .require(pixman.found(),
1978                      error_message: 'cannot enable GTK if pixman is not available') \
1979             .allowed()
1980  gtk = dependency('gtk+-3.0', version: '>=3.22.0',
1981                   method: 'pkg-config',
1982                   required: get_option('gtk'))
1983  if gtk.found()
1984    gtkx11 = dependency('gtk+-x11-3.0', version: '>=3.22.0',
1985                        method: 'pkg-config',
1986                        required: false)
1987    gtk = declare_dependency(dependencies: [gtk, gtkx11],
1988                             version: gtk.version())
1989
1990    if not get_option('vte').auto() or have_system
1991      vte = dependency('vte-2.91',
1992                       method: 'pkg-config',
1993                       required: get_option('vte'))
1994    endif
1995  elif have_gtk_clipboard
1996    error('GTK clipboard requested, but GTK not found')
1997  endif
1998endif
1999
2000x11 = not_found
2001if gtkx11.found()
2002  x11 = dependency('x11', method: 'pkg-config', required: gtkx11.found())
2003endif
2004png = not_found
2005if get_option('png').allowed() and have_system
2006   png = dependency('libpng', version: '>=1.6.34', required: get_option('png'),
2007                    method: 'pkg-config')
2008endif
2009vnc = not_found
2010jpeg = not_found
2011sasl = not_found
2012if get_option('vnc') \
2013             .disable_auto_if(not have_system) \
2014             .require(pixman.found(),
2015                      error_message: 'cannot enable VNC if pixman is not available') \
2016             .allowed()
2017  vnc = declare_dependency() # dummy dependency
2018  jpeg = dependency('libjpeg', required: get_option('vnc_jpeg'),
2019                    method: 'pkg-config')
2020  sasl = cc.find_library('sasl2', has_headers: ['sasl/sasl.h'],
2021                         required: get_option('vnc_sasl'))
2022  if sasl.found()
2023    sasl = declare_dependency(dependencies: sasl,
2024                              compile_args: '-DSTRUCT_IOVEC_DEFINED')
2025  endif
2026endif
2027
2028pam = not_found
2029if not get_option('auth_pam').auto() or have_system
2030  pam = cc.find_library('pam', has_headers: ['security/pam_appl.h'],
2031                        required: get_option('auth_pam'))
2032endif
2033if pam.found() and not cc.links('''
2034   #include <stddef.h>
2035   #include <security/pam_appl.h>
2036   int main(void) {
2037     const char *service_name = "qemu";
2038     const char *user = "frank";
2039     const struct pam_conv pam_conv = { 0 };
2040     pam_handle_t *pamh = NULL;
2041     pam_start(service_name, user, &pam_conv, &pamh);
2042     return 0;
2043   }''', dependencies: pam)
2044  pam = not_found
2045  if get_option('auth_pam').enabled()
2046    error('could not link libpam')
2047  else
2048    warning('could not link libpam, disabling')
2049  endif
2050endif
2051
2052snappy = not_found
2053if not get_option('snappy').auto() or have_system
2054  snappy = cc.find_library('snappy', has_headers: ['snappy-c.h'],
2055                           required: get_option('snappy'))
2056endif
2057if snappy.found() and not cc.links('''
2058   #include <snappy-c.h>
2059   int main(void) { snappy_max_compressed_length(4096); return 0; }''', dependencies: snappy)
2060  snappy = not_found
2061  if get_option('snappy').enabled()
2062    error('could not link libsnappy')
2063  else
2064    warning('could not link libsnappy, disabling')
2065  endif
2066endif
2067
2068lzo = not_found
2069if not get_option('lzo').auto() or have_system
2070  lzo = cc.find_library('lzo2', has_headers: ['lzo/lzo1x.h'],
2071                        required: get_option('lzo'))
2072endif
2073if lzo.found() and not cc.links('''
2074   #include <lzo/lzo1x.h>
2075   int main(void) { lzo_version(); return 0; }''', dependencies: lzo)
2076  lzo = not_found
2077  if get_option('lzo').enabled()
2078    error('could not link liblzo2')
2079  else
2080    warning('could not link liblzo2, disabling')
2081  endif
2082endif
2083
2084numa = not_found
2085if not get_option('numa').auto() or have_system or have_tools
2086  numa = cc.find_library('numa', has_headers: ['numa.h'],
2087                              required: get_option('numa'))
2088endif
2089if numa.found() and not cc.links('''
2090   #include <numa.h>
2091   int main(void) { return numa_available(); }
2092   ''', dependencies: numa)
2093  numa = not_found
2094  if get_option('numa').enabled()
2095    error('could not link numa')
2096  else
2097    warning('could not link numa, disabling')
2098  endif
2099endif
2100
2101fdt = not_found
2102fdt_opt = get_option('fdt')
2103if fdt_opt == 'enabled' and get_option('wrap_mode') == 'nodownload'
2104  fdt_opt = 'system'
2105endif
2106if fdt_opt in ['enabled', 'system'] or (fdt_opt == 'auto' and have_system)
2107  fdt = cc.find_library('fdt', required: fdt_opt == 'system')
2108  if fdt.found() and cc.links('''
2109     #include <libfdt.h>
2110     #include <libfdt_env.h>
2111     int main(void) { fdt_find_max_phandle(NULL, NULL); return 0; }''',
2112       dependencies: fdt)
2113    fdt_opt = 'system'
2114  elif fdt_opt != 'system'
2115    fdt_opt = get_option('wrap_mode') == 'nodownload' ? 'disabled' : 'internal'
2116    fdt = not_found
2117  else
2118    error('system libfdt is too old (1.5.1 or newer required)')
2119  endif
2120endif
2121if fdt_opt == 'internal'
2122  assert(not fdt.found())
2123  libfdt_proj = subproject('dtc', required: true,
2124                           default_options: ['tools=false',  'yaml=disabled',
2125                                             'python=disabled', 'default_library=static'])
2126  fdt = libfdt_proj.get_variable('libfdt_dep')
2127endif
2128
2129rdma = not_found
2130if not get_option('rdma').auto() or have_system
2131  rdma_libs = [cc.find_library('rdmacm', has_headers: ['rdma/rdma_cma.h'],
2132                               required: get_option('rdma')),
2133               cc.find_library('ibverbs', required: get_option('rdma'))]
2134  rdma = declare_dependency(dependencies: rdma_libs)
2135  foreach lib: rdma_libs
2136    if not lib.found()
2137      rdma = not_found
2138    endif
2139  endforeach
2140endif
2141
2142cacard = not_found
2143if not get_option('smartcard').auto() or have_system
2144  cacard = dependency('libcacard', required: get_option('smartcard'),
2145                      version: '>=2.5.1', method: 'pkg-config')
2146endif
2147u2f = not_found
2148if not get_option('u2f').auto() or have_system
2149  u2f = dependency('u2f-emu', required: get_option('u2f'),
2150                   method: 'pkg-config')
2151endif
2152canokey = not_found
2153if not get_option('canokey').auto() or have_system
2154  canokey = dependency('canokey-qemu', required: get_option('canokey'),
2155                   method: 'pkg-config')
2156endif
2157usbredir = not_found
2158if not get_option('usb_redir').auto() or have_system
2159  usbredir = dependency('libusbredirparser-0.5', required: get_option('usb_redir'),
2160                        version: '>=0.6', method: 'pkg-config')
2161endif
2162libusb = not_found
2163if not get_option('libusb').auto() or have_system
2164  libusb = dependency('libusb-1.0', required: get_option('libusb'),
2165                      version: '>=1.0.13', method: 'pkg-config')
2166endif
2167
2168libpmem = not_found
2169if not get_option('libpmem').auto() or have_system
2170  libpmem = dependency('libpmem', required: get_option('libpmem'),
2171                       method: 'pkg-config')
2172endif
2173libdaxctl = not_found
2174if not get_option('libdaxctl').auto() or have_system
2175  libdaxctl = dependency('libdaxctl', required: get_option('libdaxctl'),
2176                         version: '>=57', method: 'pkg-config')
2177endif
2178tasn1 = not_found
2179if gnutls.found()
2180  tasn1 = dependency('libtasn1',
2181                     required: false,
2182                     method: 'pkg-config')
2183endif
2184keyutils = not_found
2185if not get_option('libkeyutils').auto() or have_block
2186  keyutils = dependency('libkeyutils', required: get_option('libkeyutils'),
2187                        method: 'pkg-config')
2188endif
2189
2190has_gettid = cc.has_function('gettid')
2191
2192# libselinux
2193selinux = dependency('libselinux',
2194                     required: get_option('selinux'),
2195                     method: 'pkg-config')
2196
2197# Malloc tests
2198
2199malloc = []
2200if get_option('malloc') == 'system'
2201  has_malloc_trim = \
2202    get_option('malloc_trim').allowed() and \
2203    cc.has_function('malloc_trim', prefix: '#include <malloc.h>')
2204else
2205  has_malloc_trim = false
2206  malloc = cc.find_library(get_option('malloc'), required: true)
2207endif
2208if not has_malloc_trim and get_option('malloc_trim').enabled()
2209  if get_option('malloc') == 'system'
2210    error('malloc_trim not available on this platform.')
2211  else
2212    error('malloc_trim not available with non-libc memory allocator')
2213  endif
2214endif
2215
2216osdep_prefix = '''
2217  #ifndef _GNU_SOURCE
2218  #define _GNU_SOURCE
2219  #endif
2220
2221  #include <stddef.h>
2222  #include <sys/types.h>
2223
2224  #include <string.h>
2225  #include <limits.h>
2226  /* Put unistd.h before time.h as that triggers localtime_r/gmtime_r
2227   * function availability on recentish Mingw-w64 platforms. */
2228  #include <unistd.h>
2229  #include <time.h>
2230  #include <errno.h>
2231  #include <fcntl.h>
2232'''
2233
2234have_vhost_user_blk_server = get_option('vhost_user_blk_server') \
2235  .require(host_os == 'linux',
2236           error_message: 'vhost_user_blk_server requires linux') \
2237  .require(have_vhost_user,
2238           error_message: 'vhost_user_blk_server requires vhost-user support') \
2239  .disable_auto_if(not have_tools and not have_system) \
2240  .allowed()
2241
2242if get_option('fuse').disabled() and get_option('fuse_lseek').enabled()
2243  error('Cannot enable fuse-lseek while fuse is disabled')
2244endif
2245
2246fuse = dependency('fuse3', required: get_option('fuse'),
2247                  version: '>=3.1', method: 'pkg-config')
2248
2249fuse_lseek = not_found
2250if get_option('fuse_lseek').allowed()
2251  if fuse.version().version_compare('>=3.8')
2252    # Dummy dependency
2253    fuse_lseek = declare_dependency()
2254  elif get_option('fuse_lseek').enabled()
2255    if fuse.found()
2256      error('fuse-lseek requires libfuse >=3.8, found ' + fuse.version())
2257    else
2258      error('fuse-lseek requires libfuse, which was not found')
2259    endif
2260  endif
2261endif
2262
2263have_libvduse = (host_os == 'linux')
2264if get_option('libvduse').enabled()
2265    if host_os != 'linux'
2266        error('libvduse requires linux')
2267    endif
2268elif get_option('libvduse').disabled()
2269    have_libvduse = false
2270endif
2271
2272have_vduse_blk_export = (have_libvduse and host_os == 'linux')
2273if get_option('vduse_blk_export').enabled()
2274    if host_os != 'linux'
2275        error('vduse_blk_export requires linux')
2276    elif not have_libvduse
2277        error('vduse_blk_export requires libvduse support')
2278    endif
2279elif get_option('vduse_blk_export').disabled()
2280    have_vduse_blk_export = false
2281endif
2282
2283# libbpf
2284bpf_version = '1.1.0'
2285libbpf = dependency('libbpf', version: '>=' + bpf_version, required: get_option('bpf'), method: 'pkg-config')
2286if libbpf.found() and not cc.links('''
2287   #include <bpf/libbpf.h>
2288   #include <linux/bpf.h>
2289   int main(void)
2290   {
2291     // check flag availability
2292     int flag = BPF_F_MMAPABLE;
2293     bpf_object__destroy_skeleton(NULL);
2294     return 0;
2295   }''', dependencies: libbpf)
2296  libbpf = not_found
2297  if get_option('bpf').enabled()
2298    error('libbpf skeleton/mmaping test failed')
2299  else
2300    warning('libbpf skeleton/mmaping test failed, disabling')
2301  endif
2302endif
2303
2304# libxdp
2305libxdp = not_found
2306if not get_option('af_xdp').auto() or have_system
2307    if libbpf.found()
2308        libxdp = dependency('libxdp', required: get_option('af_xdp'),
2309                            version: '>=1.4.0', method: 'pkg-config')
2310    else
2311        if get_option('af_xdp').enabled()
2312            error('libxdp requested, but libbpf is not available')
2313        endif
2314    endif
2315endif
2316
2317# libdw
2318libdw = not_found
2319if not get_option('libdw').auto() or \
2320        (not get_option('prefer_static') and (have_system or have_user))
2321    libdw = dependency('libdw',
2322                       method: 'pkg-config',
2323                       required: get_option('libdw'))
2324endif
2325
2326#################
2327# config-host.h #
2328#################
2329
2330config_host_data = configuration_data()
2331
2332config_host_data.set('CONFIG_HAVE_RUST', have_rust)
2333audio_drivers_selected = []
2334if have_system
2335  audio_drivers_available = {
2336    'alsa': alsa.found(),
2337    'coreaudio': coreaudio.found(),
2338    'dsound': dsound.found(),
2339    'jack': jack.found(),
2340    'oss': oss.found(),
2341    'pa': pulse.found(),
2342    'pipewire': pipewire.found(),
2343    'sdl': sdl.found(),
2344    'sndio': sndio.found(),
2345  }
2346  foreach k, v: audio_drivers_available
2347    config_host_data.set('CONFIG_AUDIO_' + k.to_upper(), v)
2348  endforeach
2349
2350  # Default to native drivers first, OSS second, SDL third
2351  audio_drivers_priority = \
2352    [ 'pa', 'coreaudio', 'dsound', 'sndio', 'oss' ] + \
2353    (host_os == 'linux' ? [] : [ 'sdl' ])
2354  audio_drivers_default = []
2355  foreach k: audio_drivers_priority
2356    if audio_drivers_available[k]
2357      audio_drivers_default += k
2358    endif
2359  endforeach
2360
2361  foreach k: get_option('audio_drv_list')
2362    if k == 'default'
2363      audio_drivers_selected += audio_drivers_default
2364    elif not audio_drivers_available[k]
2365      error('Audio driver "@0@" not available.'.format(k))
2366    else
2367      audio_drivers_selected += k
2368    endif
2369  endforeach
2370endif
2371config_host_data.set('CONFIG_AUDIO_DRIVERS',
2372                     '"' + '", "'.join(audio_drivers_selected) + '", ')
2373
2374have_host_block_device = (host_os != 'darwin' or
2375    cc.has_header('IOKit/storage/IOMedia.h'))
2376
2377dbus_display = get_option('dbus_display') \
2378  .require(gio.version().version_compare('>=2.64'),
2379           error_message: '-display dbus requires glib>=2.64') \
2380  .require(gdbus_codegen.found(),
2381           error_message: gdbus_codegen_error.format('-display dbus')) \
2382  .allowed()
2383
2384have_virtfs = get_option('virtfs') \
2385    .require(host_os == 'linux' or host_os == 'darwin',
2386             error_message: 'virtio-9p (virtfs) requires Linux or macOS') \
2387    .require(host_os == 'linux' or cc.has_function('pthread_fchdir_np'),
2388             error_message: 'virtio-9p (virtfs) on macOS requires the presence of pthread_fchdir_np') \
2389    .require(host_os == 'darwin' or libattr.found(),
2390             error_message: 'virtio-9p (virtfs) on Linux requires libattr-devel') \
2391    .disable_auto_if(not have_tools and not have_system) \
2392    .allowed()
2393
2394qga_fsfreeze = false
2395qga_fstrim = false
2396if host_os == 'linux'
2397    if cc.has_header_symbol('linux/fs.h', 'FIFREEZE')
2398        qga_fsfreeze = true
2399    endif
2400    if cc.has_header_symbol('linux/fs.h', 'FITRIM')
2401        qga_fstrim = true
2402    endif
2403elif host_os == 'freebsd' and cc.has_header_symbol('ufs/ffs/fs.h', 'UFSSUSPEND')
2404    qga_fsfreeze = true
2405endif
2406
2407if get_option('block_drv_ro_whitelist') == ''
2408  config_host_data.set('CONFIG_BDRV_RO_WHITELIST', '')
2409else
2410  config_host_data.set('CONFIG_BDRV_RO_WHITELIST',
2411        '"' + get_option('block_drv_ro_whitelist').replace(',', '", "') + '", ')
2412endif
2413if get_option('block_drv_rw_whitelist') == ''
2414  config_host_data.set('CONFIG_BDRV_RW_WHITELIST', '')
2415else
2416  config_host_data.set('CONFIG_BDRV_RW_WHITELIST',
2417        '"' + get_option('block_drv_rw_whitelist').replace(',', '", "') + '", ')
2418endif
2419
2420foreach k : get_option('trace_backends')
2421  config_host_data.set('CONFIG_TRACE_' + k.to_upper(), true)
2422endforeach
2423config_host_data.set_quoted('CONFIG_TRACE_FILE', get_option('trace_file'))
2424config_host_data.set_quoted('CONFIG_TLS_PRIORITY', get_option('tls_priority'))
2425if iasl.found()
2426  config_host_data.set_quoted('CONFIG_IASL', iasl.full_path())
2427endif
2428config_host_data.set_quoted('CONFIG_BINDIR', get_option('prefix') / get_option('bindir'))
2429config_host_data.set_quoted('CONFIG_PREFIX', get_option('prefix'))
2430config_host_data.set_quoted('CONFIG_QEMU_CONFDIR', get_option('prefix') / qemu_confdir)
2431config_host_data.set_quoted('CONFIG_QEMU_DATADIR', get_option('prefix') / qemu_datadir)
2432config_host_data.set_quoted('CONFIG_QEMU_DESKTOPDIR', get_option('prefix') / qemu_desktopdir)
2433
2434qemu_firmwarepath = ''
2435foreach k : get_option('qemu_firmwarepath')
2436  qemu_firmwarepath += '"' + get_option('prefix') / k + '", '
2437endforeach
2438config_host_data.set('CONFIG_QEMU_FIRMWAREPATH', qemu_firmwarepath)
2439
2440config_host_data.set_quoted('CONFIG_QEMU_HELPERDIR', get_option('prefix') / get_option('libexecdir'))
2441config_host_data.set_quoted('CONFIG_QEMU_ICONDIR', get_option('prefix') / qemu_icondir)
2442config_host_data.set_quoted('CONFIG_QEMU_LOCALEDIR', get_option('prefix') / get_option('localedir'))
2443config_host_data.set_quoted('CONFIG_QEMU_LOCALSTATEDIR', get_option('prefix') / get_option('localstatedir'))
2444config_host_data.set_quoted('CONFIG_QEMU_MODDIR', get_option('prefix') / qemu_moddir)
2445config_host_data.set_quoted('CONFIG_SYSCONFDIR', get_option('prefix') / get_option('sysconfdir'))
2446
2447if enable_modules
2448  config_host_data.set('CONFIG_STAMP', run_command(
2449      meson.current_source_dir() / 'scripts/qemu-stamp.py',
2450      meson.project_version(), get_option('pkgversion'), '--',
2451      meson.current_source_dir() / 'configure',
2452      capture: true, check: true).stdout().strip())
2453endif
2454
2455have_slirp_smbd = get_option('slirp_smbd') \
2456  .require(host_os != 'windows', error_message: 'Host smbd not supported on this platform.') \
2457  .allowed()
2458if have_slirp_smbd
2459  smbd_path = get_option('smbd')
2460  if smbd_path == ''
2461    smbd_path = (host_os == 'sunos' ? '/usr/sfw/sbin/smbd' : '/usr/sbin/smbd')
2462  endif
2463  config_host_data.set_quoted('CONFIG_SMBD_COMMAND', smbd_path)
2464endif
2465
2466config_host_data.set('HOST_' + host_arch.to_upper(), 1)
2467
2468kvm_targets_c = '""'
2469if get_option('kvm').allowed() and host_os == 'linux'
2470  kvm_targets_c = '"' + '" ,"'.join(kvm_targets) + '"'
2471endif
2472config_host_data.set('CONFIG_KVM_TARGETS', kvm_targets_c)
2473
2474if get_option('module_upgrades') and not enable_modules
2475  error('Cannot enable module-upgrades as modules are not enabled')
2476endif
2477config_host_data.set('CONFIG_MODULE_UPGRADES', get_option('module_upgrades'))
2478
2479config_host_data.set('CONFIG_ATTR', libattr.found())
2480config_host_data.set('CONFIG_BDRV_WHITELIST_TOOLS', get_option('block_drv_whitelist_in_tools'))
2481config_host_data.set('CONFIG_BRLAPI', brlapi.found())
2482config_host_data.set('CONFIG_BSD', host_os in bsd_oses)
2483config_host_data.set('CONFIG_FREEBSD', host_os == 'freebsd')
2484config_host_data.set('CONFIG_CAPSTONE', capstone.found())
2485config_host_data.set('CONFIG_COCOA', cocoa.found())
2486config_host_data.set('CONFIG_DARWIN', host_os == 'darwin')
2487config_host_data.set('CONFIG_FDT', fdt.found())
2488config_host_data.set('CONFIG_FUZZ', get_option('fuzzing'))
2489config_host_data.set('CONFIG_GCOV', get_option('b_coverage'))
2490config_host_data.set('CONFIG_LIBUDEV', libudev.found())
2491config_host_data.set('CONFIG_LINUX', host_os == 'linux')
2492config_host_data.set('CONFIG_POSIX', host_os != 'windows')
2493config_host_data.set('CONFIG_WIN32', host_os == 'windows')
2494config_host_data.set('CONFIG_LZO', lzo.found())
2495config_host_data.set('CONFIG_MPATH', mpathpersist.found())
2496config_host_data.set('CONFIG_BLKIO', blkio.found())
2497if blkio.found()
2498  config_host_data.set('CONFIG_BLKIO_VHOST_VDPA_FD',
2499                       blkio.version().version_compare('>=1.3.0'))
2500  config_host_data.set('CONFIG_BLKIO_WRITE_ZEROS_FUA',
2501                       blkio.version().version_compare('>=1.4.0'))
2502endif
2503config_host_data.set('CONFIG_CURL', curl.found())
2504config_host_data.set('CONFIG_CURSES', curses.found())
2505config_host_data.set('CONFIG_GBM', gbm.found())
2506config_host_data.set('CONFIG_GIO', gio.found())
2507config_host_data.set('CONFIG_GLUSTERFS', glusterfs.found())
2508if glusterfs.found()
2509  config_host_data.set('CONFIG_GLUSTERFS_XLATOR_OPT', glusterfs.version().version_compare('>=4'))
2510  config_host_data.set('CONFIG_GLUSTERFS_DISCARD', glusterfs.version().version_compare('>=5'))
2511  config_host_data.set('CONFIG_GLUSTERFS_FALLOCATE', glusterfs.version().version_compare('>=6'))
2512  config_host_data.set('CONFIG_GLUSTERFS_ZEROFILL', glusterfs.version().version_compare('>=6'))
2513  config_host_data.set('CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT', glusterfs_ftruncate_has_stat)
2514  config_host_data.set('CONFIG_GLUSTERFS_IOCB_HAS_STAT', glusterfs_iocb_has_stat)
2515endif
2516config_host_data.set('CONFIG_GTK', gtk.found())
2517config_host_data.set('CONFIG_VTE', vte.found())
2518config_host_data.set('CONFIG_GTK_CLIPBOARD', have_gtk_clipboard)
2519config_host_data.set('CONFIG_HEXAGON_IDEF_PARSER', get_option('hexagon_idef_parser'))
2520config_host_data.set('CONFIG_LIBATTR', have_old_libattr)
2521config_host_data.set('CONFIG_LIBCAP_NG', libcap_ng.found())
2522config_host_data.set('CONFIG_EBPF', libbpf.found())
2523config_host_data.set('CONFIG_AF_XDP', libxdp.found())
2524config_host_data.set('CONFIG_LIBDAXCTL', libdaxctl.found())
2525config_host_data.set('CONFIG_LIBISCSI', libiscsi.found())
2526config_host_data.set('CONFIG_LIBNFS', libnfs.found())
2527config_host_data.set('CONFIG_LIBSSH', libssh.found())
2528config_host_data.set('CONFIG_LINUX_AIO', libaio.found())
2529config_host_data.set('CONFIG_LINUX_IO_URING', linux_io_uring.found())
2530config_host_data.set('CONFIG_LIBPMEM', libpmem.found())
2531config_host_data.set('CONFIG_MODULES', enable_modules)
2532config_host_data.set('CONFIG_NUMA', numa.found())
2533if numa.found()
2534  config_host_data.set('HAVE_NUMA_HAS_PREFERRED_MANY',
2535                       cc.has_function('numa_has_preferred_many',
2536                                       dependencies: numa))
2537endif
2538config_host_data.set('CONFIG_OPENGL', opengl.found())
2539config_host_data.set('CONFIG_PLUGIN', get_option('plugins'))
2540config_host_data.set('CONFIG_RBD', rbd.found())
2541config_host_data.set('CONFIG_RDMA', rdma.found())
2542config_host_data.set('CONFIG_RELOCATABLE', get_option('relocatable'))
2543config_host_data.set('CONFIG_SAFESTACK', get_option('safe_stack'))
2544config_host_data.set('CONFIG_SDL', sdl.found())
2545config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found())
2546config_host_data.set('CONFIG_SECCOMP', seccomp.found())
2547if seccomp.found()
2548  config_host_data.set('CONFIG_SECCOMP_SYSRAWRC', seccomp_has_sysrawrc)
2549endif
2550config_host_data.set('CONFIG_PIXMAN', pixman.found())
2551config_host_data.set('CONFIG_PASST', enable_passt)
2552config_host_data.set('CONFIG_SLIRP', slirp.found())
2553config_host_data.set('CONFIG_SNAPPY', snappy.found())
2554config_host_data.set('CONFIG_SOLARIS', host_os == 'sunos')
2555if have_tcg
2556  config_host_data.set('CONFIG_TCG', 1)
2557  config_host_data.set('CONFIG_TCG_INTERPRETER', tcg_arch == 'tci')
2558endif
2559config_host_data.set('CONFIG_TPM', have_tpm)
2560config_host_data.set('CONFIG_TSAN', get_option('tsan'))
2561config_host_data.set('CONFIG_USB_LIBUSB', libusb.found())
2562config_host_data.set('CONFIG_VDE', vde.found())
2563config_host_data.set('CONFIG_VHOST', have_vhost)
2564config_host_data.set('CONFIG_VHOST_NET', have_vhost_net)
2565config_host_data.set('CONFIG_VHOST_NET_USER', have_vhost_net_user)
2566config_host_data.set('CONFIG_VHOST_NET_VDPA', have_vhost_net_vdpa)
2567config_host_data.set('CONFIG_VHOST_KERNEL', have_vhost_kernel)
2568config_host_data.set('CONFIG_VHOST_USER', have_vhost_user)
2569config_host_data.set('CONFIG_VHOST_CRYPTO', have_vhost_user_crypto)
2570config_host_data.set('CONFIG_VHOST_VDPA', have_vhost_vdpa)
2571config_host_data.set('CONFIG_VMNET', vmnet.found())
2572config_host_data.set('CONFIG_VHOST_USER_BLK_SERVER', have_vhost_user_blk_server)
2573config_host_data.set('CONFIG_VDUSE_BLK_EXPORT', have_vduse_blk_export)
2574config_host_data.set('CONFIG_PNG', png.found())
2575config_host_data.set('CONFIG_VNC', vnc.found())
2576config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
2577config_host_data.set('CONFIG_VNC_SASL', sasl.found())
2578if virgl.found()
2579  config_host_data.set('VIRGL_VERSION_MAJOR', virgl.version().split('.')[0])
2580endif
2581config_host_data.set('CONFIG_VIRTFS', have_virtfs)
2582config_host_data.set('CONFIG_VTE', vte.found())
2583config_host_data.set('CONFIG_XKBCOMMON', xkbcommon.found())
2584config_host_data.set('CONFIG_KEYUTILS', keyutils.found())
2585config_host_data.set('CONFIG_GETTID', has_gettid)
2586config_host_data.set('CONFIG_GNUTLS', gnutls.found())
2587config_host_data.set('CONFIG_GNUTLS_CRYPTO', gnutls_crypto.found())
2588config_host_data.set('CONFIG_TASN1', tasn1.found())
2589config_host_data.set('CONFIG_GCRYPT', gcrypt.found())
2590config_host_data.set('CONFIG_NETTLE', nettle.found())
2591config_host_data.set('CONFIG_CRYPTO_SM4', crypto_sm4.found())
2592config_host_data.set('CONFIG_CRYPTO_SM3', crypto_sm3.found())
2593config_host_data.set('CONFIG_HOGWEED', hogweed.found())
2594config_host_data.set('CONFIG_QEMU_PRIVATE_XTS', xts == 'private')
2595config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim)
2596config_host_data.set('CONFIG_ZSTD', zstd.found())
2597config_host_data.set('CONFIG_QPL', qpl.found())
2598config_host_data.set('CONFIG_UADK', uadk.found())
2599config_host_data.set('CONFIG_QATZIP', qatzip.found())
2600config_host_data.set('CONFIG_FUSE', fuse.found())
2601config_host_data.set('CONFIG_FUSE_LSEEK', fuse_lseek.found())
2602config_host_data.set('CONFIG_SPICE_PROTOCOL', spice_protocol.found())
2603if spice_protocol.found()
2604config_host_data.set('CONFIG_SPICE_PROTOCOL_MAJOR', spice_protocol.version().split('.')[0])
2605config_host_data.set('CONFIG_SPICE_PROTOCOL_MINOR', spice_protocol.version().split('.')[1])
2606config_host_data.set('CONFIG_SPICE_PROTOCOL_MICRO', spice_protocol.version().split('.')[2])
2607endif
2608config_host_data.set('CONFIG_SPICE', spice.found())
2609config_host_data.set('CONFIG_X11', x11.found())
2610config_host_data.set('CONFIG_DBUS_DISPLAY', dbus_display)
2611config_host_data.set('CONFIG_CFI', get_option('cfi'))
2612config_host_data.set('CONFIG_SELINUX', selinux.found())
2613config_host_data.set('CONFIG_XEN_BACKEND', xen.found())
2614config_host_data.set('CONFIG_LIBDW', libdw.found())
2615config_host_data.set('CONFIG_IGVM', igvm.found())
2616if xen.found()
2617  # protect from xen.version() having less than three components
2618  xen_version = xen.version().split('.') + ['0', '0']
2619  xen_ctrl_version = xen_version[0] + \
2620    ('0' + xen_version[1]).substring(-2) + \
2621    ('0' + xen_version[2]).substring(-2)
2622  config_host_data.set('CONFIG_XEN_CTRL_INTERFACE_VERSION', xen_ctrl_version)
2623endif
2624config_host_data.set('QEMU_VERSION', '"@0@"'.format(meson.project_version()))
2625config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0])
2626config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1])
2627config_host_data.set('QEMU_VERSION_MICRO', meson.project_version().split('.')[2])
2628
2629config_host_data.set_quoted('CONFIG_HOST_DSOSUF', host_dsosuf)
2630config_host_data.set('HAVE_HOST_BLOCK_DEVICE', have_host_block_device)
2631
2632have_coroutine_pool = get_option('coroutine_pool')
2633if get_option('debug_stack_usage') and have_coroutine_pool
2634  message('Disabling coroutine pool to measure stack usage')
2635  have_coroutine_pool = false
2636endif
2637config_host_data.set('CONFIG_COROUTINE_POOL', have_coroutine_pool)
2638config_host_data.set('CONFIG_DEBUG_GRAPH_LOCK', get_option('debug_graph_lock'))
2639config_host_data.set('CONFIG_DEBUG_MUTEX', get_option('debug_mutex'))
2640config_host_data.set('CONFIG_DEBUG_STACK_USAGE', get_option('debug_stack_usage'))
2641config_host_data.set('CONFIG_DEBUG_TCG', get_option('debug_tcg'))
2642config_host_data.set('CONFIG_DEBUG_REMAP', get_option('debug_remap'))
2643config_host_data.set('CONFIG_QOM_CAST_DEBUG', get_option('qom_cast_debug'))
2644config_host_data.set('CONFIG_REPLICATION', get_option('replication').allowed())
2645config_host_data.set('CONFIG_FSFREEZE', qga_fsfreeze)
2646config_host_data.set('CONFIG_FSTRIM', qga_fstrim)
2647
2648# has_header
2649config_host_data.set('CONFIG_EPOLL', cc.has_header('sys/epoll.h'))
2650config_host_data.set('CONFIG_LINUX_MAGIC_H', cc.has_header('linux/magic.h'))
2651valgrind = false
2652if get_option('valgrind').allowed()
2653    if cc.has_header('valgrind/valgrind.h')
2654        valgrind = true
2655    else
2656        if get_option('valgrind').enabled()
2657            error('valgrind requested but valgrind.h not found')
2658        endif
2659    endif
2660endif
2661config_host_data.set('CONFIG_VALGRIND_H', valgrind)
2662config_host_data.set('HAVE_BTRFS_H', cc.has_header('linux/btrfs.h'))
2663config_host_data.set('HAVE_DRM_H', cc.has_header('libdrm/drm.h'))
2664config_host_data.set('HAVE_OPENAT2_H', cc.has_header('linux/openat2.h'))
2665config_host_data.set('HAVE_PTY_H', cc.has_header('pty.h'))
2666config_host_data.set('HAVE_SYS_DISK_H', cc.has_header('sys/disk.h'))
2667config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h'))
2668config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h'))
2669if host_os == 'windows'
2670  config_host_data.set('HAVE_AFUNIX_H', cc.has_header('afunix.h'))
2671endif
2672
2673# has_function
2674config_host_data.set('CONFIG_CLOSE_RANGE', cc.has_function('close_range'))
2675config_host_data.set('CONFIG_ACCEPT4', cc.has_function('accept4'))
2676config_host_data.set('CONFIG_CLOCK_ADJTIME', cc.has_function('clock_adjtime'))
2677config_host_data.set('CONFIG_DUP3', cc.has_function('dup3'))
2678config_host_data.set('CONFIG_FALLOCATE', cc.has_function('fallocate'))
2679config_host_data.set('CONFIG_POSIX_FALLOCATE', cc.has_function('posix_fallocate'))
2680config_host_data.set('CONFIG_SCHED_GETCPU', cc.has_function('sched_getcpu', prefix: '#include <sched.h>'))
2681# Note that we need to specify prefix: here to avoid incorrectly
2682# thinking that Windows has posix_memalign()
2683config_host_data.set('CONFIG_POSIX_MEMALIGN', cc.has_function('posix_memalign', prefix: '#include <stdlib.h>'))
2684config_host_data.set('CONFIG_ALIGNED_MALLOC', cc.has_function('_aligned_malloc'))
2685config_host_data.set('CONFIG_VALLOC', cc.has_function('valloc'))
2686config_host_data.set('CONFIG_MEMALIGN', cc.has_function('memalign'))
2687config_host_data.set('CONFIG_PPOLL', cc.has_function('ppoll'))
2688config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include <sys/uio.h>'))
2689config_host_data.set('CONFIG_PTHREAD_FCHDIR_NP', cc.has_function('pthread_fchdir_np'))
2690config_host_data.set('CONFIG_SENDFILE', cc.has_function('sendfile'))
2691config_host_data.set('CONFIG_SETNS', cc.has_function('setns') and cc.has_function('unshare'))
2692config_host_data.set('CONFIG_SYNCFS', cc.has_function('syncfs'))
2693config_host_data.set('CONFIG_SYNC_FILE_RANGE', cc.has_function('sync_file_range'))
2694config_host_data.set('CONFIG_TIMERFD', cc.has_function('timerfd_create'))
2695config_host_data.set('CONFIG_GETLOADAVG', cc.has_function('getloadavg'))
2696config_host_data.set('HAVE_COPY_FILE_RANGE', cc.has_function('copy_file_range'))
2697config_host_data.set('HAVE_GETIFADDRS', cc.has_function('getifaddrs'))
2698config_host_data.set('HAVE_GLIB_WITH_SLICE_ALLOCATOR', glib_has_gslice)
2699config_host_data.set('HAVE_GLIB_WITH_ALIGNED_ALLOC', glib_has_aligned_alloc)
2700config_host_data.set('HAVE_OPENPTY', cc.has_function('openpty', dependencies: util))
2701config_host_data.set('HAVE_STRCHRNUL', cc.has_function('strchrnul', prefix: osdep_prefix))
2702config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: '#include <stdlib.h>'))
2703if rbd.found()
2704  config_host_data.set('HAVE_RBD_NAMESPACE_EXISTS',
2705                       cc.has_function('rbd_namespace_exists',
2706                                       dependencies: rbd,
2707                                       prefix: '#include <rbd/librbd.h>'))
2708endif
2709if rdma.found()
2710  config_host_data.set('HAVE_IBV_ADVISE_MR',
2711                       cc.has_function('ibv_advise_mr',
2712                                       dependencies: rdma,
2713                                       prefix: '#include <infiniband/verbs.h>'))
2714endif
2715
2716have_asan_fiber = false
2717if get_option('asan') and \
2718   not cc.has_function('__sanitizer_start_switch_fiber',
2719                         args: '-fsanitize=address',
2720                         prefix: '#include <sanitizer/asan_interface.h>')
2721  warning('Missing ASAN due to missing fiber annotation interface')
2722  warning('Without code annotation, the report may be inferior.')
2723else
2724  have_asan_fiber = true
2725endif
2726config_host_data.set('CONFIG_ASAN_IFACE_FIBER', have_asan_fiber)
2727
2728have_inotify_init = cc.has_header_symbol('sys/inotify.h', 'inotify_init')
2729have_inotify_init1 = cc.has_header_symbol('sys/inotify.h', 'inotify_init1')
2730inotify = not_found
2731if (have_inotify_init or have_inotify_init1) and host_os == 'freebsd'
2732  # libinotify-kqueue
2733  inotify = cc.find_library('inotify')
2734  if have_inotify_init
2735    have_inotify_init = inotify.found()
2736  endif
2737  if have_inotify_init1
2738    have_inotify_init1 = inotify.found()
2739  endif
2740endif
2741config_host_data.set('CONFIG_INOTIFY', have_inotify_init)
2742config_host_data.set('CONFIG_INOTIFY1', have_inotify_init1)
2743
2744# has_header_symbol
2745config_host_data.set('CONFIG_BLKZONED',
2746                     cc.has_header_symbol('linux/blkzoned.h', 'BLKOPENZONE'))
2747config_host_data.set('CONFIG_EPOLL_CREATE1',
2748                     cc.has_header_symbol('sys/epoll.h', 'epoll_create1'))
2749config_host_data.set('CONFIG_FALLOCATE_PUNCH_HOLE',
2750                     cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_PUNCH_HOLE') and
2751                     cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_KEEP_SIZE'))
2752config_host_data.set('CONFIG_FALLOCATE_ZERO_RANGE',
2753                     cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_ZERO_RANGE'))
2754config_host_data.set('CONFIG_FIEMAP',
2755                     cc.has_header('linux/fiemap.h') and
2756                     cc.has_header_symbol('linux/fs.h', 'FS_IOC_FIEMAP'))
2757config_host_data.set('CONFIG_GETCPU',
2758                     cc.has_header_symbol('sched.h', 'getcpu', prefix: osdep_prefix))
2759config_host_data.set('CONFIG_GETRANDOM',
2760                     cc.has_function('getrandom') and
2761                     cc.has_header_symbol('sys/random.h', 'GRND_NONBLOCK'))
2762config_host_data.set('CONFIG_PRCTL_PR_SET_TIMERSLACK',
2763                     cc.has_header_symbol('sys/prctl.h', 'PR_SET_TIMERSLACK'))
2764config_host_data.set('CONFIG_RTNETLINK',
2765                     cc.has_header_symbol('linux/rtnetlink.h', 'IFLA_PROTO_DOWN'))
2766config_host_data.set('CONFIG_SYSMACROS',
2767                     cc.has_header_symbol('sys/sysmacros.h', 'makedev'))
2768config_host_data.set('HAVE_OPTRESET',
2769                     cc.has_header_symbol('getopt.h', 'optreset'))
2770config_host_data.set('HAVE_IPPROTO_MPTCP',
2771                     cc.has_header_symbol('netinet/in.h', 'IPPROTO_MPTCP'))
2772if libaio.found()
2773  config_host_data.set('HAVE_IO_PREP_PWRITEV2',
2774                       cc.has_header_symbol('libaio.h', 'io_prep_pwritev2'))
2775endif
2776if linux_io_uring.found()
2777  config_host_data.set('HAVE_IO_URING_PREP_WRITEV2',
2778                       cc.has_header_symbol('liburing.h', 'io_uring_prep_writev2'))
2779endif
2780config_host_data.set('HAVE_TCP_KEEPCNT',
2781                     cc.has_header_symbol('netinet/tcp.h', 'TCP_KEEPCNT') or
2782                     cc.compiles('''
2783                     #include <ws2tcpip.h>
2784                     #ifndef TCP_KEEPCNT
2785                     #error
2786                     #endif
2787                     int main(void) { return 0; }''',
2788                     name: 'Win32 TCP_KEEPCNT'))
2789# On Darwin TCP_KEEPIDLE is available under different name, TCP_KEEPALIVE.
2790# https://github.com/apple/darwin-xnu/blob/xnu-4570.1.46/bsd/man/man4/tcp.4#L172
2791config_host_data.set('HAVE_TCP_KEEPIDLE',
2792                     cc.has_header_symbol('netinet/tcp.h', 'TCP_KEEPIDLE') or
2793                     cc.has_header_symbol('netinet/tcp.h', 'TCP_KEEPALIVE') or
2794                     cc.compiles('''
2795                     #include <ws2tcpip.h>
2796                     #ifndef TCP_KEEPIDLE
2797                     #error
2798                     #endif
2799                     int main(void) { return 0; }''',
2800                     name: 'Win32 TCP_KEEPIDLE'))
2801config_host_data.set('HAVE_TCP_KEEPINTVL',
2802                     cc.has_header_symbol('netinet/tcp.h', 'TCP_KEEPINTVL') or
2803                     cc.compiles('''
2804                     #include <ws2tcpip.h>
2805                     #ifndef TCP_KEEPINTVL
2806                     #error
2807                     #endif
2808                     int main(void) { return 0; }''',
2809                     name: 'Win32 TCP_KEEPINTVL'))
2810
2811# has_member
2812config_host_data.set('HAVE_SIGEV_NOTIFY_THREAD_ID',
2813                     cc.has_member('struct sigevent', 'sigev_notify_thread_id',
2814                                   prefix: '#include <signal.h>'))
2815config_host_data.set('HAVE_STRUCT_STAT_ST_ATIM',
2816                     cc.has_member('struct stat', 'st_atim',
2817                                   prefix: '#include <sys/stat.h>'))
2818config_host_data.set('HAVE_BLK_ZONE_REP_CAPACITY',
2819                     cc.has_member('struct blk_zone', 'capacity',
2820                                   prefix: '#include <linux/blkzoned.h>'))
2821
2822# has_type
2823config_host_data.set('CONFIG_IOVEC',
2824                     cc.has_type('struct iovec',
2825                                 prefix: '#include <sys/uio.h>'))
2826config_host_data.set('HAVE_UTMPX',
2827                     cc.has_type('struct utmpx',
2828                                 prefix: '#include <utmpx.h>'))
2829
2830config_host_data.set('CONFIG_EVENTFD', cc.links('''
2831  #include <sys/eventfd.h>
2832  int main(void) { return eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); }'''))
2833config_host_data.set('CONFIG_FDATASYNC', cc.links(osdep_prefix + '''
2834  int main(void) {
2835  #if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
2836  return fdatasync(0);
2837  #else
2838  #error Not supported
2839  #endif
2840  }'''))
2841
2842has_madvise = cc.links(osdep_prefix + '''
2843  #include <sys/mman.h>
2844  int main(void) { return madvise(NULL, 0, MADV_DONTNEED); }''')
2845missing_madvise_proto = false
2846if has_madvise
2847  # Some platforms (illumos and Solaris before Solaris 11) provide madvise()
2848  # but forget to prototype it. In this case, has_madvise will be true (the
2849  # test program links despite a compile warning). To detect the
2850  # missing-prototype case, we try again with a definitely-bogus prototype.
2851  # This will only compile if the system headers don't provide the prototype;
2852  # otherwise the conflicting prototypes will cause a compiler error.
2853  missing_madvise_proto = cc.links(osdep_prefix + '''>
2854    #include <sys/mman.h>
2855    extern int madvise(int);
2856    int main(void) { return madvise(0); }''')
2857endif
2858config_host_data.set('CONFIG_MADVISE', has_madvise)
2859config_host_data.set('HAVE_MADVISE_WITHOUT_PROTOTYPE', missing_madvise_proto)
2860
2861config_host_data.set('CONFIG_MEMFD', cc.links(osdep_prefix + '''
2862  #include <sys/mman.h>
2863  int main(void) { return memfd_create("foo", MFD_ALLOW_SEALING); }'''))
2864config_host_data.set('CONFIG_OPEN_BY_HANDLE', cc.links(osdep_prefix + '''
2865  #if !defined(AT_EMPTY_PATH)
2866  # error missing definition
2867  #else
2868  int main(void) { struct file_handle fh; return open_by_handle_at(0, &fh, 0); }
2869  #endif'''))
2870
2871# On Darwin posix_madvise() has the same return semantics as plain madvise(),
2872# i.e. errno is set and -1 is returned. That's not really how POSIX defines the
2873# function. On the flip side, it has madvise() which is preferred anyways.
2874if host_os != 'darwin'
2875  config_host_data.set('CONFIG_POSIX_MADVISE', cc.links(osdep_prefix + '''
2876    #include <sys/mman.h>
2877    int main(void) { return posix_madvise(NULL, 0, POSIX_MADV_DONTNEED); }'''))
2878endif
2879
2880config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_W_TID', cc.links(osdep_prefix + '''
2881  #include <pthread.h>
2882
2883  static void *f(void *p) { return NULL; }
2884  int main(void)
2885  {
2886    pthread_t thread;
2887    pthread_create(&thread, 0, f, 0);
2888    pthread_setname_np(thread, "QEMU");
2889    return 0;
2890  }''', dependencies: threads))
2891config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_WO_TID', cc.links(osdep_prefix + '''
2892  #include <pthread.h>
2893
2894  static void *f(void *p) { pthread_setname_np("QEMU"); return NULL; }
2895  int main(void)
2896  {
2897    pthread_t thread;
2898    pthread_create(&thread, 0, f, 0);
2899    return 0;
2900  }''', dependencies: threads))
2901config_host_data.set('CONFIG_PTHREAD_SET_NAME_NP', cc.links(osdep_prefix + '''
2902  #include <pthread.h>
2903  #include <pthread_np.h>
2904
2905  static void *f(void *p) { return NULL; }
2906  int main(void)
2907  {
2908    pthread_t thread;
2909    pthread_create(&thread, 0, f, 0);
2910    pthread_set_name_np(thread, "QEMU");
2911    return 0;
2912  }''', dependencies: threads))
2913config_host_data.set('CONFIG_PTHREAD_CONDATTR_SETCLOCK', cc.links(osdep_prefix + '''
2914  #include <pthread.h>
2915
2916  int main(void)
2917  {
2918    pthread_condattr_t attr
2919    pthread_condattr_init(&attr);
2920    pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
2921    return 0;
2922  }''', dependencies: threads))
2923config_host_data.set('CONFIG_PTHREAD_AFFINITY_NP', cc.links(osdep_prefix + '''
2924  #include <pthread.h>
2925
2926  static void *f(void *p) { return NULL; }
2927  int main(void)
2928  {
2929    int setsize = CPU_ALLOC_SIZE(64);
2930    pthread_t thread;
2931    cpu_set_t *cpuset;
2932    pthread_create(&thread, 0, f, 0);
2933    cpuset = CPU_ALLOC(64);
2934    CPU_ZERO_S(setsize, cpuset);
2935    pthread_setaffinity_np(thread, setsize, cpuset);
2936    pthread_getaffinity_np(thread, setsize, cpuset);
2937    CPU_FREE(cpuset);
2938    return 0;
2939  }''', dependencies: threads))
2940config_host_data.set('CONFIG_SIGNALFD', cc.links(osdep_prefix + '''
2941  #include <sys/signalfd.h>
2942  int main(void) { return signalfd(-1, NULL, SFD_CLOEXEC); }'''))
2943config_host_data.set('CONFIG_SPLICE', cc.links(osdep_prefix + '''
2944  int main(void)
2945  {
2946    int len, fd = 0;
2947    len = tee(STDIN_FILENO, STDOUT_FILENO, INT_MAX, SPLICE_F_NONBLOCK);
2948    splice(STDIN_FILENO, NULL, fd, NULL, len, SPLICE_F_MOVE);
2949    return 0;
2950  }'''))
2951
2952config_host_data.set('HAVE_MLOCKALL', cc.links(osdep_prefix + '''
2953  #include <sys/mman.h>
2954  int main(void) {
2955    return mlockall(MCL_FUTURE);
2956  }'''))
2957
2958config_host_data.set('HAVE_MLOCK_ONFAULT', cc.links(osdep_prefix + '''
2959  #include <sys/mman.h>
2960  int main(void) {
2961      return mlockall(MCL_FUTURE | MCL_ONFAULT);
2962  }'''))
2963
2964have_l2tpv3 = false
2965if get_option('l2tpv3').allowed() and have_system
2966  have_l2tpv3 = cc.has_type('struct mmsghdr',
2967    prefix: osdep_prefix + '''
2968      #include <sys/socket.h>
2969      #include <linux/ip.h>''')
2970endif
2971config_host_data.set('CONFIG_L2TPV3', have_l2tpv3)
2972
2973have_netmap = false
2974if get_option('netmap').allowed() and have_system
2975  have_netmap = cc.compiles('''
2976    #include <inttypes.h>
2977    #include <net/if.h>
2978    #include <net/netmap.h>
2979    #include <net/netmap_user.h>
2980    #if (NETMAP_API < 11) || (NETMAP_API > 15)
2981    #error
2982    #endif
2983    int main(void) { return 0; }''')
2984  if not have_netmap and get_option('netmap').enabled()
2985    error('Netmap headers not available')
2986  endif
2987endif
2988config_host_data.set('CONFIG_NETMAP', have_netmap)
2989
2990# Work around a system header bug with some kernel/XFS header
2991# versions where they both try to define 'struct fsxattr':
2992# xfs headers will not try to redefine structs from linux headers
2993# if this macro is set.
2994config_host_data.set('HAVE_FSXATTR', cc.links('''
2995  #include <linux/fs.h>
2996  struct fsxattr foo;
2997  int main(void) {
2998    return 0;
2999  }'''))
3000
3001# Some versions of Mac OS X incorrectly define SIZE_MAX
3002config_host_data.set('HAVE_BROKEN_SIZE_MAX', not cc.compiles('''
3003    #include <stdint.h>
3004    #include <stdio.h>
3005    int main(void) {
3006        return printf("%zu", SIZE_MAX);
3007    }''', args: ['-Werror']))
3008
3009# See if 64-bit atomic operations are supported.
3010# Note that without __atomic builtins, we can only
3011# assume atomic loads/stores max at pointer size.
3012config_host_data.set('CONFIG_ATOMIC64', cc.links('''
3013  #include <stdint.h>
3014  int main(void)
3015  {
3016    uint64_t x = 0, y = 0;
3017    y = __atomic_load_n(&x, __ATOMIC_RELAXED);
3018    __atomic_store_n(&x, y, __ATOMIC_RELAXED);
3019    __atomic_compare_exchange_n(&x, &y, x, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
3020    __atomic_exchange_n(&x, y, __ATOMIC_RELAXED);
3021    __atomic_fetch_add(&x, y, __ATOMIC_RELAXED);
3022    return 0;
3023  }''', args: qemu_isa_flags))
3024
3025# has_int128_type is set to false on Emscripten to avoid errors by libffi
3026# during runtime.
3027has_int128_type = host_os != 'emscripten' and cc.compiles('''
3028  __int128_t a;
3029  __uint128_t b;
3030  int main(void) { b = a; }''')
3031config_host_data.set('CONFIG_INT128_TYPE', has_int128_type)
3032
3033has_int128 = has_int128_type and cc.links('''
3034  __int128_t a;
3035  __uint128_t b;
3036  int main (void) {
3037    a = a + b;
3038    b = a * b;
3039    a = a * a;
3040    return 0;
3041  }''')
3042config_host_data.set('CONFIG_INT128', has_int128)
3043
3044if has_int128_type
3045  # "do we have 128-bit atomics which are handled inline and specifically not
3046  # via libatomic". The reason we can't use libatomic is documented in the
3047  # comment starting "GCC is a house divided" in include/qemu/atomic128.h.
3048  # We only care about these operations on 16-byte aligned pointers, so
3049  # force 16-byte alignment of the pointer, which may be greater than
3050  # __alignof(unsigned __int128) for the host.
3051  atomic_test_128 = '''
3052    int main(int ac, char **av) {
3053      __uint128_t *p = __builtin_assume_aligned(av[ac - 1], 16);
3054      p[1] = __atomic_load_n(&p[0], __ATOMIC_RELAXED);
3055      __atomic_store_n(&p[2], p[3], __ATOMIC_RELAXED);
3056      __atomic_compare_exchange_n(&p[4], &p[5], p[6], 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
3057      return 0;
3058    }'''
3059  has_atomic128 = cc.links(atomic_test_128, args: qemu_isa_flags)
3060
3061  config_host_data.set('CONFIG_ATOMIC128', has_atomic128)
3062
3063  if not has_atomic128
3064    # Even with __builtin_assume_aligned, the above test may have failed
3065    # without optimization enabled.  Try again with optimizations locally
3066    # enabled for the function.  See
3067    #   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107389
3068    has_atomic128_opt = cc.links('__attribute__((optimize("O1")))' + atomic_test_128,
3069                                 args: qemu_isa_flags)
3070    config_host_data.set('CONFIG_ATOMIC128_OPT', has_atomic128_opt)
3071
3072    if not has_atomic128_opt
3073      config_host_data.set('CONFIG_CMPXCHG128', cc.links('''
3074        int main(void)
3075        {
3076          __uint128_t x = 0, y = 0;
3077          __sync_val_compare_and_swap_16(&x, y, x);
3078          return 0;
3079        }
3080      ''', args: qemu_isa_flags))
3081    endif
3082  endif
3083endif
3084
3085config_host_data.set('CONFIG_GETAUXVAL', cc.links(osdep_prefix + '''
3086  #include <sys/auxv.h>
3087  int main(void) {
3088    return getauxval(AT_HWCAP) == 0;
3089  }'''))
3090
3091config_host_data.set('CONFIG_ELF_AUX_INFO', cc.links(osdep_prefix + '''
3092  #include <sys/auxv.h>
3093  int main(void) {
3094    unsigned long hwcap = 0;
3095    elf_aux_info(AT_HWCAP, &hwcap, sizeof(hwcap));
3096    return hwcap;
3097  }'''))
3098
3099config_host_data.set('CONFIG_USBFS', have_linux_user and cc.compiles('''
3100  #include <linux/usbdevice_fs.h>
3101
3102  #ifndef USBDEVFS_GET_CAPABILITIES
3103  #error "USBDEVFS_GET_CAPABILITIES undefined"
3104  #endif
3105
3106  #ifndef USBDEVFS_DISCONNECT_CLAIM
3107  #error "USBDEVFS_DISCONNECT_CLAIM undefined"
3108  #endif
3109
3110  int main(void) { return 0; }'''))
3111
3112have_keyring = get_option('keyring') \
3113  .require(host_os == 'linux', error_message: 'keyring is only available on Linux') \
3114  .require(cc.compiles('''
3115    #include <errno.h>
3116    #include <asm/unistd.h>
3117    #include <linux/keyctl.h>
3118    #include <sys/syscall.h>
3119    #include <unistd.h>
3120    int main(void) {
3121        return syscall(__NR_keyctl, KEYCTL_READ, 0, NULL, NULL, 0);
3122    }'''), error_message: 'keyctl syscall not available on this system').allowed()
3123config_host_data.set('CONFIG_SECRET_KEYRING', have_keyring)
3124
3125have_cpuid_h = cc.links('''
3126  #include <cpuid.h>
3127  int main(void) {
3128    unsigned a, b, c, d;
3129    unsigned max = __get_cpuid_max(0, 0);
3130
3131    if (max >= 1) {
3132        __cpuid(1, a, b, c, d);
3133    }
3134
3135    if (max >= 7) {
3136        __cpuid_count(7, 0, a, b, c, d);
3137    }
3138
3139    return 0;
3140  }''')
3141config_host_data.set('CONFIG_CPUID_H', have_cpuid_h)
3142
3143# Don't bother to advertise asm/hwprobe.h for old versions that do
3144# not contain RISCV_HWPROBE_EXT_ZBA.
3145config_host_data.set('CONFIG_ASM_HWPROBE_H',
3146                     cc.has_header_symbol('asm/hwprobe.h',
3147                                          'RISCV_HWPROBE_EXT_ZBA'))
3148
3149if have_cpuid_h
3150  have_avx2 = cc.links('''
3151    #include <immintrin.h>
3152    static int __attribute__((target("avx2"))) bar(void *a) {
3153      __m256i x = *(__m256i *)a;
3154      return _mm256_testz_si256(x, x);
3155    }
3156    int main(int argc, char *argv[]) { return bar(argv[argc - 1]); }
3157  ''')
3158  have_avx512bw = cc.links('''
3159    #include <immintrin.h>
3160    static int __attribute__((target("avx512bw"))) bar(void *a) {
3161      __m512i *x = a;
3162      __m512i res= _mm512_abs_epi8(*x);
3163      return res[1];
3164    }
3165    int main(int argc, char *argv[]) { return bar(argv[0]); }
3166  ''')
3167  if get_option('x86_version') >= '3' and not have_avx2
3168    error('Cannot enable AVX optimizations due to missing intrinsics')
3169  elif get_option('x86_version') >= '4' and not have_avx512bw
3170    error('Cannot enable AVX512 optimizations due to missing intrinsics')
3171  endif
3172else
3173  have_avx2 = false
3174  have_avx512bw = false
3175  if get_option('x86_version') >= '3'
3176    error('Cannot enable AVX optimizations due to missing cpuid.h')
3177  endif
3178endif
3179config_host_data.set('CONFIG_AVX2_OPT', have_avx2)
3180config_host_data.set('CONFIG_AVX512BW_OPT', have_avx512bw)
3181
3182# For both AArch64 and AArch32, detect if builtins are available.
3183config_host_data.set('CONFIG_ARM_AES_BUILTIN', cc.compiles('''
3184    #include <arm_neon.h>
3185    #ifndef __ARM_FEATURE_AES
3186    __attribute__((target("+crypto")))
3187    #endif
3188    void foo(uint8x16_t *p) { *p = vaesmcq_u8(*p); }
3189  '''))
3190
3191if get_option('membarrier').disabled()
3192  have_membarrier = false
3193elif host_os == 'windows'
3194  have_membarrier = true
3195elif host_os == 'linux'
3196  have_membarrier = cc.compiles('''
3197    #include <linux/membarrier.h>
3198    #include <sys/syscall.h>
3199    #include <unistd.h>
3200    #include <stdlib.h>
3201    int main(void) {
3202        syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0);
3203        syscall(__NR_membarrier, MEMBARRIER_CMD_SHARED, 0);
3204        exit(0);
3205    }''')
3206endif
3207config_host_data.set('CONFIG_MEMBARRIER', get_option('membarrier') \
3208  .require(have_membarrier, error_message: 'membarrier system call not available') \
3209  .allowed())
3210
3211have_afalg = get_option('crypto_afalg') \
3212  .require(cc.compiles(osdep_prefix + '''
3213    #include <sys/socket.h>
3214    #include <linux/if_alg.h>
3215    int main(void) {
3216      int sock;
3217      sock = socket(AF_ALG, SOCK_SEQPACKET, 0);
3218      return sock;
3219    }
3220  '''), error_message: 'AF_ALG requested but could not be detected').allowed()
3221config_host_data.set('CONFIG_AF_ALG', have_afalg)
3222
3223config_host_data.set('CONFIG_AF_VSOCK', cc.has_header_symbol(
3224  'linux/vm_sockets.h', 'AF_VSOCK',
3225  prefix: '#include <sys/socket.h>',
3226))
3227
3228have_vss = false
3229have_vss_sdk = false # old xp/2003 SDK
3230if host_os == 'windows' and 'cpp' in all_languages
3231  have_vss = cxx.compiles('''
3232    #define __MIDL_user_allocate_free_DEFINED__
3233    #include <vss.h>
3234    int main(void) { return VSS_CTX_BACKUP; }''')
3235  have_vss_sdk = cxx.has_header('vscoordint.h')
3236endif
3237config_host_data.set('HAVE_VSS_SDK', have_vss_sdk)
3238
3239# Older versions of MinGW do not import _lock_file and _unlock_file properly.
3240# This was fixed for v6.0.0 with commit b48e3ac8969d.
3241if host_os == 'windows'
3242  config_host_data.set('HAVE__LOCK_FILE', cc.links('''
3243    #include <stdio.h>
3244    int main(void) {
3245      _lock_file(NULL);
3246      _unlock_file(NULL);
3247      return 0;
3248    }''', name: '_lock_file and _unlock_file'))
3249endif
3250
3251if spice.found()
3252  config_host_data.set('HAVE_SPICE_QXL_GL_SCANOUT2',
3253    cc.has_function('spice_qxl_gl_scanout2', dependencies: spice))
3254endif
3255
3256if host_os == 'windows'
3257  mingw_has_setjmp_longjmp = cc.links('''
3258    #include <setjmp.h>
3259    int main(void) {
3260      /*
3261       * These functions are not available in setjmp header, but may be
3262       * available at link time, from libmingwex.a.
3263       */
3264      extern int __mingw_setjmp(jmp_buf);
3265      extern void __attribute__((noreturn)) __mingw_longjmp(jmp_buf, int);
3266      jmp_buf env;
3267      __mingw_setjmp(env);
3268      __mingw_longjmp(env, 0);
3269    }
3270  ''', name: 'mingw setjmp and longjmp')
3271
3272  if cpu == 'aarch64' and not mingw_has_setjmp_longjmp
3273    error('mingw must provide setjmp/longjmp for windows-arm64')
3274  endif
3275endif
3276
3277# Detect host pointer size for the target configuration loop.
3278host_long_bits = cc.sizeof('void *') * 8
3279
3280########################
3281# Target configuration #
3282########################
3283
3284minikconf = find_program('scripts/minikconf.py')
3285
3286config_all_accel = {}
3287config_all_devices = {}
3288config_devices_mak_list = []
3289config_devices_h = {}
3290config_target_h = {}
3291config_target_mak = {}
3292config_base_arch_mak = {}
3293
3294disassemblers = {
3295  'alpha' : ['CONFIG_ALPHA_DIS'],
3296  'avr' : ['CONFIG_AVR_DIS'],
3297  'hexagon' : ['CONFIG_HEXAGON_DIS'],
3298  'hppa' : ['CONFIG_HPPA_DIS'],
3299  'i386' : ['CONFIG_I386_DIS'],
3300  'x86_64' : ['CONFIG_I386_DIS'],
3301  'm68k' : ['CONFIG_M68K_DIS'],
3302  'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
3303  'mips' : ['CONFIG_MIPS_DIS'],
3304  'or1k' : ['CONFIG_OPENRISC_DIS'],
3305  'ppc' : ['CONFIG_PPC_DIS'],
3306  'riscv' : ['CONFIG_RISCV_DIS'],
3307  'rx' : ['CONFIG_RX_DIS'],
3308  's390' : ['CONFIG_S390_DIS'],
3309  'sh4' : ['CONFIG_SH4_DIS'],
3310  'sparc' : ['CONFIG_SPARC_DIS'],
3311  'xtensa' : ['CONFIG_XTENSA_DIS'],
3312  'loongarch' : ['CONFIG_LOONGARCH_DIS'],
3313}
3314
3315have_ivshmem = config_host_data.get('CONFIG_EVENTFD')
3316host_kconfig = \
3317  (get_option('fuzzing') ? ['CONFIG_FUZZ=y'] : []) + \
3318  (have_tpm ? ['CONFIG_TPM=y'] : []) + \
3319  (pixman.found() ? ['CONFIG_PIXMAN=y'] : []) + \
3320  (spice.found() ? ['CONFIG_SPICE=y'] : []) + \
3321  (have_ivshmem ? ['CONFIG_IVSHMEM=y'] : []) + \
3322  (opengl.found() ? ['CONFIG_OPENGL=y'] : []) + \
3323  (libcbor.found() ? ['CONFIG_LIBCBOR=y'] : []) + \
3324  (gnutls.found() ? ['CONFIG_GNUTLS=y'] : []) + \
3325  (x11.found() ? ['CONFIG_X11=y'] : []) + \
3326  (fdt.found() ? ['CONFIG_FDT=y'] : []) + \
3327  (have_vhost_user ? ['CONFIG_VHOST_USER=y'] : []) + \
3328  (have_vhost_vdpa ? ['CONFIG_VHOST_VDPA=y'] : []) + \
3329  (have_vhost_kernel ? ['CONFIG_VHOST_KERNEL=y'] : []) + \
3330  (have_virtfs ? ['CONFIG_VIRTFS=y'] : []) + \
3331  (host_os == 'linux' ? ['CONFIG_LINUX=y'] : []) + \
3332  (multiprocess_allowed ? ['CONFIG_MULTIPROCESS_ALLOWED=y'] : []) + \
3333  (vfio_user_server_allowed ? ['CONFIG_VFIO_USER_SERVER_ALLOWED=y'] : []) + \
3334  (hv_balloon ? ['CONFIG_HV_BALLOON_POSSIBLE=y'] : []) + \
3335  (have_rust ? ['CONFIG_HAVE_RUST=y'] : [])
3336
3337ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ]
3338
3339default_targets = 'CONFIG_DEFAULT_TARGETS' in config_host
3340actual_target_dirs = []
3341fdt_required = []
3342foreach target : target_dirs
3343  config_target = { 'TARGET_NAME': target.split('-')[0] }
3344  if target.endswith('linux-user')
3345    if host_os != 'linux'
3346      if default_targets
3347        continue
3348      endif
3349      error('Target @0@ is only available on a Linux host'.format(target))
3350    endif
3351    config_target += { 'CONFIG_LINUX_USER': 'y' }
3352  elif target.endswith('bsd-user')
3353    if host_os not in bsd_oses
3354      if default_targets
3355        continue
3356      endif
3357      error('Target @0@ is only available on a BSD host'.format(target))
3358    endif
3359    config_target += { 'CONFIG_BSD_USER': 'y' }
3360  elif target.endswith('softmmu')
3361    config_target += { 'CONFIG_SYSTEM_ONLY': 'y' }
3362    config_target += { 'CONFIG_SOFTMMU': 'y' }
3363  endif
3364  if target.endswith('-user')
3365    config_target += {
3366      'CONFIG_USER_ONLY': 'y',
3367      'CONFIG_QEMU_INTERP_PREFIX':
3368        get_option('interp_prefix').replace('%M', config_target['TARGET_NAME']),
3369      'CONFIG_QEMU_RTSIG_MAP': get_option('rtsig_map'),
3370    }
3371  endif
3372
3373  config_target += keyval.load('configs/targets' / target + '.mak')
3374
3375  target_kconfig = []
3376  foreach sym: accelerators
3377    # Disallow 64-bit on 32-bit emulation and virtualization
3378    if host_long_bits < config_target['TARGET_LONG_BITS'].to_int()
3379      continue
3380    endif
3381    if sym == 'CONFIG_TCG' or target in accelerator_targets.get(sym, [])
3382      config_target += { sym: 'y' }
3383      config_all_accel += { sym: 'y' }
3384      target_kconfig += [ sym + '=y' ]
3385    endif
3386  endforeach
3387  if target_kconfig.length() == 0
3388    if default_targets
3389      continue
3390    endif
3391    error('No accelerator available for target @0@'.format(target))
3392  endif
3393
3394  if 'TARGET_NEED_FDT' in config_target and not fdt.found()
3395    if default_targets
3396      warning('Disabling ' + target + ' due to missing libfdt')
3397    else
3398      fdt_required += target
3399    endif
3400    continue
3401  endif
3402
3403  actual_target_dirs += target
3404
3405  # Add default keys
3406  config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
3407  if 'TARGET_BASE_ARCH' not in config_target
3408    config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
3409  endif
3410  if 'TARGET_ABI_DIR' not in config_target
3411    config_target += {'TARGET_ABI_DIR': config_target['TARGET_ARCH']}
3412  endif
3413  if 'TARGET_BIG_ENDIAN' not in config_target
3414    config_target += {'TARGET_BIG_ENDIAN': 'n'}
3415  endif
3416
3417  foreach k, v: disassemblers
3418    if host_arch.startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k)
3419      foreach sym: v
3420        config_target += { sym: 'y' }
3421      endforeach
3422    endif
3423  endforeach
3424
3425  config_target_data = configuration_data()
3426  foreach k, v: config_target
3427    if not k.startswith('TARGET_') and not k.startswith('CONFIG_')
3428      # do nothing
3429    elif ignored.contains(k)
3430      # do nothing
3431    elif k == 'TARGET_BASE_ARCH'
3432      # Note that TARGET_BASE_ARCH ends up in config-target.h but it is
3433      # not used to select files from sourcesets.
3434      config_target_data.set('TARGET_' + v.to_upper(), 1)
3435    elif k == 'TARGET_NAME' or k == 'CONFIG_QEMU_INTERP_PREFIX'
3436      config_target_data.set_quoted(k, v)
3437    elif v == 'y'
3438      config_target_data.set(k, 1)
3439    elif v == 'n'
3440      config_target_data.set(k, 0)
3441    else
3442      config_target_data.set(k, v)
3443    endif
3444  endforeach
3445  config_target_data.set('QEMU_ARCH',
3446                         'QEMU_ARCH_' + config_target['TARGET_BASE_ARCH'].to_upper())
3447  config_target_h += {target: configure_file(output: target + '-config-target.h',
3448                                               configuration: config_target_data)}
3449
3450  if target.endswith('-softmmu')
3451    target_kconfig += 'CONFIG_' + config_target['TARGET_ARCH'].to_upper() + '=y'
3452    target_kconfig += 'CONFIG_TARGET_BIG_ENDIAN=' + config_target['TARGET_BIG_ENDIAN']
3453
3454    # PVG is not cross-architecture.  Use accelerator_targets as a proxy to
3455    # figure out which target can support PVG on this host
3456    if pvg.found() and target in accelerator_targets.get('CONFIG_HVF', [])
3457      target_kconfig += 'CONFIG_MAC_PVG=y'
3458    endif
3459
3460    config_input = meson.get_external_property(target, 'default')
3461    config_devices_mak = target + '-config-devices.mak'
3462    config_devices_mak = configure_file(
3463      input: ['configs/devices' / target / config_input + '.mak', 'Kconfig'],
3464      output: config_devices_mak,
3465      depfile: config_devices_mak + '.d',
3466      capture: true,
3467      command: [minikconf,
3468                get_option('default_devices') ? '--defconfig' : '--allnoconfig',
3469                config_devices_mak, '@DEPFILE@', '@INPUT@',
3470                host_kconfig, target_kconfig])
3471
3472    config_devices_data = configuration_data()
3473    config_devices = keyval.load(config_devices_mak)
3474    foreach k, v: config_devices
3475      config_devices_data.set(k, 1)
3476    endforeach
3477    config_devices_mak_list += config_devices_mak
3478    config_devices_h += {target: configure_file(output: target + '-config-devices.h',
3479                                                configuration: config_devices_data)}
3480    config_target += config_devices
3481    config_all_devices += config_devices
3482  endif
3483  config_target_mak += {target: config_target}
3484
3485  # build a merged config for all targets with the same TARGET_BASE_ARCH
3486  target_base_arch = config_target['TARGET_BASE_ARCH']
3487  config_base_arch = config_base_arch_mak.get(target_base_arch, {}) + config_target
3488  config_base_arch_mak += {target_base_arch: config_base_arch}
3489endforeach
3490target_dirs = actual_target_dirs
3491
3492target_configs_h = []
3493foreach target: target_dirs
3494  target_configs_h += config_target_h[target]
3495  target_configs_h += config_devices_h.get(target, [])
3496endforeach
3497genh += custom_target('config-poison.h',
3498                      input: [target_configs_h],
3499                      output: 'config-poison.h',
3500                      capture: true,
3501                      command: [find_program('scripts/make-config-poison.sh'),
3502                                target_configs_h])
3503
3504if fdt_required.length() > 0
3505  error('fdt disabled but required by targets ' + ', '.join(fdt_required))
3506endif
3507
3508###############
3509# Subprojects #
3510###############
3511
3512libvfio_user_dep = not_found
3513if have_system and vfio_user_server_allowed
3514  libvfio_user_proj = subproject('libvfio-user', required: true)
3515  libvfio_user_dep = libvfio_user_proj.get_variable('libvfio_user_dep')
3516endif
3517
3518vhost_user = not_found
3519if host_os == 'linux' and have_vhost_user
3520  libvhost_user = subproject('libvhost-user')
3521  vhost_user = libvhost_user.get_variable('vhost_user_dep')
3522endif
3523
3524libvduse = not_found
3525if have_libvduse
3526  libvduse_proj = subproject('libvduse')
3527  libvduse = libvduse_proj.get_variable('libvduse_dep')
3528endif
3529
3530#####################
3531# Generated sources #
3532#####################
3533
3534config_host_h = configure_file(output: 'config-host.h', configuration: config_host_data)
3535genh += config_host_h
3536
3537hxtool = find_program('scripts/hxtool')
3538shaderinclude = find_program('scripts/shaderinclude.py')
3539qapi_gen = find_program('scripts/qapi-gen.py')
3540qapi_gen_depends = [ meson.current_source_dir() / 'scripts/qapi/__init__.py',
3541                     meson.current_source_dir() / 'scripts/qapi/commands.py',
3542                     meson.current_source_dir() / 'scripts/qapi/common.py',
3543                     meson.current_source_dir() / 'scripts/qapi/error.py',
3544                     meson.current_source_dir() / 'scripts/qapi/events.py',
3545                     meson.current_source_dir() / 'scripts/qapi/expr.py',
3546                     meson.current_source_dir() / 'scripts/qapi/gen.py',
3547                     meson.current_source_dir() / 'scripts/qapi/introspect.py',
3548                     meson.current_source_dir() / 'scripts/qapi/main.py',
3549                     meson.current_source_dir() / 'scripts/qapi/parser.py',
3550                     meson.current_source_dir() / 'scripts/qapi/schema.py',
3551                     meson.current_source_dir() / 'scripts/qapi/source.py',
3552                     meson.current_source_dir() / 'scripts/qapi/types.py',
3553                     meson.current_source_dir() / 'scripts/qapi/features.py',
3554                     meson.current_source_dir() / 'scripts/qapi/visit.py',
3555                     meson.current_source_dir() / 'scripts/qapi-gen.py'
3556]
3557
3558tracetool = [
3559  python, files('scripts/tracetool.py'),
3560   '--backend=' + ','.join(get_option('trace_backends'))
3561]
3562tracetool_depends = files(
3563  'scripts/tracetool/backend/log.py',
3564  'scripts/tracetool/backend/__init__.py',
3565  'scripts/tracetool/backend/dtrace.py',
3566  'scripts/tracetool/backend/ftrace.py',
3567  'scripts/tracetool/backend/simple.py',
3568  'scripts/tracetool/backend/syslog.py',
3569  'scripts/tracetool/backend/ust.py',
3570  'scripts/tracetool/format/ust_events_c.py',
3571  'scripts/tracetool/format/ust_events_h.py',
3572  'scripts/tracetool/format/__init__.py',
3573  'scripts/tracetool/format/d.py',
3574  'scripts/tracetool/format/simpletrace_stap.py',
3575  'scripts/tracetool/format/c.py',
3576  'scripts/tracetool/format/h.py',
3577  'scripts/tracetool/format/log_stap.py',
3578  'scripts/tracetool/format/stap.py',
3579  'scripts/tracetool/__init__.py',
3580)
3581
3582qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
3583                    meson.current_source_dir(),
3584                    get_option('pkgversion'), meson.project_version()]
3585qemu_version = custom_target('qemu-version.h',
3586                             output: 'qemu-version.h',
3587                             command: qemu_version_cmd,
3588                             capture: true,
3589                             build_by_default: true,
3590                             build_always_stale: true)
3591genh += qemu_version
3592
3593hxdep = []
3594hx_headers = [
3595  ['qemu-options.hx', 'qemu-options.def'],
3596  ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
3597]
3598if have_system
3599  hx_headers += [
3600    ['hmp-commands.hx', 'hmp-commands.h'],
3601    ['hmp-commands-info.hx', 'hmp-commands-info.h'],
3602  ]
3603endif
3604foreach d : hx_headers
3605  hxdep += custom_target(d[1],
3606                input: files(d[0]),
3607                output: d[1],
3608                capture: true,
3609                command: [hxtool, '-h', '@INPUT0@'])
3610endforeach
3611genh += hxdep
3612
3613###############
3614# Trace files #
3615###############
3616
3617# TODO: add each directory to the subdirs from its own meson.build, once
3618# we have those
3619trace_events_subdirs = [
3620  'crypto',
3621  'qapi',
3622  'qom',
3623  'monitor',
3624  'util',
3625  'gdbstub',
3626]
3627if have_linux_user
3628  trace_events_subdirs += [ 'linux-user' ]
3629endif
3630if have_bsd_user
3631  trace_events_subdirs += [ 'bsd-user' ]
3632endif
3633if have_block
3634  trace_events_subdirs += [
3635    'authz',
3636    'block',
3637    'chardev',
3638    'io',
3639    'nbd',
3640    'scsi',
3641  ]
3642endif
3643if have_system
3644  trace_events_subdirs += [
3645    'accel/hvf',
3646    'accel/kvm',
3647    'audio',
3648    'backends',
3649    'backends/tpm',
3650    'ebpf',
3651    'hw/9pfs',
3652    'hw/acpi',
3653    'hw/adc',
3654    'hw/alpha',
3655    'hw/arm',
3656    'hw/audio',
3657    'hw/block',
3658    'hw/char',
3659    'hw/display',
3660    'hw/dma',
3661    'hw/fsi',
3662    'hw/hyperv',
3663    'hw/i2c',
3664    'hw/i386',
3665    'hw/i386/xen',
3666    'hw/i386/kvm',
3667    'hw/ide',
3668    'hw/input',
3669    'hw/intc',
3670    'hw/isa',
3671    'hw/mem',
3672    'hw/mips',
3673    'hw/misc',
3674    'hw/misc/macio',
3675    'hw/net',
3676    'hw/net/can',
3677    'hw/nubus',
3678    'hw/nvme',
3679    'hw/nvram',
3680    'hw/pci',
3681    'hw/pci-host',
3682    'hw/ppc',
3683    'hw/rtc',
3684    'hw/riscv',
3685    'hw/s390x',
3686    'hw/scsi',
3687    'hw/sd',
3688    'hw/sensor',
3689    'hw/sh4',
3690    'hw/sparc',
3691    'hw/sparc64',
3692    'hw/ssi',
3693    'hw/timer',
3694    'hw/tpm',
3695    'hw/uefi',
3696    'hw/ufs',
3697    'hw/usb',
3698    'hw/vfio',
3699    'hw/vfio-user',
3700    'hw/virtio',
3701    'hw/vmapple',
3702    'hw/watchdog',
3703    'hw/xen',
3704    'hw/gpio',
3705    'migration',
3706    'net',
3707    'system',
3708    'ui',
3709    'hw/remote',
3710  ]
3711endif
3712if have_system or have_user
3713  trace_events_subdirs += [
3714    'accel/tcg',
3715    'hw/core',
3716    'target/arm',
3717    'target/arm/hvf',
3718    'target/hppa',
3719    'target/i386',
3720    'target/i386/kvm',
3721    'target/loongarch',
3722    'target/mips/tcg',
3723    'target/ppc',
3724    'target/riscv',
3725    'target/s390x',
3726    'target/s390x/kvm',
3727    'target/sparc',
3728  ]
3729endif
3730
3731###################
3732# Collect sources #
3733###################
3734
3735authz_ss = ss.source_set()
3736blockdev_ss = ss.source_set()
3737block_ss = ss.source_set()
3738chardev_ss = ss.source_set()
3739common_ss = ss.source_set()
3740crypto_ss = ss.source_set()
3741hwcore_ss = ss.source_set()
3742io_ss = ss.source_set()
3743qmp_ss = ss.source_set()
3744qom_ss = ss.source_set()
3745system_ss = ss.source_set()
3746specific_fuzz_ss = ss.source_set()
3747specific_ss = ss.source_set()
3748rust_devices_ss = ss.source_set()
3749stub_ss = ss.source_set()
3750trace_ss = ss.source_set()
3751user_ss = ss.source_set()
3752util_ss = ss.source_set()
3753
3754# accel modules
3755qtest_module_ss = ss.source_set()
3756
3757modules = {}
3758target_modules = {}
3759plugin_modules = []
3760hw_arch = {}
3761target_arch = {}
3762target_system_arch = {}
3763target_user_arch = {}
3764hw_common_arch = {}
3765target_common_arch = {}
3766target_common_system_arch = {}
3767
3768# NOTE: the trace/ subdirectory needs the qapi_trace_events variable
3769# that is filled in by qapi/.
3770subdir('qapi')
3771subdir('qobject')
3772subdir('stubs')
3773subdir('trace')
3774subdir('util')
3775subdir('qom')
3776subdir('authz')
3777subdir('crypto')
3778subdir('ui')
3779subdir('gdbstub')
3780if have_system
3781  subdir('hw')
3782else
3783  subdir('hw/core')
3784endif
3785
3786if enable_modules
3787  libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
3788  modulecommon = declare_dependency(objects: libmodulecommon.extract_all_objects(recursive: false), compile_args: '-DBUILD_DSO')
3789endif
3790
3791qom_ss = qom_ss.apply({})
3792libqom = static_library('qom', qom_ss.sources() + genh,
3793                        dependencies: [qom_ss.dependencies()],
3794                        build_by_default: false)
3795qom = declare_dependency(objects: libqom.extract_all_objects(recursive: false),
3796                         dependencies: qom_ss.dependencies())
3797
3798event_loop_base = files('event-loop-base.c')
3799event_loop_base = static_library('event-loop-base',
3800                                 sources: event_loop_base + genh,
3801                                 build_by_default: false)
3802event_loop_base = declare_dependency(objects: event_loop_base.extract_all_objects(recursive: false),
3803                                     dependencies: [qom])
3804
3805stub_ss = stub_ss.apply({})
3806
3807util_ss.add_all(trace_ss)
3808util_ss = util_ss.apply({})
3809libqemuutil = static_library('qemuutil',
3810                             build_by_default: false,
3811                             sources: util_ss.sources() + stub_ss.sources() + genh,
3812                             dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc])
3813qemuutil_deps = [event_loop_base]
3814if host_os != 'windows'
3815  qemuutil_deps += [rt]
3816endif
3817qemuutil = declare_dependency(link_with: libqemuutil,
3818                              sources: genh + version_res,
3819                              dependencies: qemuutil_deps)
3820
3821if have_system or have_user
3822  decodetree = generator(find_program('scripts/decodetree.py'),
3823                         output: 'decode-@BASENAME@.c.inc',
3824                         arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
3825  subdir('libdecnumber')
3826  subdir('target')
3827endif
3828
3829subdir('audio')
3830subdir('io')
3831subdir('chardev')
3832subdir('fsdev')
3833subdir('dump')
3834
3835if have_block
3836  block_ss.add(files(
3837    'block.c',
3838    'blockjob.c',
3839    'job.c',
3840    'qemu-io-cmds.c',
3841  ))
3842  if config_host_data.get('CONFIG_REPLICATION')
3843    block_ss.add(files('replication.c'))
3844  endif
3845
3846  subdir('nbd')
3847  subdir('scsi')
3848  subdir('block')
3849
3850  blockdev_ss.add(files(
3851    'blockdev.c',
3852    'blockdev-nbd.c',
3853    'iothread.c',
3854    'job-qmp.c',
3855  ))
3856
3857  # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
3858  # os-win32.c does not
3859  if host_os == 'windows'
3860    system_ss.add(files('os-win32.c'))
3861  elif host_os == 'emscripten'
3862    blockdev_ss.add(files('os-wasm.c'))
3863  else
3864    blockdev_ss.add(files('os-posix.c'))
3865  endif
3866endif
3867
3868common_ss.add(files('cpu-common.c'))
3869specific_ss.add(files('cpu-target.c'))
3870
3871subdir('system')
3872
3873# Work around a gcc bug/misfeature wherein constant propagation looks
3874# through an alias:
3875#   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99696
3876# to guess that a const variable is always zero.  Without lto, this is
3877# impossible, as the alias is restricted to page-vary-common.c.  Indeed,
3878# without lto, not even the alias is required -- we simply use different
3879# declarations in different compilation units.
3880pagevary = files('page-vary-common.c')
3881if get_option('b_lto')
3882  pagevary_flags = ['-fno-lto']
3883  if get_option('cfi')
3884    pagevary_flags += '-fno-sanitize=cfi-icall'
3885  endif
3886  pagevary = static_library('page-vary-common', sources: pagevary + genh,
3887                            c_args: pagevary_flags)
3888  pagevary = declare_dependency(link_with: pagevary)
3889endif
3890common_ss.add(pagevary)
3891specific_ss.add(files('page-target.c', 'page-vary-target.c'))
3892
3893common_ss.add(files('target-info.c'))
3894specific_ss.add(files('target-info-stub.c'))
3895
3896subdir('backends')
3897subdir('disas')
3898subdir('migration')
3899subdir('monitor')
3900subdir('net')
3901subdir('replay')
3902subdir('semihosting')
3903subdir('stats')
3904subdir('tcg')
3905subdir('fpu')
3906subdir('accel')
3907subdir('plugins')
3908subdir('ebpf')
3909
3910if 'CONFIG_TCG' in config_all_accel
3911  subdir('contrib/plugins')
3912endif
3913
3914common_user_inc = []
3915
3916subdir('common-user')
3917subdir('bsd-user')
3918subdir('linux-user')
3919
3920# needed for fuzzing binaries
3921subdir('tests/qtest/libqos')
3922subdir('tests/qtest/fuzz')
3923
3924# accel modules
3925target_modules += { 'accel' : { 'qtest': qtest_module_ss }}
3926
3927##############################################
3928# Internal static_libraries and dependencies #
3929##############################################
3930
3931modinfo_collect = find_program('scripts/modinfo-collect.py')
3932modinfo_generate = find_program('scripts/modinfo-generate.py')
3933modinfo_files = []
3934
3935block_mods = []
3936system_mods = []
3937emulator_modules = []
3938foreach d, list : modules
3939  if not (d == 'block' ? have_block : have_system)
3940    continue
3941  endif
3942
3943  foreach m, module_ss : list
3944    if enable_modules
3945      module_ss.add(modulecommon)
3946      module_ss = module_ss.apply(config_all_devices, strict: false)
3947      sl = static_library(d + '-' + m, [genh, module_ss.sources()],
3948                          dependencies: module_ss.dependencies(), pic: true)
3949      if d == 'block'
3950        block_mods += sl
3951      else
3952        system_mods += sl
3953      endif
3954      emulator_modules += shared_module(sl.name(),
3955                    name_prefix: '',
3956                    objects: sl.extract_all_objects(recursive: false),
3957                    dependencies: module_ss.dependencies(),
3958                    install: true,
3959                    install_dir: qemu_moddir)
3960      if module_ss.sources() != []
3961        modinfo_files += custom_target(d + '-' + m + '.modinfo',
3962                                       output: d + '-' + m + '.modinfo',
3963                                       input: sl.extract_all_objects(recursive: true),
3964                                       capture: true,
3965                                       command: [modinfo_collect, '@INPUT@'])
3966      endif
3967    else
3968      if d == 'block'
3969        block_ss.add_all(module_ss)
3970      else
3971        system_ss.add_all(module_ss)
3972      endif
3973    endif
3974  endforeach
3975endforeach
3976
3977foreach d, list : target_modules
3978  foreach m, module_ss : list
3979    if enable_modules
3980      module_ss.add(modulecommon)
3981      foreach target : target_dirs
3982        if target.endswith('-softmmu')
3983          config_target = config_target_mak[target]
3984          target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3985          c_args = ['-DCOMPILING_PER_TARGET',
3986                    '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3987                    '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3988          target_module_ss = module_ss.apply(config_target, strict: false)
3989          if target_module_ss.sources() != []
3990            module_name = d + '-' + m + '-' + config_target['TARGET_NAME']
3991            sl = static_library(module_name,
3992                                [genh, target_module_ss.sources()],
3993                                dependencies: target_module_ss.dependencies(),
3994                                include_directories: target_inc,
3995                                c_args: c_args,
3996                                pic: true)
3997            system_mods += sl
3998            emulator_modules += shared_module(sl.name(),
3999                    name_prefix: '',
4000                    objects: sl.extract_all_objects(recursive: false),
4001                    dependencies: target_module_ss.dependencies(),
4002                    install: true,
4003                    install_dir: qemu_moddir)
4004            modinfo_files += custom_target(module_name + '.modinfo',
4005                                           output: module_name + '.modinfo',
4006                                           input: sl.extract_all_objects(recursive: true),
4007                                           capture: true,
4008                                           command: [modinfo_collect, '--target', target, '@INPUT@'])
4009          endif
4010        endif
4011      endforeach
4012    else
4013      specific_ss.add_all(module_ss)
4014    endif
4015  endforeach
4016endforeach
4017
4018if enable_modules
4019  foreach target : target_dirs
4020    if target.endswith('-softmmu')
4021      config_target = config_target_mak[target]
4022      config_devices_mak = target + '-config-devices.mak'
4023      modinfo_src = custom_target('modinfo-' + target + '.c',
4024                                  output: 'modinfo-' + target + '.c',
4025                                  input: modinfo_files,
4026                                  command: [modinfo_generate, '--devices', config_devices_mak, '@INPUT@'],
4027                                  capture: true)
4028
4029      modinfo_lib = static_library('modinfo-' + target + '.c', modinfo_src)
4030      modinfo_dep = declare_dependency(link_with: modinfo_lib)
4031
4032      arch = config_target['TARGET_NAME'] == 'sparc64' ? 'sparc64' : config_target['TARGET_BASE_ARCH']
4033      hw_arch[arch].add(modinfo_dep)
4034    endif
4035  endforeach
4036
4037  if emulator_modules.length() > 0
4038    alias_target('modules', emulator_modules)
4039  endif
4040endif
4041
4042nm = find_program('nm')
4043undefsym = find_program('scripts/undefsym.py')
4044block_syms = custom_target('block.syms', output: 'block.syms',
4045                             input: [libqemuutil, block_mods],
4046                             capture: true,
4047                             command: [undefsym, nm, '@INPUT@'])
4048qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
4049                             input: [libqemuutil, system_mods],
4050                             capture: true,
4051                             command: [undefsym, nm, '@INPUT@'])
4052
4053authz_ss = authz_ss.apply({})
4054libauthz = static_library('authz', authz_ss.sources() + genh,
4055                          dependencies: [authz_ss.dependencies()],
4056                          build_by_default: false)
4057
4058authz = declare_dependency(objects: libauthz.extract_all_objects(recursive: false),
4059                           dependencies: [authz_ss.dependencies(), qom])
4060
4061crypto_ss = crypto_ss.apply({})
4062libcrypto = static_library('crypto', crypto_ss.sources() + genh,
4063                           dependencies: [crypto_ss.dependencies()],
4064                           build_by_default: false)
4065
4066crypto = declare_dependency(objects: libcrypto.extract_all_objects(recursive: false),
4067                            dependencies: [crypto_ss.dependencies(), authz, qom])
4068
4069io_ss = io_ss.apply({})
4070libio = static_library('io', io_ss.sources() + genh,
4071                       dependencies: [io_ss.dependencies()],
4072                       link_with: libqemuutil,
4073                       build_by_default: false)
4074
4075io = declare_dependency(objects: libio.extract_all_objects(recursive: false),
4076                        dependencies: [io_ss.dependencies(), crypto, qom])
4077
4078libmigration = static_library('migration', sources: migration_files + genh,
4079                              build_by_default: false)
4080migration = declare_dependency(objects: libmigration.extract_all_objects(recursive: false),
4081                               dependencies: [qom, io])
4082system_ss.add(migration)
4083
4084block_ss = block_ss.apply({})
4085libblock = static_library('block', block_ss.sources() + genh,
4086                          dependencies: block_ss.dependencies(),
4087                          build_by_default: false)
4088
4089block = declare_dependency(objects: libblock.extract_all_objects(recursive: false),
4090                           dependencies: [block_ss.dependencies(), crypto, io])
4091
4092blockdev_ss = blockdev_ss.apply({})
4093libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
4094                             dependencies: blockdev_ss.dependencies(),
4095                             build_by_default: false)
4096
4097blockdev = declare_dependency(objects: libblockdev.extract_all_objects(recursive: false),
4098                              dependencies: [blockdev_ss.dependencies(), block, event_loop_base])
4099
4100qmp_ss = qmp_ss.apply({})
4101libqmp = static_library('qmp', qmp_ss.sources() + genh,
4102                        dependencies: qmp_ss.dependencies(),
4103                        build_by_default: false)
4104
4105qmp = declare_dependency(objects: libqmp.extract_all_objects(recursive: false),
4106                         dependencies: qmp_ss.dependencies())
4107
4108libchardev = static_library('chardev', chardev_ss.sources() + genh,
4109                            dependencies: chardev_ss.dependencies(),
4110                            build_by_default: false)
4111
4112chardev = declare_dependency(objects: libchardev.extract_all_objects(recursive: false),
4113                             dependencies: [chardev_ss.dependencies(), io])
4114
4115hwcore_ss = hwcore_ss.apply({})
4116libhwcore = static_library('hwcore', sources: hwcore_ss.sources() + genh,
4117                           build_by_default: false)
4118hwcore = declare_dependency(objects: libhwcore.extract_all_objects(recursive: false))
4119common_ss.add(hwcore)
4120
4121###########
4122# Targets #
4123###########
4124
4125system_ss.add(authz, blockdev, chardev, crypto, io, qmp)
4126common_ss.add(qom, qemuutil)
4127
4128libuser = static_library('user',
4129                         user_ss.all_sources() + genh,
4130                         c_args: ['-DCONFIG_USER_ONLY',
4131                                  '-DCOMPILING_SYSTEM_VS_USER'],
4132                         include_directories: common_user_inc,
4133                         dependencies: user_ss.all_dependencies(),
4134                         build_by_default: false)
4135
4136libsystem = static_library('system',
4137                           system_ss.all_sources() + genh,
4138                           c_args: ['-DCONFIG_SOFTMMU',
4139                                    '-DCOMPILING_SYSTEM_VS_USER'],
4140                           dependencies: system_ss.all_dependencies(),
4141                           build_by_default: false)
4142
4143# Note that this library is never used directly (only through extract_objects)
4144# and is not built by default; therefore, source files not used by the build
4145# configuration will be in build.ninja, but are never built by default.
4146common_all = static_library('common',
4147                            build_by_default: false,
4148                            sources: common_ss.all_sources() + genh,
4149                            implicit_include_directories: false,
4150                            dependencies: common_ss.all_dependencies())
4151
4152# construct common libraries per base architecture
4153target_common_arch_libs = {}
4154target_common_system_arch_libs = {}
4155foreach target_base_arch, config_base_arch : config_base_arch_mak
4156  target_inc = [include_directories('target' / target_base_arch)]
4157  inc = [common_user_inc + target_inc]
4158
4159  target_common = common_ss.apply(config_base_arch, strict: false)
4160  target_system = system_ss.apply(config_base_arch, strict: false)
4161  target_user = user_ss.apply(config_base_arch, strict: false)
4162  common_deps = []
4163  system_deps = []
4164  user_deps = []
4165  foreach dep: target_common.dependencies()
4166    common_deps += dep.partial_dependency(compile_args: true, includes: true)
4167  endforeach
4168  foreach dep: target_system.dependencies()
4169    system_deps += dep.partial_dependency(compile_args: true, includes: true)
4170  endforeach
4171  foreach dep: target_user.dependencies()
4172    user_deps += dep.partial_dependency(compile_args: true, includes: true)
4173  endforeach
4174
4175  # prevent common code to access cpu compile time definition,
4176  # but still allow access to cpu.h
4177  target_c_args = ['-DCPU_DEFS_H']
4178  target_system_c_args = target_c_args + ['-DCOMPILING_SYSTEM_VS_USER', '-DCONFIG_SOFTMMU']
4179
4180  if target_base_arch in target_common_arch
4181    src = target_common_arch[target_base_arch]
4182    lib = static_library(
4183      'common_' + target_base_arch,
4184      build_by_default: false,
4185      sources: src.all_sources() + genh,
4186      include_directories: inc,
4187      c_args: target_c_args,
4188      dependencies: src.all_dependencies() + common_deps +
4189                    system_deps + user_deps)
4190    target_common_arch_libs += {target_base_arch: lib}
4191  endif
4192
4193  # merge hw_common_arch in target_common_system_arch
4194  if target_base_arch in hw_common_arch
4195    hw_src = hw_common_arch[target_base_arch]
4196    if target_base_arch in target_common_system_arch
4197      target_common_system_arch[target_base_arch].add_all(hw_src)
4198    else
4199      target_common_system_arch += {target_base_arch: hw_src}
4200    endif
4201  endif
4202
4203  if target_base_arch in target_common_system_arch
4204    src = target_common_system_arch[target_base_arch]
4205    lib = static_library(
4206      'system_' + target_base_arch,
4207      build_by_default: false,
4208      sources: src.all_sources() + genh,
4209      include_directories: inc,
4210      c_args: target_system_c_args,
4211      dependencies: src.all_dependencies() + common_deps + system_deps)
4212    target_common_system_arch_libs += {target_base_arch: lib}
4213  endif
4214endforeach
4215
4216if have_rust
4217  bindings_incdir = include_directories('.', 'include')
4218  # We would like to use --generate-cstr, but it is only available
4219  # starting with bindgen 0.66.0.  The oldest supported versions
4220  # is 0.60.x (Debian 12 has 0.60.1) which introduces --allowlist-file.
4221  bindgen_args_common = [
4222    '--disable-header-comment',
4223    '--raw-line', '// @generated',
4224    '--ctypes-prefix', 'std::os::raw',
4225    '--generate-block',
4226    '--impl-debug',
4227    '--no-doc-comments',
4228    '--with-derive-default',
4229    '--no-layout-tests',
4230    '--no-prepend-enum-name',
4231    '--allowlist-file', meson.project_source_root() + '/include/.*',
4232    '--allowlist-file', meson.project_source_root() + '/.*',
4233    '--allowlist-file', meson.project_build_root() + '/.*'
4234    ]
4235  if not rustfmt.found()
4236    if bindgen.version().version_compare('<0.65.0')
4237      bindgen_args_common += ['--no-rustfmt-bindings']
4238    else
4239      bindgen_args_common += ['--formatter', 'none']
4240    endif
4241  endif
4242  if bindgen.version().version_compare('>=0.66.0')
4243    bindgen_args_common += ['--rust-target', '1.59']
4244  endif
4245  if bindgen.version().version_compare('<0.61.0')
4246    # default in 0.61+
4247    bindgen_args_common += ['--size_t-is-usize']
4248  else
4249    bindgen_args_common += ['--merge-extern-blocks']
4250  endif
4251  subdir('rust')
4252endif
4253
4254
4255feature_to_c = find_program('scripts/feature_to_c.py')
4256rust_root_crate = find_program('scripts/rust/rust_root_crate.sh')
4257
4258if host_os == 'darwin'
4259  entitlement = find_program('scripts/entitlement.sh')
4260endif
4261
4262traceable = []
4263emulators = {}
4264foreach target : target_dirs
4265  config_target = config_target_mak[target]
4266  target_name = config_target['TARGET_NAME']
4267  target_base_arch = config_target['TARGET_BASE_ARCH']
4268  arch_srcs = [config_target_h[target]]
4269  arch_deps = []
4270  c_args = ['-DCOMPILING_PER_TARGET',
4271            '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
4272  ]
4273  link_args = emulator_link_args
4274
4275  target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
4276  if host_os == 'linux'
4277    target_inc += include_directories('linux-headers', is_system: true)
4278  endif
4279  if target.endswith('-softmmu')
4280    target_type='system'
4281    t = target_system_arch[target_base_arch].apply(config_target, strict: false)
4282    arch_srcs += t.sources()
4283    arch_deps += t.dependencies()
4284
4285    hw_dir = target_name == 'sparc64' ? 'sparc64' : target_base_arch
4286    if hw_arch.has_key(hw_dir)
4287      hw = hw_arch[hw_dir].apply(config_target, strict: false)
4288      arch_srcs += hw.sources()
4289      arch_deps += hw.dependencies()
4290    endif
4291
4292    c_args += ['-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
4293    arch_srcs += config_devices_h[target]
4294    link_args += ['@block.syms', '@qemu.syms']
4295  else
4296    abi = config_target['TARGET_ABI_DIR']
4297    target_type='user'
4298    target_inc += common_user_inc
4299    if target_base_arch in target_user_arch
4300      t = target_user_arch[target_base_arch].apply(config_target, strict: false)
4301      arch_srcs += t.sources()
4302      arch_deps += t.dependencies()
4303    endif
4304    if 'CONFIG_LINUX_USER' in config_target
4305      base_dir = 'linux-user'
4306    endif
4307    if 'CONFIG_BSD_USER' in config_target
4308      base_dir = 'bsd-user'
4309      target_inc += include_directories('bsd-user/' / host_os)
4310      target_inc += include_directories('bsd-user/host/' / host_arch)
4311      dir = base_dir / abi
4312      arch_srcs += files(dir / 'signal.c', dir / 'target_arch_cpu.c')
4313    endif
4314    target_inc += include_directories(
4315      base_dir,
4316      base_dir / abi,
4317    )
4318    if 'CONFIG_LINUX_USER' in config_target
4319      dir = base_dir / abi
4320      arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
4321      if config_target.has_key('TARGET_SYSTBL_ABI')
4322        arch_srcs += \
4323          syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
4324                                             extra_args : config_target['TARGET_SYSTBL_ABI'])
4325      endif
4326    endif
4327  endif
4328
4329  if 'TARGET_XML_FILES' in config_target
4330    gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
4331                                output: target + '-gdbstub-xml.c',
4332                                input: files(config_target['TARGET_XML_FILES'].split()),
4333                                command: [feature_to_c, '@INPUT@'],
4334                                capture: true)
4335    arch_srcs += gdbstub_xml
4336  endif
4337
4338  t = target_arch[target_base_arch].apply(config_target, strict: false)
4339  arch_srcs += t.sources()
4340  arch_deps += t.dependencies()
4341
4342  target_common = common_ss.apply(config_target, strict: false)
4343  objects = [common_all.extract_objects(target_common.sources())]
4344  arch_deps += target_common.dependencies()
4345  if target_base_arch in target_common_arch_libs
4346    src = target_common_arch[target_base_arch].apply(config_target, strict: false)
4347    lib = target_common_arch_libs[target_base_arch]
4348    objects += lib.extract_objects(src.sources())
4349    arch_deps += src.dependencies()
4350  endif
4351  if target_type == 'system'
4352    src = system_ss.apply(config_target, strict: false)
4353    objects += libsystem.extract_objects(src.sources())
4354    arch_deps += src.dependencies()
4355  endif
4356  if target_type == 'user'
4357    src = user_ss.apply(config_target, strict: false)
4358    objects += libuser.extract_objects(src.sources())
4359    arch_deps += src.dependencies()
4360  endif
4361  if target_type == 'system' and target_base_arch in target_common_system_arch_libs
4362    src = target_common_system_arch[target_base_arch].apply(config_target, strict: false)
4363    lib = target_common_system_arch_libs[target_base_arch]
4364    objects += lib.extract_objects(src.sources())
4365    arch_deps += src.dependencies()
4366  endif
4367
4368  target_specific = specific_ss.apply(config_target, strict: false)
4369  arch_srcs += target_specific.sources()
4370  arch_deps += target_specific.dependencies()
4371
4372  if have_rust and target_type == 'system'
4373    target_rust = rust_devices_ss.apply(config_target, strict: false)
4374    crates = []
4375    foreach dep : target_rust.dependencies()
4376      crates += dep.get_variable('crate')
4377    endforeach
4378    if crates.length() > 0
4379      rlib_rs = custom_target('rust_' + target.underscorify() + '.rs',
4380                              output: 'rust_' + target.underscorify() + '.rs',
4381                              command: [rust_root_crate, crates],
4382                              capture: true,
4383                              build_by_default: true,
4384                              build_always_stale: true)
4385      rlib = static_library('rust_' + target.underscorify(),
4386                            structured_sources([], {'.': rlib_rs}),
4387                            dependencies: target_rust.dependencies(),
4388                            override_options: ['rust_std=2021', 'build.rust_std=2021'],
4389                            rust_abi: 'c')
4390      arch_deps += declare_dependency(link_whole: [rlib])
4391    endif
4392  endif
4393
4394  # allow using headers from the dependencies but do not include the sources,
4395  # because this emulator only needs those in "objects".  For external
4396  # dependencies, the full dependency is included below in the executable.
4397  lib_deps = []
4398  foreach dep : arch_deps
4399    lib_deps += dep.partial_dependency(compile_args: true, includes: true)
4400  endforeach
4401
4402  lib = static_library('qemu-' + target,
4403                 sources: arch_srcs + genh,
4404                 dependencies: lib_deps,
4405                 objects: objects,
4406                 include_directories: target_inc,
4407                 c_args: c_args,
4408                 build_by_default: false)
4409
4410  if target.endswith('-softmmu')
4411    execs = [{
4412      'name': 'qemu-system-' + target_name,
4413      'win_subsystem': 'console',
4414      'sources': files('system/main.c'),
4415      'dependencies': [sdl]
4416    }]
4417    if host_os == 'windows' and (sdl.found() or gtk.found())
4418      execs += [{
4419        'name': 'qemu-system-' + target_name + 'w',
4420        'win_subsystem': 'windows',
4421        'sources': files('system/main.c'),
4422        'dependencies': [sdl]
4423      }]
4424    endif
4425    if get_option('fuzzing')
4426      specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
4427      execs += [{
4428        'name': 'qemu-fuzz-' + target_name,
4429        'win_subsystem': 'console',
4430        'sources': specific_fuzz.sources(),
4431        'dependencies': specific_fuzz.dependencies(),
4432      }]
4433    endif
4434  else
4435    execs = [{
4436      'name': 'qemu-' + target_name,
4437      'win_subsystem': 'console',
4438      'sources': [],
4439      'dependencies': []
4440    }]
4441  endif
4442  foreach exe: execs
4443    exe_name = exe['name']
4444    if host_os == 'darwin'
4445      exe_name += '-unsigned'
4446    endif
4447
4448    emulator = executable(exe_name, exe['sources'],
4449               install: true,
4450               c_args: c_args,
4451               dependencies: arch_deps + exe['dependencies'],
4452               objects: lib.extract_all_objects(recursive: true),
4453               link_depends: [block_syms, qemu_syms],
4454               link_args: link_args,
4455               win_subsystem: exe['win_subsystem'])
4456
4457    if host_os == 'darwin'
4458      icon = 'pc-bios/qemu.rsrc'
4459      build_input = [emulator, files(icon)]
4460      install_input = [
4461        get_option('bindir') / exe_name,
4462        meson.current_source_dir() / icon
4463      ]
4464      if 'CONFIG_HVF' in config_target
4465        entitlements = 'accel/hvf/entitlements.plist'
4466        build_input += files(entitlements)
4467        install_input += meson.current_source_dir() / entitlements
4468      endif
4469
4470      emulators += {exe['name'] : custom_target(exe['name'],
4471                   input: build_input,
4472                   output: exe['name'],
4473                   command: [entitlement, '@OUTPUT@', '@INPUT@'])
4474      }
4475
4476      meson.add_install_script(entitlement, '--install',
4477                               get_option('bindir') / exe['name'],
4478                               install_input)
4479    else
4480      emulators += {exe['name']: emulator}
4481    endif
4482
4483    traceable += [{
4484      'exe': exe['name'],
4485      'probe-prefix': 'qemu.' + target_type + '.' + target_name,
4486    }]
4487
4488  endforeach
4489endforeach
4490
4491# Other build targets
4492
4493if get_option('plugins')
4494  install_headers('include/qemu/qemu-plugin.h')
4495  if host_os == 'windows'
4496    # On windows, we want to deliver the qemu_plugin_api.lib file in the qemu installer,
4497    # so that plugin authors can compile against it.
4498    install_data(win32_qemu_plugin_api_lib, install_dir: 'lib')
4499  endif
4500endif
4501
4502subdir('qga')
4503
4504# Don't build qemu-keymap if xkbcommon is not explicitly enabled
4505# when we don't build tools or system
4506if xkbcommon.found()
4507  # used for the update-keymaps target, so include rules even if !have_tools
4508  qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
4509                           dependencies: [qemuutil, xkbcommon], install: have_tools)
4510endif
4511
4512if have_tools
4513  qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
4514             link_args: '@block.syms', link_depends: block_syms,
4515             dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
4516  qemu_io = executable('qemu-io', files('qemu-io.c'),
4517             link_args: '@block.syms', link_depends: block_syms,
4518             dependencies: [block, qemuutil], install: true)
4519  qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
4520               link_args: '@block.syms', link_depends: block_syms,
4521               dependencies: [blockdev, qemuutil, selinux],
4522               install: true)
4523
4524  subdir('storage-daemon')
4525
4526  foreach exe: [ 'qemu-img', 'qemu-io', 'qemu-nbd', 'qemu-storage-daemon']
4527    traceable += [{
4528      'exe': exe,
4529      'probe-prefix': 'qemu.' + exe.substring(5).replace('-', '_')
4530    }]
4531  endforeach
4532
4533  subdir('contrib/elf2dmp')
4534
4535  executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
4536             dependencies: [qemuutil, rt],
4537             install: true)
4538
4539  if have_vhost_user
4540    subdir('contrib/vhost-user-blk')
4541    subdir('contrib/vhost-user-gpu')
4542    subdir('contrib/vhost-user-input')
4543    subdir('contrib/vhost-user-scsi')
4544  endif
4545
4546  if host_os == 'linux'
4547    executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
4548               dependencies: [qemuutil, libcap_ng],
4549               install: true,
4550               install_dir: get_option('libexecdir'))
4551
4552    executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
4553               dependencies: [authz, crypto, io, qom, qemuutil,
4554                              libcap_ng, mpathpersist],
4555               install: true)
4556
4557    if cpu in ['x86', 'x86_64']
4558      executable('qemu-vmsr-helper', files('tools/i386/qemu-vmsr-helper.c'),
4559               dependencies: [authz, crypto, io, qom, qemuutil,
4560                              libcap_ng, mpathpersist],
4561               install: true)
4562    endif
4563  endif
4564
4565  if have_ivshmem
4566    subdir('contrib/ivshmem-client')
4567    subdir('contrib/ivshmem-server')
4568  endif
4569endif
4570
4571if stap.found()
4572  foreach t: traceable
4573    foreach stp: [
4574      {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / t['exe'], 'install': false},
4575      {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / t['exe'], 'install': true},
4576      {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
4577      {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
4578    ]
4579      cmd = [
4580        tracetool, '--group=all', '--format=' + stp['fmt'],
4581        '--binary=' + stp['bin'],
4582        '--probe-prefix=' + t['probe-prefix'],
4583        '@INPUT@', '@OUTPUT@'
4584      ]
4585
4586      custom_target(t['exe'] + stp['ext'],
4587                    input: trace_events_all,
4588                    output: t['exe'] + stp['ext'],
4589                    install: stp['install'],
4590                    install_dir: get_option('datadir') / 'systemtap/tapset',
4591                    command: cmd,
4592                    depend_files: tracetool_depends)
4593    endforeach
4594  endforeach
4595endif
4596
4597subdir('scripts')
4598subdir('tools')
4599subdir('pc-bios')
4600subdir('docs')
4601# Tests are disabled on emscripten because they rely on host features that aren't
4602# supported by emscripten (e.g. fork and unix socket).
4603if host_os != 'emscripten'
4604  subdir('tests')
4605endif
4606if gtk.found()
4607  subdir('po')
4608endif
4609
4610if host_machine.system() == 'windows'
4611  nsis_cmd = [
4612    find_program('scripts/nsis.py'),
4613    '@OUTPUT@',
4614    get_option('prefix'),
4615    meson.current_source_dir(),
4616    glib_pc.get_variable('bindir'),
4617    host_machine.cpu(),
4618    '--',
4619    '-DDISPLAYVERSION=' + meson.project_version(),
4620  ]
4621  if build_docs
4622    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
4623  endif
4624  if gtk.found()
4625    nsis_cmd += '-DCONFIG_GTK=y'
4626  endif
4627
4628  nsis = custom_target('nsis',
4629                       output: 'qemu-setup-' + meson.project_version() + '.exe',
4630                       input: files('qemu.nsi'),
4631                       build_always_stale: true,
4632                       command: nsis_cmd + ['@INPUT@'])
4633  alias_target('installer', nsis)
4634endif
4635
4636#########################
4637# Configuration summary #
4638#########################
4639
4640# Build environment
4641summary_info = {}
4642summary_info += {'Build directory':   meson.current_build_dir()}
4643summary_info += {'Source path':       meson.current_source_dir()}
4644summary_info += {'Download dependencies': get_option('wrap_mode') != 'nodownload'}
4645summary(summary_info, bool_yn: true, section: 'Build environment')
4646
4647# Directories
4648summary_info += {'Install prefix':    get_option('prefix')}
4649summary_info += {'BIOS directory':    qemu_datadir}
4650pathsep = host_os == 'windows' ? ';' : ':'
4651summary_info += {'firmware path':     pathsep.join(get_option('qemu_firmwarepath'))}
4652summary_info += {'binary directory':  get_option('prefix') / get_option('bindir')}
4653summary_info += {'library directory': get_option('prefix') / get_option('libdir')}
4654summary_info += {'module directory':  qemu_moddir}
4655summary_info += {'libexec directory': get_option('prefix') / get_option('libexecdir')}
4656summary_info += {'include directory': get_option('prefix') / get_option('includedir')}
4657summary_info += {'config directory':  get_option('prefix') / get_option('sysconfdir')}
4658if host_os != 'windows'
4659  summary_info += {'local state directory': get_option('prefix') / get_option('localstatedir')}
4660  summary_info += {'Manual directory':      get_option('prefix') / get_option('mandir')}
4661else
4662  summary_info += {'local state directory': 'queried at runtime'}
4663endif
4664summary_info += {'Doc directory':     get_option('prefix') / get_option('docdir')}
4665summary(summary_info, bool_yn: true, section: 'Directories')
4666
4667# Host binaries
4668summary_info = {}
4669summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
4670summary_info += {'sphinx-build':      sphinx_build}
4671
4672# FIXME: the [binaries] section of machine files, which can be probed
4673# with find_program(), would be great for passing gdb and genisoimage
4674# paths from configure to Meson.  However, there seems to be no way to
4675# hide a program (for example if gdb is too old).
4676if config_host.has_key('GDB')
4677  summary_info += {'gdb':             config_host['GDB']}
4678endif
4679summary_info += {'iasl':              iasl}
4680summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
4681if host_os == 'windows' and have_ga
4682  summary_info += {'wixl':            wixl}
4683endif
4684if slirp.found() and have_system
4685  summary_info += {'smbd':            have_slirp_smbd ? smbd_path : false}
4686endif
4687summary(summary_info, bool_yn: true, section: 'Host binaries')
4688
4689# Configurable features
4690summary_info = {}
4691summary_info += {'Documentation':     build_docs}
4692summary_info += {'system-mode emulation': have_system}
4693summary_info += {'user-mode emulation': have_user}
4694summary_info += {'block layer':       have_block}
4695summary_info += {'Install blobs':     get_option('install_blobs')}
4696summary_info += {'module support':    enable_modules}
4697if enable_modules
4698  summary_info += {'alternative module path': get_option('module_upgrades')}
4699endif
4700summary_info += {'fuzzing support':   get_option('fuzzing')}
4701if have_system
4702  summary_info += {'Audio drivers':     ' '.join(audio_drivers_selected)}
4703endif
4704summary_info += {'Trace backends':    ','.join(get_option('trace_backends'))}
4705if 'simple' in get_option('trace_backends')
4706  summary_info += {'Trace output file': get_option('trace_file') + '-<pid>'}
4707endif
4708summary_info += {'QOM debugging':     get_option('qom_cast_debug')}
4709summary_info += {'Relocatable install': get_option('relocatable')}
4710summary_info += {'vhost-kernel support': have_vhost_kernel}
4711summary_info += {'vhost-net support': have_vhost_net}
4712summary_info += {'vhost-user support': have_vhost_user}
4713summary_info += {'vhost-user-crypto support': have_vhost_user_crypto}
4714summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
4715summary_info += {'vhost-vdpa support': have_vhost_vdpa}
4716summary_info += {'build guest agent': have_ga}
4717summary(summary_info, bool_yn: true, section: 'Configurable features')
4718
4719# Compilation information
4720summary_info = {}
4721summary_info += {'host CPU':          cpu}
4722summary_info += {'host endianness':   build_machine.endian()}
4723summary_info += {'C compiler':        ' '.join(meson.get_compiler('c').cmd_array())}
4724summary_info += {'Host C compiler':   ' '.join(meson.get_compiler('c', native: true).cmd_array())}
4725if 'cpp' in all_languages
4726  summary_info += {'C++ compiler':    ' '.join(meson.get_compiler('cpp').cmd_array())}
4727else
4728  summary_info += {'C++ compiler':      false}
4729endif
4730if 'objc' in all_languages
4731  summary_info += {'Objective-C compiler': ' '.join(meson.get_compiler('objc').cmd_array())}
4732else
4733  summary_info += {'Objective-C compiler': false}
4734endif
4735summary_info += {'Rust support':      have_rust}
4736if have_rust
4737  summary_info += {'Rust target':     config_host['RUST_TARGET_TRIPLE']}
4738  summary_info += {'rustc':           ' '.join(rustc.cmd_array())}
4739  summary_info += {'rustc version':   rustc.version()}
4740  summary_info += {'rustdoc':         rustdoc}
4741  summary_info += {'bindgen':         bindgen.full_path()}
4742  summary_info += {'bindgen version': bindgen.version()}
4743endif
4744option_cflags = (get_option('debug') ? ['-g'] : [])
4745if get_option('optimization') != 'plain'
4746  option_cflags += ['-O' + get_option('optimization')]
4747endif
4748summary_info += {'CFLAGS':            ' '.join(get_option('c_args') + option_cflags)}
4749if 'cpp' in all_languages
4750  summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args') + option_cflags)}
4751endif
4752if 'objc' in all_languages
4753  summary_info += {'OBJCFLAGS':       ' '.join(get_option('objc_args') + option_cflags)}
4754endif
4755link_args = get_option('c_link_args')
4756if link_args.length() > 0
4757  summary_info += {'LDFLAGS':         ' '.join(link_args)}
4758endif
4759summary_info += {'QEMU_CFLAGS':       ' '.join(qemu_common_flags + qemu_cflags)}
4760if 'cpp' in all_languages
4761  summary_info += {'QEMU_CXXFLAGS':     ' '.join(qemu_common_flags + qemu_cxxflags)}
4762endif
4763if 'objc' in all_languages
4764  summary_info += {'QEMU_OBJCFLAGS':    ' '.join(qemu_common_flags)}
4765endif
4766summary_info += {'QEMU_LDFLAGS':      ' '.join(qemu_ldflags)}
4767summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
4768summary_info += {'PIE':               get_option('b_pie')}
4769summary_info += {'static build':      get_option('prefer_static')}
4770summary_info += {'malloc trim support': has_malloc_trim}
4771summary_info += {'membarrier':        have_membarrier}
4772summary_info += {'debug graph lock':  get_option('debug_graph_lock')}
4773summary_info += {'debug stack usage': get_option('debug_stack_usage')}
4774summary_info += {'mutex debugging':   get_option('debug_mutex')}
4775summary_info += {'memory allocator':  get_option('malloc')}
4776summary_info += {'avx2 optimization': config_host_data.get('CONFIG_AVX2_OPT')}
4777summary_info += {'avx512bw optimization': config_host_data.get('CONFIG_AVX512BW_OPT')}
4778summary_info += {'gcov':              get_option('b_coverage')}
4779summary_info += {'thread sanitizer':  get_option('tsan')}
4780summary_info += {'CFI support':       get_option('cfi')}
4781if get_option('cfi')
4782  summary_info += {'CFI debug support': get_option('cfi_debug')}
4783endif
4784summary_info += {'strip binaries':    get_option('strip')}
4785summary_info += {'sparse':            sparse}
4786summary_info += {'mingw32 support':   host_os == 'windows'}
4787summary(summary_info, bool_yn: true, section: 'Compilation')
4788
4789# snarf the cross-compilation information for tests
4790summary_info = {}
4791have_cross = false
4792foreach target: target_dirs
4793  tcg_mak = meson.current_build_dir() / 'tests/tcg' / target / 'config-target.mak'
4794  if fs.exists(tcg_mak)
4795    config_cross_tcg = keyval.load(tcg_mak)
4796    if 'CC' in config_cross_tcg
4797      summary_info += {config_cross_tcg['TARGET_NAME']: config_cross_tcg['CC']}
4798      have_cross = true
4799    endif
4800  endif
4801endforeach
4802if have_cross
4803  summary(summary_info, bool_yn: true, section: 'Cross compilers')
4804endif
4805
4806# Targets and accelerators
4807summary_info = {}
4808if have_system
4809  summary_info += {'KVM support':       config_all_accel.has_key('CONFIG_KVM')}
4810  summary_info += {'HVF support':       config_all_accel.has_key('CONFIG_HVF')}
4811  summary_info += {'WHPX support':      config_all_accel.has_key('CONFIG_WHPX')}
4812  summary_info += {'NVMM support':      config_all_accel.has_key('CONFIG_NVMM')}
4813  summary_info += {'Xen support':       xen.found()}
4814  if xen.found()
4815    summary_info += {'xen ctrl version':  xen.version()}
4816  endif
4817  summary_info += {'Xen emulation':     config_all_devices.has_key('CONFIG_XEN_EMU')}
4818endif
4819summary_info += {'TCG support':       config_all_accel.has_key('CONFIG_TCG')}
4820if config_all_accel.has_key('CONFIG_TCG')
4821  if get_option('tcg_interpreter')
4822    summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, slow)'}
4823  else
4824    summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
4825  endif
4826  summary_info += {'TCG plugins':       get_option('plugins')}
4827  summary_info += {'TCG debug enabled': get_option('debug_tcg')}
4828  if have_linux_user or have_bsd_user
4829    summary_info += {'syscall buffer debugging support': get_option('debug_remap')}
4830  endif
4831endif
4832summary_info += {'target list':       ' '.join(target_dirs)}
4833if have_system
4834  summary_info += {'default devices':   get_option('default_devices')}
4835  summary_info += {'out of process emulation': multiprocess_allowed}
4836  summary_info += {'vfio-user server': vfio_user_server_allowed}
4837endif
4838summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
4839
4840# Block layer
4841summary_info = {}
4842summary_info += {'coroutine backend': coroutine_backend}
4843summary_info += {'coroutine pool':    have_coroutine_pool}
4844if have_block
4845  summary_info += {'Block whitelist (rw)': get_option('block_drv_rw_whitelist')}
4846  summary_info += {'Block whitelist (ro)': get_option('block_drv_ro_whitelist')}
4847  summary_info += {'Use block whitelist in tools': get_option('block_drv_whitelist_in_tools')}
4848  summary_info += {'VirtFS (9P) support':    have_virtfs}
4849  summary_info += {'replication support': config_host_data.get('CONFIG_REPLICATION')}
4850  summary_info += {'bochs support':     get_option('bochs').allowed()}
4851  summary_info += {'cloop support':     get_option('cloop').allowed()}
4852  summary_info += {'dmg support':       get_option('dmg').allowed()}
4853  summary_info += {'qcow v1 support':   get_option('qcow1').allowed()}
4854  summary_info += {'vdi support':       get_option('vdi').allowed()}
4855  summary_info += {'vhdx support':      get_option('vhdx').allowed()}
4856  summary_info += {'vmdk support':      get_option('vmdk').allowed()}
4857  summary_info += {'vpc support':       get_option('vpc').allowed()}
4858  summary_info += {'vvfat support':     get_option('vvfat').allowed()}
4859  summary_info += {'qed support':       get_option('qed').allowed()}
4860  summary_info += {'parallels support': get_option('parallels').allowed()}
4861  summary_info += {'FUSE exports':      fuse}
4862  summary_info += {'VDUSE block exports': have_vduse_blk_export}
4863endif
4864summary(summary_info, bool_yn: true, section: 'Block layer support')
4865
4866# Crypto
4867summary_info = {}
4868summary_info += {'TLS priority':      get_option('tls_priority')}
4869summary_info += {'GNUTLS support':    gnutls}
4870if gnutls.found()
4871  summary_info += {'  GNUTLS crypto':   gnutls_crypto.found()}
4872endif
4873summary_info += {'libgcrypt':         gcrypt}
4874summary_info += {'nettle':            nettle}
4875if nettle.found()
4876   summary_info += {'  XTS':             xts != 'private'}
4877endif
4878summary_info += {'SM4 ALG support':   crypto_sm4}
4879summary_info += {'SM3 ALG support':   crypto_sm3}
4880summary_info += {'AF_ALG support':    have_afalg}
4881summary_info += {'rng-none':          get_option('rng_none')}
4882summary_info += {'Linux keyring':     have_keyring}
4883summary_info += {'Linux keyutils':    keyutils}
4884summary(summary_info, bool_yn: true, section: 'Crypto')
4885
4886# UI
4887summary_info = {}
4888if host_os == 'darwin'
4889  summary_info += {'Cocoa support':           cocoa}
4890endif
4891summary_info += {'D-Bus display':     dbus_display}
4892summary_info += {'SDL support':       sdl}
4893summary_info += {'SDL image support': sdl_image}
4894summary_info += {'GTK support':       gtk}
4895summary_info += {'pixman':            pixman}
4896summary_info += {'VTE support':       vte}
4897summary_info += {'PNG support':       png}
4898summary_info += {'VNC support':       vnc}
4899if vnc.found()
4900  summary_info += {'VNC SASL support':  sasl}
4901  summary_info += {'VNC JPEG support':  jpeg}
4902endif
4903summary_info += {'spice protocol support': spice_protocol}
4904if spice_protocol.found()
4905  summary_info += {'  spice server support': spice}
4906endif
4907summary_info += {'curses support':    curses}
4908summary_info += {'brlapi support':    brlapi}
4909summary(summary_info, bool_yn: true, section: 'User interface')
4910
4911# Graphics backends
4912summary_info = {}
4913summary_info += {'VirGL support':     virgl}
4914summary_info += {'Rutabaga support':  rutabaga}
4915summary(summary_info, bool_yn: true, section: 'Graphics backends')
4916
4917# Audio backends
4918summary_info = {}
4919if host_os not in ['darwin', 'haiku', 'windows']
4920  summary_info += {'OSS support':     oss}
4921  summary_info += {'sndio support':   sndio}
4922elif host_os == 'darwin'
4923  summary_info += {'CoreAudio support': coreaudio}
4924elif host_os == 'windows'
4925  summary_info += {'DirectSound support': dsound}
4926endif
4927if host_os == 'linux'
4928  summary_info += {'ALSA support':    alsa}
4929  summary_info += {'PulseAudio support': pulse}
4930endif
4931summary_info += {'PipeWire support':  pipewire}
4932summary_info += {'JACK support':      jack}
4933summary(summary_info, bool_yn: true, section: 'Audio backends')
4934
4935# Network backends
4936summary_info = {}
4937if host_os == 'darwin'
4938  summary_info += {'vmnet.framework support': vmnet}
4939endif
4940summary_info += {'AF_XDP support':    libxdp}
4941summary_info += {'passt support':     enable_passt}
4942summary_info += {'slirp support':     slirp}
4943summary_info += {'vde support':       vde}
4944summary_info += {'netmap support':    have_netmap}
4945summary_info += {'l2tpv3 support':    have_l2tpv3}
4946summary(summary_info, bool_yn: true, section: 'Network backends')
4947
4948# Libraries
4949summary_info = {}
4950summary_info += {'libtasn1':          tasn1}
4951summary_info += {'PAM':               pam}
4952summary_info += {'iconv support':     iconv}
4953summary_info += {'blkio support':     blkio}
4954summary_info += {'curl support':      curl}
4955summary_info += {'Multipath support': mpathpersist}
4956summary_info += {'Linux AIO support': libaio}
4957summary_info += {'Linux io_uring support': linux_io_uring}
4958summary_info += {'ATTR/XATTR support': libattr}
4959summary_info += {'RDMA support':      rdma}
4960summary_info += {'fdt support':       fdt_opt == 'internal' ? 'internal' : fdt}
4961summary_info += {'libcap-ng support': libcap_ng}
4962summary_info += {'bpf support':       libbpf}
4963summary_info += {'rbd support':       rbd}
4964summary_info += {'smartcard support': cacard}
4965summary_info += {'U2F support':       u2f}
4966summary_info += {'libusb':            libusb}
4967summary_info += {'usb net redir':     usbredir}
4968summary_info += {'OpenGL support (epoxy)': opengl}
4969summary_info += {'GBM':               gbm}
4970summary_info += {'libiscsi support':  libiscsi}
4971summary_info += {'libnfs support':    libnfs}
4972if host_os == 'windows'
4973  if have_ga
4974    summary_info += {'QGA VSS support':   have_qga_vss}
4975  endif
4976endif
4977summary_info += {'seccomp support':   seccomp}
4978summary_info += {'GlusterFS support': glusterfs}
4979summary_info += {'hv-balloon support': hv_balloon}
4980summary_info += {'TPM support':       have_tpm}
4981summary_info += {'IGVM support':      igvm}
4982summary_info += {'libssh support':    libssh}
4983summary_info += {'lzo support':       lzo}
4984summary_info += {'snappy support':    snappy}
4985summary_info += {'bzip2 support':     libbzip2}
4986summary_info += {'lzfse support':     liblzfse}
4987summary_info += {'zstd support':      zstd}
4988summary_info += {'Query Processing Library support': qpl}
4989summary_info += {'UADK Library support': uadk}
4990summary_info += {'qatzip support':    qatzip}
4991summary_info += {'NUMA host support': numa}
4992summary_info += {'capstone':          capstone}
4993summary_info += {'libpmem support':   libpmem}
4994summary_info += {'libdaxctl support': libdaxctl}
4995summary_info += {'libcbor support':   libcbor}
4996summary_info += {'libudev':           libudev}
4997# Dummy dependency, keep .found()
4998summary_info += {'FUSE lseek':        fuse_lseek.found()}
4999summary_info += {'selinux':           selinux}
5000summary_info += {'libdw':             libdw}
5001if host_os == 'freebsd'
5002  summary_info += {'libinotify-kqueue': inotify}
5003endif
5004if host_os == 'darwin'
5005  summary_info += {'ParavirtualizedGraphics support': pvg}
5006endif
5007summary_info += {'valgrind':          valgrind}
5008summary(summary_info, bool_yn: true, section: 'Dependencies')
5009
5010if host_arch == 'unknown'
5011  message()
5012  warning('UNSUPPORTED HOST CPU')
5013  message()
5014  message('Support for CPU host architecture ' + cpu + ' is not currently')
5015  message('maintained. The QEMU project does not guarantee that QEMU will')
5016  message('compile or work on this host CPU. You can help by volunteering')
5017  message('to maintain it and providing a build host for our continuous')
5018  message('integration setup.')
5019  if have_tcg
5020    message()
5021    message('configure has succeeded and you can continue to build, but')
5022    message('QEMU will use a slow interpreter to emulate the target CPU.')
5023  endif
5024elif host_long_bits < 64
5025  message()
5026  warning('DEPRECATED HOST CPU')
5027  message()
5028  message('Support for 32-bit CPU host architecture ' + cpu + ' is going')
5029  message('to be dropped in a future QEMU release.')
5030endif
5031
5032if not supported_oses.contains(host_os)
5033  message()
5034  warning('UNSUPPORTED HOST OS')
5035  message()
5036  message('Support for host OS ' + host_os + 'is not currently maintained.')
5037  message('configure has succeeded and you can continue to build, but')
5038  message('the QEMU project does not guarantee that QEMU will compile or')
5039  message('work on this operating system. You can help by volunteering')
5040  message('to maintain it and providing a build host for our continuous')
5041  message('integration setup. This will ensure that future versions of QEMU')
5042  message('will keep working on ' + host_os + '.')
5043endif
5044
5045if host_arch == 'unknown' or not supported_oses.contains(host_os)
5046  message()
5047  message('If you want to help supporting QEMU on this platform, please')
5048  message('contact the developers at qemu-devel@nongnu.org.')
5049endif
5050
5051actually_reloc = get_option('relocatable')
5052# check if get_relocated_path() is actually able to relocate paths
5053if get_option('relocatable') and \
5054  not (get_option('prefix') / get_option('bindir')).startswith(get_option('prefix') / '')
5055  message()
5056  warning('bindir not included within prefix, the installation will not be relocatable.')
5057  actually_reloc = false
5058endif
5059if not actually_reloc and (host_os == 'windows' or get_option('relocatable'))
5060  if host_os == 'windows'
5061    message()
5062    warning('Windows installs should usually be relocatable.')
5063  endif
5064  message()
5065  message('QEMU will have to be installed under ' + get_option('prefix') + '.')
5066  message('Use --disable-relocatable to remove this warning.')
5067endif
5068