xref: /qemu/meson.build (revision a6f4d2ec)
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    fdt = cc.find_library('fdt', required: fdt_opt == 'system')
3074    if fdt.found() and cc.links('''
3075       #include <libfdt.h>
3076       #include <libfdt_env.h>
3077       int main(void) { fdt_find_max_phandle(NULL, NULL); return 0; }''',
3078         dependencies: fdt)
3079      fdt_opt = 'system'
3080    elif fdt_opt == 'system'
3081       error('system libfdt requested, but it is too old (1.5.1 or newer required)')
3082    else
3083      fdt_opt = 'internal'
3084      fdt = not_found
3085    endif
3086  endif
3087  if not fdt.found()
3088    assert(fdt_opt == 'internal')
3089    libfdt_proj = subproject('dtc', required: true,
3090                             default_options: ['tools=false',  'yaml=disabled',
3091                                               'python=disabled', 'default_library=static'])
3092    fdt = libfdt_proj.get_variable('libfdt_dep')
3093  endif
3094else
3095  fdt_opt = 'disabled'
3096endif
3097
3098config_host_data.set('CONFIG_CAPSTONE', capstone.found())
3099config_host_data.set('CONFIG_FDT', fdt.found())
3100config_host_data.set('CONFIG_SLIRP', slirp.found())
3101
3102#####################
3103# Generated sources #
3104#####################
3105
3106genh += configure_file(output: 'config-host.h', configuration: config_host_data)
3107
3108hxtool = find_program('scripts/hxtool')
3109shaderinclude = find_program('scripts/shaderinclude.py')
3110qapi_gen = find_program('scripts/qapi-gen.py')
3111qapi_gen_depends = [ meson.current_source_dir() / 'scripts/qapi/__init__.py',
3112                     meson.current_source_dir() / 'scripts/qapi/commands.py',
3113                     meson.current_source_dir() / 'scripts/qapi/common.py',
3114                     meson.current_source_dir() / 'scripts/qapi/error.py',
3115                     meson.current_source_dir() / 'scripts/qapi/events.py',
3116                     meson.current_source_dir() / 'scripts/qapi/expr.py',
3117                     meson.current_source_dir() / 'scripts/qapi/gen.py',
3118                     meson.current_source_dir() / 'scripts/qapi/introspect.py',
3119                     meson.current_source_dir() / 'scripts/qapi/main.py',
3120                     meson.current_source_dir() / 'scripts/qapi/parser.py',
3121                     meson.current_source_dir() / 'scripts/qapi/schema.py',
3122                     meson.current_source_dir() / 'scripts/qapi/source.py',
3123                     meson.current_source_dir() / 'scripts/qapi/types.py',
3124                     meson.current_source_dir() / 'scripts/qapi/visit.py',
3125                     meson.current_source_dir() / 'scripts/qapi-gen.py'
3126]
3127
3128tracetool = [
3129  python, files('scripts/tracetool.py'),
3130   '--backend=' + ','.join(get_option('trace_backends'))
3131]
3132tracetool_depends = files(
3133  'scripts/tracetool/backend/log.py',
3134  'scripts/tracetool/backend/__init__.py',
3135  'scripts/tracetool/backend/dtrace.py',
3136  'scripts/tracetool/backend/ftrace.py',
3137  'scripts/tracetool/backend/simple.py',
3138  'scripts/tracetool/backend/syslog.py',
3139  'scripts/tracetool/backend/ust.py',
3140  'scripts/tracetool/format/ust_events_c.py',
3141  'scripts/tracetool/format/ust_events_h.py',
3142  'scripts/tracetool/format/__init__.py',
3143  'scripts/tracetool/format/d.py',
3144  'scripts/tracetool/format/simpletrace_stap.py',
3145  'scripts/tracetool/format/c.py',
3146  'scripts/tracetool/format/h.py',
3147  'scripts/tracetool/format/log_stap.py',
3148  'scripts/tracetool/format/stap.py',
3149  'scripts/tracetool/__init__.py',
3150  'scripts/tracetool/vcpu.py'
3151)
3152
3153qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
3154                    meson.current_source_dir(),
3155                    get_option('pkgversion'), meson.project_version()]
3156qemu_version = custom_target('qemu-version.h',
3157                             output: 'qemu-version.h',
3158                             command: qemu_version_cmd,
3159                             capture: true,
3160                             build_by_default: true,
3161                             build_always_stale: true)
3162genh += qemu_version
3163
3164hxdep = []
3165hx_headers = [
3166  ['qemu-options.hx', 'qemu-options.def'],
3167  ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
3168]
3169if have_system
3170  hx_headers += [
3171    ['hmp-commands.hx', 'hmp-commands.h'],
3172    ['hmp-commands-info.hx', 'hmp-commands-info.h'],
3173  ]
3174endif
3175foreach d : hx_headers
3176  hxdep += custom_target(d[1],
3177                input: files(d[0]),
3178                output: d[1],
3179                capture: true,
3180                build_by_default: true, # to be removed when added to a target
3181                command: [hxtool, '-h', '@INPUT0@'])
3182endforeach
3183genh += hxdep
3184
3185###################
3186# Collect sources #
3187###################
3188
3189authz_ss = ss.source_set()
3190blockdev_ss = ss.source_set()
3191block_ss = ss.source_set()
3192chardev_ss = ss.source_set()
3193common_ss = ss.source_set()
3194crypto_ss = ss.source_set()
3195hwcore_ss = ss.source_set()
3196io_ss = ss.source_set()
3197qmp_ss = ss.source_set()
3198qom_ss = ss.source_set()
3199system_ss = ss.source_set()
3200specific_fuzz_ss = ss.source_set()
3201specific_ss = ss.source_set()
3202stub_ss = ss.source_set()
3203trace_ss = ss.source_set()
3204user_ss = ss.source_set()
3205util_ss = ss.source_set()
3206
3207# accel modules
3208qtest_module_ss = ss.source_set()
3209tcg_module_ss = ss.source_set()
3210
3211modules = {}
3212target_modules = {}
3213hw_arch = {}
3214target_arch = {}
3215target_softmmu_arch = {}
3216target_user_arch = {}
3217
3218###############
3219# Trace files #
3220###############
3221
3222# TODO: add each directory to the subdirs from its own meson.build, once
3223# we have those
3224trace_events_subdirs = [
3225  'crypto',
3226  'qapi',
3227  'qom',
3228  'monitor',
3229  'util',
3230  'gdbstub',
3231]
3232if have_linux_user
3233  trace_events_subdirs += [ 'linux-user' ]
3234endif
3235if have_bsd_user
3236  trace_events_subdirs += [ 'bsd-user' ]
3237endif
3238if have_block
3239  trace_events_subdirs += [
3240    'authz',
3241    'block',
3242    'io',
3243    'nbd',
3244    'scsi',
3245  ]
3246endif
3247if have_system
3248  trace_events_subdirs += [
3249    'accel/kvm',
3250    'audio',
3251    'backends',
3252    'backends/tpm',
3253    'chardev',
3254    'ebpf',
3255    'hw/9pfs',
3256    'hw/acpi',
3257    'hw/adc',
3258    'hw/alpha',
3259    'hw/arm',
3260    'hw/audio',
3261    'hw/block',
3262    'hw/block/dataplane',
3263    'hw/char',
3264    'hw/display',
3265    'hw/dma',
3266    'hw/hyperv',
3267    'hw/i2c',
3268    'hw/i386',
3269    'hw/i386/xen',
3270    'hw/i386/kvm',
3271    'hw/ide',
3272    'hw/input',
3273    'hw/intc',
3274    'hw/isa',
3275    'hw/mem',
3276    'hw/mips',
3277    'hw/misc',
3278    'hw/misc/macio',
3279    'hw/net',
3280    'hw/net/can',
3281    'hw/nubus',
3282    'hw/nvme',
3283    'hw/nvram',
3284    'hw/pci',
3285    'hw/pci-host',
3286    'hw/ppc',
3287    'hw/rdma',
3288    'hw/rdma/vmw',
3289    'hw/rtc',
3290    'hw/s390x',
3291    'hw/scsi',
3292    'hw/sd',
3293    'hw/sh4',
3294    'hw/sparc',
3295    'hw/sparc64',
3296    'hw/ssi',
3297    'hw/timer',
3298    'hw/tpm',
3299    'hw/ufs',
3300    'hw/usb',
3301    'hw/vfio',
3302    'hw/virtio',
3303    'hw/watchdog',
3304    'hw/xen',
3305    'hw/gpio',
3306    'migration',
3307    'net',
3308    'softmmu',
3309    'ui',
3310    'hw/remote',
3311  ]
3312endif
3313if have_system or have_user
3314  trace_events_subdirs += [
3315    'accel/tcg',
3316    'hw/core',
3317    'target/arm',
3318    'target/arm/hvf',
3319    'target/hppa',
3320    'target/i386',
3321    'target/i386/kvm',
3322    'target/mips/tcg',
3323    'target/nios2',
3324    'target/ppc',
3325    'target/riscv',
3326    'target/s390x',
3327    'target/s390x/kvm',
3328    'target/sparc',
3329  ]
3330endif
3331
3332vhost_user = not_found
3333if targetos == 'linux' and have_vhost_user
3334  libvhost_user = subproject('libvhost-user')
3335  vhost_user = libvhost_user.get_variable('vhost_user_dep')
3336endif
3337
3338libvduse = not_found
3339if have_libvduse
3340  libvduse_proj = subproject('libvduse')
3341  libvduse = libvduse_proj.get_variable('libvduse_dep')
3342endif
3343
3344# NOTE: the trace/ subdirectory needs the qapi_trace_events variable
3345# that is filled in by qapi/.
3346subdir('qapi')
3347subdir('qobject')
3348subdir('stubs')
3349subdir('trace')
3350subdir('util')
3351subdir('qom')
3352subdir('authz')
3353subdir('crypto')
3354subdir('ui')
3355subdir('hw')
3356subdir('gdbstub')
3357
3358if enable_modules
3359  libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
3360  modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
3361endif
3362
3363qom_ss = qom_ss.apply(config_targetos, strict: false)
3364libqom = static_library('qom', qom_ss.sources() + genh,
3365                        dependencies: [qom_ss.dependencies()],
3366                        name_suffix: 'fa')
3367qom = declare_dependency(link_whole: libqom)
3368
3369event_loop_base = files('event-loop-base.c')
3370event_loop_base = static_library('event-loop-base', sources: event_loop_base + genh,
3371                                 build_by_default: true)
3372event_loop_base = declare_dependency(link_whole: event_loop_base,
3373                                     dependencies: [qom])
3374
3375stub_ss = stub_ss.apply(config_all, strict: false)
3376
3377util_ss.add_all(trace_ss)
3378util_ss = util_ss.apply(config_all, strict: false)
3379libqemuutil = static_library('qemuutil',
3380                             sources: util_ss.sources() + stub_ss.sources() + genh,
3381                             dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc, pixman])
3382qemuutil = declare_dependency(link_with: libqemuutil,
3383                              sources: genh + version_res,
3384                              dependencies: [event_loop_base])
3385
3386if have_system or have_user
3387  decodetree = generator(find_program('scripts/decodetree.py'),
3388                         output: 'decode-@BASENAME@.c.inc',
3389                         arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
3390  subdir('libdecnumber')
3391  subdir('target')
3392endif
3393
3394subdir('audio')
3395subdir('io')
3396subdir('chardev')
3397subdir('fsdev')
3398subdir('dump')
3399
3400if have_block
3401  block_ss.add(files(
3402    'block.c',
3403    'blockjob.c',
3404    'job.c',
3405    'qemu-io-cmds.c',
3406  ))
3407  if config_host_data.get('CONFIG_REPLICATION')
3408    block_ss.add(files('replication.c'))
3409  endif
3410
3411  subdir('nbd')
3412  subdir('scsi')
3413  subdir('block')
3414
3415  blockdev_ss.add(files(
3416    'blockdev.c',
3417    'blockdev-nbd.c',
3418    'iothread.c',
3419    'job-qmp.c',
3420  ), gnutls)
3421
3422  # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
3423  # os-win32.c does not
3424  blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
3425  system_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
3426endif
3427
3428common_ss.add(files('cpus-common.c'))
3429specific_ss.add(files('cpu.c'))
3430
3431subdir('softmmu')
3432
3433# Work around a gcc bug/misfeature wherein constant propagation looks
3434# through an alias:
3435#   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99696
3436# to guess that a const variable is always zero.  Without lto, this is
3437# impossible, as the alias is restricted to page-vary-common.c.  Indeed,
3438# without lto, not even the alias is required -- we simply use different
3439# declarations in different compilation units.
3440pagevary = files('page-vary-common.c')
3441if get_option('b_lto')
3442  pagevary_flags = ['-fno-lto']
3443  if get_option('cfi')
3444    pagevary_flags += '-fno-sanitize=cfi-icall'
3445  endif
3446  pagevary = static_library('page-vary-common', sources: pagevary + genh,
3447                            c_args: pagevary_flags)
3448  pagevary = declare_dependency(link_with: pagevary)
3449endif
3450common_ss.add(pagevary)
3451specific_ss.add(files('page-vary.c'))
3452
3453subdir('backends')
3454subdir('disas')
3455subdir('migration')
3456subdir('monitor')
3457subdir('net')
3458subdir('replay')
3459subdir('semihosting')
3460subdir('stats')
3461subdir('tcg')
3462subdir('fpu')
3463subdir('accel')
3464subdir('plugins')
3465subdir('ebpf')
3466
3467common_user_inc = []
3468
3469subdir('common-user')
3470subdir('bsd-user')
3471subdir('linux-user')
3472
3473# needed for fuzzing binaries
3474subdir('tests/qtest/libqos')
3475subdir('tests/qtest/fuzz')
3476
3477# accel modules
3478tcg_real_module_ss = ss.source_set()
3479tcg_real_module_ss.add_all(when: 'CONFIG_TCG_MODULAR', if_true: tcg_module_ss)
3480specific_ss.add_all(when: 'CONFIG_TCG_BUILTIN', if_true: tcg_module_ss)
3481target_modules += { 'accel' : { 'qtest': qtest_module_ss,
3482                                'tcg': tcg_real_module_ss }}
3483
3484########################
3485# Library dependencies #
3486########################
3487
3488modinfo_collect = find_program('scripts/modinfo-collect.py')
3489modinfo_generate = find_program('scripts/modinfo-generate.py')
3490modinfo_files = []
3491
3492block_mods = []
3493softmmu_mods = []
3494foreach d, list : modules
3495  if not (d == 'block' ? have_block : have_system)
3496    continue
3497  endif
3498
3499  foreach m, module_ss : list
3500    if enable_modules
3501      module_ss = module_ss.apply(config_all, strict: false)
3502      sl = static_library(d + '-' + m, [genh, module_ss.sources()],
3503                          dependencies: [modulecommon, module_ss.dependencies()], pic: true)
3504      if d == 'block'
3505        block_mods += sl
3506      else
3507        softmmu_mods += sl
3508      endif
3509      if module_ss.sources() != []
3510        # FIXME: Should use sl.extract_all_objects(recursive: true) as
3511        # input. Sources can be used multiple times but objects are
3512        # unique when it comes to lookup in compile_commands.json.
3513        # Depnds on a mesion version with
3514        # https://github.com/mesonbuild/meson/pull/8900
3515        modinfo_files += custom_target(d + '-' + m + '.modinfo',
3516                                       output: d + '-' + m + '.modinfo',
3517                                       input: module_ss.sources() + genh,
3518                                       capture: true,
3519                                       command: [modinfo_collect, module_ss.sources()])
3520      endif
3521    else
3522      if d == 'block'
3523        block_ss.add_all(module_ss)
3524      else
3525        system_ss.add_all(module_ss)
3526      endif
3527    endif
3528  endforeach
3529endforeach
3530
3531foreach d, list : target_modules
3532  foreach m, module_ss : list
3533    if enable_modules
3534      foreach target : target_dirs
3535        if target.endswith('-softmmu')
3536          config_target = config_target_mak[target]
3537          config_target += config_targetos
3538          target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3539          c_args = ['-DNEED_CPU_H',
3540                    '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3541                    '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3542          target_module_ss = module_ss.apply(config_target, strict: false)
3543          if target_module_ss.sources() != []
3544            module_name = d + '-' + m + '-' + config_target['TARGET_NAME']
3545            sl = static_library(module_name,
3546                                [genh, target_module_ss.sources()],
3547                                dependencies: [modulecommon, target_module_ss.dependencies()],
3548                                include_directories: target_inc,
3549                                c_args: c_args,
3550                                pic: true)
3551            softmmu_mods += sl
3552            # FIXME: Should use sl.extract_all_objects(recursive: true) too.
3553            modinfo_files += custom_target(module_name + '.modinfo',
3554                                           output: module_name + '.modinfo',
3555                                           input: target_module_ss.sources() + genh,
3556                                           capture: true,
3557                                           command: [modinfo_collect, '--target', target, target_module_ss.sources()])
3558          endif
3559        endif
3560      endforeach
3561    else
3562      specific_ss.add_all(module_ss)
3563    endif
3564  endforeach
3565endforeach
3566
3567if enable_modules
3568  foreach target : target_dirs
3569    if target.endswith('-softmmu')
3570      config_target = config_target_mak[target]
3571      config_devices_mak = target + '-config-devices.mak'
3572      modinfo_src = custom_target('modinfo-' + target + '.c',
3573                                  output: 'modinfo-' + target + '.c',
3574                                  input: modinfo_files,
3575                                  command: [modinfo_generate, '--devices', config_devices_mak, '@INPUT@'],
3576                                  capture: true)
3577
3578      modinfo_lib = static_library('modinfo-' + target + '.c', modinfo_src)
3579      modinfo_dep = declare_dependency(link_with: modinfo_lib)
3580
3581      arch = config_target['TARGET_NAME'] == 'sparc64' ? 'sparc64' : config_target['TARGET_BASE_ARCH']
3582      hw_arch[arch].add(modinfo_dep)
3583    endif
3584  endforeach
3585endif
3586
3587nm = find_program('nm')
3588undefsym = find_program('scripts/undefsym.py')
3589block_syms = custom_target('block.syms', output: 'block.syms',
3590                             input: [libqemuutil, block_mods],
3591                             capture: true,
3592                             command: [undefsym, nm, '@INPUT@'])
3593qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
3594                             input: [libqemuutil, softmmu_mods],
3595                             capture: true,
3596                             command: [undefsym, nm, '@INPUT@'])
3597
3598authz_ss = authz_ss.apply(config_targetos, strict: false)
3599libauthz = static_library('authz', authz_ss.sources() + genh,
3600                          dependencies: [authz_ss.dependencies()],
3601                          name_suffix: 'fa',
3602                          build_by_default: false)
3603
3604authz = declare_dependency(link_whole: libauthz,
3605                           dependencies: qom)
3606
3607crypto_ss = crypto_ss.apply(config_targetos, strict: false)
3608libcrypto = static_library('crypto', crypto_ss.sources() + genh,
3609                           dependencies: [crypto_ss.dependencies()],
3610                           name_suffix: 'fa',
3611                           build_by_default: false)
3612
3613crypto = declare_dependency(link_whole: libcrypto,
3614                            dependencies: [authz, qom])
3615
3616io_ss = io_ss.apply(config_targetos, strict: false)
3617libio = static_library('io', io_ss.sources() + genh,
3618                       dependencies: [io_ss.dependencies()],
3619                       link_with: libqemuutil,
3620                       name_suffix: 'fa',
3621                       build_by_default: false)
3622
3623io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
3624
3625libmigration = static_library('migration', sources: migration_files + genh,
3626                              name_suffix: 'fa',
3627                              build_by_default: false)
3628migration = declare_dependency(link_with: libmigration,
3629                               dependencies: [zlib, qom, io])
3630system_ss.add(migration)
3631
3632block_ss = block_ss.apply(config_targetos, strict: false)
3633libblock = static_library('block', block_ss.sources() + genh,
3634                          dependencies: block_ss.dependencies(),
3635                          link_depends: block_syms,
3636                          name_suffix: 'fa',
3637                          build_by_default: false)
3638
3639block = declare_dependency(link_whole: [libblock],
3640                           link_args: '@block.syms',
3641                           dependencies: [crypto, io])
3642
3643blockdev_ss = blockdev_ss.apply(config_targetos, strict: false)
3644libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
3645                             dependencies: blockdev_ss.dependencies(),
3646                             name_suffix: 'fa',
3647                             build_by_default: false)
3648
3649blockdev = declare_dependency(link_whole: [libblockdev],
3650                              dependencies: [block, event_loop_base])
3651
3652qmp_ss = qmp_ss.apply(config_targetos, strict: false)
3653libqmp = static_library('qmp', qmp_ss.sources() + genh,
3654                        dependencies: qmp_ss.dependencies(),
3655                        name_suffix: 'fa',
3656                        build_by_default: false)
3657
3658qmp = declare_dependency(link_whole: [libqmp])
3659
3660libchardev = static_library('chardev', chardev_ss.sources() + genh,
3661                            name_suffix: 'fa',
3662                            dependencies: chardev_ss.dependencies(),
3663                            build_by_default: false)
3664
3665chardev = declare_dependency(link_whole: libchardev)
3666
3667hwcore_ss = hwcore_ss.apply(config_targetos, strict: false)
3668libhwcore = static_library('hwcore', sources: hwcore_ss.sources() + genh,
3669                           name_suffix: 'fa',
3670                           build_by_default: false)
3671hwcore = declare_dependency(link_whole: libhwcore)
3672common_ss.add(hwcore)
3673
3674###########
3675# Targets #
3676###########
3677
3678emulator_modules = []
3679foreach m : block_mods + softmmu_mods
3680  emulator_modules += shared_module(m.name(),
3681                build_by_default: true,
3682                name_prefix: '',
3683                link_whole: m,
3684                install: true,
3685                install_dir: qemu_moddir)
3686endforeach
3687if emulator_modules.length() > 0
3688  alias_target('modules', emulator_modules)
3689endif
3690
3691system_ss.add(authz, blockdev, chardev, crypto, io, qmp)
3692common_ss.add(qom, qemuutil)
3693
3694common_ss.add_all(when: 'CONFIG_SYSTEM_ONLY', if_true: [system_ss])
3695common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
3696
3697common_all = common_ss.apply(config_all, strict: false)
3698common_all = static_library('common',
3699                            build_by_default: false,
3700                            sources: common_all.sources() + genh,
3701                            include_directories: common_user_inc,
3702                            implicit_include_directories: false,
3703                            dependencies: common_all.dependencies(),
3704                            name_suffix: 'fa')
3705
3706feature_to_c = find_program('scripts/feature_to_c.sh')
3707
3708if targetos == 'darwin'
3709  entitlement = find_program('scripts/entitlement.sh')
3710endif
3711
3712emulators = {}
3713foreach target : target_dirs
3714  config_target = config_target_mak[target]
3715  target_name = config_target['TARGET_NAME']
3716  target_base_arch = config_target['TARGET_BASE_ARCH']
3717  arch_srcs = [config_target_h[target]]
3718  arch_deps = []
3719  c_args = ['-DNEED_CPU_H',
3720            '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3721            '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3722  link_args = emulator_link_args
3723
3724  config_target += config_targetos
3725  target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3726  if targetos == 'linux'
3727    target_inc += include_directories('linux-headers', is_system: true)
3728  endif
3729  if target.endswith('-softmmu')
3730    target_type='system'
3731    t = target_softmmu_arch[target_base_arch].apply(config_target, strict: false)
3732    arch_srcs += t.sources()
3733    arch_deps += t.dependencies()
3734
3735    hw_dir = target_name == 'sparc64' ? 'sparc64' : target_base_arch
3736    hw = hw_arch[hw_dir].apply(config_target, strict: false)
3737    arch_srcs += hw.sources()
3738    arch_deps += hw.dependencies()
3739
3740    arch_srcs += config_devices_h[target]
3741    link_args += ['@block.syms', '@qemu.syms']
3742  else
3743    abi = config_target['TARGET_ABI_DIR']
3744    target_type='user'
3745    target_inc += common_user_inc
3746    if target_base_arch in target_user_arch
3747      t = target_user_arch[target_base_arch].apply(config_target, strict: false)
3748      arch_srcs += t.sources()
3749      arch_deps += t.dependencies()
3750    endif
3751    if 'CONFIG_LINUX_USER' in config_target
3752      base_dir = 'linux-user'
3753    endif
3754    if 'CONFIG_BSD_USER' in config_target
3755      base_dir = 'bsd-user'
3756      target_inc += include_directories('bsd-user/' / targetos)
3757      target_inc += include_directories('bsd-user/host/' / host_arch)
3758      dir = base_dir / abi
3759      arch_srcs += files(dir / 'signal.c', dir / 'target_arch_cpu.c')
3760    endif
3761    target_inc += include_directories(
3762      base_dir,
3763      base_dir / abi,
3764    )
3765    if 'CONFIG_LINUX_USER' in config_target
3766      dir = base_dir / abi
3767      arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
3768      if config_target.has_key('TARGET_SYSTBL_ABI')
3769        arch_srcs += \
3770          syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
3771                                             extra_args : config_target['TARGET_SYSTBL_ABI'])
3772      endif
3773    endif
3774  endif
3775
3776  if 'TARGET_XML_FILES' in config_target
3777    gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
3778                                output: target + '-gdbstub-xml.c',
3779                                input: files(config_target['TARGET_XML_FILES'].split()),
3780                                command: [feature_to_c, '@INPUT@'],
3781                                capture: true)
3782    arch_srcs += gdbstub_xml
3783  endif
3784
3785  t = target_arch[target_base_arch].apply(config_target, strict: false)
3786  arch_srcs += t.sources()
3787  arch_deps += t.dependencies()
3788
3789  target_common = common_ss.apply(config_target, strict: false)
3790  objects = common_all.extract_objects(target_common.sources())
3791  deps = target_common.dependencies()
3792
3793  target_specific = specific_ss.apply(config_target, strict: false)
3794  arch_srcs += target_specific.sources()
3795  arch_deps += target_specific.dependencies()
3796
3797  lib = static_library('qemu-' + target,
3798                 sources: arch_srcs + genh,
3799                 dependencies: arch_deps,
3800                 objects: objects,
3801                 include_directories: target_inc,
3802                 c_args: c_args,
3803                 build_by_default: false,
3804                 name_suffix: 'fa')
3805
3806  if target.endswith('-softmmu')
3807    execs = [{
3808      'name': 'qemu-system-' + target_name,
3809      'win_subsystem': 'console',
3810      'sources': files('softmmu/main.c'),
3811      'dependencies': []
3812    }]
3813    if targetos == 'windows' and (sdl.found() or gtk.found())
3814      execs += [{
3815        'name': 'qemu-system-' + target_name + 'w',
3816        'win_subsystem': 'windows',
3817        'sources': files('softmmu/main.c'),
3818        'dependencies': []
3819      }]
3820    endif
3821    if get_option('fuzzing')
3822      specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
3823      execs += [{
3824        'name': 'qemu-fuzz-' + target_name,
3825        'win_subsystem': 'console',
3826        'sources': specific_fuzz.sources(),
3827        'dependencies': specific_fuzz.dependencies(),
3828      }]
3829    endif
3830  else
3831    execs = [{
3832      'name': 'qemu-' + target_name,
3833      'win_subsystem': 'console',
3834      'sources': [],
3835      'dependencies': []
3836    }]
3837  endif
3838  foreach exe: execs
3839    exe_name = exe['name']
3840    if targetos == 'darwin'
3841      exe_name += '-unsigned'
3842    endif
3843
3844    emulator = executable(exe_name, exe['sources'],
3845               install: true,
3846               c_args: c_args,
3847               dependencies: arch_deps + deps + exe['dependencies'],
3848               objects: lib.extract_all_objects(recursive: true),
3849               link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
3850               link_args: link_args,
3851               win_subsystem: exe['win_subsystem'])
3852
3853    if targetos == 'darwin'
3854      icon = 'pc-bios/qemu.rsrc'
3855      build_input = [emulator, files(icon)]
3856      install_input = [
3857        get_option('bindir') / exe_name,
3858        meson.current_source_dir() / icon
3859      ]
3860      if 'CONFIG_HVF' in config_target
3861        entitlements = 'accel/hvf/entitlements.plist'
3862        build_input += files(entitlements)
3863        install_input += meson.current_source_dir() / entitlements
3864      endif
3865
3866      emulators += {exe['name'] : custom_target(exe['name'],
3867                   input: build_input,
3868                   output: exe['name'],
3869                   command: [entitlement, '@OUTPUT@', '@INPUT@'])
3870      }
3871
3872      meson.add_install_script(entitlement, '--install',
3873                               get_option('bindir') / exe['name'],
3874                               install_input)
3875    else
3876      emulators += {exe['name']: emulator}
3877    endif
3878
3879    if stap.found()
3880      foreach stp: [
3881        {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
3882        {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
3883        {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
3884        {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
3885      ]
3886        custom_target(exe['name'] + stp['ext'],
3887                      input: trace_events_all,
3888                      output: exe['name'] + stp['ext'],
3889                      install: stp['install'],
3890                      install_dir: get_option('datadir') / 'systemtap/tapset',
3891                      command: [
3892                        tracetool, '--group=all', '--format=' + stp['fmt'],
3893                        '--binary=' + stp['bin'],
3894                        '--target-name=' + target_name,
3895                        '--target-type=' + target_type,
3896                        '--probe-prefix=qemu.' + target_type + '.' + target_name,
3897                        '@INPUT@', '@OUTPUT@'
3898                      ],
3899                      depend_files: tracetool_depends)
3900      endforeach
3901    endif
3902  endforeach
3903endforeach
3904
3905# Other build targets
3906
3907if get_option('plugins')
3908  install_headers('include/qemu/qemu-plugin.h')
3909endif
3910
3911subdir('qga')
3912
3913# Don't build qemu-keymap if xkbcommon is not explicitly enabled
3914# when we don't build tools or system
3915if xkbcommon.found()
3916  # used for the update-keymaps target, so include rules even if !have_tools
3917  qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
3918                           dependencies: [qemuutil, xkbcommon], install: have_tools)
3919endif
3920
3921if have_tools
3922  qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
3923             dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
3924  qemu_io = executable('qemu-io', files('qemu-io.c'),
3925             dependencies: [block, qemuutil], install: true)
3926  qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
3927               dependencies: [blockdev, qemuutil, gnutls, selinux],
3928               install: true)
3929
3930  subdir('storage-daemon')
3931  subdir('contrib/rdmacm-mux')
3932  subdir('contrib/elf2dmp')
3933
3934  executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
3935             dependencies: qemuutil,
3936             install: true)
3937
3938  if have_vhost_user
3939    subdir('contrib/vhost-user-blk')
3940    subdir('contrib/vhost-user-gpu')
3941    subdir('contrib/vhost-user-input')
3942    subdir('contrib/vhost-user-scsi')
3943  endif
3944
3945  if targetos == 'linux'
3946    executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
3947               dependencies: [qemuutil, libcap_ng],
3948               install: true,
3949               install_dir: get_option('libexecdir'))
3950
3951    executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
3952               dependencies: [authz, crypto, io, qom, qemuutil,
3953                              libcap_ng, mpathpersist],
3954               install: true)
3955  endif
3956
3957  if have_ivshmem
3958    subdir('contrib/ivshmem-client')
3959    subdir('contrib/ivshmem-server')
3960  endif
3961endif
3962
3963subdir('scripts')
3964subdir('tools')
3965subdir('pc-bios')
3966subdir('docs')
3967subdir('tests')
3968if gtk.found()
3969  subdir('po')
3970endif
3971
3972if host_machine.system() == 'windows'
3973  nsis_cmd = [
3974    find_program('scripts/nsis.py'),
3975    '@OUTPUT@',
3976    get_option('prefix'),
3977    meson.current_source_dir(),
3978    glib_pc.get_variable('bindir'),
3979    host_machine.cpu(),
3980    '--',
3981    '-DDISPLAYVERSION=' + meson.project_version(),
3982  ]
3983  if build_docs
3984    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
3985  endif
3986  if gtk.found()
3987    nsis_cmd += '-DCONFIG_GTK=y'
3988  endif
3989
3990  nsis = custom_target('nsis',
3991                       output: 'qemu-setup-' + meson.project_version() + '.exe',
3992                       input: files('qemu.nsi'),
3993                       build_always_stale: true,
3994                       command: nsis_cmd + ['@INPUT@'])
3995  alias_target('installer', nsis)
3996endif
3997
3998#########################
3999# Configuration summary #
4000#########################
4001
4002# Build environment
4003summary_info = {}
4004summary_info += {'Build directory':   meson.current_build_dir()}
4005summary_info += {'Source path':       meson.current_source_dir()}
4006summary_info += {'Download dependencies': get_option('wrap_mode') != 'nodownload'}
4007summary(summary_info, bool_yn: true, section: 'Build environment')
4008
4009# Directories
4010summary_info += {'Install prefix':    get_option('prefix')}
4011summary_info += {'BIOS directory':    qemu_datadir}
4012pathsep = targetos == 'windows' ? ';' : ':'
4013summary_info += {'firmware path':     pathsep.join(get_option('qemu_firmwarepath'))}
4014summary_info += {'binary directory':  get_option('prefix') / get_option('bindir')}
4015summary_info += {'library directory': get_option('prefix') / get_option('libdir')}
4016summary_info += {'module directory':  qemu_moddir}
4017summary_info += {'libexec directory': get_option('prefix') / get_option('libexecdir')}
4018summary_info += {'include directory': get_option('prefix') / get_option('includedir')}
4019summary_info += {'config directory':  get_option('prefix') / get_option('sysconfdir')}
4020if targetos != 'windows'
4021  summary_info += {'local state directory': get_option('prefix') / get_option('localstatedir')}
4022  summary_info += {'Manual directory':      get_option('prefix') / get_option('mandir')}
4023else
4024  summary_info += {'local state directory': 'queried at runtime'}
4025endif
4026summary_info += {'Doc directory':     get_option('prefix') / get_option('docdir')}
4027summary(summary_info, bool_yn: true, section: 'Directories')
4028
4029# Host binaries
4030summary_info = {}
4031summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
4032summary_info += {'sphinx-build':      sphinx_build}
4033if config_host.has_key('HAVE_GDB_BIN')
4034  summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
4035endif
4036summary_info += {'iasl':              iasl}
4037summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
4038if targetos == 'windows' and have_ga
4039  summary_info += {'wixl':            wixl}
4040endif
4041if slirp.found() and have_system
4042  summary_info += {'smbd':            have_slirp_smbd ? smbd_path : false}
4043endif
4044summary(summary_info, bool_yn: true, section: 'Host binaries')
4045
4046# Configurable features
4047summary_info = {}
4048summary_info += {'Documentation':     build_docs}
4049summary_info += {'system-mode emulation': have_system}
4050summary_info += {'user-mode emulation': have_user}
4051summary_info += {'block layer':       have_block}
4052summary_info += {'Install blobs':     get_option('install_blobs')}
4053summary_info += {'module support':    enable_modules}
4054if enable_modules
4055  summary_info += {'alternative module path': get_option('module_upgrades')}
4056endif
4057summary_info += {'fuzzing support':   get_option('fuzzing')}
4058if have_system
4059  summary_info += {'Audio drivers':     ' '.join(audio_drivers_selected)}
4060endif
4061summary_info += {'Trace backends':    ','.join(get_option('trace_backends'))}
4062if 'simple' in get_option('trace_backends')
4063  summary_info += {'Trace output file': get_option('trace_file') + '-<pid>'}
4064endif
4065summary_info += {'D-Bus display':     dbus_display}
4066summary_info += {'QOM debugging':     get_option('qom_cast_debug')}
4067summary_info += {'vhost-kernel support': have_vhost_kernel}
4068summary_info += {'vhost-net support': have_vhost_net}
4069summary_info += {'vhost-user support': have_vhost_user}
4070summary_info += {'vhost-user-crypto support': have_vhost_user_crypto}
4071summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
4072summary_info += {'vhost-vdpa support': have_vhost_vdpa}
4073summary_info += {'build guest agent': have_ga}
4074summary(summary_info, bool_yn: true, section: 'Configurable features')
4075
4076# Compilation information
4077summary_info = {}
4078summary_info += {'host CPU':          cpu}
4079summary_info += {'host endianness':   build_machine.endian()}
4080summary_info += {'C compiler':        ' '.join(meson.get_compiler('c').cmd_array())}
4081summary_info += {'Host C compiler':   ' '.join(meson.get_compiler('c', native: true).cmd_array())}
4082if 'cpp' in all_languages
4083  summary_info += {'C++ compiler':    ' '.join(meson.get_compiler('cpp').cmd_array())}
4084else
4085  summary_info += {'C++ compiler':      false}
4086endif
4087if targetos == 'darwin'
4088  summary_info += {'Objective-C compiler': ' '.join(meson.get_compiler('objc').cmd_array())}
4089endif
4090option_cflags = (get_option('debug') ? ['-g'] : [])
4091if get_option('optimization') != 'plain'
4092  option_cflags += ['-O' + get_option('optimization')]
4093endif
4094summary_info += {'CFLAGS':            ' '.join(get_option('c_args') + option_cflags)}
4095if 'cpp' in all_languages
4096  summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args') + option_cflags)}
4097endif
4098if targetos == 'darwin'
4099  summary_info += {'OBJCFLAGS':       ' '.join(get_option('objc_args') + option_cflags)}
4100endif
4101link_args = get_option('c_link_args')
4102if link_args.length() > 0
4103  summary_info += {'LDFLAGS':         ' '.join(link_args)}
4104endif
4105summary_info += {'QEMU_CFLAGS':       ' '.join(qemu_common_flags + qemu_cflags)}
4106if 'cpp' in all_languages
4107  summary_info += {'QEMU_CXXFLAGS':     ' '.join(qemu_common_flags + qemu_cxxflags)}
4108endif
4109if 'objc' in all_languages
4110  summary_info += {'QEMU_OBJCFLAGS':    ' '.join(qemu_common_flags)}
4111endif
4112summary_info += {'QEMU_LDFLAGS':      ' '.join(qemu_ldflags)}
4113summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
4114summary_info += {'PIE':               get_option('b_pie')}
4115summary_info += {'static build':      get_option('prefer_static')}
4116summary_info += {'malloc trim support': has_malloc_trim}
4117summary_info += {'membarrier':        have_membarrier}
4118summary_info += {'debug graph lock':  get_option('debug_graph_lock')}
4119summary_info += {'debug stack usage': get_option('debug_stack_usage')}
4120summary_info += {'mutex debugging':   get_option('debug_mutex')}
4121summary_info += {'memory allocator':  get_option('malloc')}
4122summary_info += {'avx2 optimization': config_host_data.get('CONFIG_AVX2_OPT')}
4123summary_info += {'avx512bw optimization': config_host_data.get('CONFIG_AVX512BW_OPT')}
4124summary_info += {'avx512f optimization': config_host_data.get('CONFIG_AVX512F_OPT')}
4125if get_option('gprof')
4126  gprof_info = 'YES (deprecated)'
4127else
4128  gprof_info = get_option('gprof')
4129endif
4130summary_info += {'gprof':             gprof_info}
4131summary_info += {'gcov':              get_option('b_coverage')}
4132summary_info += {'thread sanitizer':  get_option('tsan')}
4133summary_info += {'CFI support':       get_option('cfi')}
4134if get_option('cfi')
4135  summary_info += {'CFI debug support': get_option('cfi_debug')}
4136endif
4137summary_info += {'strip binaries':    get_option('strip')}
4138summary_info += {'sparse':            sparse}
4139summary_info += {'mingw32 support':   targetos == 'windows'}
4140summary(summary_info, bool_yn: true, section: 'Compilation')
4141
4142# snarf the cross-compilation information for tests
4143summary_info = {}
4144have_cross = false
4145foreach target: target_dirs
4146  tcg_mak = meson.current_build_dir() / 'tests/tcg' / target / 'config-target.mak'
4147  if fs.exists(tcg_mak)
4148    config_cross_tcg = keyval.load(tcg_mak)
4149    if 'CC' in config_cross_tcg
4150      summary_info += {config_cross_tcg['TARGET_NAME']: config_cross_tcg['CC']}
4151      have_cross = true
4152    endif
4153  endif
4154endforeach
4155if have_cross
4156  summary(summary_info, bool_yn: true, section: 'Cross compilers')
4157endif
4158
4159# Targets and accelerators
4160summary_info = {}
4161if have_system
4162  summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
4163  summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
4164  summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
4165  summary_info += {'NVMM support':      config_all.has_key('CONFIG_NVMM')}
4166  summary_info += {'Xen support':       xen.found()}
4167  if xen.found()
4168    summary_info += {'xen ctrl version':  xen.version()}
4169  endif
4170  summary_info += {'Xen emulation':     config_all.has_key('CONFIG_XEN_EMU')}
4171endif
4172summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
4173if config_all.has_key('CONFIG_TCG')
4174  if get_option('tcg_interpreter')
4175    summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, slow)'}
4176  else
4177    summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
4178  endif
4179  summary_info += {'TCG plugins':       get_option('plugins')}
4180  summary_info += {'TCG debug enabled': get_option('debug_tcg')}
4181endif
4182summary_info += {'target list':       ' '.join(target_dirs)}
4183if have_system
4184  summary_info += {'default devices':   get_option('default_devices')}
4185  summary_info += {'out of process emulation': multiprocess_allowed}
4186  summary_info += {'vfio-user server': vfio_user_server_allowed}
4187endif
4188summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
4189
4190# Block layer
4191summary_info = {}
4192summary_info += {'coroutine backend': coroutine_backend}
4193summary_info += {'coroutine pool':    have_coroutine_pool}
4194if have_block
4195  summary_info += {'Block whitelist (rw)': get_option('block_drv_rw_whitelist')}
4196  summary_info += {'Block whitelist (ro)': get_option('block_drv_ro_whitelist')}
4197  summary_info += {'Use block whitelist in tools': get_option('block_drv_whitelist_in_tools')}
4198  summary_info += {'VirtFS (9P) support':    have_virtfs}
4199  summary_info += {'VirtFS (9P) Proxy Helper support (deprecated)': have_virtfs_proxy_helper}
4200  summary_info += {'Live block migration': config_host_data.get('CONFIG_LIVE_BLOCK_MIGRATION')}
4201  summary_info += {'replication support': config_host_data.get('CONFIG_REPLICATION')}
4202  summary_info += {'bochs support':     get_option('bochs').allowed()}
4203  summary_info += {'cloop support':     get_option('cloop').allowed()}
4204  summary_info += {'dmg support':       get_option('dmg').allowed()}
4205  summary_info += {'qcow v1 support':   get_option('qcow1').allowed()}
4206  summary_info += {'vdi support':       get_option('vdi').allowed()}
4207  summary_info += {'vhdx support':      get_option('vhdx').allowed()}
4208  summary_info += {'vmdk support':      get_option('vmdk').allowed()}
4209  summary_info += {'vpc support':       get_option('vpc').allowed()}
4210  summary_info += {'vvfat support':     get_option('vvfat').allowed()}
4211  summary_info += {'qed support':       get_option('qed').allowed()}
4212  summary_info += {'parallels support': get_option('parallels').allowed()}
4213  summary_info += {'FUSE exports':      fuse}
4214  summary_info += {'VDUSE block exports': have_vduse_blk_export}
4215endif
4216summary(summary_info, bool_yn: true, section: 'Block layer support')
4217
4218# Crypto
4219summary_info = {}
4220summary_info += {'TLS priority':      get_option('tls_priority')}
4221summary_info += {'GNUTLS support':    gnutls}
4222if gnutls.found()
4223  summary_info += {'  GNUTLS crypto':   gnutls_crypto.found()}
4224endif
4225summary_info += {'libgcrypt':         gcrypt}
4226summary_info += {'nettle':            nettle}
4227if nettle.found()
4228   summary_info += {'  XTS':             xts != 'private'}
4229endif
4230summary_info += {'AF_ALG support':    have_afalg}
4231summary_info += {'rng-none':          get_option('rng_none')}
4232summary_info += {'Linux keyring':     have_keyring}
4233summary_info += {'Linux keyutils':    keyutils}
4234summary(summary_info, bool_yn: true, section: 'Crypto')
4235
4236# UI
4237summary_info = {}
4238if targetos == 'darwin'
4239  summary_info += {'Cocoa support':           cocoa}
4240endif
4241summary_info += {'SDL support':       sdl}
4242summary_info += {'SDL image support': sdl_image}
4243summary_info += {'GTK support':       gtk}
4244summary_info += {'pixman':            pixman}
4245summary_info += {'VTE support':       vte}
4246summary_info += {'PNG support':       png}
4247summary_info += {'VNC support':       vnc}
4248if vnc.found()
4249  summary_info += {'VNC SASL support':  sasl}
4250  summary_info += {'VNC JPEG support':  jpeg}
4251endif
4252summary_info += {'spice protocol support': spice_protocol}
4253if spice_protocol.found()
4254  summary_info += {'  spice server support': spice}
4255endif
4256summary_info += {'curses support':    curses}
4257summary_info += {'brlapi support':    brlapi}
4258summary(summary_info, bool_yn: true, section: 'User interface')
4259
4260# Audio backends
4261summary_info = {}
4262if targetos not in ['darwin', 'haiku', 'windows']
4263  summary_info += {'OSS support':     oss}
4264  summary_info += {'sndio support':   sndio}
4265elif targetos == 'darwin'
4266  summary_info += {'CoreAudio support': coreaudio}
4267elif targetos == 'windows'
4268  summary_info += {'DirectSound support': dsound}
4269endif
4270if targetos == 'linux'
4271  summary_info += {'ALSA support':    alsa}
4272  summary_info += {'PulseAudio support': pulse}
4273endif
4274summary_info += {'PipeWire support':  pipewire}
4275summary_info += {'JACK support':      jack}
4276summary(summary_info, bool_yn: true, section: 'Audio backends')
4277
4278# Network backends
4279summary_info = {}
4280if targetos == 'darwin'
4281  summary_info += {'vmnet.framework support': vmnet}
4282endif
4283summary_info += {'AF_XDP support':    libxdp}
4284summary_info += {'slirp support':     slirp}
4285summary_info += {'vde support':       vde}
4286summary_info += {'netmap support':    have_netmap}
4287summary_info += {'l2tpv3 support':    have_l2tpv3}
4288summary(summary_info, bool_yn: true, section: 'Network backends')
4289
4290# Libraries
4291summary_info = {}
4292summary_info += {'libtasn1':          tasn1}
4293summary_info += {'PAM':               pam}
4294summary_info += {'iconv support':     iconv}
4295summary_info += {'virgl support':     virgl}
4296summary_info += {'blkio support':     blkio}
4297summary_info += {'curl support':      curl}
4298summary_info += {'Multipath support': mpathpersist}
4299summary_info += {'Linux AIO support': libaio}
4300summary_info += {'Linux io_uring support': linux_io_uring}
4301summary_info += {'ATTR/XATTR support': libattr}
4302summary_info += {'RDMA support':      rdma}
4303summary_info += {'PVRDMA support':    have_pvrdma}
4304summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
4305summary_info += {'libcap-ng support': libcap_ng}
4306summary_info += {'bpf support':       libbpf}
4307summary_info += {'rbd support':       rbd}
4308summary_info += {'smartcard support': cacard}
4309summary_info += {'U2F support':       u2f}
4310summary_info += {'libusb':            libusb}
4311summary_info += {'usb net redir':     usbredir}
4312summary_info += {'OpenGL support (epoxy)': opengl}
4313summary_info += {'GBM':               gbm}
4314summary_info += {'libiscsi support':  libiscsi}
4315summary_info += {'libnfs support':    libnfs}
4316if targetos == 'windows'
4317  if have_ga
4318    summary_info += {'QGA VSS support':   have_qga_vss}
4319  endif
4320endif
4321summary_info += {'seccomp support':   seccomp}
4322summary_info += {'GlusterFS support': glusterfs}
4323summary_info += {'TPM support':       have_tpm}
4324summary_info += {'libssh support':    libssh}
4325summary_info += {'lzo support':       lzo}
4326summary_info += {'snappy support':    snappy}
4327summary_info += {'bzip2 support':     libbzip2}
4328summary_info += {'lzfse support':     liblzfse}
4329summary_info += {'zstd support':      zstd}
4330summary_info += {'NUMA host support': numa}
4331summary_info += {'capstone':          capstone}
4332summary_info += {'libpmem support':   libpmem}
4333summary_info += {'libdaxctl support': libdaxctl}
4334summary_info += {'libudev':           libudev}
4335# Dummy dependency, keep .found()
4336summary_info += {'FUSE lseek':        fuse_lseek.found()}
4337summary_info += {'selinux':           selinux}
4338summary_info += {'libdw':             libdw}
4339summary(summary_info, bool_yn: true, section: 'Dependencies')
4340
4341if host_arch == 'unknown'
4342  message()
4343  warning('UNSUPPORTED HOST CPU')
4344  message()
4345  message('Support for CPU host architecture ' + cpu + ' is not currently')
4346  message('maintained. The QEMU project does not guarantee that QEMU will')
4347  message('compile or work on this host CPU. You can help by volunteering')
4348  message('to maintain it and providing a build host for our continuous')
4349  message('integration setup.')
4350  if get_option('tcg').allowed() and target_dirs.length() > 0
4351    message()
4352    message('configure has succeeded and you can continue to build, but')
4353    message('QEMU will use a slow interpreter to emulate the target CPU.')
4354  endif
4355endif
4356
4357if not supported_oses.contains(targetos)
4358  message()
4359  warning('UNSUPPORTED HOST OS')
4360  message()
4361  message('Support for host OS ' + targetos + 'is not currently maintained.')
4362  message('configure has succeeded and you can continue to build, but')
4363  message('the QEMU project does not guarantee that QEMU will compile or')
4364  message('work on this operating system. You can help by volunteering')
4365  message('to maintain it and providing a build host for our continuous')
4366  message('integration setup. This will ensure that future versions of QEMU')
4367  message('will keep working on ' + targetos + '.')
4368endif
4369
4370if host_arch == 'unknown' or not supported_oses.contains(targetos)
4371  message()
4372  message('If you want to help supporting QEMU on this platform, please')
4373  message('contact the developers at qemu-devel@nongnu.org.')
4374endif
4375