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