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