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