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