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