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