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