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