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