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