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