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