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