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