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