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