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