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