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