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