xref: /qemu/meson.build (revision 590102e7)
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 get_option('keyring').enabled()
1767  keyutils = dependency('libkeyutils', required: false, method: 'pkg-config')
1768endif
1769
1770has_gettid = cc.has_function('gettid')
1771
1772# libselinux
1773selinux = dependency('libselinux',
1774                     required: get_option('selinux'),
1775                     method: 'pkg-config')
1776
1777# Malloc tests
1778
1779malloc = []
1780if get_option('malloc') == 'system'
1781  has_malloc_trim = \
1782    get_option('malloc_trim').allowed() and \
1783    cc.has_function('malloc_trim', prefix: '#include <malloc.h>')
1784else
1785  has_malloc_trim = false
1786  malloc = cc.find_library(get_option('malloc'), required: true)
1787endif
1788if not has_malloc_trim and get_option('malloc_trim').enabled()
1789  if get_option('malloc') == 'system'
1790    error('malloc_trim not available on this platform.')
1791  else
1792    error('malloc_trim not available with non-libc memory allocator')
1793  endif
1794endif
1795
1796gnu_source_prefix = '''
1797  #ifndef _GNU_SOURCE
1798  #define _GNU_SOURCE
1799  #endif
1800'''
1801
1802# Check whether the glibc provides STATX_BASIC_STATS
1803
1804has_statx = cc.has_header_symbol('sys/stat.h', 'STATX_BASIC_STATS', prefix: gnu_source_prefix)
1805
1806# Check whether statx() provides mount ID information
1807
1808has_statx_mnt_id = cc.has_header_symbol('sys/stat.h', 'STATX_MNT_ID', prefix: gnu_source_prefix)
1809
1810have_vhost_user_blk_server = get_option('vhost_user_blk_server') \
1811  .require(targetos == 'linux',
1812           error_message: 'vhost_user_blk_server requires linux') \
1813  .require(have_vhost_user,
1814           error_message: 'vhost_user_blk_server requires vhost-user support') \
1815  .disable_auto_if(not have_tools and not have_system) \
1816  .allowed()
1817
1818if get_option('fuse').disabled() and get_option('fuse_lseek').enabled()
1819  error('Cannot enable fuse-lseek while fuse is disabled')
1820endif
1821
1822fuse = dependency('fuse3', required: get_option('fuse'),
1823                  version: '>=3.1', method: 'pkg-config')
1824
1825fuse_lseek = not_found
1826if get_option('fuse_lseek').allowed()
1827  if fuse.version().version_compare('>=3.8')
1828    # Dummy dependency
1829    fuse_lseek = declare_dependency()
1830  elif get_option('fuse_lseek').enabled()
1831    if fuse.found()
1832      error('fuse-lseek requires libfuse >=3.8, found ' + fuse.version())
1833    else
1834      error('fuse-lseek requires libfuse, which was not found')
1835    endif
1836  endif
1837endif
1838
1839have_libvduse = (targetos == 'linux')
1840if get_option('libvduse').enabled()
1841    if targetos != 'linux'
1842        error('libvduse requires linux')
1843    endif
1844elif get_option('libvduse').disabled()
1845    have_libvduse = false
1846endif
1847
1848have_vduse_blk_export = (have_libvduse and targetos == 'linux')
1849if get_option('vduse_blk_export').enabled()
1850    if targetos != 'linux'
1851        error('vduse_blk_export requires linux')
1852    elif not have_libvduse
1853        error('vduse_blk_export requires libvduse support')
1854    endif
1855elif get_option('vduse_blk_export').disabled()
1856    have_vduse_blk_export = false
1857endif
1858
1859# libbpf
1860libbpf = dependency('libbpf', required: get_option('bpf'), method: 'pkg-config')
1861if libbpf.found() and not cc.links('''
1862   #include <bpf/libbpf.h>
1863   int main(void)
1864   {
1865     bpf_object__destroy_skeleton(NULL);
1866     return 0;
1867   }''', dependencies: libbpf)
1868  libbpf = not_found
1869  if get_option('bpf').enabled()
1870    error('libbpf skeleton test failed')
1871  else
1872    warning('libbpf skeleton test failed, disabling')
1873  endif
1874endif
1875
1876# libxdp
1877libxdp = not_found
1878if not get_option('af_xdp').auto() or have_system
1879    libxdp = dependency('libxdp', required: get_option('af_xdp'),
1880                        version: '>=1.4.0', method: 'pkg-config')
1881endif
1882
1883# libdw
1884libdw = not_found
1885if not get_option('libdw').auto() or \
1886        (not get_option('prefer_static') and (have_system or have_user))
1887    libdw = dependency('libdw',
1888                       method: 'pkg-config',
1889                       required: get_option('libdw'))
1890endif
1891
1892#################
1893# config-host.h #
1894#################
1895
1896audio_drivers_selected = []
1897if have_system
1898  audio_drivers_available = {
1899    'alsa': alsa.found(),
1900    'coreaudio': coreaudio.found(),
1901    'dsound': dsound.found(),
1902    'jack': jack.found(),
1903    'oss': oss.found(),
1904    'pa': pulse.found(),
1905    'pipewire': pipewire.found(),
1906    'sdl': sdl.found(),
1907    'sndio': sndio.found(),
1908  }
1909  foreach k, v: audio_drivers_available
1910    config_host_data.set('CONFIG_AUDIO_' + k.to_upper(), v)
1911  endforeach
1912
1913  # Default to native drivers first, OSS second, SDL third
1914  audio_drivers_priority = \
1915    [ 'pa', 'coreaudio', 'dsound', 'sndio', 'oss' ] + \
1916    (targetos == 'linux' ? [] : [ 'sdl' ])
1917  audio_drivers_default = []
1918  foreach k: audio_drivers_priority
1919    if audio_drivers_available[k]
1920      audio_drivers_default += k
1921    endif
1922  endforeach
1923
1924  foreach k: get_option('audio_drv_list')
1925    if k == 'default'
1926      audio_drivers_selected += audio_drivers_default
1927    elif not audio_drivers_available[k]
1928      error('Audio driver "@0@" not available.'.format(k))
1929    else
1930      audio_drivers_selected += k
1931    endif
1932  endforeach
1933endif
1934config_host_data.set('CONFIG_AUDIO_DRIVERS',
1935                     '"' + '", "'.join(audio_drivers_selected) + '", ')
1936
1937if get_option('cfi')
1938  cfi_flags=[]
1939  # Check for dependency on LTO
1940  if not get_option('b_lto')
1941    error('Selected Control-Flow Integrity but LTO is disabled')
1942  endif
1943  if enable_modules
1944    error('Selected Control-Flow Integrity is not compatible with modules')
1945  endif
1946  # Check for cfi flags. CFI requires LTO so we can't use
1947  # get_supported_arguments, but need a more complex "compiles" which allows
1948  # custom arguments
1949  if cc.compiles('int main () { return 0; }', name: '-fsanitize=cfi-icall',
1950                 args: ['-flto', '-fsanitize=cfi-icall'] )
1951    cfi_flags += '-fsanitize=cfi-icall'
1952  else
1953    error('-fsanitize=cfi-icall is not supported by the compiler')
1954  endif
1955  if cc.compiles('int main () { return 0; }',
1956                 name: '-fsanitize-cfi-icall-generalize-pointers',
1957                 args: ['-flto', '-fsanitize=cfi-icall',
1958                        '-fsanitize-cfi-icall-generalize-pointers'] )
1959    cfi_flags += '-fsanitize-cfi-icall-generalize-pointers'
1960  else
1961    error('-fsanitize-cfi-icall-generalize-pointers is not supported by the compiler')
1962  endif
1963  if get_option('cfi_debug')
1964    if cc.compiles('int main () { return 0; }',
1965                   name: '-fno-sanitize-trap=cfi-icall',
1966                   args: ['-flto', '-fsanitize=cfi-icall',
1967                          '-fno-sanitize-trap=cfi-icall'] )
1968      cfi_flags += '-fno-sanitize-trap=cfi-icall'
1969    else
1970      error('-fno-sanitize-trap=cfi-icall is not supported by the compiler')
1971    endif
1972  endif
1973  add_global_arguments(cfi_flags, native: false, language: all_languages)
1974  add_global_link_arguments(cfi_flags, native: false, language: all_languages)
1975endif
1976
1977have_host_block_device = (targetos != 'darwin' or
1978    cc.has_header('IOKit/storage/IOMedia.h'))
1979
1980dbus_display = get_option('dbus_display') \
1981  .require(gio.version().version_compare('>=2.64'),
1982           error_message: '-display dbus requires glib>=2.64') \
1983  .require(gdbus_codegen.found(),
1984           error_message: gdbus_codegen_error.format('-display dbus')) \
1985  .allowed()
1986
1987have_virtfs = get_option('virtfs') \
1988    .require(targetos == 'linux' or targetos == 'darwin',
1989             error_message: 'virtio-9p (virtfs) requires Linux or macOS') \
1990    .require(targetos == 'linux' or cc.has_function('pthread_fchdir_np'),
1991             error_message: 'virtio-9p (virtfs) on macOS requires the presence of pthread_fchdir_np') \
1992    .require(targetos == 'darwin' or libattr.found(),
1993             error_message: 'virtio-9p (virtfs) on Linux requires libattr-devel') \
1994    .disable_auto_if(not have_tools and not have_system) \
1995    .allowed()
1996
1997have_virtfs_proxy_helper = get_option('virtfs_proxy_helper') \
1998    .require(targetos != 'darwin', error_message: 'the virtfs proxy helper is incompatible with macOS') \
1999    .require(have_virtfs, error_message: 'the virtfs proxy helper requires that virtfs is enabled') \
2000    .disable_auto_if(not have_tools) \
2001    .require(libcap_ng.found(), error_message: 'the virtfs proxy helper requires libcap-ng') \
2002    .allowed()
2003
2004if get_option('block_drv_ro_whitelist') == ''
2005  config_host_data.set('CONFIG_BDRV_RO_WHITELIST', '')
2006else
2007  config_host_data.set('CONFIG_BDRV_RO_WHITELIST',
2008        '"' + get_option('block_drv_ro_whitelist').replace(',', '", "') + '", ')
2009endif
2010if get_option('block_drv_rw_whitelist') == ''
2011  config_host_data.set('CONFIG_BDRV_RW_WHITELIST', '')
2012else
2013  config_host_data.set('CONFIG_BDRV_RW_WHITELIST',
2014        '"' + get_option('block_drv_rw_whitelist').replace(',', '", "') + '", ')
2015endif
2016
2017foreach k : get_option('trace_backends')
2018  config_host_data.set('CONFIG_TRACE_' + k.to_upper(), true)
2019endforeach
2020config_host_data.set_quoted('CONFIG_TRACE_FILE', get_option('trace_file'))
2021config_host_data.set_quoted('CONFIG_TLS_PRIORITY', get_option('tls_priority'))
2022if iasl.found()
2023  config_host_data.set_quoted('CONFIG_IASL', iasl.full_path())
2024endif
2025config_host_data.set_quoted('CONFIG_BINDIR', get_option('prefix') / get_option('bindir'))
2026config_host_data.set_quoted('CONFIG_PREFIX', get_option('prefix'))
2027config_host_data.set_quoted('CONFIG_QEMU_CONFDIR', get_option('prefix') / qemu_confdir)
2028config_host_data.set_quoted('CONFIG_QEMU_DATADIR', get_option('prefix') / qemu_datadir)
2029config_host_data.set_quoted('CONFIG_QEMU_DESKTOPDIR', get_option('prefix') / qemu_desktopdir)
2030
2031qemu_firmwarepath = ''
2032foreach k : get_option('qemu_firmwarepath')
2033  qemu_firmwarepath += '"' + get_option('prefix') / k + '", '
2034endforeach
2035config_host_data.set('CONFIG_QEMU_FIRMWAREPATH', qemu_firmwarepath)
2036
2037config_host_data.set_quoted('CONFIG_QEMU_HELPERDIR', get_option('prefix') / get_option('libexecdir'))
2038config_host_data.set_quoted('CONFIG_QEMU_ICONDIR', get_option('prefix') / qemu_icondir)
2039config_host_data.set_quoted('CONFIG_QEMU_LOCALEDIR', get_option('prefix') / get_option('localedir'))
2040config_host_data.set_quoted('CONFIG_QEMU_LOCALSTATEDIR', get_option('prefix') / get_option('localstatedir'))
2041config_host_data.set_quoted('CONFIG_QEMU_MODDIR', get_option('prefix') / qemu_moddir)
2042config_host_data.set_quoted('CONFIG_SYSCONFDIR', get_option('prefix') / get_option('sysconfdir'))
2043
2044if enable_modules
2045  config_host_data.set('CONFIG_STAMP', run_command(
2046      meson.current_source_dir() / 'scripts/qemu-stamp.py',
2047      meson.project_version(), get_option('pkgversion'), '--',
2048      meson.current_source_dir() / 'configure',
2049      capture: true, check: true).stdout().strip())
2050endif
2051
2052have_slirp_smbd = get_option('slirp_smbd') \
2053  .require(targetos != 'windows', error_message: 'Host smbd not supported on this platform.') \
2054  .allowed()
2055if have_slirp_smbd
2056  smbd_path = get_option('smbd')
2057  if smbd_path == ''
2058    smbd_path = (targetos == 'sunos' ? '/usr/sfw/sbin/smbd' : '/usr/sbin/smbd')
2059  endif
2060  config_host_data.set_quoted('CONFIG_SMBD_COMMAND', smbd_path)
2061endif
2062
2063config_host_data.set('HOST_' + host_arch.to_upper(), 1)
2064
2065if get_option('module_upgrades') and not enable_modules
2066  error('Cannot enable module-upgrades as modules are not enabled')
2067endif
2068config_host_data.set('CONFIG_MODULE_UPGRADES', get_option('module_upgrades'))
2069
2070config_host_data.set('CONFIG_ATTR', libattr.found())
2071config_host_data.set('CONFIG_BDRV_WHITELIST_TOOLS', get_option('block_drv_whitelist_in_tools'))
2072config_host_data.set('CONFIG_BRLAPI', brlapi.found())
2073config_host_data.set('CONFIG_BSD', targetos in bsd_oses)
2074config_host_data.set('CONFIG_COCOA', cocoa.found())
2075config_host_data.set('CONFIG_DARWIN', targetos == 'darwin')
2076config_host_data.set('CONFIG_FUZZ', get_option('fuzzing'))
2077config_host_data.set('CONFIG_GCOV', get_option('b_coverage'))
2078config_host_data.set('CONFIG_LIBUDEV', libudev.found())
2079config_host_data.set('CONFIG_LINUX', targetos == 'linux')
2080config_host_data.set('CONFIG_POSIX', targetos != 'windows')
2081config_host_data.set('CONFIG_WIN32', targetos == 'windows')
2082config_host_data.set('CONFIG_LZO', lzo.found())
2083config_host_data.set('CONFIG_MPATH', mpathpersist.found())
2084config_host_data.set('CONFIG_BLKIO', blkio.found())
2085if blkio.found()
2086  config_host_data.set('CONFIG_BLKIO_VHOST_VDPA_FD',
2087                       blkio.version().version_compare('>=1.3.0'))
2088endif
2089config_host_data.set('CONFIG_CURL', curl.found())
2090config_host_data.set('CONFIG_CURSES', curses.found())
2091config_host_data.set('CONFIG_GBM', gbm.found())
2092config_host_data.set('CONFIG_GIO', gio.found())
2093config_host_data.set('CONFIG_GLUSTERFS', glusterfs.found())
2094if glusterfs.found()
2095  config_host_data.set('CONFIG_GLUSTERFS_XLATOR_OPT', glusterfs.version().version_compare('>=4'))
2096  config_host_data.set('CONFIG_GLUSTERFS_DISCARD', glusterfs.version().version_compare('>=5'))
2097  config_host_data.set('CONFIG_GLUSTERFS_FALLOCATE', glusterfs.version().version_compare('>=6'))
2098  config_host_data.set('CONFIG_GLUSTERFS_ZEROFILL', glusterfs.version().version_compare('>=6'))
2099  config_host_data.set('CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT', glusterfs_ftruncate_has_stat)
2100  config_host_data.set('CONFIG_GLUSTERFS_IOCB_HAS_STAT', glusterfs_iocb_has_stat)
2101endif
2102config_host_data.set('CONFIG_GTK', gtk.found())
2103config_host_data.set('CONFIG_VTE', vte.found())
2104config_host_data.set('CONFIG_GTK_CLIPBOARD', have_gtk_clipboard)
2105config_host_data.set('CONFIG_HEXAGON_IDEF_PARSER', get_option('hexagon_idef_parser'))
2106config_host_data.set('CONFIG_LIBATTR', have_old_libattr)
2107config_host_data.set('CONFIG_LIBCAP_NG', libcap_ng.found())
2108config_host_data.set('CONFIG_EBPF', libbpf.found())
2109config_host_data.set('CONFIG_AF_XDP', libxdp.found())
2110config_host_data.set('CONFIG_LIBDAXCTL', libdaxctl.found())
2111config_host_data.set('CONFIG_LIBISCSI', libiscsi.found())
2112config_host_data.set('CONFIG_LIBNFS', libnfs.found())
2113config_host_data.set('CONFIG_LIBSSH', libssh.found())
2114config_host_data.set('CONFIG_LINUX_AIO', libaio.found())
2115config_host_data.set('CONFIG_LINUX_IO_URING', linux_io_uring.found())
2116config_host_data.set('CONFIG_LIBPMEM', libpmem.found())
2117config_host_data.set('CONFIG_MODULES', enable_modules)
2118config_host_data.set('CONFIG_NUMA', numa.found())
2119if numa.found()
2120  config_host_data.set('HAVE_NUMA_HAS_PREFERRED_MANY',
2121                       cc.has_function('numa_has_preferred_many',
2122                                       dependencies: numa))
2123endif
2124config_host_data.set('CONFIG_OPENGL', opengl.found())
2125config_host_data.set('CONFIG_PLUGIN', get_option('plugins'))
2126config_host_data.set('CONFIG_RBD', rbd.found())
2127config_host_data.set('CONFIG_RDMA', rdma.found())
2128config_host_data.set('CONFIG_SAFESTACK', get_option('safe_stack'))
2129config_host_data.set('CONFIG_SDL', sdl.found())
2130config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found())
2131config_host_data.set('CONFIG_SECCOMP', seccomp.found())
2132if seccomp.found()
2133  config_host_data.set('CONFIG_SECCOMP_SYSRAWRC', seccomp_has_sysrawrc)
2134endif
2135config_host_data.set('CONFIG_SNAPPY', snappy.found())
2136config_host_data.set('CONFIG_SOLARIS', targetos == 'sunos')
2137if get_option('tcg').allowed()
2138  config_host_data.set('CONFIG_TCG', 1)
2139  config_host_data.set('CONFIG_TCG_INTERPRETER', tcg_arch == 'tci')
2140endif
2141config_host_data.set('CONFIG_TPM', have_tpm)
2142config_host_data.set('CONFIG_TSAN', get_option('tsan'))
2143config_host_data.set('CONFIG_USB_LIBUSB', libusb.found())
2144config_host_data.set('CONFIG_VDE', vde.found())
2145config_host_data.set('CONFIG_VHOST_NET', have_vhost_net)
2146config_host_data.set('CONFIG_VHOST_NET_USER', have_vhost_net_user)
2147config_host_data.set('CONFIG_VHOST_NET_VDPA', have_vhost_net_vdpa)
2148config_host_data.set('CONFIG_VHOST_KERNEL', have_vhost_kernel)
2149config_host_data.set('CONFIG_VHOST_USER', have_vhost_user)
2150config_host_data.set('CONFIG_VHOST_CRYPTO', have_vhost_user_crypto)
2151config_host_data.set('CONFIG_VHOST_VDPA', have_vhost_vdpa)
2152config_host_data.set('CONFIG_VMNET', vmnet.found())
2153config_host_data.set('CONFIG_VHOST_USER_BLK_SERVER', have_vhost_user_blk_server)
2154config_host_data.set('CONFIG_VDUSE_BLK_EXPORT', have_vduse_blk_export)
2155config_host_data.set('CONFIG_PNG', png.found())
2156config_host_data.set('CONFIG_VNC', vnc.found())
2157config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
2158config_host_data.set('CONFIG_VNC_SASL', sasl.found())
2159config_host_data.set('CONFIG_VIRTFS', have_virtfs)
2160config_host_data.set('CONFIG_VTE', vte.found())
2161config_host_data.set('CONFIG_XKBCOMMON', xkbcommon.found())
2162config_host_data.set('CONFIG_KEYUTILS', keyutils.found())
2163config_host_data.set('CONFIG_GETTID', has_gettid)
2164config_host_data.set('CONFIG_GNUTLS', gnutls.found())
2165config_host_data.set('CONFIG_GNUTLS_CRYPTO', gnutls_crypto.found())
2166config_host_data.set('CONFIG_TASN1', tasn1.found())
2167config_host_data.set('CONFIG_GCRYPT', gcrypt.found())
2168config_host_data.set('CONFIG_NETTLE', nettle.found())
2169config_host_data.set('CONFIG_HOGWEED', hogweed.found())
2170config_host_data.set('CONFIG_QEMU_PRIVATE_XTS', xts == 'private')
2171config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim)
2172config_host_data.set('CONFIG_STATX', has_statx)
2173config_host_data.set('CONFIG_STATX_MNT_ID', has_statx_mnt_id)
2174config_host_data.set('CONFIG_ZSTD', zstd.found())
2175config_host_data.set('CONFIG_FUSE', fuse.found())
2176config_host_data.set('CONFIG_FUSE_LSEEK', fuse_lseek.found())
2177config_host_data.set('CONFIG_SPICE_PROTOCOL', spice_protocol.found())
2178if spice_protocol.found()
2179config_host_data.set('CONFIG_SPICE_PROTOCOL_MAJOR', spice_protocol.version().split('.')[0])
2180config_host_data.set('CONFIG_SPICE_PROTOCOL_MINOR', spice_protocol.version().split('.')[1])
2181config_host_data.set('CONFIG_SPICE_PROTOCOL_MICRO', spice_protocol.version().split('.')[2])
2182endif
2183config_host_data.set('CONFIG_SPICE', spice.found())
2184config_host_data.set('CONFIG_X11', x11.found())
2185config_host_data.set('CONFIG_DBUS_DISPLAY', dbus_display)
2186config_host_data.set('CONFIG_CFI', get_option('cfi'))
2187config_host_data.set('CONFIG_SELINUX', selinux.found())
2188config_host_data.set('CONFIG_XEN_BACKEND', xen.found())
2189config_host_data.set('CONFIG_LIBDW', libdw.found())
2190if xen.found()
2191  # protect from xen.version() having less than three components
2192  xen_version = xen.version().split('.') + ['0', '0']
2193  xen_ctrl_version = xen_version[0] + \
2194    ('0' + xen_version[1]).substring(-2) + \
2195    ('0' + xen_version[2]).substring(-2)
2196  config_host_data.set('CONFIG_XEN_CTRL_INTERFACE_VERSION', xen_ctrl_version)
2197endif
2198config_host_data.set('QEMU_VERSION', '"@0@"'.format(meson.project_version()))
2199config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0])
2200config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1])
2201config_host_data.set('QEMU_VERSION_MICRO', meson.project_version().split('.')[2])
2202
2203config_host_data.set_quoted('CONFIG_HOST_DSOSUF', host_dsosuf)
2204config_host_data.set('HAVE_HOST_BLOCK_DEVICE', have_host_block_device)
2205
2206have_coroutine_pool = get_option('coroutine_pool')
2207if get_option('debug_stack_usage') and have_coroutine_pool
2208  message('Disabling coroutine pool to measure stack usage')
2209  have_coroutine_pool = false
2210endif
2211config_host_data.set10('CONFIG_COROUTINE_POOL', have_coroutine_pool)
2212config_host_data.set('CONFIG_DEBUG_GRAPH_LOCK', get_option('debug_graph_lock'))
2213config_host_data.set('CONFIG_DEBUG_MUTEX', get_option('debug_mutex'))
2214config_host_data.set('CONFIG_DEBUG_STACK_USAGE', get_option('debug_stack_usage'))
2215config_host_data.set('CONFIG_DEBUG_TCG', get_option('debug_tcg'))
2216config_host_data.set('CONFIG_GPROF', get_option('gprof'))
2217config_host_data.set('CONFIG_LIVE_BLOCK_MIGRATION', get_option('live_block_migration').allowed())
2218config_host_data.set('CONFIG_QOM_CAST_DEBUG', get_option('qom_cast_debug'))
2219config_host_data.set('CONFIG_REPLICATION', get_option('replication').allowed())
2220
2221# has_header
2222config_host_data.set('CONFIG_EPOLL', cc.has_header('sys/epoll.h'))
2223config_host_data.set('CONFIG_LINUX_MAGIC_H', cc.has_header('linux/magic.h'))
2224config_host_data.set('CONFIG_VALGRIND_H', cc.has_header('valgrind/valgrind.h'))
2225config_host_data.set('HAVE_BTRFS_H', cc.has_header('linux/btrfs.h'))
2226config_host_data.set('HAVE_DRM_H', cc.has_header('libdrm/drm.h'))
2227config_host_data.set('HAVE_PTY_H', cc.has_header('pty.h'))
2228config_host_data.set('HAVE_SYS_DISK_H', cc.has_header('sys/disk.h'))
2229config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h'))
2230config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h'))
2231if targetos == 'windows'
2232  config_host_data.set('HAVE_AFUNIX_H', cc.has_header('afunix.h'))
2233endif
2234
2235# has_function
2236config_host_data.set('CONFIG_CLOSE_RANGE', cc.has_function('close_range'))
2237config_host_data.set('CONFIG_ACCEPT4', cc.has_function('accept4'))
2238config_host_data.set('CONFIG_CLOCK_ADJTIME', cc.has_function('clock_adjtime'))
2239config_host_data.set('CONFIG_DUP3', cc.has_function('dup3'))
2240config_host_data.set('CONFIG_FALLOCATE', cc.has_function('fallocate'))
2241config_host_data.set('CONFIG_POSIX_FALLOCATE', cc.has_function('posix_fallocate'))
2242config_host_data.set('CONFIG_GETCPU', cc.has_function('getcpu', prefix: gnu_source_prefix))
2243config_host_data.set('CONFIG_SCHED_GETCPU', cc.has_function('sched_getcpu', prefix: '#include <sched.h>'))
2244# Note that we need to specify prefix: here to avoid incorrectly
2245# thinking that Windows has posix_memalign()
2246config_host_data.set('CONFIG_POSIX_MEMALIGN', cc.has_function('posix_memalign', prefix: '#include <stdlib.h>'))
2247config_host_data.set('CONFIG_ALIGNED_MALLOC', cc.has_function('_aligned_malloc'))
2248config_host_data.set('CONFIG_VALLOC', cc.has_function('valloc'))
2249config_host_data.set('CONFIG_MEMALIGN', cc.has_function('memalign'))
2250config_host_data.set('CONFIG_PPOLL', cc.has_function('ppoll'))
2251config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include <sys/uio.h>'))
2252config_host_data.set('CONFIG_PTHREAD_FCHDIR_NP', cc.has_function('pthread_fchdir_np'))
2253config_host_data.set('CONFIG_SENDFILE', cc.has_function('sendfile'))
2254config_host_data.set('CONFIG_SETNS', cc.has_function('setns') and cc.has_function('unshare'))
2255config_host_data.set('CONFIG_SYNCFS', cc.has_function('syncfs'))
2256config_host_data.set('CONFIG_SYNC_FILE_RANGE', cc.has_function('sync_file_range'))
2257config_host_data.set('CONFIG_TIMERFD', cc.has_function('timerfd_create'))
2258config_host_data.set('HAVE_COPY_FILE_RANGE', cc.has_function('copy_file_range'))
2259config_host_data.set('HAVE_GETIFADDRS', cc.has_function('getifaddrs'))
2260config_host_data.set('HAVE_GLIB_WITH_SLICE_ALLOCATOR', glib_has_gslice)
2261config_host_data.set('HAVE_OPENPTY', cc.has_function('openpty', dependencies: util))
2262config_host_data.set('HAVE_STRCHRNUL', cc.has_function('strchrnul'))
2263config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: '#include <stdlib.h>'))
2264if rbd.found()
2265  config_host_data.set('HAVE_RBD_NAMESPACE_EXISTS',
2266                       cc.has_function('rbd_namespace_exists',
2267                                       dependencies: rbd,
2268                                       prefix: '#include <rbd/librbd.h>'))
2269endif
2270if rdma.found()
2271  config_host_data.set('HAVE_IBV_ADVISE_MR',
2272                       cc.has_function('ibv_advise_mr',
2273                                       dependencies: rdma,
2274                                       prefix: '#include <infiniband/verbs.h>'))
2275endif
2276
2277have_asan_fiber = false
2278if get_option('sanitizers') and \
2279   not cc.has_function('__sanitizer_start_switch_fiber',
2280                         args: '-fsanitize=address',
2281                         prefix: '#include <sanitizer/asan_interface.h>')
2282  warning('Missing ASAN due to missing fiber annotation interface')
2283  warning('Without code annotation, the report may be inferior.')
2284else
2285  have_asan_fiber = true
2286endif
2287config_host_data.set('CONFIG_ASAN_IFACE_FIBER', have_asan_fiber)
2288
2289# has_header_symbol
2290config_host_data.set('CONFIG_BLKZONED',
2291                     cc.has_header_symbol('linux/blkzoned.h', 'BLKOPENZONE'))
2292config_host_data.set('CONFIG_EPOLL_CREATE1',
2293                     cc.has_header_symbol('sys/epoll.h', 'epoll_create1'))
2294config_host_data.set('CONFIG_FALLOCATE_PUNCH_HOLE',
2295                     cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_PUNCH_HOLE') and
2296                     cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_KEEP_SIZE'))
2297config_host_data.set('CONFIG_FALLOCATE_ZERO_RANGE',
2298                     cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_ZERO_RANGE'))
2299config_host_data.set('CONFIG_FIEMAP',
2300                     cc.has_header('linux/fiemap.h') and
2301                     cc.has_header_symbol('linux/fs.h', 'FS_IOC_FIEMAP'))
2302config_host_data.set('CONFIG_GETRANDOM',
2303                     cc.has_function('getrandom') and
2304                     cc.has_header_symbol('sys/random.h', 'GRND_NONBLOCK'))
2305config_host_data.set('CONFIG_INOTIFY',
2306                     cc.has_header_symbol('sys/inotify.h', 'inotify_init'))
2307config_host_data.set('CONFIG_INOTIFY1',
2308                     cc.has_header_symbol('sys/inotify.h', 'inotify_init1'))
2309config_host_data.set('CONFIG_PRCTL_PR_SET_TIMERSLACK',
2310                     cc.has_header_symbol('sys/prctl.h', 'PR_SET_TIMERSLACK'))
2311config_host_data.set('CONFIG_RTNETLINK',
2312                     cc.has_header_symbol('linux/rtnetlink.h', 'IFLA_PROTO_DOWN'))
2313config_host_data.set('CONFIG_SYSMACROS',
2314                     cc.has_header_symbol('sys/sysmacros.h', 'makedev'))
2315config_host_data.set('HAVE_OPTRESET',
2316                     cc.has_header_symbol('getopt.h', 'optreset'))
2317config_host_data.set('HAVE_IPPROTO_MPTCP',
2318                     cc.has_header_symbol('netinet/in.h', 'IPPROTO_MPTCP'))
2319
2320# has_member
2321config_host_data.set('HAVE_SIGEV_NOTIFY_THREAD_ID',
2322                     cc.has_member('struct sigevent', 'sigev_notify_thread_id',
2323                                   prefix: '#include <signal.h>'))
2324config_host_data.set('HAVE_STRUCT_STAT_ST_ATIM',
2325                     cc.has_member('struct stat', 'st_atim',
2326                                   prefix: '#include <sys/stat.h>'))
2327config_host_data.set('HAVE_BLK_ZONE_REP_CAPACITY',
2328                     cc.has_member('struct blk_zone', 'capacity',
2329                                   prefix: '#include <linux/blkzoned.h>'))
2330
2331# has_type
2332config_host_data.set('CONFIG_IOVEC',
2333                     cc.has_type('struct iovec',
2334                                 prefix: '#include <sys/uio.h>'))
2335config_host_data.set('HAVE_UTMPX',
2336                     cc.has_type('struct utmpx',
2337                                 prefix: '#include <utmpx.h>'))
2338
2339config_host_data.set('CONFIG_EVENTFD', cc.links('''
2340  #include <sys/eventfd.h>
2341  int main(void) { return eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); }'''))
2342config_host_data.set('CONFIG_FDATASYNC', cc.links(gnu_source_prefix + '''
2343  #include <unistd.h>
2344  int main(void) {
2345  #if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
2346  return fdatasync(0);
2347  #else
2348  #error Not supported
2349  #endif
2350  }'''))
2351
2352has_madvise = cc.links(gnu_source_prefix + '''
2353  #include <sys/types.h>
2354  #include <sys/mman.h>
2355  #include <stddef.h>
2356  int main(void) { return madvise(NULL, 0, MADV_DONTNEED); }''')
2357missing_madvise_proto = false
2358if has_madvise
2359  # Some platforms (illumos and Solaris before Solaris 11) provide madvise()
2360  # but forget to prototype it. In this case, has_madvise will be true (the
2361  # test program links despite a compile warning). To detect the
2362  # missing-prototype case, we try again with a definitely-bogus prototype.
2363  # This will only compile if the system headers don't provide the prototype;
2364  # otherwise the conflicting prototypes will cause a compiler error.
2365  missing_madvise_proto = cc.links(gnu_source_prefix + '''
2366    #include <sys/types.h>
2367    #include <sys/mman.h>
2368    #include <stddef.h>
2369    extern int madvise(int);
2370    int main(void) { return madvise(0); }''')
2371endif
2372config_host_data.set('CONFIG_MADVISE', has_madvise)
2373config_host_data.set('HAVE_MADVISE_WITHOUT_PROTOTYPE', missing_madvise_proto)
2374
2375config_host_data.set('CONFIG_MEMFD', cc.links(gnu_source_prefix + '''
2376  #include <sys/mman.h>
2377  int main(void) { return memfd_create("foo", MFD_ALLOW_SEALING); }'''))
2378config_host_data.set('CONFIG_OPEN_BY_HANDLE', cc.links(gnu_source_prefix + '''
2379  #include <fcntl.h>
2380  #if !defined(AT_EMPTY_PATH)
2381  # error missing definition
2382  #else
2383  int main(void) { struct file_handle fh; return open_by_handle_at(0, &fh, 0); }
2384  #endif'''))
2385config_host_data.set('CONFIG_POSIX_MADVISE', cc.links(gnu_source_prefix + '''
2386  #include <sys/mman.h>
2387  #include <stddef.h>
2388  int main(void) { return posix_madvise(NULL, 0, POSIX_MADV_DONTNEED); }'''))
2389
2390config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_W_TID', cc.links(gnu_source_prefix + '''
2391  #include <pthread.h>
2392
2393  static void *f(void *p) { return NULL; }
2394  int main(void)
2395  {
2396    pthread_t thread;
2397    pthread_create(&thread, 0, f, 0);
2398    pthread_setname_np(thread, "QEMU");
2399    return 0;
2400  }''', dependencies: threads))
2401config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_WO_TID', cc.links(gnu_source_prefix + '''
2402  #include <pthread.h>
2403
2404  static void *f(void *p) { pthread_setname_np("QEMU"); return NULL; }
2405  int main(void)
2406  {
2407    pthread_t thread;
2408    pthread_create(&thread, 0, f, 0);
2409    return 0;
2410  }''', dependencies: threads))
2411config_host_data.set('CONFIG_PTHREAD_SET_NAME_NP', cc.links(gnu_source_prefix + '''
2412  #include <pthread.h>
2413  #include <pthread_np.h>
2414
2415  static void *f(void *p) { return NULL; }
2416  int main(void)
2417  {
2418    pthread_t thread;
2419    pthread_create(&thread, 0, f, 0);
2420    pthread_set_name_np(thread, "QEMU");
2421    return 0;
2422  }''', dependencies: threads))
2423config_host_data.set('CONFIG_PTHREAD_CONDATTR_SETCLOCK', cc.links(gnu_source_prefix + '''
2424  #include <pthread.h>
2425  #include <time.h>
2426
2427  int main(void)
2428  {
2429    pthread_condattr_t attr
2430    pthread_condattr_init(&attr);
2431    pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
2432    return 0;
2433  }''', dependencies: threads))
2434config_host_data.set('CONFIG_PTHREAD_AFFINITY_NP', cc.links(gnu_source_prefix + '''
2435  #include <pthread.h>
2436
2437  static void *f(void *p) { return NULL; }
2438  int main(void)
2439  {
2440    int setsize = CPU_ALLOC_SIZE(64);
2441    pthread_t thread;
2442    cpu_set_t *cpuset;
2443    pthread_create(&thread, 0, f, 0);
2444    cpuset = CPU_ALLOC(64);
2445    CPU_ZERO_S(setsize, cpuset);
2446    pthread_setaffinity_np(thread, setsize, cpuset);
2447    pthread_getaffinity_np(thread, setsize, cpuset);
2448    CPU_FREE(cpuset);
2449    return 0;
2450  }''', dependencies: threads))
2451config_host_data.set('CONFIG_SIGNALFD', cc.links(gnu_source_prefix + '''
2452  #include <sys/signalfd.h>
2453  #include <stddef.h>
2454  int main(void) { return signalfd(-1, NULL, SFD_CLOEXEC); }'''))
2455config_host_data.set('CONFIG_SPLICE', cc.links(gnu_source_prefix + '''
2456  #include <unistd.h>
2457  #include <fcntl.h>
2458  #include <limits.h>
2459
2460  int main(void)
2461  {
2462    int len, fd = 0;
2463    len = tee(STDIN_FILENO, STDOUT_FILENO, INT_MAX, SPLICE_F_NONBLOCK);
2464    splice(STDIN_FILENO, NULL, fd, NULL, len, SPLICE_F_MOVE);
2465    return 0;
2466  }'''))
2467
2468config_host_data.set('HAVE_MLOCKALL', cc.links(gnu_source_prefix + '''
2469  #include <sys/mman.h>
2470  int main(void) {
2471    return mlockall(MCL_FUTURE);
2472  }'''))
2473
2474have_l2tpv3 = false
2475if get_option('l2tpv3').allowed() and have_system
2476  have_l2tpv3 = cc.has_type('struct mmsghdr',
2477    prefix: gnu_source_prefix + '''
2478      #include <sys/socket.h>
2479      #include <linux/ip.h>''')
2480endif
2481config_host_data.set('CONFIG_L2TPV3', have_l2tpv3)
2482
2483have_netmap = false
2484if get_option('netmap').allowed() and have_system
2485  have_netmap = cc.compiles('''
2486    #include <inttypes.h>
2487    #include <net/if.h>
2488    #include <net/netmap.h>
2489    #include <net/netmap_user.h>
2490    #if (NETMAP_API < 11) || (NETMAP_API > 15)
2491    #error
2492    #endif
2493    int main(void) { return 0; }''')
2494  if not have_netmap and get_option('netmap').enabled()
2495    error('Netmap headers not available')
2496  endif
2497endif
2498config_host_data.set('CONFIG_NETMAP', have_netmap)
2499
2500# Work around a system header bug with some kernel/XFS header
2501# versions where they both try to define 'struct fsxattr':
2502# xfs headers will not try to redefine structs from linux headers
2503# if this macro is set.
2504config_host_data.set('HAVE_FSXATTR', cc.links('''
2505  #include <linux/fs.h>
2506  struct fsxattr foo;
2507  int main(void) {
2508    return 0;
2509  }'''))
2510
2511# Some versions of Mac OS X incorrectly define SIZE_MAX
2512config_host_data.set('HAVE_BROKEN_SIZE_MAX', not cc.compiles('''
2513    #include <stdint.h>
2514    #include <stdio.h>
2515    int main(void) {
2516        return printf("%zu", SIZE_MAX);
2517    }''', args: ['-Werror']))
2518
2519# See if 64-bit atomic operations are supported.
2520# Note that without __atomic builtins, we can only
2521# assume atomic loads/stores max at pointer size.
2522config_host_data.set('CONFIG_ATOMIC64', cc.links('''
2523  #include <stdint.h>
2524  int main(void)
2525  {
2526    uint64_t x = 0, y = 0;
2527    y = __atomic_load_n(&x, __ATOMIC_RELAXED);
2528    __atomic_store_n(&x, y, __ATOMIC_RELAXED);
2529    __atomic_compare_exchange_n(&x, &y, x, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
2530    __atomic_exchange_n(&x, y, __ATOMIC_RELAXED);
2531    __atomic_fetch_add(&x, y, __ATOMIC_RELAXED);
2532    return 0;
2533  }'''))
2534
2535has_int128_type = cc.compiles('''
2536  __int128_t a;
2537  __uint128_t b;
2538  int main(void) { b = a; }''')
2539config_host_data.set('CONFIG_INT128_TYPE', has_int128_type)
2540
2541has_int128 = has_int128_type and cc.links('''
2542  __int128_t a;
2543  __uint128_t b;
2544  int main (void) {
2545    a = a + b;
2546    b = a * b;
2547    a = a * a;
2548    return 0;
2549  }''')
2550config_host_data.set('CONFIG_INT128', has_int128)
2551
2552if has_int128_type
2553  # "do we have 128-bit atomics which are handled inline and specifically not
2554  # via libatomic". The reason we can't use libatomic is documented in the
2555  # comment starting "GCC is a house divided" in include/qemu/atomic128.h.
2556  # We only care about these operations on 16-byte aligned pointers, so
2557  # force 16-byte alignment of the pointer, which may be greater than
2558  # __alignof(unsigned __int128) for the host.
2559  atomic_test_128 = '''
2560    int main(int ac, char **av) {
2561      __uint128_t *p = __builtin_assume_aligned(av[ac - 1], 16);
2562      p[1] = __atomic_load_n(&p[0], __ATOMIC_RELAXED);
2563      __atomic_store_n(&p[2], p[3], __ATOMIC_RELAXED);
2564      __atomic_compare_exchange_n(&p[4], &p[5], p[6], 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
2565      return 0;
2566    }'''
2567  has_atomic128 = cc.links(atomic_test_128)
2568
2569  config_host_data.set('CONFIG_ATOMIC128', has_atomic128)
2570
2571  if not has_atomic128
2572    # Even with __builtin_assume_aligned, the above test may have failed
2573    # without optimization enabled.  Try again with optimizations locally
2574    # enabled for the function.  See
2575    #   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107389
2576    has_atomic128_opt = cc.links('__attribute__((optimize("O1")))' + atomic_test_128)
2577    config_host_data.set('CONFIG_ATOMIC128_OPT', has_atomic128_opt)
2578
2579    if not has_atomic128_opt
2580      config_host_data.set('CONFIG_CMPXCHG128', cc.links('''
2581        int main(void)
2582        {
2583          __uint128_t x = 0, y = 0;
2584          __sync_val_compare_and_swap_16(&x, y, x);
2585          return 0;
2586        }
2587      '''))
2588    endif
2589  endif
2590endif
2591
2592config_host_data.set('CONFIG_GETAUXVAL', cc.links(gnu_source_prefix + '''
2593  #include <sys/auxv.h>
2594  int main(void) {
2595    return getauxval(AT_HWCAP) == 0;
2596  }'''))
2597
2598config_host_data.set('CONFIG_USBFS', have_linux_user and cc.compiles('''
2599  #include <linux/usbdevice_fs.h>
2600
2601  #ifndef USBDEVFS_GET_CAPABILITIES
2602  #error "USBDEVFS_GET_CAPABILITIES undefined"
2603  #endif
2604
2605  #ifndef USBDEVFS_DISCONNECT_CLAIM
2606  #error "USBDEVFS_DISCONNECT_CLAIM undefined"
2607  #endif
2608
2609  int main(void) { return 0; }'''))
2610
2611have_keyring = get_option('keyring') \
2612  .require(targetos == 'linux', error_message: 'keyring is only available on Linux') \
2613  .require(cc.compiles('''
2614    #include <errno.h>
2615    #include <asm/unistd.h>
2616    #include <linux/keyctl.h>
2617    #include <sys/syscall.h>
2618    #include <unistd.h>
2619    int main(void) {
2620        return syscall(__NR_keyctl, KEYCTL_READ, 0, NULL, NULL, 0);
2621    }'''), error_message: 'keyctl syscall not available on this system').allowed()
2622config_host_data.set('CONFIG_SECRET_KEYRING', have_keyring)
2623
2624have_cpuid_h = cc.links('''
2625  #include <cpuid.h>
2626  int main(void) {
2627    unsigned a, b, c, d;
2628    unsigned max = __get_cpuid_max(0, 0);
2629
2630    if (max >= 1) {
2631        __cpuid(1, a, b, c, d);
2632    }
2633
2634    if (max >= 7) {
2635        __cpuid_count(7, 0, a, b, c, d);
2636    }
2637
2638    return 0;
2639  }''')
2640config_host_data.set('CONFIG_CPUID_H', have_cpuid_h)
2641
2642config_host_data.set('CONFIG_AVX2_OPT', get_option('avx2') \
2643  .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX2') \
2644  .require(cc.links('''
2645    #include <cpuid.h>
2646    #include <immintrin.h>
2647    static int __attribute__((target("avx2"))) bar(void *a) {
2648      __m256i x = *(__m256i *)a;
2649      return _mm256_testz_si256(x, x);
2650    }
2651    int main(int argc, char *argv[]) { return bar(argv[argc - 1]); }
2652  '''), error_message: 'AVX2 not available').allowed())
2653
2654config_host_data.set('CONFIG_AVX512F_OPT', get_option('avx512f') \
2655  .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX512F') \
2656  .require(cc.links('''
2657    #include <cpuid.h>
2658    #include <immintrin.h>
2659    static int __attribute__((target("avx512f"))) bar(void *a) {
2660      __m512i x = *(__m512i *)a;
2661      return _mm512_test_epi64_mask(x, x);
2662    }
2663    int main(int argc, char *argv[]) { return bar(argv[argc - 1]); }
2664  '''), error_message: 'AVX512F not available').allowed())
2665
2666config_host_data.set('CONFIG_AVX512BW_OPT', get_option('avx512bw') \
2667  .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX512BW') \
2668  .require(cc.links('''
2669    #include <cpuid.h>
2670    #include <immintrin.h>
2671    static int __attribute__((target("avx512bw"))) bar(void *a) {
2672      __m512i *x = a;
2673      __m512i res= _mm512_abs_epi8(*x);
2674      return res[1];
2675    }
2676    int main(int argc, char *argv[]) { return bar(argv[0]); }
2677  '''), error_message: 'AVX512BW not available').allowed())
2678
2679# For both AArch64 and AArch32, detect if builtins are available.
2680config_host_data.set('CONFIG_ARM_AES_BUILTIN', cc.compiles('''
2681    #include <arm_neon.h>
2682    #ifndef __ARM_FEATURE_AES
2683    __attribute__((target("+crypto")))
2684    #endif
2685    void foo(uint8x16_t *p) { *p = vaesmcq_u8(*p); }
2686  '''))
2687
2688have_pvrdma = get_option('pvrdma') \
2689  .require(rdma.found(), error_message: 'PVRDMA requires OpenFabrics libraries') \
2690  .require(cc.compiles(gnu_source_prefix + '''
2691    #include <sys/mman.h>
2692    int main(void)
2693    {
2694      char buf = 0;
2695      void *addr = &buf;
2696      addr = mremap(addr, 0, 1, MREMAP_MAYMOVE | MREMAP_FIXED);
2697
2698      return 0;
2699    }'''), error_message: 'PVRDMA requires mremap').allowed()
2700
2701if have_pvrdma
2702  config_host_data.set('LEGACY_RDMA_REG_MR', not cc.links('''
2703    #include <infiniband/verbs.h>
2704    int main(void)
2705    {
2706      struct ibv_mr *mr;
2707      struct ibv_pd *pd = NULL;
2708      size_t length = 10;
2709      uint64_t iova = 0;
2710      int access = 0;
2711      void *addr = NULL;
2712
2713      mr = ibv_reg_mr_iova(pd, addr, length, iova, access);
2714      ibv_dereg_mr(mr);
2715      return 0;
2716    }'''))
2717endif
2718
2719if get_option('membarrier').disabled()
2720  have_membarrier = false
2721elif targetos == 'windows'
2722  have_membarrier = true
2723elif targetos == 'linux'
2724  have_membarrier = cc.compiles('''
2725    #include <linux/membarrier.h>
2726    #include <sys/syscall.h>
2727    #include <unistd.h>
2728    #include <stdlib.h>
2729    int main(void) {
2730        syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0);
2731        syscall(__NR_membarrier, MEMBARRIER_CMD_SHARED, 0);
2732        exit(0);
2733    }''')
2734endif
2735config_host_data.set('CONFIG_MEMBARRIER', get_option('membarrier') \
2736  .require(have_membarrier, error_message: 'membarrier system call not available') \
2737  .allowed())
2738
2739have_afalg = get_option('crypto_afalg') \
2740  .require(cc.compiles(gnu_source_prefix + '''
2741    #include <errno.h>
2742    #include <sys/types.h>
2743    #include <sys/socket.h>
2744    #include <linux/if_alg.h>
2745    int main(void) {
2746      int sock;
2747      sock = socket(AF_ALG, SOCK_SEQPACKET, 0);
2748      return sock;
2749    }
2750  '''), error_message: 'AF_ALG requested but could not be detected').allowed()
2751config_host_data.set('CONFIG_AF_ALG', have_afalg)
2752
2753config_host_data.set('CONFIG_AF_VSOCK', cc.has_header_symbol(
2754  'linux/vm_sockets.h', 'AF_VSOCK',
2755  prefix: '#include <sys/socket.h>',
2756))
2757
2758have_vss = false
2759have_vss_sdk = false # old xp/2003 SDK
2760if targetos == 'windows' and 'cpp' in all_languages
2761  have_vss = cxx.compiles('''
2762    #define __MIDL_user_allocate_free_DEFINED__
2763    #include <vss.h>
2764    int main(void) { return VSS_CTX_BACKUP; }''')
2765  have_vss_sdk = cxx.has_header('vscoordint.h')
2766endif
2767config_host_data.set('HAVE_VSS_SDK', have_vss_sdk)
2768
2769# Older versions of MinGW do not import _lock_file and _unlock_file properly.
2770# This was fixed for v6.0.0 with commit b48e3ac8969d.
2771if targetos == 'windows'
2772  config_host_data.set('HAVE__LOCK_FILE', cc.links('''
2773    #include <stdio.h>
2774    int main(void) {
2775      _lock_file(NULL);
2776      _unlock_file(NULL);
2777      return 0;
2778    }''', name: '_lock_file and _unlock_file'))
2779endif
2780
2781if targetos == 'windows'
2782  mingw_has_setjmp_longjmp = cc.links('''
2783    #include <setjmp.h>
2784    int main(void) {
2785      /*
2786       * These functions are not available in setjmp header, but may be
2787       * available at link time, from libmingwex.a.
2788       */
2789      extern int __mingw_setjmp(jmp_buf);
2790      extern void __attribute__((noreturn)) __mingw_longjmp(jmp_buf, int);
2791      jmp_buf env;
2792      __mingw_setjmp(env);
2793      __mingw_longjmp(env, 0);
2794    }
2795  ''', name: 'mingw setjmp and longjmp')
2796
2797  if cpu == 'aarch64' and not mingw_has_setjmp_longjmp
2798    error('mingw must provide setjmp/longjmp for windows-arm64')
2799  endif
2800endif
2801
2802########################
2803# Target configuration #
2804########################
2805
2806minikconf = find_program('scripts/minikconf.py')
2807config_targetos = {
2808  (targetos == 'windows' ? 'CONFIG_WIN32' : 'CONFIG_POSIX'): 'y'
2809}
2810if targetos == 'darwin'
2811  config_targetos += {'CONFIG_DARWIN': 'y'}
2812elif targetos == 'linux'
2813  config_targetos += {'CONFIG_LINUX': 'y'}
2814endif
2815if targetos in bsd_oses
2816  config_targetos += {'CONFIG_BSD': 'y'}
2817endif
2818
2819config_all = {}
2820config_all_devices = {}
2821config_all_disas = {}
2822config_devices_mak_list = []
2823config_devices_h = {}
2824config_target_h = {}
2825config_target_mak = {}
2826
2827disassemblers = {
2828  'alpha' : ['CONFIG_ALPHA_DIS'],
2829  'avr' : ['CONFIG_AVR_DIS'],
2830  'cris' : ['CONFIG_CRIS_DIS'],
2831  'hexagon' : ['CONFIG_HEXAGON_DIS'],
2832  'hppa' : ['CONFIG_HPPA_DIS'],
2833  'i386' : ['CONFIG_I386_DIS'],
2834  'x86_64' : ['CONFIG_I386_DIS'],
2835  'm68k' : ['CONFIG_M68K_DIS'],
2836  'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
2837  'mips' : ['CONFIG_MIPS_DIS'],
2838  'nios2' : ['CONFIG_NIOS2_DIS'],
2839  'or1k' : ['CONFIG_OPENRISC_DIS'],
2840  'ppc' : ['CONFIG_PPC_DIS'],
2841  'riscv' : ['CONFIG_RISCV_DIS'],
2842  'rx' : ['CONFIG_RX_DIS'],
2843  's390' : ['CONFIG_S390_DIS'],
2844  'sh4' : ['CONFIG_SH4_DIS'],
2845  'sparc' : ['CONFIG_SPARC_DIS'],
2846  'xtensa' : ['CONFIG_XTENSA_DIS'],
2847  'loongarch' : ['CONFIG_LOONGARCH_DIS'],
2848}
2849
2850have_ivshmem = config_host_data.get('CONFIG_EVENTFD')
2851host_kconfig = \
2852  (get_option('fuzzing') ? ['CONFIG_FUZZ=y'] : []) + \
2853  (have_tpm ? ['CONFIG_TPM=y'] : []) + \
2854  (spice.found() ? ['CONFIG_SPICE=y'] : []) + \
2855  (have_ivshmem ? ['CONFIG_IVSHMEM=y'] : []) + \
2856  (opengl.found() ? ['CONFIG_OPENGL=y'] : []) + \
2857  (x11.found() ? ['CONFIG_X11=y'] : []) + \
2858  (have_vhost_user ? ['CONFIG_VHOST_USER=y'] : []) + \
2859  (have_vhost_vdpa ? ['CONFIG_VHOST_VDPA=y'] : []) + \
2860  (have_vhost_kernel ? ['CONFIG_VHOST_KERNEL=y'] : []) + \
2861  (have_virtfs ? ['CONFIG_VIRTFS=y'] : []) + \
2862  (targetos == 'linux' ? ['CONFIG_LINUX=y'] : []) + \
2863  (have_pvrdma ? ['CONFIG_PVRDMA=y'] : []) + \
2864  (multiprocess_allowed ? ['CONFIG_MULTIPROCESS_ALLOWED=y'] : []) + \
2865  (vfio_user_server_allowed ? ['CONFIG_VFIO_USER_SERVER_ALLOWED=y'] : [])
2866
2867ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ]
2868
2869default_targets = 'CONFIG_DEFAULT_TARGETS' in config_host
2870actual_target_dirs = []
2871fdt_required = []
2872foreach target : target_dirs
2873  config_target = { 'TARGET_NAME': target.split('-')[0] }
2874  if target.endswith('linux-user')
2875    if targetos != 'linux'
2876      if default_targets
2877        continue
2878      endif
2879      error('Target @0@ is only available on a Linux host'.format(target))
2880    endif
2881    config_target += { 'CONFIG_LINUX_USER': 'y' }
2882  elif target.endswith('bsd-user')
2883    if targetos not in bsd_oses
2884      if default_targets
2885        continue
2886      endif
2887      error('Target @0@ is only available on a BSD host'.format(target))
2888    endif
2889    config_target += { 'CONFIG_BSD_USER': 'y' }
2890  elif target.endswith('softmmu')
2891    config_target += { 'CONFIG_SYSTEM_ONLY': 'y' }
2892    config_target += { 'CONFIG_SOFTMMU': 'y' }
2893  endif
2894  if target.endswith('-user')
2895    config_target += {
2896      'CONFIG_USER_ONLY': 'y',
2897      'CONFIG_QEMU_INTERP_PREFIX':
2898        get_option('interp_prefix').replace('%M', config_target['TARGET_NAME'])
2899    }
2900  endif
2901
2902  accel_kconfig = []
2903  foreach sym: accelerators
2904    if sym == 'CONFIG_TCG' or target in accelerator_targets.get(sym, [])
2905      config_target += { sym: 'y' }
2906      config_all += { sym: 'y' }
2907      if target in modular_tcg
2908        config_target += { 'CONFIG_TCG_MODULAR': 'y' }
2909      else
2910        config_target += { 'CONFIG_TCG_BUILTIN': 'y' }
2911      endif
2912      accel_kconfig += [ sym + '=y' ]
2913    endif
2914  endforeach
2915  if accel_kconfig.length() == 0
2916    if default_targets
2917      continue
2918    endif
2919    error('No accelerator available for target @0@'.format(target))
2920  endif
2921
2922  actual_target_dirs += target
2923  config_target += keyval.load('configs/targets' / target + '.mak')
2924  config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
2925
2926  if 'TARGET_NEED_FDT' in config_target
2927    fdt_required += target
2928  endif
2929
2930  # Add default keys
2931  if 'TARGET_BASE_ARCH' not in config_target
2932    config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
2933  endif
2934  if 'TARGET_ABI_DIR' not in config_target
2935    config_target += {'TARGET_ABI_DIR': config_target['TARGET_ARCH']}
2936  endif
2937  if 'TARGET_BIG_ENDIAN' not in config_target
2938    config_target += {'TARGET_BIG_ENDIAN': 'n'}
2939  endif
2940
2941  foreach k, v: disassemblers
2942    if host_arch.startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k)
2943      foreach sym: v
2944        config_target += { sym: 'y' }
2945        config_all_disas += { sym: 'y' }
2946      endforeach
2947    endif
2948  endforeach
2949
2950  config_target_data = configuration_data()
2951  foreach k, v: config_target
2952    if not k.startswith('TARGET_') and not k.startswith('CONFIG_')
2953      # do nothing
2954    elif ignored.contains(k)
2955      # do nothing
2956    elif k == 'TARGET_BASE_ARCH'
2957      # Note that TARGET_BASE_ARCH ends up in config-target.h but it is
2958      # not used to select files from sourcesets.
2959      config_target_data.set('TARGET_' + v.to_upper(), 1)
2960    elif k == 'TARGET_NAME' or k == 'CONFIG_QEMU_INTERP_PREFIX'
2961      config_target_data.set_quoted(k, v)
2962    elif v == 'y'
2963      config_target_data.set(k, 1)
2964    elif v == 'n'
2965      config_target_data.set(k, 0)
2966    else
2967      config_target_data.set(k, v)
2968    endif
2969  endforeach
2970  config_target_data.set('QEMU_ARCH',
2971                         'QEMU_ARCH_' + config_target['TARGET_BASE_ARCH'].to_upper())
2972  config_target_h += {target: configure_file(output: target + '-config-target.h',
2973                                               configuration: config_target_data)}
2974
2975  if target.endswith('-softmmu')
2976    config_input = meson.get_external_property(target, 'default')
2977    config_devices_mak = target + '-config-devices.mak'
2978    config_devices_mak = configure_file(
2979      input: ['configs/devices' / target / config_input + '.mak', 'Kconfig'],
2980      output: config_devices_mak,
2981      depfile: config_devices_mak + '.d',
2982      capture: true,
2983      command: [minikconf,
2984                get_option('default_devices') ? '--defconfig' : '--allnoconfig',
2985                config_devices_mak, '@DEPFILE@', '@INPUT@',
2986                host_kconfig, accel_kconfig,
2987                'CONFIG_' + config_target['TARGET_ARCH'].to_upper() + '=y'])
2988
2989    config_devices_data = configuration_data()
2990    config_devices = keyval.load(config_devices_mak)
2991    foreach k, v: config_devices
2992      config_devices_data.set(k, 1)
2993    endforeach
2994    config_devices_mak_list += config_devices_mak
2995    config_devices_h += {target: configure_file(output: target + '-config-devices.h',
2996                                                configuration: config_devices_data)}
2997    config_target += config_devices
2998    config_all_devices += config_devices
2999  endif
3000  config_target_mak += {target: config_target}
3001endforeach
3002target_dirs = actual_target_dirs
3003
3004# This configuration is used to build files that are shared by
3005# multiple binaries, and then extracted out of the "common"
3006# static_library target.
3007#
3008# We do not use all_sources()/all_dependencies(), because it would
3009# build literally all source files, including devices only used by
3010# targets that are not built for this compilation.  The CONFIG_ALL
3011# pseudo symbol replaces it.
3012
3013config_all += config_all_devices
3014config_all += config_targetos
3015config_all += config_all_disas
3016config_all += {
3017  'CONFIG_XEN': xen.found(),
3018  'CONFIG_SYSTEM_ONLY': have_system,
3019  'CONFIG_USER_ONLY': have_user,
3020  'CONFIG_ALL': true,
3021}
3022
3023target_configs_h = []
3024foreach target: target_dirs
3025  target_configs_h += config_target_h[target]
3026  target_configs_h += config_devices_h.get(target, [])
3027endforeach
3028genh += custom_target('config-poison.h',
3029                      input: [target_configs_h],
3030                      output: 'config-poison.h',
3031                      capture: true,
3032                      command: [find_program('scripts/make-config-poison.sh'),
3033                                target_configs_h])
3034
3035##############
3036# Submodules #
3037##############
3038
3039capstone = not_found
3040if not get_option('capstone').auto() or have_system or have_user
3041  capstone = dependency('capstone', version: '>=3.0.5',
3042                        method: 'pkg-config',
3043                        required: get_option('capstone'))
3044
3045  # Some versions of capstone have broken pkg-config file
3046  # that reports a wrong -I path, causing the #include to
3047  # fail later. If the system has such a broken version
3048  # do not use it.
3049  if capstone.found() and not cc.compiles('#include <capstone.h>',
3050                                          dependencies: [capstone])
3051    capstone = not_found
3052    if get_option('capstone').enabled()
3053      error('capstone requested, but it does not appear to work')
3054    endif
3055  endif
3056endif
3057
3058libvfio_user_dep = not_found
3059if have_system and vfio_user_server_allowed
3060  libvfio_user_proj = subproject('libvfio-user', required: true)
3061  libvfio_user_dep = libvfio_user_proj.get_variable('libvfio_user_dep')
3062endif
3063
3064fdt = not_found
3065fdt_opt = get_option('fdt')
3066if fdt_required.length() > 0 or fdt_opt == 'enabled'
3067  if fdt_opt == 'disabled'
3068    error('fdt disabled but required by targets ' + ', '.join(fdt_required))
3069  endif
3070
3071  if fdt_opt in ['enabled', 'auto', 'system']
3072    fdt = cc.find_library('fdt', required: fdt_opt == 'system')
3073    if fdt.found() and cc.links('''
3074       #include <libfdt.h>
3075       #include <libfdt_env.h>
3076       int main(void) { fdt_find_max_phandle(NULL, NULL); return 0; }''',
3077         dependencies: fdt)
3078      fdt_opt = 'system'
3079    elif fdt_opt == 'system'
3080       error('system libfdt requested, but it is too old (1.5.1 or newer required)')
3081    else
3082      fdt_opt = 'internal'
3083      fdt = not_found
3084    endif
3085  endif
3086  if not fdt.found()
3087    assert(fdt_opt == 'internal')
3088    libfdt_proj = subproject('dtc', required: true,
3089                             default_options: ['tools=false',  'yaml=disabled',
3090                                               'python=disabled', 'default_library=static'])
3091    fdt = libfdt_proj.get_variable('libfdt_dep')
3092  endif
3093else
3094  fdt_opt = 'disabled'
3095endif
3096
3097config_host_data.set('CONFIG_CAPSTONE', capstone.found())
3098config_host_data.set('CONFIG_FDT', fdt.found())
3099config_host_data.set('CONFIG_SLIRP', slirp.found())
3100
3101#####################
3102# Generated sources #
3103#####################
3104
3105genh += configure_file(output: 'config-host.h', configuration: config_host_data)
3106
3107hxtool = find_program('scripts/hxtool')
3108shaderinclude = find_program('scripts/shaderinclude.py')
3109qapi_gen = find_program('scripts/qapi-gen.py')
3110qapi_gen_depends = [ meson.current_source_dir() / 'scripts/qapi/__init__.py',
3111                     meson.current_source_dir() / 'scripts/qapi/commands.py',
3112                     meson.current_source_dir() / 'scripts/qapi/common.py',
3113                     meson.current_source_dir() / 'scripts/qapi/error.py',
3114                     meson.current_source_dir() / 'scripts/qapi/events.py',
3115                     meson.current_source_dir() / 'scripts/qapi/expr.py',
3116                     meson.current_source_dir() / 'scripts/qapi/gen.py',
3117                     meson.current_source_dir() / 'scripts/qapi/introspect.py',
3118                     meson.current_source_dir() / 'scripts/qapi/main.py',
3119                     meson.current_source_dir() / 'scripts/qapi/parser.py',
3120                     meson.current_source_dir() / 'scripts/qapi/schema.py',
3121                     meson.current_source_dir() / 'scripts/qapi/source.py',
3122                     meson.current_source_dir() / 'scripts/qapi/types.py',
3123                     meson.current_source_dir() / 'scripts/qapi/visit.py',
3124                     meson.current_source_dir() / 'scripts/qapi-gen.py'
3125]
3126
3127tracetool = [
3128  python, files('scripts/tracetool.py'),
3129   '--backend=' + ','.join(get_option('trace_backends'))
3130]
3131tracetool_depends = files(
3132  'scripts/tracetool/backend/log.py',
3133  'scripts/tracetool/backend/__init__.py',
3134  'scripts/tracetool/backend/dtrace.py',
3135  'scripts/tracetool/backend/ftrace.py',
3136  'scripts/tracetool/backend/simple.py',
3137  'scripts/tracetool/backend/syslog.py',
3138  'scripts/tracetool/backend/ust.py',
3139  'scripts/tracetool/format/ust_events_c.py',
3140  'scripts/tracetool/format/ust_events_h.py',
3141  'scripts/tracetool/format/__init__.py',
3142  'scripts/tracetool/format/d.py',
3143  'scripts/tracetool/format/simpletrace_stap.py',
3144  'scripts/tracetool/format/c.py',
3145  'scripts/tracetool/format/h.py',
3146  'scripts/tracetool/format/log_stap.py',
3147  'scripts/tracetool/format/stap.py',
3148  'scripts/tracetool/__init__.py',
3149  'scripts/tracetool/vcpu.py'
3150)
3151
3152qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
3153                    meson.current_source_dir(),
3154                    get_option('pkgversion'), meson.project_version()]
3155qemu_version = custom_target('qemu-version.h',
3156                             output: 'qemu-version.h',
3157                             command: qemu_version_cmd,
3158                             capture: true,
3159                             build_by_default: true,
3160                             build_always_stale: true)
3161genh += qemu_version
3162
3163hxdep = []
3164hx_headers = [
3165  ['qemu-options.hx', 'qemu-options.def'],
3166  ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
3167]
3168if have_system
3169  hx_headers += [
3170    ['hmp-commands.hx', 'hmp-commands.h'],
3171    ['hmp-commands-info.hx', 'hmp-commands-info.h'],
3172  ]
3173endif
3174foreach d : hx_headers
3175  hxdep += custom_target(d[1],
3176                input: files(d[0]),
3177                output: d[1],
3178                capture: true,
3179                build_by_default: true, # to be removed when added to a target
3180                command: [hxtool, '-h', '@INPUT0@'])
3181endforeach
3182genh += hxdep
3183
3184###################
3185# Collect sources #
3186###################
3187
3188authz_ss = ss.source_set()
3189blockdev_ss = ss.source_set()
3190block_ss = ss.source_set()
3191chardev_ss = ss.source_set()
3192common_ss = ss.source_set()
3193crypto_ss = ss.source_set()
3194hwcore_ss = ss.source_set()
3195io_ss = ss.source_set()
3196qmp_ss = ss.source_set()
3197qom_ss = ss.source_set()
3198system_ss = ss.source_set()
3199specific_fuzz_ss = ss.source_set()
3200specific_ss = ss.source_set()
3201stub_ss = ss.source_set()
3202trace_ss = ss.source_set()
3203user_ss = ss.source_set()
3204util_ss = ss.source_set()
3205
3206# accel modules
3207qtest_module_ss = ss.source_set()
3208tcg_module_ss = ss.source_set()
3209
3210modules = {}
3211target_modules = {}
3212hw_arch = {}
3213target_arch = {}
3214target_softmmu_arch = {}
3215target_user_arch = {}
3216
3217###############
3218# Trace files #
3219###############
3220
3221# TODO: add each directory to the subdirs from its own meson.build, once
3222# we have those
3223trace_events_subdirs = [
3224  'crypto',
3225  'qapi',
3226  'qom',
3227  'monitor',
3228  'util',
3229  'gdbstub',
3230]
3231if have_linux_user
3232  trace_events_subdirs += [ 'linux-user' ]
3233endif
3234if have_bsd_user
3235  trace_events_subdirs += [ 'bsd-user' ]
3236endif
3237if have_block
3238  trace_events_subdirs += [
3239    'authz',
3240    'block',
3241    'io',
3242    'nbd',
3243    'scsi',
3244  ]
3245endif
3246if have_system
3247  trace_events_subdirs += [
3248    'accel/kvm',
3249    'audio',
3250    'backends',
3251    'backends/tpm',
3252    'chardev',
3253    'ebpf',
3254    'hw/9pfs',
3255    'hw/acpi',
3256    'hw/adc',
3257    'hw/alpha',
3258    'hw/arm',
3259    'hw/audio',
3260    'hw/block',
3261    'hw/block/dataplane',
3262    'hw/char',
3263    'hw/display',
3264    'hw/dma',
3265    'hw/hyperv',
3266    'hw/i2c',
3267    'hw/i386',
3268    'hw/i386/xen',
3269    'hw/i386/kvm',
3270    'hw/ide',
3271    'hw/input',
3272    'hw/intc',
3273    'hw/isa',
3274    'hw/mem',
3275    'hw/mips',
3276    'hw/misc',
3277    'hw/misc/macio',
3278    'hw/net',
3279    'hw/net/can',
3280    'hw/nubus',
3281    'hw/nvme',
3282    'hw/nvram',
3283    'hw/pci',
3284    'hw/pci-host',
3285    'hw/ppc',
3286    'hw/rdma',
3287    'hw/rdma/vmw',
3288    'hw/rtc',
3289    'hw/s390x',
3290    'hw/scsi',
3291    'hw/sd',
3292    'hw/sh4',
3293    'hw/sparc',
3294    'hw/sparc64',
3295    'hw/ssi',
3296    'hw/timer',
3297    'hw/tpm',
3298    'hw/ufs',
3299    'hw/usb',
3300    'hw/vfio',
3301    'hw/virtio',
3302    'hw/watchdog',
3303    'hw/xen',
3304    'hw/gpio',
3305    'migration',
3306    'net',
3307    'softmmu',
3308    'ui',
3309    'hw/remote',
3310  ]
3311endif
3312if have_system or have_user
3313  trace_events_subdirs += [
3314    'accel/tcg',
3315    'hw/core',
3316    'target/arm',
3317    'target/arm/hvf',
3318    'target/hppa',
3319    'target/i386',
3320    'target/i386/kvm',
3321    'target/mips/tcg',
3322    'target/nios2',
3323    'target/ppc',
3324    'target/riscv',
3325    'target/s390x',
3326    'target/s390x/kvm',
3327    'target/sparc',
3328  ]
3329endif
3330
3331vhost_user = not_found
3332if targetos == 'linux' and have_vhost_user
3333  libvhost_user = subproject('libvhost-user')
3334  vhost_user = libvhost_user.get_variable('vhost_user_dep')
3335endif
3336
3337libvduse = not_found
3338if have_libvduse
3339  libvduse_proj = subproject('libvduse')
3340  libvduse = libvduse_proj.get_variable('libvduse_dep')
3341endif
3342
3343# NOTE: the trace/ subdirectory needs the qapi_trace_events variable
3344# that is filled in by qapi/.
3345subdir('qapi')
3346subdir('qobject')
3347subdir('stubs')
3348subdir('trace')
3349subdir('util')
3350subdir('qom')
3351subdir('authz')
3352subdir('crypto')
3353subdir('ui')
3354subdir('hw')
3355subdir('gdbstub')
3356
3357if enable_modules
3358  libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
3359  modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
3360endif
3361
3362qom_ss = qom_ss.apply(config_targetos, strict: false)
3363libqom = static_library('qom', qom_ss.sources() + genh,
3364                        dependencies: [qom_ss.dependencies()],
3365                        name_suffix: 'fa')
3366qom = declare_dependency(link_whole: libqom)
3367
3368event_loop_base = files('event-loop-base.c')
3369event_loop_base = static_library('event-loop-base', sources: event_loop_base + genh,
3370                                 build_by_default: true)
3371event_loop_base = declare_dependency(link_whole: event_loop_base,
3372                                     dependencies: [qom])
3373
3374stub_ss = stub_ss.apply(config_all, strict: false)
3375
3376util_ss.add_all(trace_ss)
3377util_ss = util_ss.apply(config_all, strict: false)
3378libqemuutil = static_library('qemuutil',
3379                             sources: util_ss.sources() + stub_ss.sources() + genh,
3380                             dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc, pixman])
3381qemuutil = declare_dependency(link_with: libqemuutil,
3382                              sources: genh + version_res,
3383                              dependencies: [event_loop_base])
3384
3385if have_system or have_user
3386  decodetree = generator(find_program('scripts/decodetree.py'),
3387                         output: 'decode-@BASENAME@.c.inc',
3388                         arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
3389  subdir('libdecnumber')
3390  subdir('target')
3391endif
3392
3393subdir('audio')
3394subdir('io')
3395subdir('chardev')
3396subdir('fsdev')
3397subdir('dump')
3398
3399if have_block
3400  block_ss.add(files(
3401    'block.c',
3402    'blockjob.c',
3403    'job.c',
3404    'qemu-io-cmds.c',
3405  ))
3406  if config_host_data.get('CONFIG_REPLICATION')
3407    block_ss.add(files('replication.c'))
3408  endif
3409
3410  subdir('nbd')
3411  subdir('scsi')
3412  subdir('block')
3413
3414  blockdev_ss.add(files(
3415    'blockdev.c',
3416    'blockdev-nbd.c',
3417    'iothread.c',
3418    'job-qmp.c',
3419  ), gnutls)
3420
3421  # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
3422  # os-win32.c does not
3423  blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
3424  system_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
3425endif
3426
3427common_ss.add(files('cpus-common.c'))
3428specific_ss.add(files('cpu.c'))
3429
3430subdir('softmmu')
3431
3432# Work around a gcc bug/misfeature wherein constant propagation looks
3433# through an alias:
3434#   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99696
3435# to guess that a const variable is always zero.  Without lto, this is
3436# impossible, as the alias is restricted to page-vary-common.c.  Indeed,
3437# without lto, not even the alias is required -- we simply use different
3438# declarations in different compilation units.
3439pagevary = files('page-vary-common.c')
3440if get_option('b_lto')
3441  pagevary_flags = ['-fno-lto']
3442  if get_option('cfi')
3443    pagevary_flags += '-fno-sanitize=cfi-icall'
3444  endif
3445  pagevary = static_library('page-vary-common', sources: pagevary + genh,
3446                            c_args: pagevary_flags)
3447  pagevary = declare_dependency(link_with: pagevary)
3448endif
3449common_ss.add(pagevary)
3450specific_ss.add(files('page-vary.c'))
3451
3452subdir('backends')
3453subdir('disas')
3454subdir('migration')
3455subdir('monitor')
3456subdir('net')
3457subdir('replay')
3458subdir('semihosting')
3459subdir('stats')
3460subdir('tcg')
3461subdir('fpu')
3462subdir('accel')
3463subdir('plugins')
3464subdir('ebpf')
3465
3466common_user_inc = []
3467
3468subdir('common-user')
3469subdir('bsd-user')
3470subdir('linux-user')
3471
3472# needed for fuzzing binaries
3473subdir('tests/qtest/libqos')
3474subdir('tests/qtest/fuzz')
3475
3476# accel modules
3477tcg_real_module_ss = ss.source_set()
3478tcg_real_module_ss.add_all(when: 'CONFIG_TCG_MODULAR', if_true: tcg_module_ss)
3479specific_ss.add_all(when: 'CONFIG_TCG_BUILTIN', if_true: tcg_module_ss)
3480target_modules += { 'accel' : { 'qtest': qtest_module_ss,
3481                                'tcg': tcg_real_module_ss }}
3482
3483########################
3484# Library dependencies #
3485########################
3486
3487modinfo_collect = find_program('scripts/modinfo-collect.py')
3488modinfo_generate = find_program('scripts/modinfo-generate.py')
3489modinfo_files = []
3490
3491block_mods = []
3492softmmu_mods = []
3493foreach d, list : modules
3494  if not (d == 'block' ? have_block : have_system)
3495    continue
3496  endif
3497
3498  foreach m, module_ss : list
3499    if enable_modules
3500      module_ss = module_ss.apply(config_all, strict: false)
3501      sl = static_library(d + '-' + m, [genh, module_ss.sources()],
3502                          dependencies: [modulecommon, module_ss.dependencies()], pic: true)
3503      if d == 'block'
3504        block_mods += sl
3505      else
3506        softmmu_mods += sl
3507      endif
3508      if module_ss.sources() != []
3509        # FIXME: Should use sl.extract_all_objects(recursive: true) as
3510        # input. Sources can be used multiple times but objects are
3511        # unique when it comes to lookup in compile_commands.json.
3512        # Depnds on a mesion version with
3513        # https://github.com/mesonbuild/meson/pull/8900
3514        modinfo_files += custom_target(d + '-' + m + '.modinfo',
3515                                       output: d + '-' + m + '.modinfo',
3516                                       input: module_ss.sources() + genh,
3517                                       capture: true,
3518                                       command: [modinfo_collect, module_ss.sources()])
3519      endif
3520    else
3521      if d == 'block'
3522        block_ss.add_all(module_ss)
3523      else
3524        system_ss.add_all(module_ss)
3525      endif
3526    endif
3527  endforeach
3528endforeach
3529
3530foreach d, list : target_modules
3531  foreach m, module_ss : list
3532    if enable_modules
3533      foreach target : target_dirs
3534        if target.endswith('-softmmu')
3535          config_target = config_target_mak[target]
3536          config_target += config_targetos
3537          target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3538          c_args = ['-DNEED_CPU_H',
3539                    '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3540                    '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3541          target_module_ss = module_ss.apply(config_target, strict: false)
3542          if target_module_ss.sources() != []
3543            module_name = d + '-' + m + '-' + config_target['TARGET_NAME']
3544            sl = static_library(module_name,
3545                                [genh, target_module_ss.sources()],
3546                                dependencies: [modulecommon, target_module_ss.dependencies()],
3547                                include_directories: target_inc,
3548                                c_args: c_args,
3549                                pic: true)
3550            softmmu_mods += sl
3551            # FIXME: Should use sl.extract_all_objects(recursive: true) too.
3552            modinfo_files += custom_target(module_name + '.modinfo',
3553                                           output: module_name + '.modinfo',
3554                                           input: target_module_ss.sources() + genh,
3555                                           capture: true,
3556                                           command: [modinfo_collect, '--target', target, target_module_ss.sources()])
3557          endif
3558        endif
3559      endforeach
3560    else
3561      specific_ss.add_all(module_ss)
3562    endif
3563  endforeach
3564endforeach
3565
3566if enable_modules
3567  foreach target : target_dirs
3568    if target.endswith('-softmmu')
3569      config_target = config_target_mak[target]
3570      config_devices_mak = target + '-config-devices.mak'
3571      modinfo_src = custom_target('modinfo-' + target + '.c',
3572                                  output: 'modinfo-' + target + '.c',
3573                                  input: modinfo_files,
3574                                  command: [modinfo_generate, '--devices', config_devices_mak, '@INPUT@'],
3575                                  capture: true)
3576
3577      modinfo_lib = static_library('modinfo-' + target + '.c', modinfo_src)
3578      modinfo_dep = declare_dependency(link_with: modinfo_lib)
3579
3580      arch = config_target['TARGET_NAME'] == 'sparc64' ? 'sparc64' : config_target['TARGET_BASE_ARCH']
3581      hw_arch[arch].add(modinfo_dep)
3582    endif
3583  endforeach
3584endif
3585
3586nm = find_program('nm')
3587undefsym = find_program('scripts/undefsym.py')
3588block_syms = custom_target('block.syms', output: 'block.syms',
3589                             input: [libqemuutil, block_mods],
3590                             capture: true,
3591                             command: [undefsym, nm, '@INPUT@'])
3592qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
3593                             input: [libqemuutil, softmmu_mods],
3594                             capture: true,
3595                             command: [undefsym, nm, '@INPUT@'])
3596
3597authz_ss = authz_ss.apply(config_targetos, strict: false)
3598libauthz = static_library('authz', authz_ss.sources() + genh,
3599                          dependencies: [authz_ss.dependencies()],
3600                          name_suffix: 'fa',
3601                          build_by_default: false)
3602
3603authz = declare_dependency(link_whole: libauthz,
3604                           dependencies: qom)
3605
3606crypto_ss = crypto_ss.apply(config_targetos, strict: false)
3607libcrypto = static_library('crypto', crypto_ss.sources() + genh,
3608                           dependencies: [crypto_ss.dependencies()],
3609                           name_suffix: 'fa',
3610                           build_by_default: false)
3611
3612crypto = declare_dependency(link_whole: libcrypto,
3613                            dependencies: [authz, qom])
3614
3615io_ss = io_ss.apply(config_targetos, strict: false)
3616libio = static_library('io', io_ss.sources() + genh,
3617                       dependencies: [io_ss.dependencies()],
3618                       link_with: libqemuutil,
3619                       name_suffix: 'fa',
3620                       build_by_default: false)
3621
3622io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
3623
3624libmigration = static_library('migration', sources: migration_files + genh,
3625                              name_suffix: 'fa',
3626                              build_by_default: false)
3627migration = declare_dependency(link_with: libmigration,
3628                               dependencies: [zlib, qom, io])
3629system_ss.add(migration)
3630
3631block_ss = block_ss.apply(config_targetos, strict: false)
3632libblock = static_library('block', block_ss.sources() + genh,
3633                          dependencies: block_ss.dependencies(),
3634                          link_depends: block_syms,
3635                          name_suffix: 'fa',
3636                          build_by_default: false)
3637
3638block = declare_dependency(link_whole: [libblock],
3639                           link_args: '@block.syms',
3640                           dependencies: [crypto, io])
3641
3642blockdev_ss = blockdev_ss.apply(config_targetos, strict: false)
3643libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
3644                             dependencies: blockdev_ss.dependencies(),
3645                             name_suffix: 'fa',
3646                             build_by_default: false)
3647
3648blockdev = declare_dependency(link_whole: [libblockdev],
3649                              dependencies: [block, event_loop_base])
3650
3651qmp_ss = qmp_ss.apply(config_targetos, strict: false)
3652libqmp = static_library('qmp', qmp_ss.sources() + genh,
3653                        dependencies: qmp_ss.dependencies(),
3654                        name_suffix: 'fa',
3655                        build_by_default: false)
3656
3657qmp = declare_dependency(link_whole: [libqmp])
3658
3659libchardev = static_library('chardev', chardev_ss.sources() + genh,
3660                            name_suffix: 'fa',
3661                            dependencies: chardev_ss.dependencies(),
3662                            build_by_default: false)
3663
3664chardev = declare_dependency(link_whole: libchardev)
3665
3666hwcore_ss = hwcore_ss.apply(config_targetos, strict: false)
3667libhwcore = static_library('hwcore', sources: hwcore_ss.sources() + genh,
3668                           name_suffix: 'fa',
3669                           build_by_default: false)
3670hwcore = declare_dependency(link_whole: libhwcore)
3671common_ss.add(hwcore)
3672
3673###########
3674# Targets #
3675###########
3676
3677emulator_modules = []
3678foreach m : block_mods + softmmu_mods
3679  emulator_modules += shared_module(m.name(),
3680                build_by_default: true,
3681                name_prefix: '',
3682                link_whole: m,
3683                install: true,
3684                install_dir: qemu_moddir)
3685endforeach
3686if emulator_modules.length() > 0
3687  alias_target('modules', emulator_modules)
3688endif
3689
3690system_ss.add(authz, blockdev, chardev, crypto, io, qmp)
3691common_ss.add(qom, qemuutil)
3692
3693common_ss.add_all(when: 'CONFIG_SYSTEM_ONLY', if_true: [system_ss])
3694common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
3695
3696common_all = common_ss.apply(config_all, strict: false)
3697common_all = static_library('common',
3698                            build_by_default: false,
3699                            sources: common_all.sources() + genh,
3700                            include_directories: common_user_inc,
3701                            implicit_include_directories: false,
3702                            dependencies: common_all.dependencies(),
3703                            name_suffix: 'fa')
3704
3705feature_to_c = find_program('scripts/feature_to_c.sh')
3706
3707if targetos == 'darwin'
3708  entitlement = find_program('scripts/entitlement.sh')
3709endif
3710
3711emulators = {}
3712foreach target : target_dirs
3713  config_target = config_target_mak[target]
3714  target_name = config_target['TARGET_NAME']
3715  target_base_arch = config_target['TARGET_BASE_ARCH']
3716  arch_srcs = [config_target_h[target]]
3717  arch_deps = []
3718  c_args = ['-DNEED_CPU_H',
3719            '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3720            '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3721  link_args = emulator_link_args
3722
3723  config_target += config_targetos
3724  target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3725  if targetos == 'linux'
3726    target_inc += include_directories('linux-headers', is_system: true)
3727  endif
3728  if target.endswith('-softmmu')
3729    target_type='system'
3730    t = target_softmmu_arch[target_base_arch].apply(config_target, strict: false)
3731    arch_srcs += t.sources()
3732    arch_deps += t.dependencies()
3733
3734    hw_dir = target_name == 'sparc64' ? 'sparc64' : target_base_arch
3735    hw = hw_arch[hw_dir].apply(config_target, strict: false)
3736    arch_srcs += hw.sources()
3737    arch_deps += hw.dependencies()
3738
3739    arch_srcs += config_devices_h[target]
3740    link_args += ['@block.syms', '@qemu.syms']
3741  else
3742    abi = config_target['TARGET_ABI_DIR']
3743    target_type='user'
3744    target_inc += common_user_inc
3745    if target_base_arch in target_user_arch
3746      t = target_user_arch[target_base_arch].apply(config_target, strict: false)
3747      arch_srcs += t.sources()
3748      arch_deps += t.dependencies()
3749    endif
3750    if 'CONFIG_LINUX_USER' in config_target
3751      base_dir = 'linux-user'
3752    endif
3753    if 'CONFIG_BSD_USER' in config_target
3754      base_dir = 'bsd-user'
3755      target_inc += include_directories('bsd-user/' / targetos)
3756      target_inc += include_directories('bsd-user/host/' / host_arch)
3757      dir = base_dir / abi
3758      arch_srcs += files(dir / 'signal.c', dir / 'target_arch_cpu.c')
3759    endif
3760    target_inc += include_directories(
3761      base_dir,
3762      base_dir / abi,
3763    )
3764    if 'CONFIG_LINUX_USER' in config_target
3765      dir = base_dir / abi
3766      arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
3767      if config_target.has_key('TARGET_SYSTBL_ABI')
3768        arch_srcs += \
3769          syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
3770                                             extra_args : config_target['TARGET_SYSTBL_ABI'])
3771      endif
3772    endif
3773  endif
3774
3775  if 'TARGET_XML_FILES' in config_target
3776    gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
3777                                output: target + '-gdbstub-xml.c',
3778                                input: files(config_target['TARGET_XML_FILES'].split()),
3779                                command: [feature_to_c, '@INPUT@'],
3780                                capture: true)
3781    arch_srcs += gdbstub_xml
3782  endif
3783
3784  t = target_arch[target_base_arch].apply(config_target, strict: false)
3785  arch_srcs += t.sources()
3786  arch_deps += t.dependencies()
3787
3788  target_common = common_ss.apply(config_target, strict: false)
3789  objects = common_all.extract_objects(target_common.sources())
3790  deps = target_common.dependencies()
3791
3792  target_specific = specific_ss.apply(config_target, strict: false)
3793  arch_srcs += target_specific.sources()
3794  arch_deps += target_specific.dependencies()
3795
3796  lib = static_library('qemu-' + target,
3797                 sources: arch_srcs + genh,
3798                 dependencies: arch_deps,
3799                 objects: objects,
3800                 include_directories: target_inc,
3801                 c_args: c_args,
3802                 build_by_default: false,
3803                 name_suffix: 'fa')
3804
3805  if target.endswith('-softmmu')
3806    execs = [{
3807      'name': 'qemu-system-' + target_name,
3808      'win_subsystem': 'console',
3809      'sources': files('softmmu/main.c'),
3810      'dependencies': []
3811    }]
3812    if targetos == 'windows' and (sdl.found() or gtk.found())
3813      execs += [{
3814        'name': 'qemu-system-' + target_name + 'w',
3815        'win_subsystem': 'windows',
3816        'sources': files('softmmu/main.c'),
3817        'dependencies': []
3818      }]
3819    endif
3820    if get_option('fuzzing')
3821      specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
3822      execs += [{
3823        'name': 'qemu-fuzz-' + target_name,
3824        'win_subsystem': 'console',
3825        'sources': specific_fuzz.sources(),
3826        'dependencies': specific_fuzz.dependencies(),
3827      }]
3828    endif
3829  else
3830    execs = [{
3831      'name': 'qemu-' + target_name,
3832      'win_subsystem': 'console',
3833      'sources': [],
3834      'dependencies': []
3835    }]
3836  endif
3837  foreach exe: execs
3838    exe_name = exe['name']
3839    if targetos == 'darwin'
3840      exe_name += '-unsigned'
3841    endif
3842
3843    emulator = executable(exe_name, exe['sources'],
3844               install: true,
3845               c_args: c_args,
3846               dependencies: arch_deps + deps + exe['dependencies'],
3847               objects: lib.extract_all_objects(recursive: true),
3848               link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
3849               link_args: link_args,
3850               win_subsystem: exe['win_subsystem'])
3851
3852    if targetos == 'darwin'
3853      icon = 'pc-bios/qemu.rsrc'
3854      build_input = [emulator, files(icon)]
3855      install_input = [
3856        get_option('bindir') / exe_name,
3857        meson.current_source_dir() / icon
3858      ]
3859      if 'CONFIG_HVF' in config_target
3860        entitlements = 'accel/hvf/entitlements.plist'
3861        build_input += files(entitlements)
3862        install_input += meson.current_source_dir() / entitlements
3863      endif
3864
3865      emulators += {exe['name'] : custom_target(exe['name'],
3866                   input: build_input,
3867                   output: exe['name'],
3868                   command: [entitlement, '@OUTPUT@', '@INPUT@'])
3869      }
3870
3871      meson.add_install_script(entitlement, '--install',
3872                               get_option('bindir') / exe['name'],
3873                               install_input)
3874    else
3875      emulators += {exe['name']: emulator}
3876    endif
3877
3878    if stap.found()
3879      foreach stp: [
3880        {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
3881        {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
3882        {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
3883        {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
3884      ]
3885        custom_target(exe['name'] + stp['ext'],
3886                      input: trace_events_all,
3887                      output: exe['name'] + stp['ext'],
3888                      install: stp['install'],
3889                      install_dir: get_option('datadir') / 'systemtap/tapset',
3890                      command: [
3891                        tracetool, '--group=all', '--format=' + stp['fmt'],
3892                        '--binary=' + stp['bin'],
3893                        '--target-name=' + target_name,
3894                        '--target-type=' + target_type,
3895                        '--probe-prefix=qemu.' + target_type + '.' + target_name,
3896                        '@INPUT@', '@OUTPUT@'
3897                      ],
3898                      depend_files: tracetool_depends)
3899      endforeach
3900    endif
3901  endforeach
3902endforeach
3903
3904# Other build targets
3905
3906if get_option('plugins')
3907  install_headers('include/qemu/qemu-plugin.h')
3908endif
3909
3910subdir('qga')
3911
3912# Don't build qemu-keymap if xkbcommon is not explicitly enabled
3913# when we don't build tools or system
3914if xkbcommon.found()
3915  # used for the update-keymaps target, so include rules even if !have_tools
3916  qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
3917                           dependencies: [qemuutil, xkbcommon], install: have_tools)
3918endif
3919
3920if have_tools
3921  qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
3922             dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
3923  qemu_io = executable('qemu-io', files('qemu-io.c'),
3924             dependencies: [block, qemuutil], install: true)
3925  qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
3926               dependencies: [blockdev, qemuutil, gnutls, selinux],
3927               install: true)
3928
3929  subdir('storage-daemon')
3930  subdir('contrib/rdmacm-mux')
3931  subdir('contrib/elf2dmp')
3932
3933  executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
3934             dependencies: qemuutil,
3935             install: true)
3936
3937  if have_vhost_user
3938    subdir('contrib/vhost-user-blk')
3939    subdir('contrib/vhost-user-gpu')
3940    subdir('contrib/vhost-user-input')
3941    subdir('contrib/vhost-user-scsi')
3942  endif
3943
3944  if targetos == 'linux'
3945    executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
3946               dependencies: [qemuutil, libcap_ng],
3947               install: true,
3948               install_dir: get_option('libexecdir'))
3949
3950    executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
3951               dependencies: [authz, crypto, io, qom, qemuutil,
3952                              libcap_ng, mpathpersist],
3953               install: true)
3954  endif
3955
3956  if have_ivshmem
3957    subdir('contrib/ivshmem-client')
3958    subdir('contrib/ivshmem-server')
3959  endif
3960endif
3961
3962subdir('scripts')
3963subdir('tools')
3964subdir('pc-bios')
3965subdir('docs')
3966subdir('tests')
3967if gtk.found()
3968  subdir('po')
3969endif
3970
3971if host_machine.system() == 'windows'
3972  nsis_cmd = [
3973    find_program('scripts/nsis.py'),
3974    '@OUTPUT@',
3975    get_option('prefix'),
3976    meson.current_source_dir(),
3977    glib_pc.get_variable('bindir'),
3978    host_machine.cpu(),
3979    '--',
3980    '-DDISPLAYVERSION=' + meson.project_version(),
3981  ]
3982  if build_docs
3983    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
3984  endif
3985  if gtk.found()
3986    nsis_cmd += '-DCONFIG_GTK=y'
3987  endif
3988
3989  nsis = custom_target('nsis',
3990                       output: 'qemu-setup-' + meson.project_version() + '.exe',
3991                       input: files('qemu.nsi'),
3992                       build_always_stale: true,
3993                       command: nsis_cmd + ['@INPUT@'])
3994  alias_target('installer', nsis)
3995endif
3996
3997#########################
3998# Configuration summary #
3999#########################
4000
4001# Build environment
4002summary_info = {}
4003summary_info += {'Build directory':   meson.current_build_dir()}
4004summary_info += {'Source path':       meson.current_source_dir()}
4005summary_info += {'Download dependencies': get_option('wrap_mode') != 'nodownload'}
4006summary(summary_info, bool_yn: true, section: 'Build environment')
4007
4008# Directories
4009summary_info += {'Install prefix':    get_option('prefix')}
4010summary_info += {'BIOS directory':    qemu_datadir}
4011pathsep = targetos == 'windows' ? ';' : ':'
4012summary_info += {'firmware path':     pathsep.join(get_option('qemu_firmwarepath'))}
4013summary_info += {'binary directory':  get_option('prefix') / get_option('bindir')}
4014summary_info += {'library directory': get_option('prefix') / get_option('libdir')}
4015summary_info += {'module directory':  qemu_moddir}
4016summary_info += {'libexec directory': get_option('prefix') / get_option('libexecdir')}
4017summary_info += {'include directory': get_option('prefix') / get_option('includedir')}
4018summary_info += {'config directory':  get_option('prefix') / get_option('sysconfdir')}
4019if targetos != 'windows'
4020  summary_info += {'local state directory': get_option('prefix') / get_option('localstatedir')}
4021  summary_info += {'Manual directory':      get_option('prefix') / get_option('mandir')}
4022else
4023  summary_info += {'local state directory': 'queried at runtime'}
4024endif
4025summary_info += {'Doc directory':     get_option('prefix') / get_option('docdir')}
4026summary(summary_info, bool_yn: true, section: 'Directories')
4027
4028# Host binaries
4029summary_info = {}
4030summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
4031summary_info += {'sphinx-build':      sphinx_build}
4032if config_host.has_key('HAVE_GDB_BIN')
4033  summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
4034endif
4035summary_info += {'iasl':              iasl}
4036summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
4037if targetos == 'windows' and have_ga
4038  summary_info += {'wixl':            wixl}
4039endif
4040if slirp.found() and have_system
4041  summary_info += {'smbd':            have_slirp_smbd ? smbd_path : false}
4042endif
4043summary(summary_info, bool_yn: true, section: 'Host binaries')
4044
4045# Configurable features
4046summary_info = {}
4047summary_info += {'Documentation':     build_docs}
4048summary_info += {'system-mode emulation': have_system}
4049summary_info += {'user-mode emulation': have_user}
4050summary_info += {'block layer':       have_block}
4051summary_info += {'Install blobs':     get_option('install_blobs')}
4052summary_info += {'module support':    enable_modules}
4053if enable_modules
4054  summary_info += {'alternative module path': get_option('module_upgrades')}
4055endif
4056summary_info += {'fuzzing support':   get_option('fuzzing')}
4057if have_system
4058  summary_info += {'Audio drivers':     ' '.join(audio_drivers_selected)}
4059endif
4060summary_info += {'Trace backends':    ','.join(get_option('trace_backends'))}
4061if 'simple' in get_option('trace_backends')
4062  summary_info += {'Trace output file': get_option('trace_file') + '-<pid>'}
4063endif
4064summary_info += {'D-Bus display':     dbus_display}
4065summary_info += {'QOM debugging':     get_option('qom_cast_debug')}
4066summary_info += {'vhost-kernel support': have_vhost_kernel}
4067summary_info += {'vhost-net support': have_vhost_net}
4068summary_info += {'vhost-user support': have_vhost_user}
4069summary_info += {'vhost-user-crypto support': have_vhost_user_crypto}
4070summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
4071summary_info += {'vhost-vdpa support': have_vhost_vdpa}
4072summary_info += {'build guest agent': have_ga}
4073summary(summary_info, bool_yn: true, section: 'Configurable features')
4074
4075# Compilation information
4076summary_info = {}
4077summary_info += {'host CPU':          cpu}
4078summary_info += {'host endianness':   build_machine.endian()}
4079summary_info += {'C compiler':        ' '.join(meson.get_compiler('c').cmd_array())}
4080summary_info += {'Host C compiler':   ' '.join(meson.get_compiler('c', native: true).cmd_array())}
4081if 'cpp' in all_languages
4082  summary_info += {'C++ compiler':    ' '.join(meson.get_compiler('cpp').cmd_array())}
4083else
4084  summary_info += {'C++ compiler':      false}
4085endif
4086if targetos == 'darwin'
4087  summary_info += {'Objective-C compiler': ' '.join(meson.get_compiler('objc').cmd_array())}
4088endif
4089option_cflags = (get_option('debug') ? ['-g'] : [])
4090if get_option('optimization') != 'plain'
4091  option_cflags += ['-O' + get_option('optimization')]
4092endif
4093summary_info += {'CFLAGS':            ' '.join(get_option('c_args') + option_cflags)}
4094if 'cpp' in all_languages
4095  summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args') + option_cflags)}
4096endif
4097if targetos == 'darwin'
4098  summary_info += {'OBJCFLAGS':       ' '.join(get_option('objc_args') + option_cflags)}
4099endif
4100link_args = get_option('c_link_args')
4101if link_args.length() > 0
4102  summary_info += {'LDFLAGS':         ' '.join(link_args)}
4103endif
4104summary_info += {'QEMU_CFLAGS':       ' '.join(qemu_common_flags + qemu_cflags)}
4105if 'cpp' in all_languages
4106  summary_info += {'QEMU_CXXFLAGS':     ' '.join(qemu_common_flags + qemu_cxxflags)}
4107endif
4108if 'objc' in all_languages
4109  summary_info += {'QEMU_OBJCFLAGS':    ' '.join(qemu_common_flags)}
4110endif
4111summary_info += {'QEMU_LDFLAGS':      ' '.join(qemu_ldflags)}
4112summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
4113summary_info += {'PIE':               get_option('b_pie')}
4114summary_info += {'static build':      get_option('prefer_static')}
4115summary_info += {'malloc trim support': has_malloc_trim}
4116summary_info += {'membarrier':        have_membarrier}
4117summary_info += {'debug graph lock':  get_option('debug_graph_lock')}
4118summary_info += {'debug stack usage': get_option('debug_stack_usage')}
4119summary_info += {'mutex debugging':   get_option('debug_mutex')}
4120summary_info += {'memory allocator':  get_option('malloc')}
4121summary_info += {'avx2 optimization': config_host_data.get('CONFIG_AVX2_OPT')}
4122summary_info += {'avx512bw optimization': config_host_data.get('CONFIG_AVX512BW_OPT')}
4123summary_info += {'avx512f optimization': config_host_data.get('CONFIG_AVX512F_OPT')}
4124if get_option('gprof')
4125  gprof_info = 'YES (deprecated)'
4126else
4127  gprof_info = get_option('gprof')
4128endif
4129summary_info += {'gprof':             gprof_info}
4130summary_info += {'gcov':              get_option('b_coverage')}
4131summary_info += {'thread sanitizer':  get_option('tsan')}
4132summary_info += {'CFI support':       get_option('cfi')}
4133if get_option('cfi')
4134  summary_info += {'CFI debug support': get_option('cfi_debug')}
4135endif
4136summary_info += {'strip binaries':    get_option('strip')}
4137summary_info += {'sparse':            sparse}
4138summary_info += {'mingw32 support':   targetos == 'windows'}
4139summary(summary_info, bool_yn: true, section: 'Compilation')
4140
4141# snarf the cross-compilation information for tests
4142summary_info = {}
4143have_cross = false
4144foreach target: target_dirs
4145  tcg_mak = meson.current_build_dir() / 'tests/tcg' / target / 'config-target.mak'
4146  if fs.exists(tcg_mak)
4147    config_cross_tcg = keyval.load(tcg_mak)
4148    if 'CC' in config_cross_tcg
4149      summary_info += {config_cross_tcg['TARGET_NAME']: config_cross_tcg['CC']}
4150      have_cross = true
4151    endif
4152  endif
4153endforeach
4154if have_cross
4155  summary(summary_info, bool_yn: true, section: 'Cross compilers')
4156endif
4157
4158# Targets and accelerators
4159summary_info = {}
4160if have_system
4161  summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
4162  summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
4163  summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
4164  summary_info += {'NVMM support':      config_all.has_key('CONFIG_NVMM')}
4165  summary_info += {'Xen support':       xen.found()}
4166  if xen.found()
4167    summary_info += {'xen ctrl version':  xen.version()}
4168  endif
4169  summary_info += {'Xen emulation':     config_all.has_key('CONFIG_XEN_EMU')}
4170endif
4171summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
4172if config_all.has_key('CONFIG_TCG')
4173  if get_option('tcg_interpreter')
4174    summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, slow)'}
4175  else
4176    summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
4177  endif
4178  summary_info += {'TCG plugins':       get_option('plugins')}
4179  summary_info += {'TCG debug enabled': get_option('debug_tcg')}
4180endif
4181summary_info += {'target list':       ' '.join(target_dirs)}
4182if have_system
4183  summary_info += {'default devices':   get_option('default_devices')}
4184  summary_info += {'out of process emulation': multiprocess_allowed}
4185  summary_info += {'vfio-user server': vfio_user_server_allowed}
4186endif
4187summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
4188
4189# Block layer
4190summary_info = {}
4191summary_info += {'coroutine backend': coroutine_backend}
4192summary_info += {'coroutine pool':    have_coroutine_pool}
4193if have_block
4194  summary_info += {'Block whitelist (rw)': get_option('block_drv_rw_whitelist')}
4195  summary_info += {'Block whitelist (ro)': get_option('block_drv_ro_whitelist')}
4196  summary_info += {'Use block whitelist in tools': get_option('block_drv_whitelist_in_tools')}
4197  summary_info += {'VirtFS (9P) support':    have_virtfs}
4198  summary_info += {'VirtFS (9P) Proxy Helper support (deprecated)': have_virtfs_proxy_helper}
4199  summary_info += {'Live block migration': config_host_data.get('CONFIG_LIVE_BLOCK_MIGRATION')}
4200  summary_info += {'replication support': config_host_data.get('CONFIG_REPLICATION')}
4201  summary_info += {'bochs support':     get_option('bochs').allowed()}
4202  summary_info += {'cloop support':     get_option('cloop').allowed()}
4203  summary_info += {'dmg support':       get_option('dmg').allowed()}
4204  summary_info += {'qcow v1 support':   get_option('qcow1').allowed()}
4205  summary_info += {'vdi support':       get_option('vdi').allowed()}
4206  summary_info += {'vhdx support':      get_option('vhdx').allowed()}
4207  summary_info += {'vmdk support':      get_option('vmdk').allowed()}
4208  summary_info += {'vpc support':       get_option('vpc').allowed()}
4209  summary_info += {'vvfat support':     get_option('vvfat').allowed()}
4210  summary_info += {'qed support':       get_option('qed').allowed()}
4211  summary_info += {'parallels support': get_option('parallels').allowed()}
4212  summary_info += {'FUSE exports':      fuse}
4213  summary_info += {'VDUSE block exports': have_vduse_blk_export}
4214endif
4215summary(summary_info, bool_yn: true, section: 'Block layer support')
4216
4217# Crypto
4218summary_info = {}
4219summary_info += {'TLS priority':      get_option('tls_priority')}
4220summary_info += {'GNUTLS support':    gnutls}
4221if gnutls.found()
4222  summary_info += {'  GNUTLS crypto':   gnutls_crypto.found()}
4223endif
4224summary_info += {'libgcrypt':         gcrypt}
4225summary_info += {'nettle':            nettle}
4226if nettle.found()
4227   summary_info += {'  XTS':             xts != 'private'}
4228endif
4229summary_info += {'AF_ALG support':    have_afalg}
4230summary_info += {'rng-none':          get_option('rng_none')}
4231summary_info += {'Linux keyring':     have_keyring}
4232summary(summary_info, bool_yn: true, section: 'Crypto')
4233
4234# UI
4235summary_info = {}
4236if targetos == 'darwin'
4237  summary_info += {'Cocoa support':           cocoa}
4238endif
4239summary_info += {'SDL support':       sdl}
4240summary_info += {'SDL image support': sdl_image}
4241summary_info += {'GTK support':       gtk}
4242summary_info += {'pixman':            pixman}
4243summary_info += {'VTE support':       vte}
4244summary_info += {'PNG support':       png}
4245summary_info += {'VNC support':       vnc}
4246if vnc.found()
4247  summary_info += {'VNC SASL support':  sasl}
4248  summary_info += {'VNC JPEG support':  jpeg}
4249endif
4250summary_info += {'spice protocol support': spice_protocol}
4251if spice_protocol.found()
4252  summary_info += {'  spice server support': spice}
4253endif
4254summary_info += {'curses support':    curses}
4255summary_info += {'brlapi support':    brlapi}
4256summary(summary_info, bool_yn: true, section: 'User interface')
4257
4258# Audio backends
4259summary_info = {}
4260if targetos not in ['darwin', 'haiku', 'windows']
4261  summary_info += {'OSS support':     oss}
4262  summary_info += {'sndio support':   sndio}
4263elif targetos == 'darwin'
4264  summary_info += {'CoreAudio support': coreaudio}
4265elif targetos == 'windows'
4266  summary_info += {'DirectSound support': dsound}
4267endif
4268if targetos == 'linux'
4269  summary_info += {'ALSA support':    alsa}
4270  summary_info += {'PulseAudio support': pulse}
4271endif
4272summary_info += {'PipeWire support':  pipewire}
4273summary_info += {'JACK support':      jack}
4274summary(summary_info, bool_yn: true, section: 'Audio backends')
4275
4276# Network backends
4277summary_info = {}
4278if targetos == 'darwin'
4279  summary_info += {'vmnet.framework support': vmnet}
4280endif
4281summary_info += {'AF_XDP support':    libxdp}
4282summary_info += {'slirp support':     slirp}
4283summary_info += {'vde support':       vde}
4284summary_info += {'netmap support':    have_netmap}
4285summary_info += {'l2tpv3 support':    have_l2tpv3}
4286summary(summary_info, bool_yn: true, section: 'Network backends')
4287
4288# Libraries
4289summary_info = {}
4290summary_info += {'libtasn1':          tasn1}
4291summary_info += {'PAM':               pam}
4292summary_info += {'iconv support':     iconv}
4293summary_info += {'virgl support':     virgl}
4294summary_info += {'blkio support':     blkio}
4295summary_info += {'curl support':      curl}
4296summary_info += {'Multipath support': mpathpersist}
4297summary_info += {'Linux AIO support': libaio}
4298summary_info += {'Linux io_uring support': linux_io_uring}
4299summary_info += {'ATTR/XATTR support': libattr}
4300summary_info += {'RDMA support':      rdma}
4301summary_info += {'PVRDMA support':    have_pvrdma}
4302summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
4303summary_info += {'libcap-ng support': libcap_ng}
4304summary_info += {'bpf support':       libbpf}
4305summary_info += {'rbd support':       rbd}
4306summary_info += {'smartcard support': cacard}
4307summary_info += {'U2F support':       u2f}
4308summary_info += {'libusb':            libusb}
4309summary_info += {'usb net redir':     usbredir}
4310summary_info += {'OpenGL support (epoxy)': opengl}
4311summary_info += {'GBM':               gbm}
4312summary_info += {'libiscsi support':  libiscsi}
4313summary_info += {'libnfs support':    libnfs}
4314if targetos == 'windows'
4315  if have_ga
4316    summary_info += {'QGA VSS support':   have_qga_vss}
4317  endif
4318endif
4319summary_info += {'seccomp support':   seccomp}
4320summary_info += {'GlusterFS support': glusterfs}
4321summary_info += {'TPM support':       have_tpm}
4322summary_info += {'libssh support':    libssh}
4323summary_info += {'lzo support':       lzo}
4324summary_info += {'snappy support':    snappy}
4325summary_info += {'bzip2 support':     libbzip2}
4326summary_info += {'lzfse support':     liblzfse}
4327summary_info += {'zstd support':      zstd}
4328summary_info += {'NUMA host support': numa}
4329summary_info += {'capstone':          capstone}
4330summary_info += {'libpmem support':   libpmem}
4331summary_info += {'libdaxctl support': libdaxctl}
4332summary_info += {'libudev':           libudev}
4333# Dummy dependency, keep .found()
4334summary_info += {'FUSE lseek':        fuse_lseek.found()}
4335summary_info += {'selinux':           selinux}
4336summary_info += {'libdw':             libdw}
4337summary(summary_info, bool_yn: true, section: 'Dependencies')
4338
4339if host_arch == 'unknown'
4340  message()
4341  warning('UNSUPPORTED HOST CPU')
4342  message()
4343  message('Support for CPU host architecture ' + cpu + ' is not currently')
4344  message('maintained. The QEMU project does not guarantee that QEMU will')
4345  message('compile or work on this host CPU. You can help by volunteering')
4346  message('to maintain it and providing a build host for our continuous')
4347  message('integration setup.')
4348  if get_option('tcg').allowed() and target_dirs.length() > 0
4349    message()
4350    message('configure has succeeded and you can continue to build, but')
4351    message('QEMU will use a slow interpreter to emulate the target CPU.')
4352  endif
4353endif
4354
4355if not supported_oses.contains(targetos)
4356  message()
4357  warning('UNSUPPORTED HOST OS')
4358  message()
4359  message('Support for host OS ' + targetos + 'is not currently maintained.')
4360  message('configure has succeeded and you can continue to build, but')
4361  message('the QEMU project does not guarantee that QEMU will compile or')
4362  message('work on this operating system. You can help by volunteering')
4363  message('to maintain it and providing a build host for our continuous')
4364  message('integration setup. This will ensure that future versions of QEMU')
4365  message('will keep working on ' + targetos + '.')
4366endif
4367
4368if host_arch == 'unknown' or not supported_oses.contains(targetos)
4369  message()
4370  message('If you want to help supporting QEMU on this platform, please')
4371  message('contact the developers at qemu-devel@nongnu.org.')
4372endif
4373