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