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