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