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