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