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