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