xref: /openbmc/qemu/meson.build (revision 4f752191)
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  add_project_arguments(rustc_args, native: false, language: 'rust')
3349  add_project_arguments(rustc_args, native: true, language: 'rust')
3350endif
3351
3352hxtool = find_program('scripts/hxtool')
3353shaderinclude = find_program('scripts/shaderinclude.py')
3354qapi_gen = find_program('scripts/qapi-gen.py')
3355qapi_gen_depends = [ meson.current_source_dir() / 'scripts/qapi/__init__.py',
3356                     meson.current_source_dir() / 'scripts/qapi/commands.py',
3357                     meson.current_source_dir() / 'scripts/qapi/common.py',
3358                     meson.current_source_dir() / 'scripts/qapi/error.py',
3359                     meson.current_source_dir() / 'scripts/qapi/events.py',
3360                     meson.current_source_dir() / 'scripts/qapi/expr.py',
3361                     meson.current_source_dir() / 'scripts/qapi/gen.py',
3362                     meson.current_source_dir() / 'scripts/qapi/introspect.py',
3363                     meson.current_source_dir() / 'scripts/qapi/main.py',
3364                     meson.current_source_dir() / 'scripts/qapi/parser.py',
3365                     meson.current_source_dir() / 'scripts/qapi/schema.py',
3366                     meson.current_source_dir() / 'scripts/qapi/source.py',
3367                     meson.current_source_dir() / 'scripts/qapi/types.py',
3368                     meson.current_source_dir() / 'scripts/qapi/visit.py',
3369                     meson.current_source_dir() / 'scripts/qapi-gen.py'
3370]
3371
3372tracetool = [
3373  python, files('scripts/tracetool.py'),
3374   '--backend=' + ','.join(get_option('trace_backends'))
3375]
3376tracetool_depends = files(
3377  'scripts/tracetool/backend/log.py',
3378  'scripts/tracetool/backend/__init__.py',
3379  'scripts/tracetool/backend/dtrace.py',
3380  'scripts/tracetool/backend/ftrace.py',
3381  'scripts/tracetool/backend/simple.py',
3382  'scripts/tracetool/backend/syslog.py',
3383  'scripts/tracetool/backend/ust.py',
3384  'scripts/tracetool/format/ust_events_c.py',
3385  'scripts/tracetool/format/ust_events_h.py',
3386  'scripts/tracetool/format/__init__.py',
3387  'scripts/tracetool/format/d.py',
3388  'scripts/tracetool/format/simpletrace_stap.py',
3389  'scripts/tracetool/format/c.py',
3390  'scripts/tracetool/format/h.py',
3391  'scripts/tracetool/format/log_stap.py',
3392  'scripts/tracetool/format/stap.py',
3393  'scripts/tracetool/__init__.py',
3394)
3395
3396qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
3397                    meson.current_source_dir(),
3398                    get_option('pkgversion'), meson.project_version()]
3399qemu_version = custom_target('qemu-version.h',
3400                             output: 'qemu-version.h',
3401                             command: qemu_version_cmd,
3402                             capture: true,
3403                             build_by_default: true,
3404                             build_always_stale: true)
3405genh += qemu_version
3406
3407hxdep = []
3408hx_headers = [
3409  ['qemu-options.hx', 'qemu-options.def'],
3410  ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
3411]
3412if have_system
3413  hx_headers += [
3414    ['hmp-commands.hx', 'hmp-commands.h'],
3415    ['hmp-commands-info.hx', 'hmp-commands-info.h'],
3416  ]
3417endif
3418foreach d : hx_headers
3419  hxdep += custom_target(d[1],
3420                input: files(d[0]),
3421                output: d[1],
3422                capture: true,
3423                command: [hxtool, '-h', '@INPUT0@'])
3424endforeach
3425genh += hxdep
3426
3427###############
3428# Trace files #
3429###############
3430
3431# TODO: add each directory to the subdirs from its own meson.build, once
3432# we have those
3433trace_events_subdirs = [
3434  'crypto',
3435  'qapi',
3436  'qom',
3437  'monitor',
3438  'util',
3439  'gdbstub',
3440]
3441if have_linux_user
3442  trace_events_subdirs += [ 'linux-user' ]
3443endif
3444if have_bsd_user
3445  trace_events_subdirs += [ 'bsd-user' ]
3446endif
3447if have_block
3448  trace_events_subdirs += [
3449    'authz',
3450    'block',
3451    'chardev',
3452    'io',
3453    'nbd',
3454    'scsi',
3455  ]
3456endif
3457if have_system
3458  trace_events_subdirs += [
3459    'accel/kvm',
3460    'audio',
3461    'backends',
3462    'backends/tpm',
3463    'ebpf',
3464    'hw/9pfs',
3465    'hw/acpi',
3466    'hw/adc',
3467    'hw/alpha',
3468    'hw/arm',
3469    'hw/audio',
3470    'hw/block',
3471    'hw/char',
3472    'hw/display',
3473    'hw/dma',
3474    'hw/fsi',
3475    'hw/hyperv',
3476    'hw/i2c',
3477    'hw/i386',
3478    'hw/i386/xen',
3479    'hw/i386/kvm',
3480    'hw/ide',
3481    'hw/input',
3482    'hw/intc',
3483    'hw/isa',
3484    'hw/mem',
3485    'hw/mips',
3486    'hw/misc',
3487    'hw/misc/macio',
3488    'hw/net',
3489    'hw/net/can',
3490    'hw/nubus',
3491    'hw/nvme',
3492    'hw/nvram',
3493    'hw/pci',
3494    'hw/pci-host',
3495    'hw/ppc',
3496    'hw/rtc',
3497    'hw/riscv',
3498    'hw/s390x',
3499    'hw/scsi',
3500    'hw/sd',
3501    'hw/sh4',
3502    'hw/sparc',
3503    'hw/sparc64',
3504    'hw/ssi',
3505    'hw/timer',
3506    'hw/tpm',
3507    'hw/ufs',
3508    'hw/usb',
3509    'hw/vfio',
3510    'hw/virtio',
3511    'hw/watchdog',
3512    'hw/xen',
3513    'hw/gpio',
3514    'migration',
3515    'net',
3516    'system',
3517    'ui',
3518    'hw/remote',
3519  ]
3520endif
3521if have_system or have_user
3522  trace_events_subdirs += [
3523    'accel/tcg',
3524    'hw/core',
3525    'target/arm',
3526    'target/arm/hvf',
3527    'target/hppa',
3528    'target/i386',
3529    'target/i386/kvm',
3530    'target/loongarch',
3531    'target/mips/tcg',
3532    'target/ppc',
3533    'target/riscv',
3534    'target/s390x',
3535    'target/s390x/kvm',
3536    'target/sparc',
3537  ]
3538endif
3539
3540###################
3541# Collect sources #
3542###################
3543
3544authz_ss = ss.source_set()
3545blockdev_ss = ss.source_set()
3546block_ss = ss.source_set()
3547chardev_ss = ss.source_set()
3548common_ss = ss.source_set()
3549crypto_ss = ss.source_set()
3550hwcore_ss = ss.source_set()
3551io_ss = ss.source_set()
3552qmp_ss = ss.source_set()
3553qom_ss = ss.source_set()
3554system_ss = ss.source_set()
3555specific_fuzz_ss = ss.source_set()
3556specific_ss = ss.source_set()
3557rust_devices_ss = ss.source_set()
3558stub_ss = ss.source_set()
3559trace_ss = ss.source_set()
3560user_ss = ss.source_set()
3561util_ss = ss.source_set()
3562
3563# accel modules
3564qtest_module_ss = ss.source_set()
3565tcg_module_ss = ss.source_set()
3566
3567modules = {}
3568target_modules = {}
3569hw_arch = {}
3570target_arch = {}
3571target_system_arch = {}
3572target_user_arch = {}
3573
3574# NOTE: the trace/ subdirectory needs the qapi_trace_events variable
3575# that is filled in by qapi/.
3576subdir('qapi')
3577subdir('qobject')
3578subdir('stubs')
3579subdir('trace')
3580subdir('util')
3581subdir('qom')
3582subdir('authz')
3583subdir('crypto')
3584subdir('ui')
3585subdir('gdbstub')
3586if have_system
3587  subdir('hw')
3588else
3589  subdir('hw/core')
3590endif
3591
3592if enable_modules
3593  libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
3594  modulecommon = declare_dependency(objects: libmodulecommon.extract_all_objects(recursive: false), compile_args: '-DBUILD_DSO')
3595endif
3596
3597qom_ss = qom_ss.apply({})
3598libqom = static_library('qom', qom_ss.sources() + genh,
3599                        dependencies: [qom_ss.dependencies()],
3600                        build_by_default: false)
3601qom = declare_dependency(objects: libqom.extract_all_objects(recursive: false),
3602                         dependencies: qom_ss.dependencies())
3603
3604event_loop_base = files('event-loop-base.c')
3605event_loop_base = static_library('event-loop-base',
3606                                 sources: event_loop_base + genh,
3607                                 build_by_default: false)
3608event_loop_base = declare_dependency(objects: event_loop_base.extract_all_objects(recursive: false),
3609                                     dependencies: [qom])
3610
3611stub_ss = stub_ss.apply({})
3612
3613util_ss.add_all(trace_ss)
3614util_ss = util_ss.apply({})
3615libqemuutil = static_library('qemuutil',
3616                             build_by_default: false,
3617                             sources: util_ss.sources() + stub_ss.sources() + genh,
3618                             dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc])
3619qemuutil = declare_dependency(link_with: libqemuutil,
3620                              sources: genh + version_res,
3621                              dependencies: [event_loop_base])
3622
3623if have_system or have_user
3624  decodetree = generator(find_program('scripts/decodetree.py'),
3625                         output: 'decode-@BASENAME@.c.inc',
3626                         arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
3627  subdir('libdecnumber')
3628  subdir('target')
3629endif
3630
3631subdir('audio')
3632subdir('io')
3633subdir('chardev')
3634subdir('fsdev')
3635subdir('dump')
3636
3637if have_block
3638  block_ss.add(files(
3639    'block.c',
3640    'blockjob.c',
3641    'job.c',
3642    'qemu-io-cmds.c',
3643  ))
3644  if config_host_data.get('CONFIG_REPLICATION')
3645    block_ss.add(files('replication.c'))
3646  endif
3647
3648  subdir('nbd')
3649  subdir('scsi')
3650  subdir('block')
3651
3652  blockdev_ss.add(files(
3653    'blockdev.c',
3654    'blockdev-nbd.c',
3655    'iothread.c',
3656    'job-qmp.c',
3657  ))
3658
3659  # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
3660  # os-win32.c does not
3661  if host_os == 'windows'
3662    system_ss.add(files('os-win32.c'))
3663  else
3664    blockdev_ss.add(files('os-posix.c'))
3665  endif
3666endif
3667
3668common_ss.add(files('cpu-common.c'))
3669specific_ss.add(files('cpu-target.c'))
3670
3671subdir('system')
3672
3673# Work around a gcc bug/misfeature wherein constant propagation looks
3674# through an alias:
3675#   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99696
3676# to guess that a const variable is always zero.  Without lto, this is
3677# impossible, as the alias is restricted to page-vary-common.c.  Indeed,
3678# without lto, not even the alias is required -- we simply use different
3679# declarations in different compilation units.
3680pagevary = files('page-vary-common.c')
3681if get_option('b_lto')
3682  pagevary_flags = ['-fno-lto']
3683  if get_option('cfi')
3684    pagevary_flags += '-fno-sanitize=cfi-icall'
3685  endif
3686  pagevary = static_library('page-vary-common', sources: pagevary + genh,
3687                            c_args: pagevary_flags)
3688  pagevary = declare_dependency(link_with: pagevary)
3689endif
3690common_ss.add(pagevary)
3691specific_ss.add(files('page-target.c', 'page-vary-target.c'))
3692
3693subdir('backends')
3694subdir('disas')
3695subdir('migration')
3696subdir('monitor')
3697subdir('net')
3698subdir('replay')
3699subdir('semihosting')
3700subdir('stats')
3701subdir('tcg')
3702subdir('fpu')
3703subdir('accel')
3704subdir('plugins')
3705subdir('ebpf')
3706
3707common_user_inc = []
3708
3709subdir('common-user')
3710subdir('bsd-user')
3711subdir('linux-user')
3712
3713# needed for fuzzing binaries
3714subdir('tests/qtest/libqos')
3715subdir('tests/qtest/fuzz')
3716
3717# accel modules
3718tcg_real_module_ss = ss.source_set()
3719tcg_real_module_ss.add_all(when: 'CONFIG_TCG_MODULAR', if_true: tcg_module_ss)
3720specific_ss.add_all(when: 'CONFIG_TCG_BUILTIN', if_true: tcg_module_ss)
3721target_modules += { 'accel' : { 'qtest': qtest_module_ss,
3722                                'tcg': tcg_real_module_ss }}
3723
3724##############################################
3725# Internal static_libraries and dependencies #
3726##############################################
3727
3728modinfo_collect = find_program('scripts/modinfo-collect.py')
3729modinfo_generate = find_program('scripts/modinfo-generate.py')
3730modinfo_files = []
3731
3732block_mods = []
3733system_mods = []
3734emulator_modules = []
3735foreach d, list : modules
3736  if not (d == 'block' ? have_block : have_system)
3737    continue
3738  endif
3739
3740  foreach m, module_ss : list
3741    if enable_modules
3742      module_ss.add(modulecommon)
3743      module_ss = module_ss.apply(config_all_devices, strict: false)
3744      sl = static_library(d + '-' + m, [genh, module_ss.sources()],
3745                          dependencies: module_ss.dependencies(), pic: true)
3746      if d == 'block'
3747        block_mods += sl
3748      else
3749        system_mods += sl
3750      endif
3751      emulator_modules += shared_module(sl.name(),
3752                    name_prefix: '',
3753                    objects: sl.extract_all_objects(recursive: false),
3754                    dependencies: module_ss.dependencies(),
3755                    install: true,
3756                    install_dir: qemu_moddir)
3757      if module_ss.sources() != []
3758        # FIXME: Should use sl.extract_all_objects(recursive: true) as
3759        # input. Sources can be used multiple times but objects are
3760        # unique when it comes to lookup in compile_commands.json.
3761        # Depnds on a mesion version with
3762        # https://github.com/mesonbuild/meson/pull/8900
3763        modinfo_files += custom_target(d + '-' + m + '.modinfo',
3764                                       output: d + '-' + m + '.modinfo',
3765                                       input: module_ss.sources() + genh,
3766                                       capture: true,
3767                                       command: [modinfo_collect, module_ss.sources()])
3768      endif
3769    else
3770      if d == 'block'
3771        block_ss.add_all(module_ss)
3772      else
3773        system_ss.add_all(module_ss)
3774      endif
3775    endif
3776  endforeach
3777endforeach
3778
3779foreach d, list : target_modules
3780  foreach m, module_ss : list
3781    if enable_modules
3782      module_ss.add(modulecommon)
3783      foreach target : target_dirs
3784        if target.endswith('-softmmu')
3785          config_target = config_target_mak[target]
3786          target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3787          c_args = ['-DCOMPILING_PER_TARGET',
3788                    '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3789                    '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3790          target_module_ss = module_ss.apply(config_target, strict: false)
3791          if target_module_ss.sources() != []
3792            module_name = d + '-' + m + '-' + config_target['TARGET_NAME']
3793            sl = static_library(module_name,
3794                                [genh, target_module_ss.sources()],
3795                                dependencies: target_module_ss.dependencies(),
3796                                include_directories: target_inc,
3797                                c_args: c_args,
3798                                pic: true)
3799            system_mods += sl
3800            emulator_modules += shared_module(sl.name(),
3801                    name_prefix: '',
3802                    objects: sl.extract_all_objects(recursive: false),
3803                    dependencies: target_module_ss.dependencies(),
3804                    install: true,
3805                    install_dir: qemu_moddir)
3806            # FIXME: Should use sl.extract_all_objects(recursive: true) too.
3807            modinfo_files += custom_target(module_name + '.modinfo',
3808                                           output: module_name + '.modinfo',
3809                                           input: target_module_ss.sources() + genh,
3810                                           capture: true,
3811                                           command: [modinfo_collect, '--target', target, target_module_ss.sources()])
3812          endif
3813        endif
3814      endforeach
3815    else
3816      specific_ss.add_all(module_ss)
3817    endif
3818  endforeach
3819endforeach
3820
3821if enable_modules
3822  foreach target : target_dirs
3823    if target.endswith('-softmmu')
3824      config_target = config_target_mak[target]
3825      config_devices_mak = target + '-config-devices.mak'
3826      modinfo_src = custom_target('modinfo-' + target + '.c',
3827                                  output: 'modinfo-' + target + '.c',
3828                                  input: modinfo_files,
3829                                  command: [modinfo_generate, '--devices', config_devices_mak, '@INPUT@'],
3830                                  capture: true)
3831
3832      modinfo_lib = static_library('modinfo-' + target + '.c', modinfo_src)
3833      modinfo_dep = declare_dependency(link_with: modinfo_lib)
3834
3835      arch = config_target['TARGET_NAME'] == 'sparc64' ? 'sparc64' : config_target['TARGET_BASE_ARCH']
3836      hw_arch[arch].add(modinfo_dep)
3837    endif
3838  endforeach
3839
3840  if emulator_modules.length() > 0
3841    alias_target('modules', emulator_modules)
3842  endif
3843endif
3844
3845nm = find_program('nm')
3846undefsym = find_program('scripts/undefsym.py')
3847block_syms = custom_target('block.syms', output: 'block.syms',
3848                             input: [libqemuutil, block_mods],
3849                             capture: true,
3850                             command: [undefsym, nm, '@INPUT@'])
3851qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
3852                             input: [libqemuutil, system_mods],
3853                             capture: true,
3854                             command: [undefsym, nm, '@INPUT@'])
3855
3856authz_ss = authz_ss.apply({})
3857libauthz = static_library('authz', authz_ss.sources() + genh,
3858                          dependencies: [authz_ss.dependencies()],
3859                          build_by_default: false)
3860
3861authz = declare_dependency(objects: libauthz.extract_all_objects(recursive: false),
3862                           dependencies: [authz_ss.dependencies(), qom])
3863
3864crypto_ss = crypto_ss.apply({})
3865libcrypto = static_library('crypto', crypto_ss.sources() + genh,
3866                           dependencies: [crypto_ss.dependencies()],
3867                           build_by_default: false)
3868
3869crypto = declare_dependency(objects: libcrypto.extract_all_objects(recursive: false),
3870                            dependencies: [crypto_ss.dependencies(), authz, qom])
3871
3872io_ss = io_ss.apply({})
3873libio = static_library('io', io_ss.sources() + genh,
3874                       dependencies: [io_ss.dependencies()],
3875                       link_with: libqemuutil,
3876                       build_by_default: false)
3877
3878io = declare_dependency(objects: libio.extract_all_objects(recursive: false),
3879                        dependencies: [io_ss.dependencies(), crypto, qom])
3880
3881libmigration = static_library('migration', sources: migration_files + genh,
3882                              build_by_default: false)
3883migration = declare_dependency(objects: libmigration.extract_all_objects(recursive: false),
3884                               dependencies: [qom, io])
3885system_ss.add(migration)
3886
3887block_ss = block_ss.apply({})
3888libblock = static_library('block', block_ss.sources() + genh,
3889                          dependencies: block_ss.dependencies(),
3890                          build_by_default: false)
3891
3892block = declare_dependency(objects: libblock.extract_all_objects(recursive: false),
3893                           dependencies: [block_ss.dependencies(), crypto, io])
3894
3895blockdev_ss = blockdev_ss.apply({})
3896libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
3897                             dependencies: blockdev_ss.dependencies(),
3898                             build_by_default: false)
3899
3900blockdev = declare_dependency(objects: libblockdev.extract_all_objects(recursive: false),
3901                              dependencies: [blockdev_ss.dependencies(), block, event_loop_base])
3902
3903qmp_ss = qmp_ss.apply({})
3904libqmp = static_library('qmp', qmp_ss.sources() + genh,
3905                        dependencies: qmp_ss.dependencies(),
3906                        build_by_default: false)
3907
3908qmp = declare_dependency(objects: libqmp.extract_all_objects(recursive: false),
3909                         dependencies: qmp_ss.dependencies())
3910
3911libchardev = static_library('chardev', chardev_ss.sources() + genh,
3912                            dependencies: chardev_ss.dependencies(),
3913                            build_by_default: false)
3914
3915chardev = declare_dependency(objects: libchardev.extract_all_objects(recursive: false),
3916                             dependencies: chardev_ss.dependencies())
3917
3918hwcore_ss = hwcore_ss.apply({})
3919libhwcore = static_library('hwcore', sources: hwcore_ss.sources() + genh,
3920                           build_by_default: false)
3921hwcore = declare_dependency(objects: libhwcore.extract_all_objects(recursive: false))
3922common_ss.add(hwcore)
3923
3924###########
3925# Targets #
3926###########
3927
3928system_ss.add(authz, blockdev, chardev, crypto, io, qmp)
3929common_ss.add(qom, qemuutil)
3930
3931common_ss.add_all(when: 'CONFIG_SYSTEM_ONLY', if_true: [system_ss])
3932common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
3933
3934# Note that this library is never used directly (only through extract_objects)
3935# and is not built by default; therefore, source files not used by the build
3936# configuration will be in build.ninja, but are never built by default.
3937common_all = static_library('common',
3938                            build_by_default: false,
3939                            sources: common_ss.all_sources() + genh,
3940                            include_directories: common_user_inc,
3941                            implicit_include_directories: false,
3942                            dependencies: common_ss.all_dependencies())
3943
3944if have_rust and have_system
3945  bindgen_args = [
3946    '--disable-header-comment',
3947    '--raw-line', '// @generated',
3948    '--ctypes-prefix', 'core::ffi',
3949    '--formatter', 'rustfmt',
3950    '--generate-block',
3951    '--generate-cstr',
3952    '--impl-debug',
3953    '--merge-extern-blocks',
3954    '--no-doc-comments',
3955    '--use-core',
3956    '--with-derive-default',
3957    '--no-layout-tests',
3958    '--no-prepend-enum-name',
3959    '--allowlist-file', meson.project_source_root() + '/include/.*',
3960    '--allowlist-file', meson.project_source_root() + '/.*',
3961    '--allowlist-file', meson.project_build_root() + '/.*'
3962    ]
3963  c_enums = [
3964    'DeviceCategory',
3965    'GpioPolarity',
3966    'MachineInitPhase',
3967    'MemoryDeviceInfoKind',
3968    'MigrationPolicy',
3969    'MigrationPriority',
3970    'QEMUChrEvent',
3971    'QEMUClockType',
3972    'device_endian',
3973    'module_init_type',
3974  ]
3975  foreach enum : c_enums
3976    bindgen_args += ['--rustified-enum', enum]
3977  endforeach
3978  c_bitfields = [
3979    'ClockEvent',
3980    'VMStateFlags',
3981  ]
3982  foreach enum : c_bitfields
3983    bindgen_args += ['--bitfield-enum', enum]
3984  endforeach
3985
3986  # TODO: Remove this comment when the clang/libclang mismatch issue is solved.
3987  #
3988  # Rust bindings generation with `bindgen` might fail in some cases where the
3989  # detected `libclang` does not match the expected `clang` version/target. In
3990  # this case you must pass the path to `clang` and `libclang` to your build
3991  # command invocation using the environment variables CLANG_PATH and
3992  # LIBCLANG_PATH
3993  bindings_rs = rust.bindgen(
3994    input: 'rust/wrapper.h',
3995    dependencies: common_ss.all_dependencies(),
3996    output: 'bindings.rs',
3997    include_directories: include_directories('.', 'include'),
3998    bindgen_version: ['>=0.69.4'],
3999    args: bindgen_args,
4000    )
4001  subdir('rust')
4002endif
4003
4004
4005feature_to_c = find_program('scripts/feature_to_c.py')
4006rust_root_crate = find_program('scripts/rust/rust_root_crate.sh')
4007
4008if host_os == 'darwin'
4009  entitlement = find_program('scripts/entitlement.sh')
4010endif
4011
4012traceable = []
4013emulators = {}
4014foreach target : target_dirs
4015  config_target = config_target_mak[target]
4016  target_name = config_target['TARGET_NAME']
4017  target_base_arch = config_target['TARGET_BASE_ARCH']
4018  arch_srcs = [config_target_h[target]]
4019  arch_deps = []
4020  c_args = ['-DCOMPILING_PER_TARGET',
4021            '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
4022            '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
4023  link_args = emulator_link_args
4024
4025  target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
4026  if host_os == 'linux'
4027    target_inc += include_directories('linux-headers', is_system: true)
4028  endif
4029  if target.endswith('-softmmu')
4030    target_type='system'
4031    t = target_system_arch[target_base_arch].apply(config_target, strict: false)
4032    arch_srcs += t.sources()
4033    arch_deps += t.dependencies()
4034
4035    hw_dir = target_name == 'sparc64' ? 'sparc64' : target_base_arch
4036    if hw_arch.has_key(hw_dir)
4037      hw = hw_arch[hw_dir].apply(config_target, strict: false)
4038      arch_srcs += hw.sources()
4039      arch_deps += hw.dependencies()
4040    endif
4041
4042    arch_srcs += config_devices_h[target]
4043    link_args += ['@block.syms', '@qemu.syms']
4044  else
4045    abi = config_target['TARGET_ABI_DIR']
4046    target_type='user'
4047    target_inc += common_user_inc
4048    if target_base_arch in target_user_arch
4049      t = target_user_arch[target_base_arch].apply(config_target, strict: false)
4050      arch_srcs += t.sources()
4051      arch_deps += t.dependencies()
4052    endif
4053    if 'CONFIG_LINUX_USER' in config_target
4054      base_dir = 'linux-user'
4055    endif
4056    if 'CONFIG_BSD_USER' in config_target
4057      base_dir = 'bsd-user'
4058      target_inc += include_directories('bsd-user/' / host_os)
4059      target_inc += include_directories('bsd-user/host/' / host_arch)
4060      dir = base_dir / abi
4061      arch_srcs += files(dir / 'signal.c', dir / 'target_arch_cpu.c')
4062    endif
4063    target_inc += include_directories(
4064      base_dir,
4065      base_dir / abi,
4066    )
4067    if 'CONFIG_LINUX_USER' in config_target
4068      dir = base_dir / abi
4069      arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
4070      if config_target.has_key('TARGET_SYSTBL_ABI')
4071        arch_srcs += \
4072          syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
4073                                             extra_args : config_target['TARGET_SYSTBL_ABI'])
4074      endif
4075    endif
4076  endif
4077
4078  if 'TARGET_XML_FILES' in config_target
4079    gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
4080                                output: target + '-gdbstub-xml.c',
4081                                input: files(config_target['TARGET_XML_FILES'].split()),
4082                                command: [feature_to_c, '@INPUT@'],
4083                                capture: true)
4084    arch_srcs += gdbstub_xml
4085  endif
4086
4087  t = target_arch[target_base_arch].apply(config_target, strict: false)
4088  arch_srcs += t.sources()
4089  arch_deps += t.dependencies()
4090
4091  target_common = common_ss.apply(config_target, strict: false)
4092  objects = common_all.extract_objects(target_common.sources())
4093  arch_deps += target_common.dependencies()
4094
4095  target_specific = specific_ss.apply(config_target, strict: false)
4096  arch_srcs += target_specific.sources()
4097  arch_deps += target_specific.dependencies()
4098
4099  if have_rust and have_system
4100    target_rust = rust_devices_ss.apply(config_target, strict: false)
4101    crates = []
4102    foreach dep : target_rust.dependencies()
4103      crates += dep.get_variable('crate')
4104    endforeach
4105    if crates.length() > 0
4106      rlib_rs = custom_target('rust_' + target.underscorify() + '.rs',
4107                              output: 'rust_' + target.underscorify() + '.rs',
4108                              command: [rust_root_crate, crates],
4109                              capture: true,
4110                              build_by_default: true,
4111                              build_always_stale: true)
4112      rlib = static_library('rust_' + target.underscorify(),
4113                            rlib_rs,
4114                            dependencies: target_rust.dependencies(),
4115                            override_options: ['rust_std=2021', 'build.rust_std=2021'],
4116                            rust_abi: 'c')
4117      arch_deps += declare_dependency(link_whole: [rlib])
4118    endif
4119  endif
4120
4121  # allow using headers from the dependencies but do not include the sources,
4122  # because this emulator only needs those in "objects".  For external
4123  # dependencies, the full dependency is included below in the executable.
4124  lib_deps = []
4125  foreach dep : arch_deps
4126    lib_deps += dep.partial_dependency(compile_args: true, includes: true)
4127  endforeach
4128
4129  lib = static_library('qemu-' + target,
4130                 sources: arch_srcs + genh,
4131                 dependencies: lib_deps,
4132                 objects: objects,
4133                 include_directories: target_inc,
4134                 c_args: c_args,
4135                 build_by_default: false)
4136
4137  if target.endswith('-softmmu')
4138    execs = [{
4139      'name': 'qemu-system-' + target_name,
4140      'win_subsystem': 'console',
4141      'sources': files('system/main.c'),
4142      'dependencies': []
4143    }]
4144    if host_os == 'windows' and (sdl.found() or gtk.found())
4145      execs += [{
4146        'name': 'qemu-system-' + target_name + 'w',
4147        'win_subsystem': 'windows',
4148        'sources': files('system/main.c'),
4149        'dependencies': []
4150      }]
4151    endif
4152    if get_option('fuzzing')
4153      specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
4154      execs += [{
4155        'name': 'qemu-fuzz-' + target_name,
4156        'win_subsystem': 'console',
4157        'sources': specific_fuzz.sources(),
4158        'dependencies': specific_fuzz.dependencies(),
4159      }]
4160    endif
4161  else
4162    execs = [{
4163      'name': 'qemu-' + target_name,
4164      'win_subsystem': 'console',
4165      'sources': [],
4166      'dependencies': []
4167    }]
4168  endif
4169  foreach exe: execs
4170    exe_name = exe['name']
4171    if host_os == 'darwin'
4172      exe_name += '-unsigned'
4173    endif
4174
4175    emulator = executable(exe_name, exe['sources'],
4176               install: true,
4177               c_args: c_args,
4178               dependencies: arch_deps + exe['dependencies'],
4179               objects: lib.extract_all_objects(recursive: true),
4180               link_depends: [block_syms, qemu_syms],
4181               link_args: link_args,
4182               win_subsystem: exe['win_subsystem'])
4183
4184    if host_os == 'darwin'
4185      icon = 'pc-bios/qemu.rsrc'
4186      build_input = [emulator, files(icon)]
4187      install_input = [
4188        get_option('bindir') / exe_name,
4189        meson.current_source_dir() / icon
4190      ]
4191      if 'CONFIG_HVF' in config_target
4192        entitlements = 'accel/hvf/entitlements.plist'
4193        build_input += files(entitlements)
4194        install_input += meson.current_source_dir() / entitlements
4195      endif
4196
4197      emulators += {exe['name'] : custom_target(exe['name'],
4198                   input: build_input,
4199                   output: exe['name'],
4200                   command: [entitlement, '@OUTPUT@', '@INPUT@'])
4201      }
4202
4203      meson.add_install_script(entitlement, '--install',
4204                               get_option('bindir') / exe['name'],
4205                               install_input)
4206    else
4207      emulators += {exe['name']: emulator}
4208    endif
4209
4210    traceable += [{
4211      'exe': exe['name'],
4212      'probe-prefix': 'qemu.' + target_type + '.' + target_name,
4213    }]
4214
4215  endforeach
4216endforeach
4217
4218# Other build targets
4219
4220if get_option('plugins')
4221  install_headers('include/qemu/qemu-plugin.h')
4222  if host_os == 'windows'
4223    # On windows, we want to deliver the qemu_plugin_api.lib file in the qemu installer,
4224    # so that plugin authors can compile against it.
4225    install_data(win32_qemu_plugin_api_lib, install_dir: 'lib')
4226  endif
4227endif
4228
4229subdir('qga')
4230
4231# Don't build qemu-keymap if xkbcommon is not explicitly enabled
4232# when we don't build tools or system
4233if xkbcommon.found()
4234  # used for the update-keymaps target, so include rules even if !have_tools
4235  qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
4236                           dependencies: [qemuutil, xkbcommon], install: have_tools)
4237endif
4238
4239if have_tools
4240  qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
4241             link_args: '@block.syms', link_depends: block_syms,
4242             dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
4243  qemu_io = executable('qemu-io', files('qemu-io.c'),
4244             link_args: '@block.syms', link_depends: block_syms,
4245             dependencies: [block, qemuutil], install: true)
4246  qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
4247               link_args: '@block.syms', link_depends: block_syms,
4248               dependencies: [blockdev, qemuutil, selinux],
4249               install: true)
4250
4251  subdir('storage-daemon')
4252
4253  foreach exe: [ 'qemu-img', 'qemu-io', 'qemu-nbd', 'qemu-storage-daemon']
4254    traceable += [{
4255      'exe': exe,
4256      'probe-prefix': 'qemu.' + exe.substring(5).replace('-', '_')
4257    }]
4258  endforeach
4259
4260  subdir('contrib/elf2dmp')
4261
4262  executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
4263             dependencies: qemuutil,
4264             install: true)
4265
4266  if have_vhost_user
4267    subdir('contrib/vhost-user-blk')
4268    subdir('contrib/vhost-user-gpu')
4269    subdir('contrib/vhost-user-input')
4270    subdir('contrib/vhost-user-scsi')
4271  endif
4272
4273  if host_os == 'linux'
4274    executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
4275               dependencies: [qemuutil, libcap_ng],
4276               install: true,
4277               install_dir: get_option('libexecdir'))
4278
4279    executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
4280               dependencies: [authz, crypto, io, qom, qemuutil,
4281                              libcap_ng, mpathpersist],
4282               install: true)
4283
4284    if cpu in ['x86', 'x86_64']
4285      executable('qemu-vmsr-helper', files('tools/i386/qemu-vmsr-helper.c'),
4286               dependencies: [authz, crypto, io, qom, qemuutil,
4287                              libcap_ng, mpathpersist],
4288               install: true)
4289    endif
4290  endif
4291
4292  if have_ivshmem
4293    subdir('contrib/ivshmem-client')
4294    subdir('contrib/ivshmem-server')
4295  endif
4296endif
4297
4298if stap.found()
4299  foreach t: traceable
4300    foreach stp: [
4301      {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / t['exe'], 'install': false},
4302      {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / t['exe'], 'install': true},
4303      {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
4304      {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
4305    ]
4306      cmd = [
4307        tracetool, '--group=all', '--format=' + stp['fmt'],
4308        '--binary=' + stp['bin'],
4309        '--probe-prefix=' + t['probe-prefix'],
4310        '@INPUT@', '@OUTPUT@'
4311      ]
4312
4313      custom_target(t['exe'] + stp['ext'],
4314                    input: trace_events_all,
4315                    output: t['exe'] + stp['ext'],
4316                    install: stp['install'],
4317                    install_dir: get_option('datadir') / 'systemtap/tapset',
4318                    command: cmd,
4319                    depend_files: tracetool_depends)
4320    endforeach
4321  endforeach
4322endif
4323
4324subdir('scripts')
4325subdir('tools')
4326subdir('pc-bios')
4327subdir('docs')
4328subdir('tests')
4329if gtk.found()
4330  subdir('po')
4331endif
4332
4333if host_machine.system() == 'windows'
4334  nsis_cmd = [
4335    find_program('scripts/nsis.py'),
4336    '@OUTPUT@',
4337    get_option('prefix'),
4338    meson.current_source_dir(),
4339    glib_pc.get_variable('bindir'),
4340    host_machine.cpu(),
4341    '--',
4342    '-DDISPLAYVERSION=' + meson.project_version(),
4343  ]
4344  if build_docs
4345    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
4346  endif
4347  if gtk.found()
4348    nsis_cmd += '-DCONFIG_GTK=y'
4349  endif
4350
4351  nsis = custom_target('nsis',
4352                       output: 'qemu-setup-' + meson.project_version() + '.exe',
4353                       input: files('qemu.nsi'),
4354                       build_always_stale: true,
4355                       command: nsis_cmd + ['@INPUT@'])
4356  alias_target('installer', nsis)
4357endif
4358
4359#########################
4360# Configuration summary #
4361#########################
4362
4363# Build environment
4364summary_info = {}
4365summary_info += {'Build directory':   meson.current_build_dir()}
4366summary_info += {'Source path':       meson.current_source_dir()}
4367summary_info += {'Download dependencies': get_option('wrap_mode') != 'nodownload'}
4368summary(summary_info, bool_yn: true, section: 'Build environment')
4369
4370# Directories
4371summary_info += {'Install prefix':    get_option('prefix')}
4372summary_info += {'BIOS directory':    qemu_datadir}
4373pathsep = host_os == 'windows' ? ';' : ':'
4374summary_info += {'firmware path':     pathsep.join(get_option('qemu_firmwarepath'))}
4375summary_info += {'binary directory':  get_option('prefix') / get_option('bindir')}
4376summary_info += {'library directory': get_option('prefix') / get_option('libdir')}
4377summary_info += {'module directory':  qemu_moddir}
4378summary_info += {'libexec directory': get_option('prefix') / get_option('libexecdir')}
4379summary_info += {'include directory': get_option('prefix') / get_option('includedir')}
4380summary_info += {'config directory':  get_option('prefix') / get_option('sysconfdir')}
4381if host_os != 'windows'
4382  summary_info += {'local state directory': get_option('prefix') / get_option('localstatedir')}
4383  summary_info += {'Manual directory':      get_option('prefix') / get_option('mandir')}
4384else
4385  summary_info += {'local state directory': 'queried at runtime'}
4386endif
4387summary_info += {'Doc directory':     get_option('prefix') / get_option('docdir')}
4388summary(summary_info, bool_yn: true, section: 'Directories')
4389
4390# Host binaries
4391summary_info = {}
4392summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
4393summary_info += {'sphinx-build':      sphinx_build}
4394
4395# FIXME: the [binaries] section of machine files, which can be probed
4396# with find_program(), would be great for passing gdb and genisoimage
4397# paths from configure to Meson.  However, there seems to be no way to
4398# hide a program (for example if gdb is too old).
4399if config_host.has_key('GDB')
4400  summary_info += {'gdb':             config_host['GDB']}
4401endif
4402summary_info += {'iasl':              iasl}
4403summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
4404if host_os == 'windows' and have_ga
4405  summary_info += {'wixl':            wixl}
4406endif
4407if slirp.found() and have_system
4408  summary_info += {'smbd':            have_slirp_smbd ? smbd_path : false}
4409endif
4410summary(summary_info, bool_yn: true, section: 'Host binaries')
4411
4412# Configurable features
4413summary_info = {}
4414summary_info += {'Documentation':     build_docs}
4415summary_info += {'system-mode emulation': have_system}
4416summary_info += {'user-mode emulation': have_user}
4417summary_info += {'block layer':       have_block}
4418summary_info += {'Install blobs':     get_option('install_blobs')}
4419summary_info += {'module support':    enable_modules}
4420if enable_modules
4421  summary_info += {'alternative module path': get_option('module_upgrades')}
4422endif
4423summary_info += {'fuzzing support':   get_option('fuzzing')}
4424if have_system
4425  summary_info += {'Audio drivers':     ' '.join(audio_drivers_selected)}
4426endif
4427summary_info += {'Trace backends':    ','.join(get_option('trace_backends'))}
4428if 'simple' in get_option('trace_backends')
4429  summary_info += {'Trace output file': get_option('trace_file') + '-<pid>'}
4430endif
4431summary_info += {'D-Bus display':     dbus_display}
4432summary_info += {'QOM debugging':     get_option('qom_cast_debug')}
4433summary_info += {'Relocatable install': get_option('relocatable')}
4434summary_info += {'vhost-kernel support': have_vhost_kernel}
4435summary_info += {'vhost-net support': have_vhost_net}
4436summary_info += {'vhost-user support': have_vhost_user}
4437summary_info += {'vhost-user-crypto support': have_vhost_user_crypto}
4438summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
4439summary_info += {'vhost-vdpa support': have_vhost_vdpa}
4440summary_info += {'build guest agent': have_ga}
4441summary(summary_info, bool_yn: true, section: 'Configurable features')
4442
4443# Compilation information
4444summary_info = {}
4445summary_info += {'host CPU':          cpu}
4446summary_info += {'host endianness':   build_machine.endian()}
4447summary_info += {'C compiler':        ' '.join(meson.get_compiler('c').cmd_array())}
4448summary_info += {'Host C compiler':   ' '.join(meson.get_compiler('c', native: true).cmd_array())}
4449if 'cpp' in all_languages
4450  summary_info += {'C++ compiler':    ' '.join(meson.get_compiler('cpp').cmd_array())}
4451else
4452  summary_info += {'C++ compiler':      false}
4453endif
4454if 'objc' in all_languages
4455  summary_info += {'Objective-C compiler': ' '.join(meson.get_compiler('objc').cmd_array())}
4456else
4457  summary_info += {'Objective-C compiler': false}
4458endif
4459summary_info += {'Rust support':      have_rust}
4460if have_rust
4461  summary_info += {'rustc version':   rustc.version()}
4462  summary_info += {'rustc':           ' '.join(rustc.cmd_array())}
4463  summary_info += {'Rust target':     config_host['RUST_TARGET_TRIPLE']}
4464endif
4465option_cflags = (get_option('debug') ? ['-g'] : [])
4466if get_option('optimization') != 'plain'
4467  option_cflags += ['-O' + get_option('optimization')]
4468endif
4469summary_info += {'CFLAGS':            ' '.join(get_option('c_args') + option_cflags)}
4470if 'cpp' in all_languages
4471  summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args') + option_cflags)}
4472endif
4473if 'objc' in all_languages
4474  summary_info += {'OBJCFLAGS':       ' '.join(get_option('objc_args') + option_cflags)}
4475endif
4476link_args = get_option('c_link_args')
4477if link_args.length() > 0
4478  summary_info += {'LDFLAGS':         ' '.join(link_args)}
4479endif
4480summary_info += {'QEMU_CFLAGS':       ' '.join(qemu_common_flags + qemu_cflags)}
4481if 'cpp' in all_languages
4482  summary_info += {'QEMU_CXXFLAGS':     ' '.join(qemu_common_flags + qemu_cxxflags)}
4483endif
4484if 'objc' in all_languages
4485  summary_info += {'QEMU_OBJCFLAGS':    ' '.join(qemu_common_flags)}
4486endif
4487summary_info += {'QEMU_LDFLAGS':      ' '.join(qemu_ldflags)}
4488summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
4489summary_info += {'PIE':               get_option('b_pie')}
4490summary_info += {'static build':      get_option('prefer_static')}
4491summary_info += {'malloc trim support': has_malloc_trim}
4492summary_info += {'membarrier':        have_membarrier}
4493summary_info += {'debug graph lock':  get_option('debug_graph_lock')}
4494summary_info += {'debug stack usage': get_option('debug_stack_usage')}
4495summary_info += {'mutex debugging':   get_option('debug_mutex')}
4496summary_info += {'memory allocator':  get_option('malloc')}
4497summary_info += {'avx2 optimization': config_host_data.get('CONFIG_AVX2_OPT')}
4498summary_info += {'avx512bw optimization': config_host_data.get('CONFIG_AVX512BW_OPT')}
4499summary_info += {'gcov':              get_option('b_coverage')}
4500summary_info += {'thread sanitizer':  get_option('tsan')}
4501summary_info += {'CFI support':       get_option('cfi')}
4502if get_option('cfi')
4503  summary_info += {'CFI debug support': get_option('cfi_debug')}
4504endif
4505summary_info += {'strip binaries':    get_option('strip')}
4506summary_info += {'sparse':            sparse}
4507summary_info += {'mingw32 support':   host_os == 'windows'}
4508summary(summary_info, bool_yn: true, section: 'Compilation')
4509
4510# snarf the cross-compilation information for tests
4511summary_info = {}
4512have_cross = false
4513foreach target: target_dirs
4514  tcg_mak = meson.current_build_dir() / 'tests/tcg' / target / 'config-target.mak'
4515  if fs.exists(tcg_mak)
4516    config_cross_tcg = keyval.load(tcg_mak)
4517    if 'CC' in config_cross_tcg
4518      summary_info += {config_cross_tcg['TARGET_NAME']: config_cross_tcg['CC']}
4519      have_cross = true
4520    endif
4521  endif
4522endforeach
4523if have_cross
4524  summary(summary_info, bool_yn: true, section: 'Cross compilers')
4525endif
4526
4527# Targets and accelerators
4528summary_info = {}
4529if have_system
4530  summary_info += {'KVM support':       config_all_accel.has_key('CONFIG_KVM')}
4531  summary_info += {'HVF support':       config_all_accel.has_key('CONFIG_HVF')}
4532  summary_info += {'WHPX support':      config_all_accel.has_key('CONFIG_WHPX')}
4533  summary_info += {'NVMM support':      config_all_accel.has_key('CONFIG_NVMM')}
4534  summary_info += {'Xen support':       xen.found()}
4535  if xen.found()
4536    summary_info += {'xen ctrl version':  xen.version()}
4537  endif
4538  summary_info += {'Xen emulation':     config_all_devices.has_key('CONFIG_XEN_EMU')}
4539endif
4540summary_info += {'TCG support':       config_all_accel.has_key('CONFIG_TCG')}
4541if config_all_accel.has_key('CONFIG_TCG')
4542  if get_option('tcg_interpreter')
4543    summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, slow)'}
4544  else
4545    summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
4546  endif
4547  summary_info += {'TCG plugins':       get_option('plugins')}
4548  summary_info += {'TCG debug enabled': get_option('debug_tcg')}
4549  if have_linux_user or have_bsd_user
4550    summary_info += {'syscall buffer debugging support': get_option('debug_remap')}
4551  endif
4552endif
4553summary_info += {'target list':       ' '.join(target_dirs)}
4554if have_system
4555  summary_info += {'default devices':   get_option('default_devices')}
4556  summary_info += {'out of process emulation': multiprocess_allowed}
4557  summary_info += {'vfio-user server': vfio_user_server_allowed}
4558endif
4559summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
4560
4561# Block layer
4562summary_info = {}
4563summary_info += {'coroutine backend': coroutine_backend}
4564summary_info += {'coroutine pool':    have_coroutine_pool}
4565if have_block
4566  summary_info += {'Block whitelist (rw)': get_option('block_drv_rw_whitelist')}
4567  summary_info += {'Block whitelist (ro)': get_option('block_drv_ro_whitelist')}
4568  summary_info += {'Use block whitelist in tools': get_option('block_drv_whitelist_in_tools')}
4569  summary_info += {'VirtFS (9P) support':    have_virtfs}
4570  summary_info += {'replication support': config_host_data.get('CONFIG_REPLICATION')}
4571  summary_info += {'bochs support':     get_option('bochs').allowed()}
4572  summary_info += {'cloop support':     get_option('cloop').allowed()}
4573  summary_info += {'dmg support':       get_option('dmg').allowed()}
4574  summary_info += {'qcow v1 support':   get_option('qcow1').allowed()}
4575  summary_info += {'vdi support':       get_option('vdi').allowed()}
4576  summary_info += {'vhdx support':      get_option('vhdx').allowed()}
4577  summary_info += {'vmdk support':      get_option('vmdk').allowed()}
4578  summary_info += {'vpc support':       get_option('vpc').allowed()}
4579  summary_info += {'vvfat support':     get_option('vvfat').allowed()}
4580  summary_info += {'qed support':       get_option('qed').allowed()}
4581  summary_info += {'parallels support': get_option('parallels').allowed()}
4582  summary_info += {'FUSE exports':      fuse}
4583  summary_info += {'VDUSE block exports': have_vduse_blk_export}
4584endif
4585summary(summary_info, bool_yn: true, section: 'Block layer support')
4586
4587# Crypto
4588summary_info = {}
4589summary_info += {'TLS priority':      get_option('tls_priority')}
4590summary_info += {'GNUTLS support':    gnutls}
4591if gnutls.found()
4592  summary_info += {'  GNUTLS crypto':   gnutls_crypto.found()}
4593endif
4594summary_info += {'libgcrypt':         gcrypt}
4595summary_info += {'nettle':            nettle}
4596if nettle.found()
4597   summary_info += {'  XTS':             xts != 'private'}
4598endif
4599summary_info += {'SM4 ALG support':   crypto_sm4}
4600summary_info += {'AF_ALG support':    have_afalg}
4601summary_info += {'rng-none':          get_option('rng_none')}
4602summary_info += {'Linux keyring':     have_keyring}
4603summary_info += {'Linux keyutils':    keyutils}
4604summary(summary_info, bool_yn: true, section: 'Crypto')
4605
4606# UI
4607summary_info = {}
4608if host_os == 'darwin'
4609  summary_info += {'Cocoa support':           cocoa}
4610endif
4611summary_info += {'SDL support':       sdl}
4612summary_info += {'SDL image support': sdl_image}
4613summary_info += {'GTK support':       gtk}
4614summary_info += {'pixman':            pixman}
4615summary_info += {'VTE support':       vte}
4616summary_info += {'PNG support':       png}
4617summary_info += {'VNC support':       vnc}
4618if vnc.found()
4619  summary_info += {'VNC SASL support':  sasl}
4620  summary_info += {'VNC JPEG support':  jpeg}
4621endif
4622summary_info += {'spice protocol support': spice_protocol}
4623if spice_protocol.found()
4624  summary_info += {'  spice server support': spice}
4625endif
4626summary_info += {'curses support':    curses}
4627summary_info += {'brlapi support':    brlapi}
4628summary(summary_info, bool_yn: true, section: 'User interface')
4629
4630# Graphics backends
4631summary_info = {}
4632summary_info += {'VirGL support':     virgl}
4633summary_info += {'Rutabaga support':  rutabaga}
4634summary(summary_info, bool_yn: true, section: 'Graphics backends')
4635
4636# Audio backends
4637summary_info = {}
4638if host_os not in ['darwin', 'haiku', 'windows']
4639  summary_info += {'OSS support':     oss}
4640  summary_info += {'sndio support':   sndio}
4641elif host_os == 'darwin'
4642  summary_info += {'CoreAudio support': coreaudio}
4643elif host_os == 'windows'
4644  summary_info += {'DirectSound support': dsound}
4645endif
4646if host_os == 'linux'
4647  summary_info += {'ALSA support':    alsa}
4648  summary_info += {'PulseAudio support': pulse}
4649endif
4650summary_info += {'PipeWire support':  pipewire}
4651summary_info += {'JACK support':      jack}
4652summary(summary_info, bool_yn: true, section: 'Audio backends')
4653
4654# Network backends
4655summary_info = {}
4656if host_os == 'darwin'
4657  summary_info += {'vmnet.framework support': vmnet}
4658endif
4659summary_info += {'AF_XDP support':    libxdp}
4660summary_info += {'slirp support':     slirp}
4661summary_info += {'vde support':       vde}
4662summary_info += {'netmap support':    have_netmap}
4663summary_info += {'l2tpv3 support':    have_l2tpv3}
4664summary(summary_info, bool_yn: true, section: 'Network backends')
4665
4666# Libraries
4667summary_info = {}
4668summary_info += {'libtasn1':          tasn1}
4669summary_info += {'PAM':               pam}
4670summary_info += {'iconv support':     iconv}
4671summary_info += {'blkio support':     blkio}
4672summary_info += {'curl support':      curl}
4673summary_info += {'Multipath support': mpathpersist}
4674summary_info += {'Linux AIO support': libaio}
4675summary_info += {'Linux io_uring support': linux_io_uring}
4676summary_info += {'ATTR/XATTR support': libattr}
4677summary_info += {'RDMA support':      rdma}
4678summary_info += {'fdt support':       fdt_opt == 'internal' ? 'internal' : fdt}
4679summary_info += {'libcap-ng support': libcap_ng}
4680summary_info += {'bpf support':       libbpf}
4681summary_info += {'rbd support':       rbd}
4682summary_info += {'smartcard support': cacard}
4683summary_info += {'U2F support':       u2f}
4684summary_info += {'libusb':            libusb}
4685summary_info += {'usb net redir':     usbredir}
4686summary_info += {'OpenGL support (epoxy)': opengl}
4687summary_info += {'GBM':               gbm}
4688summary_info += {'libiscsi support':  libiscsi}
4689summary_info += {'libnfs support':    libnfs}
4690if host_os == 'windows'
4691  if have_ga
4692    summary_info += {'QGA VSS support':   have_qga_vss}
4693  endif
4694endif
4695summary_info += {'seccomp support':   seccomp}
4696summary_info += {'GlusterFS support': glusterfs}
4697summary_info += {'hv-balloon support': hv_balloon}
4698summary_info += {'TPM support':       have_tpm}
4699summary_info += {'libssh support':    libssh}
4700summary_info += {'lzo support':       lzo}
4701summary_info += {'snappy support':    snappy}
4702summary_info += {'bzip2 support':     libbzip2}
4703summary_info += {'lzfse support':     liblzfse}
4704summary_info += {'zstd support':      zstd}
4705summary_info += {'Query Processing Library support': qpl}
4706summary_info += {'UADK Library support': uadk}
4707summary_info += {'qatzip support':    qatzip}
4708summary_info += {'NUMA host support': numa}
4709summary_info += {'capstone':          capstone}
4710summary_info += {'libpmem support':   libpmem}
4711summary_info += {'libdaxctl support': libdaxctl}
4712summary_info += {'libcbor support':   libcbor}
4713summary_info += {'libudev':           libudev}
4714# Dummy dependency, keep .found()
4715summary_info += {'FUSE lseek':        fuse_lseek.found()}
4716summary_info += {'selinux':           selinux}
4717summary_info += {'libdw':             libdw}
4718if host_os == 'freebsd'
4719  summary_info += {'libinotify-kqueue': inotify}
4720endif
4721summary(summary_info, bool_yn: true, section: 'Dependencies')
4722
4723if host_arch == 'unknown'
4724  message()
4725  warning('UNSUPPORTED HOST CPU')
4726  message()
4727  message('Support for CPU host architecture ' + cpu + ' is not currently')
4728  message('maintained. The QEMU project does not guarantee that QEMU will')
4729  message('compile or work on this host CPU. You can help by volunteering')
4730  message('to maintain it and providing a build host for our continuous')
4731  message('integration setup.')
4732  if get_option('tcg').allowed() and target_dirs.length() > 0
4733    message()
4734    message('configure has succeeded and you can continue to build, but')
4735    message('QEMU will use a slow interpreter to emulate the target CPU.')
4736  endif
4737elif host_arch == 'mips'
4738  message()
4739  warning('DEPRECATED HOST CPU')
4740  message()
4741  message('Support for CPU host architecture ' + cpu + ' is going to be')
4742  message('dropped as soon as the QEMU project stops supporting Debian 12')
4743  message('("Bookworm"). Going forward, the QEMU project will not guarantee')
4744  message('that QEMU will compile or work on this host CPU.')
4745endif
4746
4747if not supported_oses.contains(host_os)
4748  message()
4749  warning('UNSUPPORTED HOST OS')
4750  message()
4751  message('Support for host OS ' + host_os + 'is not currently maintained.')
4752  message('configure has succeeded and you can continue to build, but')
4753  message('the QEMU project does not guarantee that QEMU will compile or')
4754  message('work on this operating system. You can help by volunteering')
4755  message('to maintain it and providing a build host for our continuous')
4756  message('integration setup. This will ensure that future versions of QEMU')
4757  message('will keep working on ' + host_os + '.')
4758endif
4759
4760if host_arch == 'unknown' or not supported_oses.contains(host_os)
4761  message()
4762  message('If you want to help supporting QEMU on this platform, please')
4763  message('contact the developers at qemu-devel@nongnu.org.')
4764endif
4765
4766actually_reloc = get_option('relocatable')
4767# check if get_relocated_path() is actually able to relocate paths
4768if get_option('relocatable') and \
4769  not (get_option('prefix') / get_option('bindir')).startswith(get_option('prefix') / '')
4770  message()
4771  warning('bindir not included within prefix, the installation will not be relocatable.')
4772  actually_reloc = false
4773endif
4774if not actually_reloc and (host_os == 'windows' or get_option('relocatable'))
4775  if host_os == 'windows'
4776    message()
4777    warning('Windows installs should usually be relocatable.')
4778  endif
4779  message()
4780  message('QEMU will have to be installed under ' + get_option('prefix') + '.')
4781  message('Use --disable-relocatable to remove this warning.')
4782endif
4783