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