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