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