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