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