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