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