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