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