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