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