xref: /openbmc/qemu/meson.build (revision 3ef11c99)
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'))
2308  config_host_data.set('CONFIG_BLKIO_WRITE_ZEROS_FUA',
2309                       blkio.version().version_compare('>=1.4.0'))
2310endif
2311config_host_data.set('CONFIG_CURL', curl.found())
2312config_host_data.set('CONFIG_CURSES', curses.found())
2313config_host_data.set('CONFIG_GBM', gbm.found())
2314config_host_data.set('CONFIG_GIO', gio.found())
2315config_host_data.set('CONFIG_GLUSTERFS', glusterfs.found())
2316if glusterfs.found()
2317  config_host_data.set('CONFIG_GLUSTERFS_XLATOR_OPT', glusterfs.version().version_compare('>=4'))
2318  config_host_data.set('CONFIG_GLUSTERFS_DISCARD', glusterfs.version().version_compare('>=5'))
2319  config_host_data.set('CONFIG_GLUSTERFS_FALLOCATE', glusterfs.version().version_compare('>=6'))
2320  config_host_data.set('CONFIG_GLUSTERFS_ZEROFILL', glusterfs.version().version_compare('>=6'))
2321  config_host_data.set('CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT', glusterfs_ftruncate_has_stat)
2322  config_host_data.set('CONFIG_GLUSTERFS_IOCB_HAS_STAT', glusterfs_iocb_has_stat)
2323endif
2324config_host_data.set('CONFIG_GTK', gtk.found())
2325config_host_data.set('CONFIG_VTE', vte.found())
2326config_host_data.set('CONFIG_GTK_CLIPBOARD', have_gtk_clipboard)
2327config_host_data.set('CONFIG_HEXAGON_IDEF_PARSER', get_option('hexagon_idef_parser'))
2328config_host_data.set('CONFIG_LIBATTR', have_old_libattr)
2329config_host_data.set('CONFIG_LIBCAP_NG', libcap_ng.found())
2330config_host_data.set('CONFIG_EBPF', libbpf.found())
2331config_host_data.set('CONFIG_AF_XDP', libxdp.found())
2332config_host_data.set('CONFIG_LIBDAXCTL', libdaxctl.found())
2333config_host_data.set('CONFIG_LIBISCSI', libiscsi.found())
2334config_host_data.set('CONFIG_LIBNFS', libnfs.found())
2335config_host_data.set('CONFIG_LIBSSH', libssh.found())
2336config_host_data.set('CONFIG_LINUX_AIO', libaio.found())
2337config_host_data.set('CONFIG_LINUX_IO_URING', linux_io_uring.found())
2338config_host_data.set('CONFIG_LIBPMEM', libpmem.found())
2339config_host_data.set('CONFIG_MODULES', enable_modules)
2340config_host_data.set('CONFIG_NUMA', numa.found())
2341if numa.found()
2342  config_host_data.set('HAVE_NUMA_HAS_PREFERRED_MANY',
2343                       cc.has_function('numa_has_preferred_many',
2344                                       dependencies: numa))
2345endif
2346config_host_data.set('CONFIG_OPENGL', opengl.found())
2347config_host_data.set('CONFIG_PLUGIN', get_option('plugins'))
2348config_host_data.set('CONFIG_RBD', rbd.found())
2349config_host_data.set('CONFIG_RDMA', rdma.found())
2350config_host_data.set('CONFIG_RELOCATABLE', get_option('relocatable'))
2351config_host_data.set('CONFIG_SAFESTACK', get_option('safe_stack'))
2352config_host_data.set('CONFIG_SDL', sdl.found())
2353config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found())
2354config_host_data.set('CONFIG_SECCOMP', seccomp.found())
2355if seccomp.found()
2356  config_host_data.set('CONFIG_SECCOMP_SYSRAWRC', seccomp_has_sysrawrc)
2357endif
2358config_host_data.set('CONFIG_PIXMAN', pixman.found())
2359config_host_data.set('CONFIG_SLIRP', slirp.found())
2360config_host_data.set('CONFIG_SNAPPY', snappy.found())
2361config_host_data.set('CONFIG_SOLARIS', host_os == 'sunos')
2362if get_option('tcg').allowed()
2363  config_host_data.set('CONFIG_TCG', 1)
2364  config_host_data.set('CONFIG_TCG_INTERPRETER', tcg_arch == 'tci')
2365endif
2366config_host_data.set('CONFIG_TPM', have_tpm)
2367config_host_data.set('CONFIG_TSAN', get_option('tsan'))
2368config_host_data.set('CONFIG_USB_LIBUSB', libusb.found())
2369config_host_data.set('CONFIG_VDE', vde.found())
2370config_host_data.set('CONFIG_VHOST', have_vhost)
2371config_host_data.set('CONFIG_VHOST_NET', have_vhost_net)
2372config_host_data.set('CONFIG_VHOST_NET_USER', have_vhost_net_user)
2373config_host_data.set('CONFIG_VHOST_NET_VDPA', have_vhost_net_vdpa)
2374config_host_data.set('CONFIG_VHOST_KERNEL', have_vhost_kernel)
2375config_host_data.set('CONFIG_VHOST_USER', have_vhost_user)
2376config_host_data.set('CONFIG_VHOST_CRYPTO', have_vhost_user_crypto)
2377config_host_data.set('CONFIG_VHOST_VDPA', have_vhost_vdpa)
2378config_host_data.set('CONFIG_VMNET', vmnet.found())
2379config_host_data.set('CONFIG_VHOST_USER_BLK_SERVER', have_vhost_user_blk_server)
2380config_host_data.set('CONFIG_VDUSE_BLK_EXPORT', have_vduse_blk_export)
2381config_host_data.set('CONFIG_PNG', png.found())
2382config_host_data.set('CONFIG_VNC', vnc.found())
2383config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
2384config_host_data.set('CONFIG_VNC_SASL', sasl.found())
2385if virgl.found()
2386  config_host_data.set('HAVE_VIRGL_D3D_INFO_EXT',
2387                       cc.has_member('struct virgl_renderer_resource_info_ext', 'd3d_tex2d',
2388                                     prefix: '#include <virglrenderer.h>',
2389                                     dependencies: virgl))
2390endif
2391config_host_data.set('CONFIG_VIRTFS', have_virtfs)
2392config_host_data.set('CONFIG_VTE', vte.found())
2393config_host_data.set('CONFIG_XKBCOMMON', xkbcommon.found())
2394config_host_data.set('CONFIG_KEYUTILS', keyutils.found())
2395config_host_data.set('CONFIG_GETTID', has_gettid)
2396config_host_data.set('CONFIG_GNUTLS', gnutls.found())
2397config_host_data.set('CONFIG_GNUTLS_CRYPTO', gnutls_crypto.found())
2398config_host_data.set('CONFIG_TASN1', tasn1.found())
2399config_host_data.set('CONFIG_GCRYPT', gcrypt.found())
2400config_host_data.set('CONFIG_NETTLE', nettle.found())
2401config_host_data.set('CONFIG_CRYPTO_SM4', crypto_sm4.found())
2402config_host_data.set('CONFIG_HOGWEED', hogweed.found())
2403config_host_data.set('CONFIG_QEMU_PRIVATE_XTS', xts == 'private')
2404config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim)
2405config_host_data.set('CONFIG_STATX', has_statx)
2406config_host_data.set('CONFIG_STATX_MNT_ID', has_statx_mnt_id)
2407config_host_data.set('CONFIG_ZSTD', zstd.found())
2408config_host_data.set('CONFIG_QPL', qpl.found())
2409config_host_data.set('CONFIG_UADK', uadk.found())
2410config_host_data.set('CONFIG_FUSE', fuse.found())
2411config_host_data.set('CONFIG_FUSE_LSEEK', fuse_lseek.found())
2412config_host_data.set('CONFIG_SPICE_PROTOCOL', spice_protocol.found())
2413if spice_protocol.found()
2414config_host_data.set('CONFIG_SPICE_PROTOCOL_MAJOR', spice_protocol.version().split('.')[0])
2415config_host_data.set('CONFIG_SPICE_PROTOCOL_MINOR', spice_protocol.version().split('.')[1])
2416config_host_data.set('CONFIG_SPICE_PROTOCOL_MICRO', spice_protocol.version().split('.')[2])
2417endif
2418config_host_data.set('CONFIG_SPICE', spice.found())
2419config_host_data.set('CONFIG_X11', x11.found())
2420config_host_data.set('CONFIG_DBUS_DISPLAY', dbus_display)
2421config_host_data.set('CONFIG_CFI', get_option('cfi'))
2422config_host_data.set('CONFIG_SELINUX', selinux.found())
2423config_host_data.set('CONFIG_XEN_BACKEND', xen.found())
2424config_host_data.set('CONFIG_LIBDW', libdw.found())
2425if xen.found()
2426  # protect from xen.version() having less than three components
2427  xen_version = xen.version().split('.') + ['0', '0']
2428  xen_ctrl_version = xen_version[0] + \
2429    ('0' + xen_version[1]).substring(-2) + \
2430    ('0' + xen_version[2]).substring(-2)
2431  config_host_data.set('CONFIG_XEN_CTRL_INTERFACE_VERSION', xen_ctrl_version)
2432endif
2433config_host_data.set('QEMU_VERSION', '"@0@"'.format(meson.project_version()))
2434config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0])
2435config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1])
2436config_host_data.set('QEMU_VERSION_MICRO', meson.project_version().split('.')[2])
2437
2438config_host_data.set_quoted('CONFIG_HOST_DSOSUF', host_dsosuf)
2439config_host_data.set('HAVE_HOST_BLOCK_DEVICE', have_host_block_device)
2440
2441have_coroutine_pool = get_option('coroutine_pool')
2442if get_option('debug_stack_usage') and have_coroutine_pool
2443  message('Disabling coroutine pool to measure stack usage')
2444  have_coroutine_pool = false
2445endif
2446config_host_data.set('CONFIG_COROUTINE_POOL', have_coroutine_pool)
2447config_host_data.set('CONFIG_DEBUG_GRAPH_LOCK', get_option('debug_graph_lock'))
2448config_host_data.set('CONFIG_DEBUG_MUTEX', get_option('debug_mutex'))
2449config_host_data.set('CONFIG_DEBUG_STACK_USAGE', get_option('debug_stack_usage'))
2450config_host_data.set('CONFIG_DEBUG_TCG', get_option('debug_tcg'))
2451config_host_data.set('CONFIG_DEBUG_REMAP', get_option('debug_remap'))
2452config_host_data.set('CONFIG_QOM_CAST_DEBUG', get_option('qom_cast_debug'))
2453config_host_data.set('CONFIG_REPLICATION', get_option('replication').allowed())
2454config_host_data.set('CONFIG_FSFREEZE', qga_fsfreeze)
2455config_host_data.set('CONFIG_FSTRIM', qga_fstrim)
2456
2457# has_header
2458config_host_data.set('CONFIG_EPOLL', cc.has_header('sys/epoll.h'))
2459config_host_data.set('CONFIG_LINUX_MAGIC_H', cc.has_header('linux/magic.h'))
2460config_host_data.set('CONFIG_VALGRIND_H', cc.has_header('valgrind/valgrind.h'))
2461config_host_data.set('HAVE_BTRFS_H', cc.has_header('linux/btrfs.h'))
2462config_host_data.set('HAVE_DRM_H', cc.has_header('libdrm/drm.h'))
2463config_host_data.set('HAVE_PTY_H', cc.has_header('pty.h'))
2464config_host_data.set('HAVE_SYS_DISK_H', cc.has_header('sys/disk.h'))
2465config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h'))
2466config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h'))
2467if host_os == 'windows'
2468  config_host_data.set('HAVE_AFUNIX_H', cc.has_header('afunix.h'))
2469endif
2470
2471# has_function
2472config_host_data.set('CONFIG_CLOSE_RANGE', cc.has_function('close_range'))
2473config_host_data.set('CONFIG_ACCEPT4', cc.has_function('accept4'))
2474config_host_data.set('CONFIG_CLOCK_ADJTIME', cc.has_function('clock_adjtime'))
2475config_host_data.set('CONFIG_DUP3', cc.has_function('dup3'))
2476config_host_data.set('CONFIG_FALLOCATE', cc.has_function('fallocate'))
2477config_host_data.set('CONFIG_POSIX_FALLOCATE', cc.has_function('posix_fallocate'))
2478config_host_data.set('CONFIG_GETCPU', cc.has_function('getcpu', prefix: gnu_source_prefix))
2479config_host_data.set('CONFIG_SCHED_GETCPU', cc.has_function('sched_getcpu', prefix: '#include <sched.h>'))
2480# Note that we need to specify prefix: here to avoid incorrectly
2481# thinking that Windows has posix_memalign()
2482config_host_data.set('CONFIG_POSIX_MEMALIGN', cc.has_function('posix_memalign', prefix: '#include <stdlib.h>'))
2483config_host_data.set('CONFIG_ALIGNED_MALLOC', cc.has_function('_aligned_malloc'))
2484config_host_data.set('CONFIG_VALLOC', cc.has_function('valloc'))
2485config_host_data.set('CONFIG_MEMALIGN', cc.has_function('memalign'))
2486config_host_data.set('CONFIG_PPOLL', cc.has_function('ppoll'))
2487config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include <sys/uio.h>'))
2488config_host_data.set('CONFIG_PTHREAD_FCHDIR_NP', cc.has_function('pthread_fchdir_np'))
2489config_host_data.set('CONFIG_SENDFILE', cc.has_function('sendfile'))
2490config_host_data.set('CONFIG_SETNS', cc.has_function('setns') and cc.has_function('unshare'))
2491config_host_data.set('CONFIG_SYNCFS', cc.has_function('syncfs'))
2492config_host_data.set('CONFIG_SYNC_FILE_RANGE', cc.has_function('sync_file_range'))
2493config_host_data.set('CONFIG_TIMERFD', cc.has_function('timerfd_create'))
2494config_host_data.set('HAVE_COPY_FILE_RANGE', cc.has_function('copy_file_range'))
2495config_host_data.set('HAVE_GETIFADDRS', cc.has_function('getifaddrs'))
2496config_host_data.set('HAVE_GLIB_WITH_SLICE_ALLOCATOR', glib_has_gslice)
2497config_host_data.set('HAVE_OPENPTY', cc.has_function('openpty', dependencies: util))
2498config_host_data.set('HAVE_STRCHRNUL', cc.has_function('strchrnul'))
2499config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: '#include <stdlib.h>'))
2500if rbd.found()
2501  config_host_data.set('HAVE_RBD_NAMESPACE_EXISTS',
2502                       cc.has_function('rbd_namespace_exists',
2503                                       dependencies: rbd,
2504                                       prefix: '#include <rbd/librbd.h>'))
2505endif
2506if rdma.found()
2507  config_host_data.set('HAVE_IBV_ADVISE_MR',
2508                       cc.has_function('ibv_advise_mr',
2509                                       dependencies: rdma,
2510                                       prefix: '#include <infiniband/verbs.h>'))
2511endif
2512
2513have_asan_fiber = false
2514if get_option('sanitizers') and \
2515   not cc.has_function('__sanitizer_start_switch_fiber',
2516                         args: '-fsanitize=address',
2517                         prefix: '#include <sanitizer/asan_interface.h>')
2518  warning('Missing ASAN due to missing fiber annotation interface')
2519  warning('Without code annotation, the report may be inferior.')
2520else
2521  have_asan_fiber = true
2522endif
2523config_host_data.set('CONFIG_ASAN_IFACE_FIBER', have_asan_fiber)
2524
2525have_inotify_init = cc.has_header_symbol('sys/inotify.h', 'inotify_init')
2526have_inotify_init1 = cc.has_header_symbol('sys/inotify.h', 'inotify_init1')
2527inotify = not_found
2528if (have_inotify_init or have_inotify_init1) and host_os == 'freebsd'
2529  # libinotify-kqueue
2530  inotify = cc.find_library('inotify')
2531  if have_inotify_init
2532    have_inotify_init = inotify.found()
2533  endif
2534  if have_inotify_init1
2535    have_inotify_init1 = inotify.found()
2536  endif
2537endif
2538config_host_data.set('CONFIG_INOTIFY', have_inotify_init)
2539config_host_data.set('CONFIG_INOTIFY1', have_inotify_init1)
2540
2541# has_header_symbol
2542config_host_data.set('CONFIG_BLKZONED',
2543                     cc.has_header_symbol('linux/blkzoned.h', 'BLKOPENZONE'))
2544config_host_data.set('CONFIG_EPOLL_CREATE1',
2545                     cc.has_header_symbol('sys/epoll.h', 'epoll_create1'))
2546config_host_data.set('CONFIG_FALLOCATE_PUNCH_HOLE',
2547                     cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_PUNCH_HOLE') and
2548                     cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_KEEP_SIZE'))
2549config_host_data.set('CONFIG_FALLOCATE_ZERO_RANGE',
2550                     cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_ZERO_RANGE'))
2551config_host_data.set('CONFIG_FIEMAP',
2552                     cc.has_header('linux/fiemap.h') and
2553                     cc.has_header_symbol('linux/fs.h', 'FS_IOC_FIEMAP'))
2554config_host_data.set('CONFIG_GETRANDOM',
2555                     cc.has_function('getrandom') and
2556                     cc.has_header_symbol('sys/random.h', 'GRND_NONBLOCK'))
2557config_host_data.set('CONFIG_PRCTL_PR_SET_TIMERSLACK',
2558                     cc.has_header_symbol('sys/prctl.h', 'PR_SET_TIMERSLACK'))
2559config_host_data.set('CONFIG_RTNETLINK',
2560                     cc.has_header_symbol('linux/rtnetlink.h', 'IFLA_PROTO_DOWN'))
2561config_host_data.set('CONFIG_SYSMACROS',
2562                     cc.has_header_symbol('sys/sysmacros.h', 'makedev'))
2563config_host_data.set('HAVE_OPTRESET',
2564                     cc.has_header_symbol('getopt.h', 'optreset'))
2565config_host_data.set('HAVE_IPPROTO_MPTCP',
2566                     cc.has_header_symbol('netinet/in.h', 'IPPROTO_MPTCP'))
2567
2568# has_member
2569config_host_data.set('HAVE_SIGEV_NOTIFY_THREAD_ID',
2570                     cc.has_member('struct sigevent', 'sigev_notify_thread_id',
2571                                   prefix: '#include <signal.h>'))
2572config_host_data.set('HAVE_STRUCT_STAT_ST_ATIM',
2573                     cc.has_member('struct stat', 'st_atim',
2574                                   prefix: '#include <sys/stat.h>'))
2575config_host_data.set('HAVE_BLK_ZONE_REP_CAPACITY',
2576                     cc.has_member('struct blk_zone', 'capacity',
2577                                   prefix: '#include <linux/blkzoned.h>'))
2578
2579# has_type
2580config_host_data.set('CONFIG_IOVEC',
2581                     cc.has_type('struct iovec',
2582                                 prefix: '#include <sys/uio.h>'))
2583config_host_data.set('HAVE_UTMPX',
2584                     cc.has_type('struct utmpx',
2585                                 prefix: '#include <utmpx.h>'))
2586
2587config_host_data.set('CONFIG_EVENTFD', cc.links('''
2588  #include <sys/eventfd.h>
2589  int main(void) { return eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); }'''))
2590config_host_data.set('CONFIG_FDATASYNC', cc.links(gnu_source_prefix + '''
2591  #include <unistd.h>
2592  int main(void) {
2593  #if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
2594  return fdatasync(0);
2595  #else
2596  #error Not supported
2597  #endif
2598  }'''))
2599
2600has_madvise = cc.links(gnu_source_prefix + '''
2601  #include <sys/types.h>
2602  #include <sys/mman.h>
2603  #include <stddef.h>
2604  int main(void) { return madvise(NULL, 0, MADV_DONTNEED); }''')
2605missing_madvise_proto = false
2606if has_madvise
2607  # Some platforms (illumos and Solaris before Solaris 11) provide madvise()
2608  # but forget to prototype it. In this case, has_madvise will be true (the
2609  # test program links despite a compile warning). To detect the
2610  # missing-prototype case, we try again with a definitely-bogus prototype.
2611  # This will only compile if the system headers don't provide the prototype;
2612  # otherwise the conflicting prototypes will cause a compiler error.
2613  missing_madvise_proto = cc.links(gnu_source_prefix + '''
2614    #include <sys/types.h>
2615    #include <sys/mman.h>
2616    #include <stddef.h>
2617    extern int madvise(int);
2618    int main(void) { return madvise(0); }''')
2619endif
2620config_host_data.set('CONFIG_MADVISE', has_madvise)
2621config_host_data.set('HAVE_MADVISE_WITHOUT_PROTOTYPE', missing_madvise_proto)
2622
2623config_host_data.set('CONFIG_MEMFD', cc.links(gnu_source_prefix + '''
2624  #include <sys/mman.h>
2625  int main(void) { return memfd_create("foo", MFD_ALLOW_SEALING); }'''))
2626config_host_data.set('CONFIG_OPEN_BY_HANDLE', cc.links(gnu_source_prefix + '''
2627  #include <fcntl.h>
2628  #if !defined(AT_EMPTY_PATH)
2629  # error missing definition
2630  #else
2631  int main(void) { struct file_handle fh; return open_by_handle_at(0, &fh, 0); }
2632  #endif'''))
2633
2634# On Darwin posix_madvise() has the same return semantics as plain madvise(),
2635# i.e. errno is set and -1 is returned. That's not really how POSIX defines the
2636# function. On the flip side, it has madvise() which is preferred anyways.
2637if host_os != 'darwin'
2638  config_host_data.set('CONFIG_POSIX_MADVISE', cc.links(gnu_source_prefix + '''
2639    #include <sys/mman.h>
2640    #include <stddef.h>
2641    int main(void) { return posix_madvise(NULL, 0, POSIX_MADV_DONTNEED); }'''))
2642endif
2643
2644config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_W_TID', cc.links(gnu_source_prefix + '''
2645  #include <pthread.h>
2646
2647  static void *f(void *p) { return NULL; }
2648  int main(void)
2649  {
2650    pthread_t thread;
2651    pthread_create(&thread, 0, f, 0);
2652    pthread_setname_np(thread, "QEMU");
2653    return 0;
2654  }''', dependencies: threads))
2655config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_WO_TID', cc.links(gnu_source_prefix + '''
2656  #include <pthread.h>
2657
2658  static void *f(void *p) { pthread_setname_np("QEMU"); return NULL; }
2659  int main(void)
2660  {
2661    pthread_t thread;
2662    pthread_create(&thread, 0, f, 0);
2663    return 0;
2664  }''', dependencies: threads))
2665config_host_data.set('CONFIG_PTHREAD_SET_NAME_NP', cc.links(gnu_source_prefix + '''
2666  #include <pthread.h>
2667  #include <pthread_np.h>
2668
2669  static void *f(void *p) { return NULL; }
2670  int main(void)
2671  {
2672    pthread_t thread;
2673    pthread_create(&thread, 0, f, 0);
2674    pthread_set_name_np(thread, "QEMU");
2675    return 0;
2676  }''', dependencies: threads))
2677config_host_data.set('CONFIG_PTHREAD_CONDATTR_SETCLOCK', cc.links(gnu_source_prefix + '''
2678  #include <pthread.h>
2679  #include <time.h>
2680
2681  int main(void)
2682  {
2683    pthread_condattr_t attr
2684    pthread_condattr_init(&attr);
2685    pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
2686    return 0;
2687  }''', dependencies: threads))
2688config_host_data.set('CONFIG_PTHREAD_AFFINITY_NP', cc.links(gnu_source_prefix + '''
2689  #include <pthread.h>
2690
2691  static void *f(void *p) { return NULL; }
2692  int main(void)
2693  {
2694    int setsize = CPU_ALLOC_SIZE(64);
2695    pthread_t thread;
2696    cpu_set_t *cpuset;
2697    pthread_create(&thread, 0, f, 0);
2698    cpuset = CPU_ALLOC(64);
2699    CPU_ZERO_S(setsize, cpuset);
2700    pthread_setaffinity_np(thread, setsize, cpuset);
2701    pthread_getaffinity_np(thread, setsize, cpuset);
2702    CPU_FREE(cpuset);
2703    return 0;
2704  }''', dependencies: threads))
2705config_host_data.set('CONFIG_SIGNALFD', cc.links(gnu_source_prefix + '''
2706  #include <sys/signalfd.h>
2707  #include <stddef.h>
2708  int main(void) { return signalfd(-1, NULL, SFD_CLOEXEC); }'''))
2709config_host_data.set('CONFIG_SPLICE', cc.links(gnu_source_prefix + '''
2710  #include <unistd.h>
2711  #include <fcntl.h>
2712  #include <limits.h>
2713
2714  int main(void)
2715  {
2716    int len, fd = 0;
2717    len = tee(STDIN_FILENO, STDOUT_FILENO, INT_MAX, SPLICE_F_NONBLOCK);
2718    splice(STDIN_FILENO, NULL, fd, NULL, len, SPLICE_F_MOVE);
2719    return 0;
2720  }'''))
2721
2722config_host_data.set('HAVE_MLOCKALL', cc.links(gnu_source_prefix + '''
2723  #include <sys/mman.h>
2724  int main(void) {
2725    return mlockall(MCL_FUTURE);
2726  }'''))
2727
2728have_l2tpv3 = false
2729if get_option('l2tpv3').allowed() and have_system
2730  have_l2tpv3 = cc.has_type('struct mmsghdr',
2731    prefix: gnu_source_prefix + '''
2732      #include <sys/socket.h>
2733      #include <linux/ip.h>''')
2734endif
2735config_host_data.set('CONFIG_L2TPV3', have_l2tpv3)
2736
2737have_netmap = false
2738if get_option('netmap').allowed() and have_system
2739  have_netmap = cc.compiles('''
2740    #include <inttypes.h>
2741    #include <net/if.h>
2742    #include <net/netmap.h>
2743    #include <net/netmap_user.h>
2744    #if (NETMAP_API < 11) || (NETMAP_API > 15)
2745    #error
2746    #endif
2747    int main(void) { return 0; }''')
2748  if not have_netmap and get_option('netmap').enabled()
2749    error('Netmap headers not available')
2750  endif
2751endif
2752config_host_data.set('CONFIG_NETMAP', have_netmap)
2753
2754# Work around a system header bug with some kernel/XFS header
2755# versions where they both try to define 'struct fsxattr':
2756# xfs headers will not try to redefine structs from linux headers
2757# if this macro is set.
2758config_host_data.set('HAVE_FSXATTR', cc.links('''
2759  #include <linux/fs.h>
2760  struct fsxattr foo;
2761  int main(void) {
2762    return 0;
2763  }'''))
2764
2765# Some versions of Mac OS X incorrectly define SIZE_MAX
2766config_host_data.set('HAVE_BROKEN_SIZE_MAX', not cc.compiles('''
2767    #include <stdint.h>
2768    #include <stdio.h>
2769    int main(void) {
2770        return printf("%zu", SIZE_MAX);
2771    }''', args: ['-Werror']))
2772
2773# See if 64-bit atomic operations are supported.
2774# Note that without __atomic builtins, we can only
2775# assume atomic loads/stores max at pointer size.
2776config_host_data.set('CONFIG_ATOMIC64', cc.links('''
2777  #include <stdint.h>
2778  int main(void)
2779  {
2780    uint64_t x = 0, y = 0;
2781    y = __atomic_load_n(&x, __ATOMIC_RELAXED);
2782    __atomic_store_n(&x, y, __ATOMIC_RELAXED);
2783    __atomic_compare_exchange_n(&x, &y, x, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
2784    __atomic_exchange_n(&x, y, __ATOMIC_RELAXED);
2785    __atomic_fetch_add(&x, y, __ATOMIC_RELAXED);
2786    return 0;
2787  }'''))
2788
2789has_int128_type = cc.compiles('''
2790  __int128_t a;
2791  __uint128_t b;
2792  int main(void) { b = a; }''')
2793config_host_data.set('CONFIG_INT128_TYPE', has_int128_type)
2794
2795has_int128 = has_int128_type and cc.links('''
2796  __int128_t a;
2797  __uint128_t b;
2798  int main (void) {
2799    a = a + b;
2800    b = a * b;
2801    a = a * a;
2802    return 0;
2803  }''')
2804config_host_data.set('CONFIG_INT128', has_int128)
2805
2806if has_int128_type
2807  # "do we have 128-bit atomics which are handled inline and specifically not
2808  # via libatomic". The reason we can't use libatomic is documented in the
2809  # comment starting "GCC is a house divided" in include/qemu/atomic128.h.
2810  # We only care about these operations on 16-byte aligned pointers, so
2811  # force 16-byte alignment of the pointer, which may be greater than
2812  # __alignof(unsigned __int128) for the host.
2813  atomic_test_128 = '''
2814    int main(int ac, char **av) {
2815      __uint128_t *p = __builtin_assume_aligned(av[ac - 1], 16);
2816      p[1] = __atomic_load_n(&p[0], __ATOMIC_RELAXED);
2817      __atomic_store_n(&p[2], p[3], __ATOMIC_RELAXED);
2818      __atomic_compare_exchange_n(&p[4], &p[5], p[6], 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
2819      return 0;
2820    }'''
2821  has_atomic128 = cc.links(atomic_test_128)
2822
2823  config_host_data.set('CONFIG_ATOMIC128', has_atomic128)
2824
2825  if not has_atomic128
2826    # Even with __builtin_assume_aligned, the above test may have failed
2827    # without optimization enabled.  Try again with optimizations locally
2828    # enabled for the function.  See
2829    #   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107389
2830    has_atomic128_opt = cc.links('__attribute__((optimize("O1")))' + atomic_test_128)
2831    config_host_data.set('CONFIG_ATOMIC128_OPT', has_atomic128_opt)
2832
2833    if not has_atomic128_opt
2834      config_host_data.set('CONFIG_CMPXCHG128', cc.links('''
2835        int main(void)
2836        {
2837          __uint128_t x = 0, y = 0;
2838          __sync_val_compare_and_swap_16(&x, y, x);
2839          return 0;
2840        }
2841      '''))
2842    endif
2843  endif
2844endif
2845
2846config_host_data.set('CONFIG_GETAUXVAL', cc.links(gnu_source_prefix + '''
2847  #include <sys/auxv.h>
2848  int main(void) {
2849    return getauxval(AT_HWCAP) == 0;
2850  }'''))
2851
2852config_host_data.set('CONFIG_ELF_AUX_INFO', cc.links(gnu_source_prefix + '''
2853  #include <sys/auxv.h>
2854  int main(void) {
2855    unsigned long hwcap = 0;
2856    elf_aux_info(AT_HWCAP, &hwcap, sizeof(hwcap));
2857    return hwcap;
2858  }'''))
2859
2860config_host_data.set('CONFIG_USBFS', have_linux_user and cc.compiles('''
2861  #include <linux/usbdevice_fs.h>
2862
2863  #ifndef USBDEVFS_GET_CAPABILITIES
2864  #error "USBDEVFS_GET_CAPABILITIES undefined"
2865  #endif
2866
2867  #ifndef USBDEVFS_DISCONNECT_CLAIM
2868  #error "USBDEVFS_DISCONNECT_CLAIM undefined"
2869  #endif
2870
2871  int main(void) { return 0; }'''))
2872
2873have_keyring = get_option('keyring') \
2874  .require(host_os == 'linux', error_message: 'keyring is only available on Linux') \
2875  .require(cc.compiles('''
2876    #include <errno.h>
2877    #include <asm/unistd.h>
2878    #include <linux/keyctl.h>
2879    #include <sys/syscall.h>
2880    #include <unistd.h>
2881    int main(void) {
2882        return syscall(__NR_keyctl, KEYCTL_READ, 0, NULL, NULL, 0);
2883    }'''), error_message: 'keyctl syscall not available on this system').allowed()
2884config_host_data.set('CONFIG_SECRET_KEYRING', have_keyring)
2885
2886have_cpuid_h = cc.links('''
2887  #include <cpuid.h>
2888  int main(void) {
2889    unsigned a, b, c, d;
2890    unsigned max = __get_cpuid_max(0, 0);
2891
2892    if (max >= 1) {
2893        __cpuid(1, a, b, c, d);
2894    }
2895
2896    if (max >= 7) {
2897        __cpuid_count(7, 0, a, b, c, d);
2898    }
2899
2900    return 0;
2901  }''')
2902config_host_data.set('CONFIG_CPUID_H', have_cpuid_h)
2903
2904# Don't bother to advertise asm/hwprobe.h for old versions that do
2905# not contain RISCV_HWPROBE_EXT_ZBA.
2906config_host_data.set('CONFIG_ASM_HWPROBE_H',
2907                     cc.has_header_symbol('asm/hwprobe.h',
2908                                          'RISCV_HWPROBE_EXT_ZBA'))
2909
2910config_host_data.set('CONFIG_AVX2_OPT', get_option('avx2') \
2911  .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX2') \
2912  .require(cc.links('''
2913    #include <cpuid.h>
2914    #include <immintrin.h>
2915    static int __attribute__((target("avx2"))) bar(void *a) {
2916      __m256i x = *(__m256i *)a;
2917      return _mm256_testz_si256(x, x);
2918    }
2919    int main(int argc, char *argv[]) { return bar(argv[argc - 1]); }
2920  '''), error_message: 'AVX2 not available').allowed())
2921
2922config_host_data.set('CONFIG_AVX512BW_OPT', get_option('avx512bw') \
2923  .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX512BW') \
2924  .require(cc.links('''
2925    #include <cpuid.h>
2926    #include <immintrin.h>
2927    static int __attribute__((target("avx512bw"))) bar(void *a) {
2928      __m512i *x = a;
2929      __m512i res= _mm512_abs_epi8(*x);
2930      return res[1];
2931    }
2932    int main(int argc, char *argv[]) { return bar(argv[0]); }
2933  '''), error_message: 'AVX512BW not available').allowed())
2934
2935# For both AArch64 and AArch32, detect if builtins are available.
2936config_host_data.set('CONFIG_ARM_AES_BUILTIN', cc.compiles('''
2937    #include <arm_neon.h>
2938    #ifndef __ARM_FEATURE_AES
2939    __attribute__((target("+crypto")))
2940    #endif
2941    void foo(uint8x16_t *p) { *p = vaesmcq_u8(*p); }
2942  '''))
2943
2944if get_option('membarrier').disabled()
2945  have_membarrier = false
2946elif host_os == 'windows'
2947  have_membarrier = true
2948elif host_os == 'linux'
2949  have_membarrier = cc.compiles('''
2950    #include <linux/membarrier.h>
2951    #include <sys/syscall.h>
2952    #include <unistd.h>
2953    #include <stdlib.h>
2954    int main(void) {
2955        syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0);
2956        syscall(__NR_membarrier, MEMBARRIER_CMD_SHARED, 0);
2957        exit(0);
2958    }''')
2959endif
2960config_host_data.set('CONFIG_MEMBARRIER', get_option('membarrier') \
2961  .require(have_membarrier, error_message: 'membarrier system call not available') \
2962  .allowed())
2963
2964have_afalg = get_option('crypto_afalg') \
2965  .require(cc.compiles(gnu_source_prefix + '''
2966    #include <errno.h>
2967    #include <sys/types.h>
2968    #include <sys/socket.h>
2969    #include <linux/if_alg.h>
2970    int main(void) {
2971      int sock;
2972      sock = socket(AF_ALG, SOCK_SEQPACKET, 0);
2973      return sock;
2974    }
2975  '''), error_message: 'AF_ALG requested but could not be detected').allowed()
2976config_host_data.set('CONFIG_AF_ALG', have_afalg)
2977
2978config_host_data.set('CONFIG_AF_VSOCK', cc.has_header_symbol(
2979  'linux/vm_sockets.h', 'AF_VSOCK',
2980  prefix: '#include <sys/socket.h>',
2981))
2982
2983have_vss = false
2984have_vss_sdk = false # old xp/2003 SDK
2985if host_os == 'windows' and 'cpp' in all_languages
2986  have_vss = cxx.compiles('''
2987    #define __MIDL_user_allocate_free_DEFINED__
2988    #include <vss.h>
2989    int main(void) { return VSS_CTX_BACKUP; }''')
2990  have_vss_sdk = cxx.has_header('vscoordint.h')
2991endif
2992config_host_data.set('HAVE_VSS_SDK', have_vss_sdk)
2993
2994# Older versions of MinGW do not import _lock_file and _unlock_file properly.
2995# This was fixed for v6.0.0 with commit b48e3ac8969d.
2996if host_os == 'windows'
2997  config_host_data.set('HAVE__LOCK_FILE', cc.links('''
2998    #include <stdio.h>
2999    int main(void) {
3000      _lock_file(NULL);
3001      _unlock_file(NULL);
3002      return 0;
3003    }''', name: '_lock_file and _unlock_file'))
3004endif
3005
3006if host_os == 'windows'
3007  mingw_has_setjmp_longjmp = cc.links('''
3008    #include <setjmp.h>
3009    int main(void) {
3010      /*
3011       * These functions are not available in setjmp header, but may be
3012       * available at link time, from libmingwex.a.
3013       */
3014      extern int __mingw_setjmp(jmp_buf);
3015      extern void __attribute__((noreturn)) __mingw_longjmp(jmp_buf, int);
3016      jmp_buf env;
3017      __mingw_setjmp(env);
3018      __mingw_longjmp(env, 0);
3019    }
3020  ''', name: 'mingw setjmp and longjmp')
3021
3022  if cpu == 'aarch64' and not mingw_has_setjmp_longjmp
3023    error('mingw must provide setjmp/longjmp for windows-arm64')
3024  endif
3025endif
3026
3027########################
3028# Target configuration #
3029########################
3030
3031minikconf = find_program('scripts/minikconf.py')
3032
3033config_all_accel = {}
3034config_all_devices = {}
3035config_devices_mak_list = []
3036config_devices_h = {}
3037config_target_h = {}
3038config_target_mak = {}
3039
3040disassemblers = {
3041  'alpha' : ['CONFIG_ALPHA_DIS'],
3042  'avr' : ['CONFIG_AVR_DIS'],
3043  'cris' : ['CONFIG_CRIS_DIS'],
3044  'hexagon' : ['CONFIG_HEXAGON_DIS'],
3045  'hppa' : ['CONFIG_HPPA_DIS'],
3046  'i386' : ['CONFIG_I386_DIS'],
3047  'x86_64' : ['CONFIG_I386_DIS'],
3048  'm68k' : ['CONFIG_M68K_DIS'],
3049  'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
3050  'mips' : ['CONFIG_MIPS_DIS'],
3051  'or1k' : ['CONFIG_OPENRISC_DIS'],
3052  'ppc' : ['CONFIG_PPC_DIS'],
3053  'riscv' : ['CONFIG_RISCV_DIS'],
3054  'rx' : ['CONFIG_RX_DIS'],
3055  's390' : ['CONFIG_S390_DIS'],
3056  'sh4' : ['CONFIG_SH4_DIS'],
3057  'sparc' : ['CONFIG_SPARC_DIS'],
3058  'xtensa' : ['CONFIG_XTENSA_DIS'],
3059  'loongarch' : ['CONFIG_LOONGARCH_DIS'],
3060}
3061
3062have_ivshmem = config_host_data.get('CONFIG_EVENTFD')
3063host_kconfig = \
3064  (get_option('fuzzing') ? ['CONFIG_FUZZ=y'] : []) + \
3065  (have_tpm ? ['CONFIG_TPM=y'] : []) + \
3066  (pixman.found() ? ['CONFIG_PIXMAN=y'] : []) + \
3067  (spice.found() ? ['CONFIG_SPICE=y'] : []) + \
3068  (have_ivshmem ? ['CONFIG_IVSHMEM=y'] : []) + \
3069  (opengl.found() ? ['CONFIG_OPENGL=y'] : []) + \
3070  (x11.found() ? ['CONFIG_X11=y'] : []) + \
3071  (fdt.found() ? ['CONFIG_FDT=y'] : []) + \
3072  (have_vhost_user ? ['CONFIG_VHOST_USER=y'] : []) + \
3073  (have_vhost_vdpa ? ['CONFIG_VHOST_VDPA=y'] : []) + \
3074  (have_vhost_kernel ? ['CONFIG_VHOST_KERNEL=y'] : []) + \
3075  (have_virtfs ? ['CONFIG_VIRTFS=y'] : []) + \
3076  (host_os == 'linux' ? ['CONFIG_LINUX=y'] : []) + \
3077  (multiprocess_allowed ? ['CONFIG_MULTIPROCESS_ALLOWED=y'] : []) + \
3078  (vfio_user_server_allowed ? ['CONFIG_VFIO_USER_SERVER_ALLOWED=y'] : []) + \
3079  (hv_balloon ? ['CONFIG_HV_BALLOON_POSSIBLE=y'] : [])
3080
3081ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ]
3082
3083default_targets = 'CONFIG_DEFAULT_TARGETS' in config_host
3084actual_target_dirs = []
3085fdt_required = []
3086foreach target : target_dirs
3087  config_target = { 'TARGET_NAME': target.split('-')[0] }
3088  if target.endswith('linux-user')
3089    if host_os != 'linux'
3090      if default_targets
3091        continue
3092      endif
3093      error('Target @0@ is only available on a Linux host'.format(target))
3094    endif
3095    config_target += { 'CONFIG_LINUX_USER': 'y' }
3096  elif target.endswith('bsd-user')
3097    if host_os not in bsd_oses
3098      if default_targets
3099        continue
3100      endif
3101      error('Target @0@ is only available on a BSD host'.format(target))
3102    endif
3103    config_target += { 'CONFIG_BSD_USER': 'y' }
3104  elif target.endswith('softmmu')
3105    config_target += { 'CONFIG_SYSTEM_ONLY': 'y' }
3106    config_target += { 'CONFIG_SOFTMMU': 'y' }
3107  endif
3108  if target.endswith('-user')
3109    config_target += {
3110      'CONFIG_USER_ONLY': 'y',
3111      'CONFIG_QEMU_INTERP_PREFIX':
3112        get_option('interp_prefix').replace('%M', config_target['TARGET_NAME'])
3113    }
3114  endif
3115
3116  target_kconfig = []
3117  foreach sym: accelerators
3118    if sym == 'CONFIG_TCG' or target in accelerator_targets.get(sym, [])
3119      config_target += { sym: 'y' }
3120      config_all_accel += { sym: 'y' }
3121      if target in modular_tcg
3122        config_target += { 'CONFIG_TCG_MODULAR': 'y' }
3123      else
3124        config_target += { 'CONFIG_TCG_BUILTIN': 'y' }
3125      endif
3126      target_kconfig += [ sym + '=y' ]
3127    endif
3128  endforeach
3129  if target_kconfig.length() == 0
3130    if default_targets
3131      continue
3132    endif
3133    error('No accelerator available for target @0@'.format(target))
3134  endif
3135
3136  config_target += keyval.load('configs/targets' / target + '.mak')
3137  config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
3138
3139  if 'TARGET_NEED_FDT' in config_target and not fdt.found()
3140    if default_targets
3141      warning('Disabling ' + target + ' due to missing libfdt')
3142    else
3143      fdt_required += target
3144    endif
3145    continue
3146  endif
3147
3148  actual_target_dirs += target
3149
3150  # Add default keys
3151  if 'TARGET_BASE_ARCH' not in config_target
3152    config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
3153  endif
3154  if 'TARGET_ABI_DIR' not in config_target
3155    config_target += {'TARGET_ABI_DIR': config_target['TARGET_ARCH']}
3156  endif
3157  if 'TARGET_BIG_ENDIAN' not in config_target
3158    config_target += {'TARGET_BIG_ENDIAN': 'n'}
3159  endif
3160
3161  foreach k, v: disassemblers
3162    if host_arch.startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k)
3163      foreach sym: v
3164        config_target += { sym: 'y' }
3165      endforeach
3166    endif
3167  endforeach
3168
3169  config_target_data = configuration_data()
3170  foreach k, v: config_target
3171    if not k.startswith('TARGET_') and not k.startswith('CONFIG_')
3172      # do nothing
3173    elif ignored.contains(k)
3174      # do nothing
3175    elif k == 'TARGET_BASE_ARCH'
3176      # Note that TARGET_BASE_ARCH ends up in config-target.h but it is
3177      # not used to select files from sourcesets.
3178      config_target_data.set('TARGET_' + v.to_upper(), 1)
3179    elif k == 'TARGET_NAME' or k == 'CONFIG_QEMU_INTERP_PREFIX'
3180      config_target_data.set_quoted(k, v)
3181    elif v == 'y'
3182      config_target_data.set(k, 1)
3183    elif v == 'n'
3184      config_target_data.set(k, 0)
3185    else
3186      config_target_data.set(k, v)
3187    endif
3188  endforeach
3189  config_target_data.set('QEMU_ARCH',
3190                         'QEMU_ARCH_' + config_target['TARGET_BASE_ARCH'].to_upper())
3191  config_target_h += {target: configure_file(output: target + '-config-target.h',
3192                                               configuration: config_target_data)}
3193
3194  if target.endswith('-softmmu')
3195    target_kconfig += 'CONFIG_' + config_target['TARGET_ARCH'].to_upper() + '=y'
3196    target_kconfig += 'CONFIG_TARGET_BIG_ENDIAN=' + config_target['TARGET_BIG_ENDIAN']
3197
3198    config_input = meson.get_external_property(target, 'default')
3199    config_devices_mak = target + '-config-devices.mak'
3200    config_devices_mak = configure_file(
3201      input: ['configs/devices' / target / config_input + '.mak', 'Kconfig'],
3202      output: config_devices_mak,
3203      depfile: config_devices_mak + '.d',
3204      capture: true,
3205      command: [minikconf,
3206                get_option('default_devices') ? '--defconfig' : '--allnoconfig',
3207                config_devices_mak, '@DEPFILE@', '@INPUT@',
3208                host_kconfig, target_kconfig])
3209
3210    config_devices_data = configuration_data()
3211    config_devices = keyval.load(config_devices_mak)
3212    foreach k, v: config_devices
3213      config_devices_data.set(k, 1)
3214    endforeach
3215    config_devices_mak_list += config_devices_mak
3216    config_devices_h += {target: configure_file(output: target + '-config-devices.h',
3217                                                configuration: config_devices_data)}
3218    config_target += config_devices
3219    config_all_devices += config_devices
3220  endif
3221  config_target_mak += {target: config_target}
3222endforeach
3223target_dirs = actual_target_dirs
3224
3225target_configs_h = []
3226foreach target: target_dirs
3227  target_configs_h += config_target_h[target]
3228  target_configs_h += config_devices_h.get(target, [])
3229endforeach
3230genh += custom_target('config-poison.h',
3231                      input: [target_configs_h],
3232                      output: 'config-poison.h',
3233                      capture: true,
3234                      command: [find_program('scripts/make-config-poison.sh'),
3235                                target_configs_h])
3236
3237if fdt_required.length() > 0
3238  error('fdt disabled but required by targets ' + ', '.join(fdt_required))
3239endif
3240
3241###############
3242# Subprojects #
3243###############
3244
3245libvfio_user_dep = not_found
3246if have_system and vfio_user_server_allowed
3247  libvfio_user_proj = subproject('libvfio-user', required: true)
3248  libvfio_user_dep = libvfio_user_proj.get_variable('libvfio_user_dep')
3249endif
3250
3251vhost_user = not_found
3252if host_os == 'linux' and have_vhost_user
3253  libvhost_user = subproject('libvhost-user')
3254  vhost_user = libvhost_user.get_variable('vhost_user_dep')
3255endif
3256
3257libvduse = not_found
3258if have_libvduse
3259  libvduse_proj = subproject('libvduse')
3260  libvduse = libvduse_proj.get_variable('libvduse_dep')
3261endif
3262
3263#####################
3264# Generated sources #
3265#####################
3266
3267genh += configure_file(output: 'config-host.h', configuration: config_host_data)
3268
3269hxtool = find_program('scripts/hxtool')
3270shaderinclude = find_program('scripts/shaderinclude.py')
3271qapi_gen = find_program('scripts/qapi-gen.py')
3272qapi_gen_depends = [ meson.current_source_dir() / 'scripts/qapi/__init__.py',
3273                     meson.current_source_dir() / 'scripts/qapi/commands.py',
3274                     meson.current_source_dir() / 'scripts/qapi/common.py',
3275                     meson.current_source_dir() / 'scripts/qapi/error.py',
3276                     meson.current_source_dir() / 'scripts/qapi/events.py',
3277                     meson.current_source_dir() / 'scripts/qapi/expr.py',
3278                     meson.current_source_dir() / 'scripts/qapi/gen.py',
3279                     meson.current_source_dir() / 'scripts/qapi/introspect.py',
3280                     meson.current_source_dir() / 'scripts/qapi/main.py',
3281                     meson.current_source_dir() / 'scripts/qapi/parser.py',
3282                     meson.current_source_dir() / 'scripts/qapi/schema.py',
3283                     meson.current_source_dir() / 'scripts/qapi/source.py',
3284                     meson.current_source_dir() / 'scripts/qapi/types.py',
3285                     meson.current_source_dir() / 'scripts/qapi/visit.py',
3286                     meson.current_source_dir() / 'scripts/qapi-gen.py'
3287]
3288
3289tracetool = [
3290  python, files('scripts/tracetool.py'),
3291   '--backend=' + ','.join(get_option('trace_backends'))
3292]
3293tracetool_depends = files(
3294  'scripts/tracetool/backend/log.py',
3295  'scripts/tracetool/backend/__init__.py',
3296  'scripts/tracetool/backend/dtrace.py',
3297  'scripts/tracetool/backend/ftrace.py',
3298  'scripts/tracetool/backend/simple.py',
3299  'scripts/tracetool/backend/syslog.py',
3300  'scripts/tracetool/backend/ust.py',
3301  'scripts/tracetool/format/ust_events_c.py',
3302  'scripts/tracetool/format/ust_events_h.py',
3303  'scripts/tracetool/format/__init__.py',
3304  'scripts/tracetool/format/d.py',
3305  'scripts/tracetool/format/simpletrace_stap.py',
3306  'scripts/tracetool/format/c.py',
3307  'scripts/tracetool/format/h.py',
3308  'scripts/tracetool/format/log_stap.py',
3309  'scripts/tracetool/format/stap.py',
3310  'scripts/tracetool/__init__.py',
3311)
3312
3313qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
3314                    meson.current_source_dir(),
3315                    get_option('pkgversion'), meson.project_version()]
3316qemu_version = custom_target('qemu-version.h',
3317                             output: 'qemu-version.h',
3318                             command: qemu_version_cmd,
3319                             capture: true,
3320                             build_by_default: true,
3321                             build_always_stale: true)
3322genh += qemu_version
3323
3324hxdep = []
3325hx_headers = [
3326  ['qemu-options.hx', 'qemu-options.def'],
3327  ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
3328]
3329if have_system
3330  hx_headers += [
3331    ['hmp-commands.hx', 'hmp-commands.h'],
3332    ['hmp-commands-info.hx', 'hmp-commands-info.h'],
3333  ]
3334endif
3335foreach d : hx_headers
3336  hxdep += custom_target(d[1],
3337                input: files(d[0]),
3338                output: d[1],
3339                capture: true,
3340                command: [hxtool, '-h', '@INPUT0@'])
3341endforeach
3342genh += hxdep
3343
3344###############
3345# Trace files #
3346###############
3347
3348# TODO: add each directory to the subdirs from its own meson.build, once
3349# we have those
3350trace_events_subdirs = [
3351  'crypto',
3352  'qapi',
3353  'qom',
3354  'monitor',
3355  'util',
3356  'gdbstub',
3357]
3358if have_linux_user
3359  trace_events_subdirs += [ 'linux-user' ]
3360endif
3361if have_bsd_user
3362  trace_events_subdirs += [ 'bsd-user' ]
3363endif
3364if have_block
3365  trace_events_subdirs += [
3366    'authz',
3367    'block',
3368    'chardev',
3369    'io',
3370    'nbd',
3371    'scsi',
3372  ]
3373endif
3374if have_system
3375  trace_events_subdirs += [
3376    'accel/kvm',
3377    'audio',
3378    'backends',
3379    'backends/tpm',
3380    'ebpf',
3381    'hw/9pfs',
3382    'hw/acpi',
3383    'hw/adc',
3384    'hw/alpha',
3385    'hw/arm',
3386    'hw/audio',
3387    'hw/block',
3388    'hw/char',
3389    'hw/display',
3390    'hw/dma',
3391    'hw/fsi',
3392    'hw/hyperv',
3393    'hw/i2c',
3394    'hw/i386',
3395    'hw/i386/xen',
3396    'hw/i386/kvm',
3397    'hw/ide',
3398    'hw/input',
3399    'hw/intc',
3400    'hw/isa',
3401    'hw/mem',
3402    'hw/mips',
3403    'hw/misc',
3404    'hw/misc/macio',
3405    'hw/net',
3406    'hw/net/can',
3407    'hw/nubus',
3408    'hw/nvme',
3409    'hw/nvram',
3410    'hw/pci',
3411    'hw/pci-host',
3412    'hw/ppc',
3413    'hw/rtc',
3414    'hw/s390x',
3415    'hw/scsi',
3416    'hw/sd',
3417    'hw/sh4',
3418    'hw/sparc',
3419    'hw/sparc64',
3420    'hw/ssi',
3421    'hw/timer',
3422    'hw/tpm',
3423    'hw/ufs',
3424    'hw/usb',
3425    'hw/vfio',
3426    'hw/virtio',
3427    'hw/watchdog',
3428    'hw/xen',
3429    'hw/gpio',
3430    'migration',
3431    'net',
3432    'system',
3433    'ui',
3434    'hw/remote',
3435  ]
3436endif
3437if have_system or have_user
3438  trace_events_subdirs += [
3439    'accel/tcg',
3440    'hw/core',
3441    'target/arm',
3442    'target/arm/hvf',
3443    'target/hppa',
3444    'target/i386',
3445    'target/i386/kvm',
3446    'target/loongarch',
3447    'target/mips/tcg',
3448    'target/ppc',
3449    'target/riscv',
3450    'target/s390x',
3451    'target/s390x/kvm',
3452    'target/sparc',
3453  ]
3454endif
3455
3456###################
3457# Collect sources #
3458###################
3459
3460authz_ss = ss.source_set()
3461blockdev_ss = ss.source_set()
3462block_ss = ss.source_set()
3463chardev_ss = ss.source_set()
3464common_ss = ss.source_set()
3465crypto_ss = ss.source_set()
3466hwcore_ss = ss.source_set()
3467io_ss = ss.source_set()
3468qmp_ss = ss.source_set()
3469qom_ss = ss.source_set()
3470system_ss = ss.source_set()
3471specific_fuzz_ss = ss.source_set()
3472specific_ss = ss.source_set()
3473stub_ss = ss.source_set()
3474trace_ss = ss.source_set()
3475user_ss = ss.source_set()
3476util_ss = ss.source_set()
3477
3478# accel modules
3479qtest_module_ss = ss.source_set()
3480tcg_module_ss = ss.source_set()
3481
3482modules = {}
3483target_modules = {}
3484hw_arch = {}
3485target_arch = {}
3486target_system_arch = {}
3487target_user_arch = {}
3488
3489# NOTE: the trace/ subdirectory needs the qapi_trace_events variable
3490# that is filled in by qapi/.
3491subdir('qapi')
3492subdir('qobject')
3493subdir('stubs')
3494subdir('trace')
3495subdir('util')
3496subdir('qom')
3497subdir('authz')
3498subdir('crypto')
3499subdir('ui')
3500subdir('gdbstub')
3501if have_system
3502  subdir('hw')
3503else
3504  subdir('hw/core')
3505endif
3506
3507if enable_modules
3508  libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
3509  modulecommon = declare_dependency(objects: libmodulecommon.extract_all_objects(recursive: false), compile_args: '-DBUILD_DSO')
3510endif
3511
3512qom_ss = qom_ss.apply({})
3513libqom = static_library('qom', qom_ss.sources() + genh,
3514                        dependencies: [qom_ss.dependencies()],
3515                        build_by_default: false)
3516qom = declare_dependency(objects: libqom.extract_all_objects(recursive: false),
3517                         dependencies: qom_ss.dependencies())
3518
3519event_loop_base = files('event-loop-base.c')
3520event_loop_base = static_library('event-loop-base',
3521                                 sources: event_loop_base + genh,
3522                                 build_by_default: false)
3523event_loop_base = declare_dependency(objects: event_loop_base.extract_all_objects(recursive: false),
3524                                     dependencies: [qom])
3525
3526stub_ss = stub_ss.apply({})
3527
3528util_ss.add_all(trace_ss)
3529util_ss = util_ss.apply({})
3530libqemuutil = static_library('qemuutil',
3531                             build_by_default: false,
3532                             sources: util_ss.sources() + stub_ss.sources() + genh,
3533                             dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc])
3534qemuutil = declare_dependency(link_with: libqemuutil,
3535                              sources: genh + version_res,
3536                              dependencies: [event_loop_base])
3537
3538if have_system or have_user
3539  decodetree = generator(find_program('scripts/decodetree.py'),
3540                         output: 'decode-@BASENAME@.c.inc',
3541                         arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
3542  subdir('libdecnumber')
3543  subdir('target')
3544endif
3545
3546subdir('audio')
3547subdir('io')
3548subdir('chardev')
3549subdir('fsdev')
3550subdir('dump')
3551
3552if have_block
3553  block_ss.add(files(
3554    'block.c',
3555    'blockjob.c',
3556    'job.c',
3557    'qemu-io-cmds.c',
3558  ))
3559  if config_host_data.get('CONFIG_REPLICATION')
3560    block_ss.add(files('replication.c'))
3561  endif
3562
3563  subdir('nbd')
3564  subdir('scsi')
3565  subdir('block')
3566
3567  blockdev_ss.add(files(
3568    'blockdev.c',
3569    'blockdev-nbd.c',
3570    'iothread.c',
3571    'job-qmp.c',
3572  ))
3573
3574  # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
3575  # os-win32.c does not
3576  if host_os == 'windows'
3577    system_ss.add(files('os-win32.c'))
3578  else
3579    blockdev_ss.add(files('os-posix.c'))
3580  endif
3581endif
3582
3583common_ss.add(files('cpu-common.c'))
3584specific_ss.add(files('cpu-target.c'))
3585
3586subdir('system')
3587
3588# Work around a gcc bug/misfeature wherein constant propagation looks
3589# through an alias:
3590#   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99696
3591# to guess that a const variable is always zero.  Without lto, this is
3592# impossible, as the alias is restricted to page-vary-common.c.  Indeed,
3593# without lto, not even the alias is required -- we simply use different
3594# declarations in different compilation units.
3595pagevary = files('page-vary-common.c')
3596if get_option('b_lto')
3597  pagevary_flags = ['-fno-lto']
3598  if get_option('cfi')
3599    pagevary_flags += '-fno-sanitize=cfi-icall'
3600  endif
3601  pagevary = static_library('page-vary-common', sources: pagevary + genh,
3602                            c_args: pagevary_flags)
3603  pagevary = declare_dependency(link_with: pagevary)
3604endif
3605common_ss.add(pagevary)
3606specific_ss.add(files('page-target.c', 'page-vary-target.c'))
3607
3608subdir('backends')
3609subdir('disas')
3610subdir('migration')
3611subdir('monitor')
3612subdir('net')
3613subdir('replay')
3614subdir('semihosting')
3615subdir('stats')
3616subdir('tcg')
3617subdir('fpu')
3618subdir('accel')
3619subdir('plugins')
3620subdir('ebpf')
3621
3622common_user_inc = []
3623
3624subdir('common-user')
3625subdir('bsd-user')
3626subdir('linux-user')
3627
3628# needed for fuzzing binaries
3629subdir('tests/qtest/libqos')
3630subdir('tests/qtest/fuzz')
3631
3632# accel modules
3633tcg_real_module_ss = ss.source_set()
3634tcg_real_module_ss.add_all(when: 'CONFIG_TCG_MODULAR', if_true: tcg_module_ss)
3635specific_ss.add_all(when: 'CONFIG_TCG_BUILTIN', if_true: tcg_module_ss)
3636target_modules += { 'accel' : { 'qtest': qtest_module_ss,
3637                                'tcg': tcg_real_module_ss }}
3638
3639##############################################
3640# Internal static_libraries and dependencies #
3641##############################################
3642
3643modinfo_collect = find_program('scripts/modinfo-collect.py')
3644modinfo_generate = find_program('scripts/modinfo-generate.py')
3645modinfo_files = []
3646
3647block_mods = []
3648system_mods = []
3649emulator_modules = []
3650foreach d, list : modules
3651  if not (d == 'block' ? have_block : have_system)
3652    continue
3653  endif
3654
3655  foreach m, module_ss : list
3656    if enable_modules
3657      module_ss.add(modulecommon)
3658      module_ss = module_ss.apply(config_all_devices, strict: false)
3659      sl = static_library(d + '-' + m, [genh, module_ss.sources()],
3660                          dependencies: module_ss.dependencies(), pic: true)
3661      if d == 'block'
3662        block_mods += sl
3663      else
3664        system_mods += sl
3665      endif
3666      emulator_modules += shared_module(sl.name(),
3667                    name_prefix: '',
3668                    objects: sl.extract_all_objects(recursive: false),
3669                    dependencies: module_ss.dependencies(),
3670                    install: true,
3671                    install_dir: qemu_moddir)
3672      if module_ss.sources() != []
3673        # FIXME: Should use sl.extract_all_objects(recursive: true) as
3674        # input. Sources can be used multiple times but objects are
3675        # unique when it comes to lookup in compile_commands.json.
3676        # Depnds on a mesion version with
3677        # https://github.com/mesonbuild/meson/pull/8900
3678        modinfo_files += custom_target(d + '-' + m + '.modinfo',
3679                                       output: d + '-' + m + '.modinfo',
3680                                       input: module_ss.sources() + genh,
3681                                       capture: true,
3682                                       command: [modinfo_collect, module_ss.sources()])
3683      endif
3684    else
3685      if d == 'block'
3686        block_ss.add_all(module_ss)
3687      else
3688        system_ss.add_all(module_ss)
3689      endif
3690    endif
3691  endforeach
3692endforeach
3693
3694foreach d, list : target_modules
3695  foreach m, module_ss : list
3696    if enable_modules
3697      module_ss.add(modulecommon)
3698      foreach target : target_dirs
3699        if target.endswith('-softmmu')
3700          config_target = config_target_mak[target]
3701          target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3702          c_args = ['-DCOMPILING_PER_TARGET',
3703                    '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3704                    '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3705          target_module_ss = module_ss.apply(config_target, strict: false)
3706          if target_module_ss.sources() != []
3707            module_name = d + '-' + m + '-' + config_target['TARGET_NAME']
3708            sl = static_library(module_name,
3709                                [genh, target_module_ss.sources()],
3710                                dependencies: target_module_ss.dependencies(),
3711                                include_directories: target_inc,
3712                                c_args: c_args,
3713                                pic: true)
3714            system_mods += sl
3715            emulator_modules += shared_module(sl.name(),
3716                    name_prefix: '',
3717                    objects: sl.extract_all_objects(recursive: false),
3718                    dependencies: target_module_ss.dependencies(),
3719                    install: true,
3720                    install_dir: qemu_moddir)
3721            # FIXME: Should use sl.extract_all_objects(recursive: true) too.
3722            modinfo_files += custom_target(module_name + '.modinfo',
3723                                           output: module_name + '.modinfo',
3724                                           input: target_module_ss.sources() + genh,
3725                                           capture: true,
3726                                           command: [modinfo_collect, '--target', target, target_module_ss.sources()])
3727          endif
3728        endif
3729      endforeach
3730    else
3731      specific_ss.add_all(module_ss)
3732    endif
3733  endforeach
3734endforeach
3735
3736if enable_modules
3737  foreach target : target_dirs
3738    if target.endswith('-softmmu')
3739      config_target = config_target_mak[target]
3740      config_devices_mak = target + '-config-devices.mak'
3741      modinfo_src = custom_target('modinfo-' + target + '.c',
3742                                  output: 'modinfo-' + target + '.c',
3743                                  input: modinfo_files,
3744                                  command: [modinfo_generate, '--devices', config_devices_mak, '@INPUT@'],
3745                                  capture: true)
3746
3747      modinfo_lib = static_library('modinfo-' + target + '.c', modinfo_src)
3748      modinfo_dep = declare_dependency(link_with: modinfo_lib)
3749
3750      arch = config_target['TARGET_NAME'] == 'sparc64' ? 'sparc64' : config_target['TARGET_BASE_ARCH']
3751      hw_arch[arch].add(modinfo_dep)
3752    endif
3753  endforeach
3754
3755  if emulator_modules.length() > 0
3756    alias_target('modules', emulator_modules)
3757  endif
3758endif
3759
3760nm = find_program('nm')
3761undefsym = find_program('scripts/undefsym.py')
3762block_syms = custom_target('block.syms', output: 'block.syms',
3763                             input: [libqemuutil, block_mods],
3764                             capture: true,
3765                             command: [undefsym, nm, '@INPUT@'])
3766qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
3767                             input: [libqemuutil, system_mods],
3768                             capture: true,
3769                             command: [undefsym, nm, '@INPUT@'])
3770
3771authz_ss = authz_ss.apply({})
3772libauthz = static_library('authz', authz_ss.sources() + genh,
3773                          dependencies: [authz_ss.dependencies()],
3774                          build_by_default: false)
3775
3776authz = declare_dependency(objects: libauthz.extract_all_objects(recursive: false),
3777                           dependencies: [authz_ss.dependencies(), qom])
3778
3779crypto_ss = crypto_ss.apply({})
3780libcrypto = static_library('crypto', crypto_ss.sources() + genh,
3781                           dependencies: [crypto_ss.dependencies()],
3782                           build_by_default: false)
3783
3784crypto = declare_dependency(objects: libcrypto.extract_all_objects(recursive: false),
3785                            dependencies: [crypto_ss.dependencies(), authz, qom])
3786
3787io_ss = io_ss.apply({})
3788libio = static_library('io', io_ss.sources() + genh,
3789                       dependencies: [io_ss.dependencies()],
3790                       link_with: libqemuutil,
3791                       build_by_default: false)
3792
3793io = declare_dependency(objects: libio.extract_all_objects(recursive: false),
3794                        dependencies: [io_ss.dependencies(), crypto, qom])
3795
3796libmigration = static_library('migration', sources: migration_files + genh,
3797                              build_by_default: false)
3798migration = declare_dependency(objects: libmigration.extract_all_objects(recursive: false),
3799                               dependencies: [qom, io])
3800system_ss.add(migration)
3801
3802block_ss = block_ss.apply({})
3803libblock = static_library('block', block_ss.sources() + genh,
3804                          dependencies: block_ss.dependencies(),
3805                          build_by_default: false)
3806
3807block = declare_dependency(objects: libblock.extract_all_objects(recursive: false),
3808                           dependencies: [block_ss.dependencies(), crypto, io])
3809
3810blockdev_ss = blockdev_ss.apply({})
3811libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
3812                             dependencies: blockdev_ss.dependencies(),
3813                             build_by_default: false)
3814
3815blockdev = declare_dependency(objects: libblockdev.extract_all_objects(recursive: false),
3816                              dependencies: [blockdev_ss.dependencies(), block, event_loop_base])
3817
3818qmp_ss = qmp_ss.apply({})
3819libqmp = static_library('qmp', qmp_ss.sources() + genh,
3820                        dependencies: qmp_ss.dependencies(),
3821                        build_by_default: false)
3822
3823qmp = declare_dependency(objects: libqmp.extract_all_objects(recursive: false),
3824                         dependencies: qmp_ss.dependencies())
3825
3826libchardev = static_library('chardev', chardev_ss.sources() + genh,
3827                            dependencies: chardev_ss.dependencies(),
3828                            build_by_default: false)
3829
3830chardev = declare_dependency(objects: libchardev.extract_all_objects(recursive: false),
3831                             dependencies: chardev_ss.dependencies())
3832
3833hwcore_ss = hwcore_ss.apply({})
3834libhwcore = static_library('hwcore', sources: hwcore_ss.sources() + genh,
3835                           build_by_default: false)
3836hwcore = declare_dependency(objects: libhwcore.extract_all_objects(recursive: false))
3837common_ss.add(hwcore)
3838
3839###########
3840# Targets #
3841###########
3842
3843system_ss.add(authz, blockdev, chardev, crypto, io, qmp)
3844common_ss.add(qom, qemuutil)
3845
3846common_ss.add_all(when: 'CONFIG_SYSTEM_ONLY', if_true: [system_ss])
3847common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
3848
3849# Note that this library is never used directly (only through extract_objects)
3850# and is not built by default; therefore, source files not used by the build
3851# configuration will be in build.ninja, but are never built by default.
3852common_all = static_library('common',
3853                            build_by_default: false,
3854                            sources: common_ss.all_sources() + genh,
3855                            include_directories: common_user_inc,
3856                            implicit_include_directories: false,
3857                            dependencies: common_ss.all_dependencies())
3858
3859feature_to_c = find_program('scripts/feature_to_c.py')
3860
3861if host_os == 'darwin'
3862  entitlement = find_program('scripts/entitlement.sh')
3863endif
3864
3865traceable = []
3866emulators = {}
3867foreach target : target_dirs
3868  config_target = config_target_mak[target]
3869  target_name = config_target['TARGET_NAME']
3870  target_base_arch = config_target['TARGET_BASE_ARCH']
3871  arch_srcs = [config_target_h[target]]
3872  arch_deps = []
3873  c_args = ['-DCOMPILING_PER_TARGET',
3874            '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3875            '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3876  link_args = emulator_link_args
3877
3878  target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3879  if host_os == 'linux'
3880    target_inc += include_directories('linux-headers', is_system: true)
3881  endif
3882  if target.endswith('-softmmu')
3883    target_type='system'
3884    t = target_system_arch[target_base_arch].apply(config_target, strict: false)
3885    arch_srcs += t.sources()
3886    arch_deps += t.dependencies()
3887
3888    hw_dir = target_name == 'sparc64' ? 'sparc64' : target_base_arch
3889    if hw_arch.has_key(hw_dir)
3890      hw = hw_arch[hw_dir].apply(config_target, strict: false)
3891      arch_srcs += hw.sources()
3892      arch_deps += hw.dependencies()
3893    endif
3894
3895    arch_srcs += config_devices_h[target]
3896    link_args += ['@block.syms', '@qemu.syms']
3897  else
3898    abi = config_target['TARGET_ABI_DIR']
3899    target_type='user'
3900    target_inc += common_user_inc
3901    if target_base_arch in target_user_arch
3902      t = target_user_arch[target_base_arch].apply(config_target, strict: false)
3903      arch_srcs += t.sources()
3904      arch_deps += t.dependencies()
3905    endif
3906    if 'CONFIG_LINUX_USER' in config_target
3907      base_dir = 'linux-user'
3908    endif
3909    if 'CONFIG_BSD_USER' in config_target
3910      base_dir = 'bsd-user'
3911      target_inc += include_directories('bsd-user/' / host_os)
3912      target_inc += include_directories('bsd-user/host/' / host_arch)
3913      dir = base_dir / abi
3914      arch_srcs += files(dir / 'signal.c', dir / 'target_arch_cpu.c')
3915    endif
3916    target_inc += include_directories(
3917      base_dir,
3918      base_dir / abi,
3919    )
3920    if 'CONFIG_LINUX_USER' in config_target
3921      dir = base_dir / abi
3922      arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
3923      if config_target.has_key('TARGET_SYSTBL_ABI')
3924        arch_srcs += \
3925          syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
3926                                             extra_args : config_target['TARGET_SYSTBL_ABI'])
3927      endif
3928    endif
3929  endif
3930
3931  if 'TARGET_XML_FILES' in config_target
3932    gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
3933                                output: target + '-gdbstub-xml.c',
3934                                input: files(config_target['TARGET_XML_FILES'].split()),
3935                                command: [feature_to_c, '@INPUT@'],
3936                                capture: true)
3937    arch_srcs += gdbstub_xml
3938  endif
3939
3940  t = target_arch[target_base_arch].apply(config_target, strict: false)
3941  arch_srcs += t.sources()
3942  arch_deps += t.dependencies()
3943
3944  target_common = common_ss.apply(config_target, strict: false)
3945  objects = common_all.extract_objects(target_common.sources())
3946  arch_deps += target_common.dependencies()
3947
3948  target_specific = specific_ss.apply(config_target, strict: false)
3949  arch_srcs += target_specific.sources()
3950  arch_deps += target_specific.dependencies()
3951
3952  # allow using headers from the dependencies but do not include the sources,
3953  # because this emulator only needs those in "objects".  For external
3954  # dependencies, the full dependency is included below in the executable.
3955  lib_deps = []
3956  foreach dep : arch_deps
3957    lib_deps += dep.partial_dependency(compile_args: true, includes: true)
3958  endforeach
3959
3960  lib = static_library('qemu-' + target,
3961                 sources: arch_srcs + genh,
3962                 dependencies: lib_deps,
3963                 objects: objects,
3964                 include_directories: target_inc,
3965                 c_args: c_args,
3966                 build_by_default: false)
3967
3968  if target.endswith('-softmmu')
3969    execs = [{
3970      'name': 'qemu-system-' + target_name,
3971      'win_subsystem': 'console',
3972      'sources': files('system/main.c'),
3973      'dependencies': []
3974    }]
3975    if host_os == 'windows' and (sdl.found() or gtk.found())
3976      execs += [{
3977        'name': 'qemu-system-' + target_name + 'w',
3978        'win_subsystem': 'windows',
3979        'sources': files('system/main.c'),
3980        'dependencies': []
3981      }]
3982    endif
3983    if get_option('fuzzing')
3984      specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
3985      execs += [{
3986        'name': 'qemu-fuzz-' + target_name,
3987        'win_subsystem': 'console',
3988        'sources': specific_fuzz.sources(),
3989        'dependencies': specific_fuzz.dependencies(),
3990      }]
3991    endif
3992  else
3993    execs = [{
3994      'name': 'qemu-' + target_name,
3995      'win_subsystem': 'console',
3996      'sources': [],
3997      'dependencies': []
3998    }]
3999  endif
4000  foreach exe: execs
4001    exe_name = exe['name']
4002    if host_os == 'darwin'
4003      exe_name += '-unsigned'
4004    endif
4005
4006    emulator = executable(exe_name, exe['sources'],
4007               install: true,
4008               c_args: c_args,
4009               dependencies: arch_deps + exe['dependencies'],
4010               objects: lib.extract_all_objects(recursive: true),
4011               link_depends: [block_syms, qemu_syms],
4012               link_args: link_args,
4013               win_subsystem: exe['win_subsystem'])
4014
4015    if host_os == 'darwin'
4016      icon = 'pc-bios/qemu.rsrc'
4017      build_input = [emulator, files(icon)]
4018      install_input = [
4019        get_option('bindir') / exe_name,
4020        meson.current_source_dir() / icon
4021      ]
4022      if 'CONFIG_HVF' in config_target
4023        entitlements = 'accel/hvf/entitlements.plist'
4024        build_input += files(entitlements)
4025        install_input += meson.current_source_dir() / entitlements
4026      endif
4027
4028      emulators += {exe['name'] : custom_target(exe['name'],
4029                   input: build_input,
4030                   output: exe['name'],
4031                   command: [entitlement, '@OUTPUT@', '@INPUT@'])
4032      }
4033
4034      meson.add_install_script(entitlement, '--install',
4035                               get_option('bindir') / exe['name'],
4036                               install_input)
4037    else
4038      emulators += {exe['name']: emulator}
4039    endif
4040
4041    traceable += [{
4042      'exe': exe['name'],
4043      'probe-prefix': 'qemu.' + target_type + '.' + target_name,
4044    }]
4045
4046  endforeach
4047endforeach
4048
4049# Other build targets
4050
4051if get_option('plugins')
4052  install_headers('include/qemu/qemu-plugin.h')
4053  if host_os == 'windows'
4054    # On windows, we want to deliver the qemu_plugin_api.lib file in the qemu installer,
4055    # so that plugin authors can compile against it.
4056    install_data(win32_qemu_plugin_api_lib, install_dir: 'lib')
4057  endif
4058endif
4059
4060subdir('qga')
4061
4062# Don't build qemu-keymap if xkbcommon is not explicitly enabled
4063# when we don't build tools or system
4064if xkbcommon.found()
4065  # used for the update-keymaps target, so include rules even if !have_tools
4066  qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
4067                           dependencies: [qemuutil, xkbcommon], install: have_tools)
4068endif
4069
4070if have_tools
4071  qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
4072             link_args: '@block.syms', link_depends: block_syms,
4073             dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
4074  qemu_io = executable('qemu-io', files('qemu-io.c'),
4075             link_args: '@block.syms', link_depends: block_syms,
4076             dependencies: [block, qemuutil], install: true)
4077  qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
4078               link_args: '@block.syms', link_depends: block_syms,
4079               dependencies: [blockdev, qemuutil, selinux],
4080               install: true)
4081
4082  subdir('storage-daemon')
4083
4084  foreach exe: [ 'qemu-img', 'qemu-io', 'qemu-nbd', 'qemu-storage-daemon']
4085    traceable += [{
4086      'exe': exe,
4087      'probe-prefix': 'qemu.' + exe.substring(5).replace('-', '_')
4088    }]
4089  endforeach
4090
4091  subdir('contrib/elf2dmp')
4092
4093  executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
4094             dependencies: qemuutil,
4095             install: true)
4096
4097  if have_vhost_user
4098    subdir('contrib/vhost-user-blk')
4099    subdir('contrib/vhost-user-gpu')
4100    subdir('contrib/vhost-user-input')
4101    subdir('contrib/vhost-user-scsi')
4102  endif
4103
4104  if host_os == 'linux'
4105    executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
4106               dependencies: [qemuutil, libcap_ng],
4107               install: true,
4108               install_dir: get_option('libexecdir'))
4109
4110    executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
4111               dependencies: [authz, crypto, io, qom, qemuutil,
4112                              libcap_ng, mpathpersist],
4113               install: true)
4114
4115    if cpu in ['x86', 'x86_64']
4116      executable('qemu-vmsr-helper', files('tools/i386/qemu-vmsr-helper.c'),
4117               dependencies: [authz, crypto, io, qom, qemuutil,
4118                              libcap_ng, mpathpersist],
4119               install: true)
4120    endif
4121  endif
4122
4123  if have_ivshmem
4124    subdir('contrib/ivshmem-client')
4125    subdir('contrib/ivshmem-server')
4126  endif
4127endif
4128
4129if stap.found()
4130  foreach t: traceable
4131    foreach stp: [
4132      {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / t['exe'], 'install': false},
4133      {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / t['exe'], 'install': true},
4134      {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
4135      {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
4136    ]
4137      cmd = [
4138        tracetool, '--group=all', '--format=' + stp['fmt'],
4139        '--binary=' + stp['bin'],
4140        '--probe-prefix=' + t['probe-prefix'],
4141        '@INPUT@', '@OUTPUT@'
4142      ]
4143
4144      custom_target(t['exe'] + stp['ext'],
4145                    input: trace_events_all,
4146                    output: t['exe'] + stp['ext'],
4147                    install: stp['install'],
4148                    install_dir: get_option('datadir') / 'systemtap/tapset',
4149                    command: cmd,
4150                    depend_files: tracetool_depends)
4151    endforeach
4152  endforeach
4153endif
4154
4155subdir('scripts')
4156subdir('tools')
4157subdir('pc-bios')
4158subdir('docs')
4159subdir('tests')
4160if gtk.found()
4161  subdir('po')
4162endif
4163
4164if host_machine.system() == 'windows'
4165  nsis_cmd = [
4166    find_program('scripts/nsis.py'),
4167    '@OUTPUT@',
4168    get_option('prefix'),
4169    meson.current_source_dir(),
4170    glib_pc.get_variable('bindir'),
4171    host_machine.cpu(),
4172    '--',
4173    '-DDISPLAYVERSION=' + meson.project_version(),
4174  ]
4175  if build_docs
4176    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
4177  endif
4178  if gtk.found()
4179    nsis_cmd += '-DCONFIG_GTK=y'
4180  endif
4181
4182  nsis = custom_target('nsis',
4183                       output: 'qemu-setup-' + meson.project_version() + '.exe',
4184                       input: files('qemu.nsi'),
4185                       build_always_stale: true,
4186                       command: nsis_cmd + ['@INPUT@'])
4187  alias_target('installer', nsis)
4188endif
4189
4190#########################
4191# Configuration summary #
4192#########################
4193
4194# Build environment
4195summary_info = {}
4196summary_info += {'Build directory':   meson.current_build_dir()}
4197summary_info += {'Source path':       meson.current_source_dir()}
4198summary_info += {'Download dependencies': get_option('wrap_mode') != 'nodownload'}
4199summary(summary_info, bool_yn: true, section: 'Build environment')
4200
4201# Directories
4202summary_info += {'Install prefix':    get_option('prefix')}
4203summary_info += {'BIOS directory':    qemu_datadir}
4204pathsep = host_os == 'windows' ? ';' : ':'
4205summary_info += {'firmware path':     pathsep.join(get_option('qemu_firmwarepath'))}
4206summary_info += {'binary directory':  get_option('prefix') / get_option('bindir')}
4207summary_info += {'library directory': get_option('prefix') / get_option('libdir')}
4208summary_info += {'module directory':  qemu_moddir}
4209summary_info += {'libexec directory': get_option('prefix') / get_option('libexecdir')}
4210summary_info += {'include directory': get_option('prefix') / get_option('includedir')}
4211summary_info += {'config directory':  get_option('prefix') / get_option('sysconfdir')}
4212if host_os != 'windows'
4213  summary_info += {'local state directory': get_option('prefix') / get_option('localstatedir')}
4214  summary_info += {'Manual directory':      get_option('prefix') / get_option('mandir')}
4215else
4216  summary_info += {'local state directory': 'queried at runtime'}
4217endif
4218summary_info += {'Doc directory':     get_option('prefix') / get_option('docdir')}
4219summary(summary_info, bool_yn: true, section: 'Directories')
4220
4221# Host binaries
4222summary_info = {}
4223summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
4224summary_info += {'sphinx-build':      sphinx_build}
4225
4226# FIXME: the [binaries] section of machine files, which can be probed
4227# with find_program(), would be great for passing gdb and genisoimage
4228# paths from configure to Meson.  However, there seems to be no way to
4229# hide a program (for example if gdb is too old).
4230if config_host.has_key('GDB')
4231  summary_info += {'gdb':             config_host['GDB']}
4232endif
4233summary_info += {'iasl':              iasl}
4234summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
4235if host_os == 'windows' and have_ga
4236  summary_info += {'wixl':            wixl}
4237endif
4238if slirp.found() and have_system
4239  summary_info += {'smbd':            have_slirp_smbd ? smbd_path : false}
4240endif
4241summary(summary_info, bool_yn: true, section: 'Host binaries')
4242
4243# Configurable features
4244summary_info = {}
4245summary_info += {'Documentation':     build_docs}
4246summary_info += {'system-mode emulation': have_system}
4247summary_info += {'user-mode emulation': have_user}
4248summary_info += {'block layer':       have_block}
4249summary_info += {'Install blobs':     get_option('install_blobs')}
4250summary_info += {'module support':    enable_modules}
4251if enable_modules
4252  summary_info += {'alternative module path': get_option('module_upgrades')}
4253endif
4254summary_info += {'fuzzing support':   get_option('fuzzing')}
4255if have_system
4256  summary_info += {'Audio drivers':     ' '.join(audio_drivers_selected)}
4257endif
4258summary_info += {'Trace backends':    ','.join(get_option('trace_backends'))}
4259if 'simple' in get_option('trace_backends')
4260  summary_info += {'Trace output file': get_option('trace_file') + '-<pid>'}
4261endif
4262summary_info += {'D-Bus display':     dbus_display}
4263summary_info += {'QOM debugging':     get_option('qom_cast_debug')}
4264summary_info += {'Relocatable install': get_option('relocatable')}
4265summary_info += {'vhost-kernel support': have_vhost_kernel}
4266summary_info += {'vhost-net support': have_vhost_net}
4267summary_info += {'vhost-user support': have_vhost_user}
4268summary_info += {'vhost-user-crypto support': have_vhost_user_crypto}
4269summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
4270summary_info += {'vhost-vdpa support': have_vhost_vdpa}
4271summary_info += {'build guest agent': have_ga}
4272summary(summary_info, bool_yn: true, section: 'Configurable features')
4273
4274# Compilation information
4275summary_info = {}
4276summary_info += {'host CPU':          cpu}
4277summary_info += {'host endianness':   build_machine.endian()}
4278summary_info += {'C compiler':        ' '.join(meson.get_compiler('c').cmd_array())}
4279summary_info += {'Host C compiler':   ' '.join(meson.get_compiler('c', native: true).cmd_array())}
4280if 'cpp' in all_languages
4281  summary_info += {'C++ compiler':    ' '.join(meson.get_compiler('cpp').cmd_array())}
4282else
4283  summary_info += {'C++ compiler':      false}
4284endif
4285if 'objc' in all_languages
4286  summary_info += {'Objective-C compiler': ' '.join(meson.get_compiler('objc').cmd_array())}
4287else
4288  summary_info += {'Objective-C compiler': false}
4289endif
4290option_cflags = (get_option('debug') ? ['-g'] : [])
4291if get_option('optimization') != 'plain'
4292  option_cflags += ['-O' + get_option('optimization')]
4293endif
4294summary_info += {'CFLAGS':            ' '.join(get_option('c_args') + option_cflags)}
4295if 'cpp' in all_languages
4296  summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args') + option_cflags)}
4297endif
4298if 'objc' in all_languages
4299  summary_info += {'OBJCFLAGS':       ' '.join(get_option('objc_args') + option_cflags)}
4300endif
4301link_args = get_option('c_link_args')
4302if link_args.length() > 0
4303  summary_info += {'LDFLAGS':         ' '.join(link_args)}
4304endif
4305summary_info += {'QEMU_CFLAGS':       ' '.join(qemu_common_flags + qemu_cflags)}
4306if 'cpp' in all_languages
4307  summary_info += {'QEMU_CXXFLAGS':     ' '.join(qemu_common_flags + qemu_cxxflags)}
4308endif
4309if 'objc' in all_languages
4310  summary_info += {'QEMU_OBJCFLAGS':    ' '.join(qemu_common_flags)}
4311endif
4312summary_info += {'QEMU_LDFLAGS':      ' '.join(qemu_ldflags)}
4313summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
4314summary_info += {'PIE':               get_option('b_pie')}
4315summary_info += {'static build':      get_option('prefer_static')}
4316summary_info += {'malloc trim support': has_malloc_trim}
4317summary_info += {'membarrier':        have_membarrier}
4318summary_info += {'debug graph lock':  get_option('debug_graph_lock')}
4319summary_info += {'debug stack usage': get_option('debug_stack_usage')}
4320summary_info += {'mutex debugging':   get_option('debug_mutex')}
4321summary_info += {'memory allocator':  get_option('malloc')}
4322summary_info += {'avx2 optimization': config_host_data.get('CONFIG_AVX2_OPT')}
4323summary_info += {'avx512bw optimization': config_host_data.get('CONFIG_AVX512BW_OPT')}
4324summary_info += {'gcov':              get_option('b_coverage')}
4325summary_info += {'thread sanitizer':  get_option('tsan')}
4326summary_info += {'CFI support':       get_option('cfi')}
4327if get_option('cfi')
4328  summary_info += {'CFI debug support': get_option('cfi_debug')}
4329endif
4330summary_info += {'strip binaries':    get_option('strip')}
4331summary_info += {'sparse':            sparse}
4332summary_info += {'mingw32 support':   host_os == 'windows'}
4333summary(summary_info, bool_yn: true, section: 'Compilation')
4334
4335# snarf the cross-compilation information for tests
4336summary_info = {}
4337have_cross = false
4338foreach target: target_dirs
4339  tcg_mak = meson.current_build_dir() / 'tests/tcg' / target / 'config-target.mak'
4340  if fs.exists(tcg_mak)
4341    config_cross_tcg = keyval.load(tcg_mak)
4342    if 'CC' in config_cross_tcg
4343      summary_info += {config_cross_tcg['TARGET_NAME']: config_cross_tcg['CC']}
4344      have_cross = true
4345    endif
4346  endif
4347endforeach
4348if have_cross
4349  summary(summary_info, bool_yn: true, section: 'Cross compilers')
4350endif
4351
4352# Targets and accelerators
4353summary_info = {}
4354if have_system
4355  summary_info += {'KVM support':       config_all_accel.has_key('CONFIG_KVM')}
4356  summary_info += {'HVF support':       config_all_accel.has_key('CONFIG_HVF')}
4357  summary_info += {'WHPX support':      config_all_accel.has_key('CONFIG_WHPX')}
4358  summary_info += {'NVMM support':      config_all_accel.has_key('CONFIG_NVMM')}
4359  summary_info += {'Xen support':       xen.found()}
4360  if xen.found()
4361    summary_info += {'xen ctrl version':  xen.version()}
4362  endif
4363  summary_info += {'Xen emulation':     config_all_devices.has_key('CONFIG_XEN_EMU')}
4364endif
4365summary_info += {'TCG support':       config_all_accel.has_key('CONFIG_TCG')}
4366if config_all_accel.has_key('CONFIG_TCG')
4367  if get_option('tcg_interpreter')
4368    summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, slow)'}
4369  else
4370    summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
4371  endif
4372  summary_info += {'TCG plugins':       get_option('plugins')}
4373  summary_info += {'TCG debug enabled': get_option('debug_tcg')}
4374  if have_linux_user or have_bsd_user
4375    summary_info += {'syscall buffer debugging support': get_option('debug_remap')}
4376  endif
4377endif
4378summary_info += {'target list':       ' '.join(target_dirs)}
4379if have_system
4380  summary_info += {'default devices':   get_option('default_devices')}
4381  summary_info += {'out of process emulation': multiprocess_allowed}
4382  summary_info += {'vfio-user server': vfio_user_server_allowed}
4383endif
4384summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
4385
4386# Block layer
4387summary_info = {}
4388summary_info += {'coroutine backend': coroutine_backend}
4389summary_info += {'coroutine pool':    have_coroutine_pool}
4390if have_block
4391  summary_info += {'Block whitelist (rw)': get_option('block_drv_rw_whitelist')}
4392  summary_info += {'Block whitelist (ro)': get_option('block_drv_ro_whitelist')}
4393  summary_info += {'Use block whitelist in tools': get_option('block_drv_whitelist_in_tools')}
4394  summary_info += {'VirtFS (9P) support':    have_virtfs}
4395  summary_info += {'VirtFS (9P) Proxy Helper support (deprecated)': have_virtfs_proxy_helper}
4396  summary_info += {'replication support': config_host_data.get('CONFIG_REPLICATION')}
4397  summary_info += {'bochs support':     get_option('bochs').allowed()}
4398  summary_info += {'cloop support':     get_option('cloop').allowed()}
4399  summary_info += {'dmg support':       get_option('dmg').allowed()}
4400  summary_info += {'qcow v1 support':   get_option('qcow1').allowed()}
4401  summary_info += {'vdi support':       get_option('vdi').allowed()}
4402  summary_info += {'vhdx support':      get_option('vhdx').allowed()}
4403  summary_info += {'vmdk support':      get_option('vmdk').allowed()}
4404  summary_info += {'vpc support':       get_option('vpc').allowed()}
4405  summary_info += {'vvfat support':     get_option('vvfat').allowed()}
4406  summary_info += {'qed support':       get_option('qed').allowed()}
4407  summary_info += {'parallels support': get_option('parallels').allowed()}
4408  summary_info += {'FUSE exports':      fuse}
4409  summary_info += {'VDUSE block exports': have_vduse_blk_export}
4410endif
4411summary(summary_info, bool_yn: true, section: 'Block layer support')
4412
4413# Crypto
4414summary_info = {}
4415summary_info += {'TLS priority':      get_option('tls_priority')}
4416summary_info += {'GNUTLS support':    gnutls}
4417if gnutls.found()
4418  summary_info += {'  GNUTLS crypto':   gnutls_crypto.found()}
4419endif
4420summary_info += {'libgcrypt':         gcrypt}
4421summary_info += {'nettle':            nettle}
4422if nettle.found()
4423   summary_info += {'  XTS':             xts != 'private'}
4424endif
4425summary_info += {'SM4 ALG support':   crypto_sm4}
4426summary_info += {'AF_ALG support':    have_afalg}
4427summary_info += {'rng-none':          get_option('rng_none')}
4428summary_info += {'Linux keyring':     have_keyring}
4429summary_info += {'Linux keyutils':    keyutils}
4430summary(summary_info, bool_yn: true, section: 'Crypto')
4431
4432# UI
4433summary_info = {}
4434if host_os == 'darwin'
4435  summary_info += {'Cocoa support':           cocoa}
4436endif
4437summary_info += {'SDL support':       sdl}
4438summary_info += {'SDL image support': sdl_image}
4439summary_info += {'GTK support':       gtk}
4440summary_info += {'pixman':            pixman}
4441summary_info += {'VTE support':       vte}
4442summary_info += {'PNG support':       png}
4443summary_info += {'VNC support':       vnc}
4444if vnc.found()
4445  summary_info += {'VNC SASL support':  sasl}
4446  summary_info += {'VNC JPEG support':  jpeg}
4447endif
4448summary_info += {'spice protocol support': spice_protocol}
4449if spice_protocol.found()
4450  summary_info += {'  spice server support': spice}
4451endif
4452summary_info += {'curses support':    curses}
4453summary_info += {'brlapi support':    brlapi}
4454summary(summary_info, bool_yn: true, section: 'User interface')
4455
4456# Graphics backends
4457summary_info = {}
4458summary_info += {'VirGL support':     virgl}
4459summary_info += {'Rutabaga support':  rutabaga}
4460summary(summary_info, bool_yn: true, section: 'Graphics backends')
4461
4462# Audio backends
4463summary_info = {}
4464if host_os not in ['darwin', 'haiku', 'windows']
4465  summary_info += {'OSS support':     oss}
4466  summary_info += {'sndio support':   sndio}
4467elif host_os == 'darwin'
4468  summary_info += {'CoreAudio support': coreaudio}
4469elif host_os == 'windows'
4470  summary_info += {'DirectSound support': dsound}
4471endif
4472if host_os == 'linux'
4473  summary_info += {'ALSA support':    alsa}
4474  summary_info += {'PulseAudio support': pulse}
4475endif
4476summary_info += {'PipeWire support':  pipewire}
4477summary_info += {'JACK support':      jack}
4478summary(summary_info, bool_yn: true, section: 'Audio backends')
4479
4480# Network backends
4481summary_info = {}
4482if host_os == 'darwin'
4483  summary_info += {'vmnet.framework support': vmnet}
4484endif
4485summary_info += {'AF_XDP support':    libxdp}
4486summary_info += {'slirp support':     slirp}
4487summary_info += {'vde support':       vde}
4488summary_info += {'netmap support':    have_netmap}
4489summary_info += {'l2tpv3 support':    have_l2tpv3}
4490summary(summary_info, bool_yn: true, section: 'Network backends')
4491
4492# Libraries
4493summary_info = {}
4494summary_info += {'libtasn1':          tasn1}
4495summary_info += {'PAM':               pam}
4496summary_info += {'iconv support':     iconv}
4497summary_info += {'blkio support':     blkio}
4498summary_info += {'curl support':      curl}
4499summary_info += {'Multipath support': mpathpersist}
4500summary_info += {'Linux AIO support': libaio}
4501summary_info += {'Linux io_uring support': linux_io_uring}
4502summary_info += {'ATTR/XATTR support': libattr}
4503summary_info += {'RDMA support':      rdma}
4504summary_info += {'fdt support':       fdt_opt == 'internal' ? 'internal' : fdt}
4505summary_info += {'libcap-ng support': libcap_ng}
4506summary_info += {'bpf support':       libbpf}
4507summary_info += {'rbd support':       rbd}
4508summary_info += {'smartcard support': cacard}
4509summary_info += {'U2F support':       u2f}
4510summary_info += {'libusb':            libusb}
4511summary_info += {'usb net redir':     usbredir}
4512summary_info += {'OpenGL support (epoxy)': opengl}
4513summary_info += {'GBM':               gbm}
4514summary_info += {'libiscsi support':  libiscsi}
4515summary_info += {'libnfs support':    libnfs}
4516if host_os == 'windows'
4517  if have_ga
4518    summary_info += {'QGA VSS support':   have_qga_vss}
4519  endif
4520endif
4521summary_info += {'seccomp support':   seccomp}
4522summary_info += {'GlusterFS support': glusterfs}
4523summary_info += {'hv-balloon support': hv_balloon}
4524summary_info += {'TPM support':       have_tpm}
4525summary_info += {'libssh support':    libssh}
4526summary_info += {'lzo support':       lzo}
4527summary_info += {'snappy support':    snappy}
4528summary_info += {'bzip2 support':     libbzip2}
4529summary_info += {'lzfse support':     liblzfse}
4530summary_info += {'zstd support':      zstd}
4531summary_info += {'Query Processing Library support': qpl}
4532summary_info += {'UADK Library support': uadk}
4533summary_info += {'NUMA host support': numa}
4534summary_info += {'capstone':          capstone}
4535summary_info += {'libpmem support':   libpmem}
4536summary_info += {'libdaxctl support': libdaxctl}
4537summary_info += {'libudev':           libudev}
4538# Dummy dependency, keep .found()
4539summary_info += {'FUSE lseek':        fuse_lseek.found()}
4540summary_info += {'selinux':           selinux}
4541summary_info += {'libdw':             libdw}
4542if host_os == 'freebsd'
4543  summary_info += {'libinotify-kqueue': inotify}
4544endif
4545summary(summary_info, bool_yn: true, section: 'Dependencies')
4546
4547if host_arch == 'unknown'
4548  message()
4549  warning('UNSUPPORTED HOST CPU')
4550  message()
4551  message('Support for CPU host architecture ' + cpu + ' is not currently')
4552  message('maintained. The QEMU project does not guarantee that QEMU will')
4553  message('compile or work on this host CPU. You can help by volunteering')
4554  message('to maintain it and providing a build host for our continuous')
4555  message('integration setup.')
4556  if get_option('tcg').allowed() and target_dirs.length() > 0
4557    message()
4558    message('configure has succeeded and you can continue to build, but')
4559    message('QEMU will use a slow interpreter to emulate the target CPU.')
4560  endif
4561endif
4562
4563if not supported_oses.contains(host_os)
4564  message()
4565  warning('UNSUPPORTED HOST OS')
4566  message()
4567  message('Support for host OS ' + host_os + 'is not currently maintained.')
4568  message('configure has succeeded and you can continue to build, but')
4569  message('the QEMU project does not guarantee that QEMU will compile or')
4570  message('work on this operating system. You can help by volunteering')
4571  message('to maintain it and providing a build host for our continuous')
4572  message('integration setup. This will ensure that future versions of QEMU')
4573  message('will keep working on ' + host_os + '.')
4574endif
4575
4576if host_arch == 'unknown' or not supported_oses.contains(host_os)
4577  message()
4578  message('If you want to help supporting QEMU on this platform, please')
4579  message('contact the developers at qemu-devel@nongnu.org.')
4580endif
4581
4582actually_reloc = get_option('relocatable')
4583# check if get_relocated_path() is actually able to relocate paths
4584if get_option('relocatable') and \
4585  not (get_option('prefix') / get_option('bindir')).startswith(get_option('prefix') / '')
4586  message()
4587  warning('bindir not included within prefix, the installation will not be relocatable.')
4588  actually_reloc = false
4589endif
4590if not actually_reloc and (host_os == 'windows' or get_option('relocatable'))
4591  if host_os == 'windows'
4592    message()
4593    warning('Windows installs should usually be relocatable.')
4594  endif
4595  message()
4596  message('QEMU will have to be installed under ' + get_option('prefix') + '.')
4597  message('Use --disable-relocatable to remove this warning.')
4598endif
4599