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