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