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