xref: /openbmc/qemu/meson.build (revision cf7c6d1004eaaae85fd6156556e2f38ff493ef48)
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_GETIFADDRS', cc.has_function('getifaddrs'))
1691config_host_data.set('HAVE_OPENPTY', cc.has_function('openpty', dependencies: util))
1692config_host_data.set('HAVE_STRCHRNUL', cc.has_function('strchrnul'))
1693config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: '#include <stdlib.h>'))
1694if rdma.found()
1695  config_host_data.set('HAVE_IBV_ADVISE_MR',
1696                       cc.has_function('ibv_advise_mr',
1697                                       dependencies: rdma,
1698                                       prefix: '#include <infiniband/verbs.h>'))
1699endif
1700
1701# has_header_symbol
1702config_host_data.set('CONFIG_BYTESWAP_H',
1703                     cc.has_header_symbol('byteswap.h', 'bswap_32'))
1704config_host_data.set('CONFIG_EPOLL_CREATE1',
1705                     cc.has_header_symbol('sys/epoll.h', 'epoll_create1'))
1706config_host_data.set('CONFIG_FALLOCATE_PUNCH_HOLE',
1707                     cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_PUNCH_HOLE') and
1708                     cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_KEEP_SIZE'))
1709config_host_data.set('CONFIG_FALLOCATE_ZERO_RANGE',
1710                     cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_ZERO_RANGE'))
1711config_host_data.set('CONFIG_FIEMAP',
1712                     cc.has_header('linux/fiemap.h') and
1713                     cc.has_header_symbol('linux/fs.h', 'FS_IOC_FIEMAP'))
1714config_host_data.set('CONFIG_GETRANDOM',
1715                     cc.has_function('getrandom') and
1716                     cc.has_header_symbol('sys/random.h', 'GRND_NONBLOCK'))
1717config_host_data.set('CONFIG_INOTIFY',
1718                     cc.has_header_symbol('sys/inotify.h', 'inotify_init'))
1719config_host_data.set('CONFIG_INOTIFY1',
1720                     cc.has_header_symbol('sys/inotify.h', 'inotify_init1'))
1721config_host_data.set('CONFIG_MACHINE_BSWAP_H',
1722                     cc.has_header_symbol('machine/bswap.h', 'bswap32',
1723                                          prefix: '''#include <sys/endian.h>
1724                                                     #include <sys/types.h>'''))
1725config_host_data.set('CONFIG_PRCTL_PR_SET_TIMERSLACK',
1726                     cc.has_header_symbol('sys/prctl.h', 'PR_SET_TIMERSLACK'))
1727config_host_data.set('CONFIG_RTNETLINK',
1728                     cc.has_header_symbol('linux/rtnetlink.h', 'IFLA_PROTO_DOWN'))
1729config_host_data.set('CONFIG_SYSMACROS',
1730                     cc.has_header_symbol('sys/sysmacros.h', 'makedev'))
1731config_host_data.set('HAVE_OPTRESET',
1732                     cc.has_header_symbol('getopt.h', 'optreset'))
1733config_host_data.set('HAVE_IPPROTO_MPTCP',
1734                     cc.has_header_symbol('netinet/in.h', 'IPPROTO_MPTCP'))
1735
1736# has_member
1737config_host_data.set('HAVE_SIGEV_NOTIFY_THREAD_ID',
1738                     cc.has_member('struct sigevent', 'sigev_notify_thread_id',
1739                                   prefix: '#include <signal.h>'))
1740config_host_data.set('HAVE_STRUCT_STAT_ST_ATIM',
1741                     cc.has_member('struct stat', 'st_atim',
1742                                   prefix: '#include <sys/stat.h>'))
1743
1744# has_type
1745config_host_data.set('CONFIG_IOVEC',
1746                     cc.has_type('struct iovec',
1747                                 prefix: '#include <sys/uio.h>'))
1748config_host_data.set('HAVE_UTMPX',
1749                     cc.has_type('struct utmpx',
1750                                 prefix: '#include <utmpx.h>'))
1751
1752config_host_data.set('CONFIG_EVENTFD', cc.links('''
1753  #include <sys/eventfd.h>
1754  int main(void) { return eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); }'''))
1755config_host_data.set('CONFIG_FDATASYNC', cc.links(gnu_source_prefix + '''
1756  #include <unistd.h>
1757  int main(void) {
1758  #if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
1759  return fdatasync(0);
1760  #else
1761  #error Not supported
1762  #endif
1763  }'''))
1764
1765has_madvise = cc.links(gnu_source_prefix + '''
1766  #include <sys/types.h>
1767  #include <sys/mman.h>
1768  #include <stddef.h>
1769  int main(void) { return madvise(NULL, 0, MADV_DONTNEED); }''')
1770missing_madvise_proto = false
1771if has_madvise
1772  # Some platforms (illumos and Solaris before Solaris 11) provide madvise()
1773  # but forget to prototype it. In this case, has_madvise will be true (the
1774  # test program links despite a compile warning). To detect the
1775  # missing-prototype case, we try again with a definitely-bogus prototype.
1776  # This will only compile if the system headers don't provide the prototype;
1777  # otherwise the conflicting prototypes will cause a compiler error.
1778  missing_madvise_proto = cc.links(gnu_source_prefix + '''
1779    #include <sys/types.h>
1780    #include <sys/mman.h>
1781    #include <stddef.h>
1782    extern int madvise(int);
1783    int main(void) { return madvise(0); }''')
1784endif
1785config_host_data.set('CONFIG_MADVISE', has_madvise)
1786config_host_data.set('HAVE_MADVISE_WITHOUT_PROTOTYPE', missing_madvise_proto)
1787
1788config_host_data.set('CONFIG_MEMFD', cc.links(gnu_source_prefix + '''
1789  #include <sys/mman.h>
1790  int main(void) { return memfd_create("foo", MFD_ALLOW_SEALING); }'''))
1791config_host_data.set('CONFIG_OPEN_BY_HANDLE', cc.links(gnu_source_prefix + '''
1792  #include <fcntl.h>
1793  #if !defined(AT_EMPTY_PATH)
1794  # error missing definition
1795  #else
1796  int main(void) { struct file_handle fh; return open_by_handle_at(0, &fh, 0); }
1797  #endif'''))
1798config_host_data.set('CONFIG_PIPE2', cc.links(gnu_source_prefix + '''
1799  #include <unistd.h>
1800  #include <fcntl.h>
1801
1802  int main(void)
1803  {
1804      int pipefd[2];
1805      return pipe2(pipefd, O_CLOEXEC);
1806  }'''))
1807config_host_data.set('CONFIG_POSIX_MADVISE', cc.links(gnu_source_prefix + '''
1808  #include <sys/mman.h>
1809  #include <stddef.h>
1810  int main(void) { return posix_madvise(NULL, 0, POSIX_MADV_DONTNEED); }'''))
1811
1812config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_W_TID', cc.links(gnu_source_prefix + '''
1813  #include <pthread.h>
1814
1815  static void *f(void *p) { return NULL; }
1816  int main(void)
1817  {
1818    pthread_t thread;
1819    pthread_create(&thread, 0, f, 0);
1820    pthread_setname_np(thread, "QEMU");
1821    return 0;
1822  }''', dependencies: threads))
1823config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_WO_TID', cc.links(gnu_source_prefix + '''
1824  #include <pthread.h>
1825
1826  static void *f(void *p) { pthread_setname_np("QEMU"); return NULL; }
1827  int main(void)
1828  {
1829    pthread_t thread;
1830    pthread_create(&thread, 0, f, 0);
1831    return 0;
1832  }''', dependencies: threads))
1833config_host_data.set('CONFIG_PTHREAD_CONDATTR_SETCLOCK', cc.links(gnu_source_prefix + '''
1834  #include <pthread.h>
1835  #include <time.h>
1836
1837  int main(void)
1838  {
1839    pthread_condattr_t attr
1840    pthread_condattr_init(&attr);
1841    pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
1842    return 0;
1843  }''', dependencies: threads))
1844
1845config_host_data.set('CONFIG_SIGNALFD', cc.links(gnu_source_prefix + '''
1846  #include <sys/signalfd.h>
1847  #include <stddef.h>
1848  int main(void) { return signalfd(-1, NULL, SFD_CLOEXEC); }'''))
1849config_host_data.set('CONFIG_SPLICE', cc.links(gnu_source_prefix + '''
1850  #include <unistd.h>
1851  #include <fcntl.h>
1852  #include <limits.h>
1853
1854  int main(void)
1855  {
1856    int len, fd = 0;
1857    len = tee(STDIN_FILENO, STDOUT_FILENO, INT_MAX, SPLICE_F_NONBLOCK);
1858    splice(STDIN_FILENO, NULL, fd, NULL, len, SPLICE_F_MOVE);
1859    return 0;
1860  }'''))
1861
1862config_host_data.set('HAVE_MLOCKALL', cc.links(gnu_source_prefix + '''
1863  #include <sys/mman.h>
1864  int main(int argc, char *argv[]) {
1865    return mlockall(MCL_FUTURE);
1866  }'''))
1867
1868have_l2tpv3 = false
1869if get_option('l2tpv3').allowed() and have_system
1870  have_l2tpv3 = cc.has_type('struct mmsghdr',
1871    prefix: gnu_source_prefix + '''
1872      #include <sys/socket.h>
1873      #include <linux/ip.h>''')
1874endif
1875config_host_data.set('CONFIG_L2TPV3', have_l2tpv3)
1876
1877have_netmap = false
1878if get_option('netmap').allowed() and have_system
1879  have_netmap = cc.compiles('''
1880    #include <inttypes.h>
1881    #include <net/if.h>
1882    #include <net/netmap.h>
1883    #include <net/netmap_user.h>
1884    #if (NETMAP_API < 11) || (NETMAP_API > 15)
1885    #error
1886    #endif
1887    int main(void) { return 0; }''')
1888  if not have_netmap and get_option('netmap').enabled()
1889    error('Netmap headers not available')
1890  endif
1891endif
1892config_host_data.set('CONFIG_NETMAP', have_netmap)
1893
1894# Work around a system header bug with some kernel/XFS header
1895# versions where they both try to define 'struct fsxattr':
1896# xfs headers will not try to redefine structs from linux headers
1897# if this macro is set.
1898config_host_data.set('HAVE_FSXATTR', cc.links('''
1899  #include <linux/fs.h>
1900  struct fsxattr foo;
1901  int main(void) {
1902    return 0;
1903  }'''))
1904
1905# Some versions of Mac OS X incorrectly define SIZE_MAX
1906config_host_data.set('HAVE_BROKEN_SIZE_MAX', not cc.compiles('''
1907    #include <stdint.h>
1908    #include <stdio.h>
1909    int main(int argc, char *argv[]) {
1910        return printf("%zu", SIZE_MAX);
1911    }''', args: ['-Werror']))
1912
1913atomic_test = '''
1914  #include <stdint.h>
1915  int main(void)
1916  {
1917    @0@ x = 0, y = 0;
1918    y = __atomic_load_n(&x, __ATOMIC_RELAXED);
1919    __atomic_store_n(&x, y, __ATOMIC_RELAXED);
1920    __atomic_compare_exchange_n(&x, &y, x, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
1921    __atomic_exchange_n(&x, y, __ATOMIC_RELAXED);
1922    __atomic_fetch_add(&x, y, __ATOMIC_RELAXED);
1923    return 0;
1924  }'''
1925
1926# See if 64-bit atomic operations are supported.
1927# Note that without __atomic builtins, we can only
1928# assume atomic loads/stores max at pointer size.
1929config_host_data.set('CONFIG_ATOMIC64', cc.links(atomic_test.format('uint64_t')))
1930
1931has_int128 = cc.links('''
1932  __int128_t a;
1933  __uint128_t b;
1934  int main (void) {
1935    a = a + b;
1936    b = a * b;
1937    a = a * a;
1938    return 0;
1939  }''')
1940
1941config_host_data.set('CONFIG_INT128', has_int128)
1942
1943if has_int128
1944  # "do we have 128-bit atomics which are handled inline and specifically not
1945  # via libatomic". The reason we can't use libatomic is documented in the
1946  # comment starting "GCC is a house divided" in include/qemu/atomic128.h.
1947  has_atomic128 = cc.links(atomic_test.format('unsigned __int128'))
1948
1949  config_host_data.set('CONFIG_ATOMIC128', has_atomic128)
1950
1951  if not has_atomic128
1952    has_cmpxchg128 = cc.links('''
1953      int main(void)
1954      {
1955        unsigned __int128 x = 0, y = 0;
1956        __sync_val_compare_and_swap_16(&x, y, x);
1957        return 0;
1958      }
1959    ''')
1960
1961    config_host_data.set('CONFIG_CMPXCHG128', has_cmpxchg128)
1962  endif
1963endif
1964
1965config_host_data.set('CONFIG_GETAUXVAL', cc.links(gnu_source_prefix + '''
1966  #include <sys/auxv.h>
1967  int main(void) {
1968    return getauxval(AT_HWCAP) == 0;
1969  }'''))
1970
1971config_host_data.set('CONFIG_USBFS', have_linux_user and cc.compiles('''
1972  #include <linux/usbdevice_fs.h>
1973
1974  #ifndef USBDEVFS_GET_CAPABILITIES
1975  #error "USBDEVFS_GET_CAPABILITIES undefined"
1976  #endif
1977
1978  #ifndef USBDEVFS_DISCONNECT_CLAIM
1979  #error "USBDEVFS_DISCONNECT_CLAIM undefined"
1980  #endif
1981
1982  int main(void) { return 0; }'''))
1983
1984have_keyring = get_option('keyring') \
1985  .require(targetos == 'linux', error_message: 'keyring is only available on Linux') \
1986  .require(cc.compiles('''
1987    #include <errno.h>
1988    #include <asm/unistd.h>
1989    #include <linux/keyctl.h>
1990    #include <sys/syscall.h>
1991    #include <unistd.h>
1992    int main(void) {
1993        return syscall(__NR_keyctl, KEYCTL_READ, 0, NULL, NULL, 0);
1994    }'''), error_message: 'keyctl syscall not available on this system').allowed()
1995config_host_data.set('CONFIG_SECRET_KEYRING', have_keyring)
1996
1997have_cpuid_h = cc.links('''
1998  #include <cpuid.h>
1999  int main(void) {
2000    unsigned a, b, c, d;
2001    unsigned max = __get_cpuid_max(0, 0);
2002
2003    if (max >= 1) {
2004        __cpuid(1, a, b, c, d);
2005    }
2006
2007    if (max >= 7) {
2008        __cpuid_count(7, 0, a, b, c, d);
2009    }
2010
2011    return 0;
2012  }''')
2013config_host_data.set('CONFIG_CPUID_H', have_cpuid_h)
2014
2015config_host_data.set('CONFIG_AVX2_OPT', get_option('avx2') \
2016  .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX2') \
2017  .require(cc.links('''
2018    #pragma GCC push_options
2019    #pragma GCC target("avx2")
2020    #include <cpuid.h>
2021    #include <immintrin.h>
2022    static int bar(void *a) {
2023      __m256i x = *(__m256i *)a;
2024      return _mm256_testz_si256(x, x);
2025    }
2026    int main(int argc, char *argv[]) { return bar(argv[0]); }
2027  '''), error_message: 'AVX2 not available').allowed())
2028
2029config_host_data.set('CONFIG_AVX512F_OPT', get_option('avx512f') \
2030  .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX512F') \
2031  .require(cc.links('''
2032    #pragma GCC push_options
2033    #pragma GCC target("avx512f")
2034    #include <cpuid.h>
2035    #include <immintrin.h>
2036    static int bar(void *a) {
2037      __m512i x = *(__m512i *)a;
2038      return _mm512_test_epi64_mask(x, x);
2039    }
2040    int main(int argc, char *argv[]) { return bar(argv[0]); }
2041  '''), error_message: 'AVX512F not available').allowed())
2042
2043have_pvrdma = get_option('pvrdma') \
2044  .require(rdma.found(), error_message: 'PVRDMA requires OpenFabrics libraries') \
2045  .require(cc.compiles('''
2046    int main(void)
2047    {
2048      char buf = 0;
2049      void *addr = &buf;
2050      addr = mremap(addr, 0, 1, MREMAP_MAYMOVE | MREMAP_FIXED);
2051
2052      return 0;
2053    }'''), error_message: 'PVRDMA requires mremap').allowed()
2054
2055if have_pvrdma
2056  config_host_data.set('LEGACY_RDMA_REG_MR', not cc.compiles('''
2057    #include <infiniband/verbs.h>
2058    int main(void)
2059    {
2060      struct ibv_mr *mr;
2061      struct ibv_pd *pd = NULL;
2062      size_t length = 10;
2063      uint64_t iova = 0;
2064      int access = 0;
2065      void *addr = NULL;
2066
2067      mr = ibv_reg_mr_iova(pd, addr, length, iova, access);
2068      ibv_dereg_mr(mr);
2069      return 0;
2070    }'''))
2071endif
2072
2073if get_option('membarrier').disabled()
2074  have_membarrier = false
2075elif targetos == 'windows'
2076  have_membarrier = true
2077elif targetos == 'linux'
2078  have_membarrier = cc.compiles('''
2079    #include <linux/membarrier.h>
2080    #include <sys/syscall.h>
2081    #include <unistd.h>
2082    #include <stdlib.h>
2083    int main(void) {
2084        syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0);
2085        syscall(__NR_membarrier, MEMBARRIER_CMD_SHARED, 0);
2086        exit(0);
2087    }''')
2088endif
2089config_host_data.set('CONFIG_MEMBARRIER', get_option('membarrier') \
2090  .require(have_membarrier, error_message: 'membarrier system call not available') \
2091  .allowed())
2092
2093have_afalg = get_option('crypto_afalg') \
2094  .require(cc.compiles(gnu_source_prefix + '''
2095    #include <errno.h>
2096    #include <sys/types.h>
2097    #include <sys/socket.h>
2098    #include <linux/if_alg.h>
2099    int main(void) {
2100      int sock;
2101      sock = socket(AF_ALG, SOCK_SEQPACKET, 0);
2102      return sock;
2103    }
2104  '''), error_message: 'AF_ALG requested but could not be detected').allowed()
2105config_host_data.set('CONFIG_AF_ALG', have_afalg)
2106
2107config_host_data.set('CONFIG_AF_VSOCK', cc.has_header_symbol(
2108  'linux/vm_sockets.h', 'AF_VSOCK',
2109  prefix: '#include <sys/socket.h>',
2110))
2111
2112have_vss = false
2113have_vss_sdk = false # old xp/2003 SDK
2114if targetos == 'windows' and link_language == 'cpp'
2115  have_vss = cxx.compiles('''
2116    #define __MIDL_user_allocate_free_DEFINED__
2117    #include <vss.h>
2118    int main(void) { return VSS_CTX_BACKUP; }''')
2119  have_vss_sdk = cxx.has_header('vscoordint.h')
2120endif
2121config_host_data.set('HAVE_VSS_SDK', have_vss_sdk)
2122
2123ignored = ['CONFIG_QEMU_INTERP_PREFIX', # actually per-target
2124    'HAVE_GDB_BIN']
2125arrays = ['CONFIG_BDRV_RW_WHITELIST', 'CONFIG_BDRV_RO_WHITELIST']
2126foreach k, v: config_host
2127  if ignored.contains(k)
2128    # do nothing
2129  elif arrays.contains(k)
2130    if v != ''
2131      v = '"' + '", "'.join(v.split()) + '", '
2132    endif
2133    config_host_data.set(k, v)
2134  elif k.startswith('CONFIG_')
2135    config_host_data.set(k, v == 'y' ? 1 : v)
2136  endif
2137endforeach
2138
2139# Older versions of MinGW do not import _lock_file and _unlock_file properly.
2140# This was fixed for v6.0.0 with commit b48e3ac8969d.
2141if targetos == 'windows'
2142  config_host_data.set('HAVE__LOCK_FILE', cc.links('''
2143    #include <stdio.h>
2144    int main(void) {
2145      _lock_file(NULL);
2146      _unlock_file(NULL);
2147      return 0;
2148    }''', name: '_lock_file and _unlock_file'))
2149endif
2150
2151########################
2152# Target configuration #
2153########################
2154
2155minikconf = find_program('scripts/minikconf.py')
2156config_all = {}
2157config_all_devices = {}
2158config_all_disas = {}
2159config_devices_mak_list = []
2160config_devices_h = {}
2161config_target_h = {}
2162config_target_mak = {}
2163
2164disassemblers = {
2165  'alpha' : ['CONFIG_ALPHA_DIS'],
2166  'arm' : ['CONFIG_ARM_DIS'],
2167  'avr' : ['CONFIG_AVR_DIS'],
2168  'cris' : ['CONFIG_CRIS_DIS'],
2169  'hexagon' : ['CONFIG_HEXAGON_DIS'],
2170  'hppa' : ['CONFIG_HPPA_DIS'],
2171  'i386' : ['CONFIG_I386_DIS'],
2172  'x86_64' : ['CONFIG_I386_DIS'],
2173  'm68k' : ['CONFIG_M68K_DIS'],
2174  'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
2175  'mips' : ['CONFIG_MIPS_DIS'],
2176  'nios2' : ['CONFIG_NIOS2_DIS'],
2177  'or1k' : ['CONFIG_OPENRISC_DIS'],
2178  'ppc' : ['CONFIG_PPC_DIS'],
2179  'riscv' : ['CONFIG_RISCV_DIS'],
2180  'rx' : ['CONFIG_RX_DIS'],
2181  's390' : ['CONFIG_S390_DIS'],
2182  'sh4' : ['CONFIG_SH4_DIS'],
2183  'sparc' : ['CONFIG_SPARC_DIS'],
2184  'xtensa' : ['CONFIG_XTENSA_DIS'],
2185}
2186if link_language == 'cpp'
2187  disassemblers += {
2188    'aarch64' : [ 'CONFIG_ARM_A64_DIS'],
2189    'arm' : [ 'CONFIG_ARM_DIS', 'CONFIG_ARM_A64_DIS'],
2190    'mips' : [ 'CONFIG_MIPS_DIS', 'CONFIG_NANOMIPS_DIS'],
2191  }
2192endif
2193
2194have_ivshmem = config_host_data.get('CONFIG_EVENTFD')
2195host_kconfig = \
2196  (get_option('fuzzing') ? ['CONFIG_FUZZ=y'] : []) + \
2197  (have_tpm ? ['CONFIG_TPM=y'] : []) + \
2198  (spice.found() ? ['CONFIG_SPICE=y'] : []) + \
2199  (have_ivshmem ? ['CONFIG_IVSHMEM=y'] : []) + \
2200  (opengl.found() ? ['CONFIG_OPENGL=y'] : []) + \
2201  (x11.found() ? ['CONFIG_X11=y'] : []) + \
2202  ('CONFIG_VHOST_USER' in config_host ? ['CONFIG_VHOST_USER=y'] : []) + \
2203  ('CONFIG_VHOST_VDPA' in config_host ? ['CONFIG_VHOST_VDPA=y'] : []) + \
2204  ('CONFIG_VHOST_KERNEL' in config_host ? ['CONFIG_VHOST_KERNEL=y'] : []) + \
2205  (have_virtfs ? ['CONFIG_VIRTFS=y'] : []) + \
2206  ('CONFIG_LINUX' in config_host ? ['CONFIG_LINUX=y'] : []) + \
2207  (have_pvrdma ? ['CONFIG_PVRDMA=y'] : []) + \
2208  (multiprocess_allowed ? ['CONFIG_MULTIPROCESS_ALLOWED=y'] : [])
2209
2210ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ]
2211
2212default_targets = 'CONFIG_DEFAULT_TARGETS' in config_host
2213actual_target_dirs = []
2214fdt_required = []
2215foreach target : target_dirs
2216  config_target = { 'TARGET_NAME': target.split('-')[0] }
2217  if target.endswith('linux-user')
2218    if targetos != 'linux'
2219      if default_targets
2220        continue
2221      endif
2222      error('Target @0@ is only available on a Linux host'.format(target))
2223    endif
2224    config_target += { 'CONFIG_LINUX_USER': 'y' }
2225  elif target.endswith('bsd-user')
2226    if 'CONFIG_BSD' not in config_host
2227      if default_targets
2228        continue
2229      endif
2230      error('Target @0@ is only available on a BSD host'.format(target))
2231    endif
2232    config_target += { 'CONFIG_BSD_USER': 'y' }
2233  elif target.endswith('softmmu')
2234    config_target += { 'CONFIG_SOFTMMU': 'y' }
2235  endif
2236  if target.endswith('-user')
2237    config_target += {
2238      'CONFIG_USER_ONLY': 'y',
2239      'CONFIG_QEMU_INTERP_PREFIX':
2240        config_host['CONFIG_QEMU_INTERP_PREFIX'].format(config_target['TARGET_NAME'])
2241    }
2242  endif
2243
2244  accel_kconfig = []
2245  foreach sym: accelerators
2246    if sym == 'CONFIG_TCG' or target in accelerator_targets.get(sym, [])
2247      config_target += { sym: 'y' }
2248      config_all += { sym: 'y' }
2249      if sym == 'CONFIG_TCG' and tcg_arch == 'tci'
2250        config_target += { 'CONFIG_TCG_INTERPRETER': 'y' }
2251      endif
2252      if target in modular_tcg
2253        config_target += { 'CONFIG_TCG_MODULAR': 'y' }
2254      else
2255        config_target += { 'CONFIG_TCG_BUILTIN': 'y' }
2256      endif
2257      accel_kconfig += [ sym + '=y' ]
2258    endif
2259  endforeach
2260  if accel_kconfig.length() == 0
2261    if default_targets
2262      continue
2263    endif
2264    error('No accelerator available for target @0@'.format(target))
2265  endif
2266
2267  actual_target_dirs += target
2268  config_target += keyval.load('configs/targets' / target + '.mak')
2269  config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
2270
2271  if 'TARGET_NEED_FDT' in config_target
2272    fdt_required += target
2273  endif
2274
2275  # Add default keys
2276  if 'TARGET_BASE_ARCH' not in config_target
2277    config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
2278  endif
2279  if 'TARGET_ABI_DIR' not in config_target
2280    config_target += {'TARGET_ABI_DIR': config_target['TARGET_ARCH']}
2281  endif
2282  if 'TARGET_BIG_ENDIAN' not in config_target
2283    config_target += {'TARGET_BIG_ENDIAN': 'n'}
2284  endif
2285
2286  foreach k, v: disassemblers
2287    if host_arch.startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k)
2288      foreach sym: v
2289        config_target += { sym: 'y' }
2290        config_all_disas += { sym: 'y' }
2291      endforeach
2292    endif
2293  endforeach
2294
2295  config_target_data = configuration_data()
2296  foreach k, v: config_target
2297    if not k.startswith('TARGET_') and not k.startswith('CONFIG_')
2298      # do nothing
2299    elif ignored.contains(k)
2300      # do nothing
2301    elif k == 'TARGET_BASE_ARCH'
2302      # Note that TARGET_BASE_ARCH ends up in config-target.h but it is
2303      # not used to select files from sourcesets.
2304      config_target_data.set('TARGET_' + v.to_upper(), 1)
2305    elif k == 'TARGET_NAME' or k == 'CONFIG_QEMU_INTERP_PREFIX'
2306      config_target_data.set_quoted(k, v)
2307    elif v == 'y'
2308      config_target_data.set(k, 1)
2309    elif v == 'n'
2310      config_target_data.set(k, 0)
2311    else
2312      config_target_data.set(k, v)
2313    endif
2314  endforeach
2315  config_target_data.set('QEMU_ARCH',
2316                         'QEMU_ARCH_' + config_target['TARGET_BASE_ARCH'].to_upper())
2317  config_target_h += {target: configure_file(output: target + '-config-target.h',
2318                                               configuration: config_target_data)}
2319
2320  if target.endswith('-softmmu')
2321    config_input = meson.get_external_property(target, 'default')
2322    config_devices_mak = target + '-config-devices.mak'
2323    config_devices_mak = configure_file(
2324      input: ['configs/devices' / target / config_input + '.mak', 'Kconfig'],
2325      output: config_devices_mak,
2326      depfile: config_devices_mak + '.d',
2327      capture: true,
2328      command: [minikconf,
2329                get_option('default_devices') ? '--defconfig' : '--allnoconfig',
2330                config_devices_mak, '@DEPFILE@', '@INPUT@',
2331                host_kconfig, accel_kconfig,
2332                'CONFIG_' + config_target['TARGET_ARCH'].to_upper() + '=y'])
2333
2334    config_devices_data = configuration_data()
2335    config_devices = keyval.load(config_devices_mak)
2336    foreach k, v: config_devices
2337      config_devices_data.set(k, 1)
2338    endforeach
2339    config_devices_mak_list += config_devices_mak
2340    config_devices_h += {target: configure_file(output: target + '-config-devices.h',
2341                                                configuration: config_devices_data)}
2342    config_target += config_devices
2343    config_all_devices += config_devices
2344  endif
2345  config_target_mak += {target: config_target}
2346endforeach
2347target_dirs = actual_target_dirs
2348
2349# This configuration is used to build files that are shared by
2350# multiple binaries, and then extracted out of the "common"
2351# static_library target.
2352#
2353# We do not use all_sources()/all_dependencies(), because it would
2354# build literally all source files, including devices only used by
2355# targets that are not built for this compilation.  The CONFIG_ALL
2356# pseudo symbol replaces it.
2357
2358config_all += config_all_devices
2359config_all += config_host
2360config_all += config_all_disas
2361config_all += {
2362  'CONFIG_XEN': config_host.has_key('CONFIG_XEN_BACKEND'),
2363  'CONFIG_SOFTMMU': have_system,
2364  'CONFIG_USER_ONLY': have_user,
2365  'CONFIG_ALL': true,
2366}
2367
2368target_configs_h = []
2369foreach target: target_dirs
2370  target_configs_h += config_target_h[target]
2371  target_configs_h += config_devices_h.get(target, [])
2372endforeach
2373genh += custom_target('config-poison.h',
2374                      input: [target_configs_h],
2375                      output: 'config-poison.h',
2376                      capture: true,
2377                      command: [find_program('scripts/make-config-poison.sh'),
2378                                target_configs_h])
2379
2380##############
2381# Submodules #
2382##############
2383
2384capstone = not_found
2385capstone_opt = get_option('capstone')
2386if capstone_opt in ['enabled', 'auto', 'system']
2387  have_internal = fs.exists(meson.current_source_dir() / 'capstone/Makefile')
2388  capstone = dependency('capstone', version: '>=4.0',
2389                        kwargs: static_kwargs, method: 'pkg-config',
2390                        required: capstone_opt == 'system' or
2391                                  capstone_opt == 'enabled' and not have_internal)
2392
2393  # Some versions of capstone have broken pkg-config file
2394  # that reports a wrong -I path, causing the #include to
2395  # fail later. If the system has such a broken version
2396  # do not use it.
2397  if capstone.found() and not cc.compiles('#include <capstone.h>',
2398                                          dependencies: [capstone])
2399    capstone = not_found
2400    if capstone_opt == 'system'
2401      error('system capstone requested, it does not appear to work')
2402    endif
2403  endif
2404
2405  if capstone.found()
2406    capstone_opt = 'system'
2407  elif have_internal
2408    capstone_opt = 'internal'
2409  else
2410    capstone_opt = 'disabled'
2411  endif
2412endif
2413if capstone_opt == 'internal'
2414  capstone_data = configuration_data()
2415  capstone_data.set('CAPSTONE_USE_SYS_DYN_MEM', '1')
2416
2417  capstone_files = files(
2418    'capstone/cs.c',
2419    'capstone/MCInst.c',
2420    'capstone/MCInstrDesc.c',
2421    'capstone/MCRegisterInfo.c',
2422    'capstone/SStream.c',
2423    'capstone/utils.c'
2424  )
2425
2426  if 'CONFIG_ARM_DIS' in config_all_disas
2427    capstone_data.set('CAPSTONE_HAS_ARM', '1')
2428    capstone_files += files(
2429      'capstone/arch/ARM/ARMDisassembler.c',
2430      'capstone/arch/ARM/ARMInstPrinter.c',
2431      'capstone/arch/ARM/ARMMapping.c',
2432      'capstone/arch/ARM/ARMModule.c'
2433    )
2434  endif
2435
2436  # FIXME: This config entry currently depends on a c++ compiler.
2437  # Which is needed for building libvixl, but not for capstone.
2438  if 'CONFIG_ARM_A64_DIS' in config_all_disas
2439    capstone_data.set('CAPSTONE_HAS_ARM64', '1')
2440    capstone_files += files(
2441      'capstone/arch/AArch64/AArch64BaseInfo.c',
2442      'capstone/arch/AArch64/AArch64Disassembler.c',
2443      'capstone/arch/AArch64/AArch64InstPrinter.c',
2444      'capstone/arch/AArch64/AArch64Mapping.c',
2445      'capstone/arch/AArch64/AArch64Module.c'
2446    )
2447  endif
2448
2449  if 'CONFIG_PPC_DIS' in config_all_disas
2450    capstone_data.set('CAPSTONE_HAS_POWERPC', '1')
2451    capstone_files += files(
2452      'capstone/arch/PowerPC/PPCDisassembler.c',
2453      'capstone/arch/PowerPC/PPCInstPrinter.c',
2454      'capstone/arch/PowerPC/PPCMapping.c',
2455      'capstone/arch/PowerPC/PPCModule.c'
2456    )
2457  endif
2458
2459  if 'CONFIG_S390_DIS' in config_all_disas
2460    capstone_data.set('CAPSTONE_HAS_SYSZ', '1')
2461    capstone_files += files(
2462      'capstone/arch/SystemZ/SystemZDisassembler.c',
2463      'capstone/arch/SystemZ/SystemZInstPrinter.c',
2464      'capstone/arch/SystemZ/SystemZMapping.c',
2465      'capstone/arch/SystemZ/SystemZModule.c',
2466      'capstone/arch/SystemZ/SystemZMCTargetDesc.c'
2467    )
2468  endif
2469
2470  if 'CONFIG_I386_DIS' in config_all_disas
2471    capstone_data.set('CAPSTONE_HAS_X86', 1)
2472    capstone_files += files(
2473      'capstone/arch/X86/X86Disassembler.c',
2474      'capstone/arch/X86/X86DisassemblerDecoder.c',
2475      'capstone/arch/X86/X86ATTInstPrinter.c',
2476      'capstone/arch/X86/X86IntelInstPrinter.c',
2477      'capstone/arch/X86/X86InstPrinterCommon.c',
2478      'capstone/arch/X86/X86Mapping.c',
2479      'capstone/arch/X86/X86Module.c'
2480    )
2481  endif
2482
2483  configure_file(output: 'capstone-defs.h', configuration: capstone_data)
2484
2485  capstone_cargs = [
2486    # FIXME: There does not seem to be a way to completely replace the c_args
2487    # that come from add_project_arguments() -- we can only add to them.
2488    # So: disable all warnings with a big hammer.
2489    '-Wno-error', '-w',
2490
2491    # Include all configuration defines via a header file, which will wind up
2492    # as a dependency on the object file, and thus changes here will result
2493    # in a rebuild.
2494    '-include', 'capstone-defs.h'
2495  ]
2496
2497  libcapstone = static_library('capstone',
2498                               build_by_default: false,
2499                               sources: capstone_files,
2500                               c_args: capstone_cargs,
2501                               include_directories: 'capstone/include')
2502  capstone = declare_dependency(link_with: libcapstone,
2503                                include_directories: 'capstone/include/capstone')
2504endif
2505
2506slirp = not_found
2507slirp_opt = 'disabled'
2508if have_system
2509  slirp_opt = get_option('slirp')
2510  if slirp_opt in ['enabled', 'auto', 'system']
2511    have_internal = fs.exists(meson.current_source_dir() / 'slirp/meson.build')
2512    slirp = dependency('slirp', kwargs: static_kwargs,
2513                       method: 'pkg-config',
2514                       required: slirp_opt == 'system' or
2515                                 slirp_opt == 'enabled' and not have_internal)
2516    if slirp.found()
2517      slirp_opt = 'system'
2518    elif have_internal
2519      slirp_opt = 'internal'
2520    else
2521      slirp_opt = 'disabled'
2522    endif
2523  endif
2524  if slirp_opt == 'internal'
2525    slirp_deps = []
2526    if targetos == 'windows'
2527      slirp_deps = cc.find_library('iphlpapi')
2528    elif targetos == 'darwin'
2529      slirp_deps = cc.find_library('resolv')
2530    endif
2531    slirp_conf = configuration_data()
2532    slirp_conf.set('SLIRP_MAJOR_VERSION', meson.project_version().split('.')[0])
2533    slirp_conf.set('SLIRP_MINOR_VERSION', meson.project_version().split('.')[1])
2534    slirp_conf.set('SLIRP_MICRO_VERSION', meson.project_version().split('.')[2])
2535    slirp_conf.set_quoted('SLIRP_VERSION_STRING', meson.project_version())
2536    slirp_cargs = ['-DG_LOG_DOMAIN="Slirp"']
2537    slirp_files = [
2538      'slirp/src/arp_table.c',
2539      'slirp/src/bootp.c',
2540      'slirp/src/cksum.c',
2541      'slirp/src/dhcpv6.c',
2542      'slirp/src/dnssearch.c',
2543      'slirp/src/if.c',
2544      'slirp/src/ip6_icmp.c',
2545      'slirp/src/ip6_input.c',
2546      'slirp/src/ip6_output.c',
2547      'slirp/src/ip_icmp.c',
2548      'slirp/src/ip_input.c',
2549      'slirp/src/ip_output.c',
2550      'slirp/src/mbuf.c',
2551      'slirp/src/misc.c',
2552      'slirp/src/ncsi.c',
2553      'slirp/src/ndp_table.c',
2554      'slirp/src/sbuf.c',
2555      'slirp/src/slirp.c',
2556      'slirp/src/socket.c',
2557      'slirp/src/state.c',
2558      'slirp/src/stream.c',
2559      'slirp/src/tcp_input.c',
2560      'slirp/src/tcp_output.c',
2561      'slirp/src/tcp_subr.c',
2562      'slirp/src/tcp_timer.c',
2563      'slirp/src/tftp.c',
2564      'slirp/src/udp.c',
2565      'slirp/src/udp6.c',
2566      'slirp/src/util.c',
2567      'slirp/src/version.c',
2568      'slirp/src/vmstate.c',
2569    ]
2570
2571    configure_file(
2572      input : 'slirp/src/libslirp-version.h.in',
2573      output : 'libslirp-version.h',
2574      configuration: slirp_conf)
2575
2576    slirp_inc = include_directories('slirp', 'slirp/src')
2577    libslirp = static_library('slirp',
2578                              build_by_default: false,
2579                              sources: slirp_files,
2580                              c_args: slirp_cargs,
2581                              include_directories: slirp_inc)
2582    slirp = declare_dependency(link_with: libslirp,
2583                               dependencies: slirp_deps,
2584                               include_directories: slirp_inc)
2585  endif
2586endif
2587
2588# For CFI, we need to compile slirp as a static library together with qemu.
2589# This is because we register slirp functions as callbacks for QEMU Timers.
2590# When using a system-wide shared libslirp, the type information for the
2591# callback is missing and the timer call produces a false positive with CFI.
2592#
2593# Now that slirp_opt has been defined, check if the selected slirp is compatible
2594# with control-flow integrity.
2595if get_option('cfi') and slirp_opt == 'system'
2596  error('Control-Flow Integrity is not compatible with system-wide slirp.' \
2597         + ' Please configure with --enable-slirp=git')
2598endif
2599
2600fdt = not_found
2601if have_system
2602  fdt_opt = get_option('fdt')
2603  if fdt_opt in ['enabled', 'auto', 'system']
2604    have_internal = fs.exists(meson.current_source_dir() / 'dtc/libfdt/Makefile.libfdt')
2605    fdt = cc.find_library('fdt', kwargs: static_kwargs,
2606                          required: fdt_opt == 'system' or
2607                                    fdt_opt == 'enabled' and not have_internal)
2608    if fdt.found() and cc.links('''
2609       #include <libfdt.h>
2610       #include <libfdt_env.h>
2611       int main(void) { fdt_find_max_phandle(NULL, NULL); return 0; }''',
2612         dependencies: fdt)
2613      fdt_opt = 'system'
2614    elif fdt_opt == 'system'
2615       error('system libfdt requested, but it is too old (1.5.1 or newer required)')
2616    elif have_internal
2617      fdt_opt = 'internal'
2618    else
2619      fdt_opt = 'disabled'
2620      fdt = not_found
2621    endif
2622  endif
2623  if fdt_opt == 'internal'
2624    fdt_files = files(
2625      'dtc/libfdt/fdt.c',
2626      'dtc/libfdt/fdt_ro.c',
2627      'dtc/libfdt/fdt_wip.c',
2628      'dtc/libfdt/fdt_sw.c',
2629      'dtc/libfdt/fdt_rw.c',
2630      'dtc/libfdt/fdt_strerror.c',
2631      'dtc/libfdt/fdt_empty_tree.c',
2632      'dtc/libfdt/fdt_addresses.c',
2633      'dtc/libfdt/fdt_overlay.c',
2634      'dtc/libfdt/fdt_check.c',
2635    )
2636
2637    fdt_inc = include_directories('dtc/libfdt')
2638    libfdt = static_library('fdt',
2639                            build_by_default: false,
2640                            sources: fdt_files,
2641                            include_directories: fdt_inc)
2642    fdt = declare_dependency(link_with: libfdt,
2643                             include_directories: fdt_inc)
2644  endif
2645else
2646  fdt_opt = 'disabled'
2647endif
2648if not fdt.found() and fdt_required.length() > 0
2649  error('fdt not available but required by targets ' + ', '.join(fdt_required))
2650endif
2651
2652config_host_data.set('CONFIG_CAPSTONE', capstone.found())
2653config_host_data.set('CONFIG_FDT', fdt.found())
2654config_host_data.set('CONFIG_SLIRP', slirp.found())
2655
2656#####################
2657# Generated sources #
2658#####################
2659
2660genh += configure_file(output: 'config-host.h', configuration: config_host_data)
2661
2662hxtool = find_program('scripts/hxtool')
2663shaderinclude = find_program('scripts/shaderinclude.pl')
2664qapi_gen = find_program('scripts/qapi-gen.py')
2665qapi_gen_depends = [ meson.current_source_dir() / 'scripts/qapi/__init__.py',
2666                     meson.current_source_dir() / 'scripts/qapi/commands.py',
2667                     meson.current_source_dir() / 'scripts/qapi/common.py',
2668                     meson.current_source_dir() / 'scripts/qapi/error.py',
2669                     meson.current_source_dir() / 'scripts/qapi/events.py',
2670                     meson.current_source_dir() / 'scripts/qapi/expr.py',
2671                     meson.current_source_dir() / 'scripts/qapi/gen.py',
2672                     meson.current_source_dir() / 'scripts/qapi/introspect.py',
2673                     meson.current_source_dir() / 'scripts/qapi/parser.py',
2674                     meson.current_source_dir() / 'scripts/qapi/schema.py',
2675                     meson.current_source_dir() / 'scripts/qapi/source.py',
2676                     meson.current_source_dir() / 'scripts/qapi/types.py',
2677                     meson.current_source_dir() / 'scripts/qapi/visit.py',
2678                     meson.current_source_dir() / 'scripts/qapi/common.py',
2679                     meson.current_source_dir() / 'scripts/qapi-gen.py'
2680]
2681
2682tracetool = [
2683  python, files('scripts/tracetool.py'),
2684   '--backend=' + ','.join(get_option('trace_backends'))
2685]
2686tracetool_depends = files(
2687  'scripts/tracetool/backend/log.py',
2688  'scripts/tracetool/backend/__init__.py',
2689  'scripts/tracetool/backend/dtrace.py',
2690  'scripts/tracetool/backend/ftrace.py',
2691  'scripts/tracetool/backend/simple.py',
2692  'scripts/tracetool/backend/syslog.py',
2693  'scripts/tracetool/backend/ust.py',
2694  'scripts/tracetool/format/ust_events_c.py',
2695  'scripts/tracetool/format/ust_events_h.py',
2696  'scripts/tracetool/format/__init__.py',
2697  'scripts/tracetool/format/d.py',
2698  'scripts/tracetool/format/simpletrace_stap.py',
2699  'scripts/tracetool/format/c.py',
2700  'scripts/tracetool/format/h.py',
2701  'scripts/tracetool/format/log_stap.py',
2702  'scripts/tracetool/format/stap.py',
2703  'scripts/tracetool/__init__.py',
2704  'scripts/tracetool/transform.py',
2705  'scripts/tracetool/vcpu.py'
2706)
2707
2708qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
2709                    meson.current_source_dir(),
2710                    config_host['PKGVERSION'], meson.project_version()]
2711qemu_version = custom_target('qemu-version.h',
2712                             output: 'qemu-version.h',
2713                             command: qemu_version_cmd,
2714                             capture: true,
2715                             build_by_default: true,
2716                             build_always_stale: true)
2717genh += qemu_version
2718
2719hxdep = []
2720hx_headers = [
2721  ['qemu-options.hx', 'qemu-options.def'],
2722  ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
2723]
2724if have_system
2725  hx_headers += [
2726    ['hmp-commands.hx', 'hmp-commands.h'],
2727    ['hmp-commands-info.hx', 'hmp-commands-info.h'],
2728  ]
2729endif
2730foreach d : hx_headers
2731  hxdep += custom_target(d[1],
2732                input: files(d[0]),
2733                output: d[1],
2734                capture: true,
2735                build_by_default: true, # to be removed when added to a target
2736                command: [hxtool, '-h', '@INPUT0@'])
2737endforeach
2738genh += hxdep
2739
2740###################
2741# Collect sources #
2742###################
2743
2744authz_ss = ss.source_set()
2745blockdev_ss = ss.source_set()
2746block_ss = ss.source_set()
2747chardev_ss = ss.source_set()
2748common_ss = ss.source_set()
2749crypto_ss = ss.source_set()
2750hwcore_ss = ss.source_set()
2751io_ss = ss.source_set()
2752qmp_ss = ss.source_set()
2753qom_ss = ss.source_set()
2754softmmu_ss = ss.source_set()
2755specific_fuzz_ss = ss.source_set()
2756specific_ss = ss.source_set()
2757stub_ss = ss.source_set()
2758trace_ss = ss.source_set()
2759user_ss = ss.source_set()
2760util_ss = ss.source_set()
2761
2762# accel modules
2763qtest_module_ss = ss.source_set()
2764tcg_module_ss = ss.source_set()
2765
2766modules = {}
2767target_modules = {}
2768hw_arch = {}
2769target_arch = {}
2770target_softmmu_arch = {}
2771target_user_arch = {}
2772
2773###############
2774# Trace files #
2775###############
2776
2777# TODO: add each directory to the subdirs from its own meson.build, once
2778# we have those
2779trace_events_subdirs = [
2780  'crypto',
2781  'qapi',
2782  'qom',
2783  'monitor',
2784  'util',
2785]
2786if have_linux_user
2787  trace_events_subdirs += [ 'linux-user' ]
2788endif
2789if have_bsd_user
2790  trace_events_subdirs += [ 'bsd-user' ]
2791endif
2792if have_block
2793  trace_events_subdirs += [
2794    'authz',
2795    'block',
2796    'io',
2797    'nbd',
2798    'scsi',
2799  ]
2800endif
2801if have_system
2802  trace_events_subdirs += [
2803    'accel/kvm',
2804    'audio',
2805    'backends',
2806    'backends/tpm',
2807    'chardev',
2808    'ebpf',
2809    'hw/9pfs',
2810    'hw/acpi',
2811    'hw/adc',
2812    'hw/alpha',
2813    'hw/arm',
2814    'hw/audio',
2815    'hw/block',
2816    'hw/block/dataplane',
2817    'hw/char',
2818    'hw/display',
2819    'hw/dma',
2820    'hw/hppa',
2821    'hw/hyperv',
2822    'hw/i2c',
2823    'hw/i386',
2824    'hw/i386/xen',
2825    'hw/ide',
2826    'hw/input',
2827    'hw/intc',
2828    'hw/isa',
2829    'hw/mem',
2830    'hw/mips',
2831    'hw/misc',
2832    'hw/misc/macio',
2833    'hw/net',
2834    'hw/net/can',
2835    'hw/nubus',
2836    'hw/nvme',
2837    'hw/nvram',
2838    'hw/pci',
2839    'hw/pci-host',
2840    'hw/ppc',
2841    'hw/rdma',
2842    'hw/rdma/vmw',
2843    'hw/rtc',
2844    'hw/s390x',
2845    'hw/scsi',
2846    'hw/sd',
2847    'hw/sh4',
2848    'hw/sparc',
2849    'hw/sparc64',
2850    'hw/ssi',
2851    'hw/timer',
2852    'hw/tpm',
2853    'hw/usb',
2854    'hw/vfio',
2855    'hw/virtio',
2856    'hw/watchdog',
2857    'hw/xen',
2858    'hw/gpio',
2859    'migration',
2860    'net',
2861    'softmmu',
2862    'ui',
2863    'hw/remote',
2864  ]
2865endif
2866if have_system or have_user
2867  trace_events_subdirs += [
2868    'accel/tcg',
2869    'hw/core',
2870    'target/arm',
2871    'target/arm/hvf',
2872    'target/hppa',
2873    'target/i386',
2874    'target/i386/kvm',
2875    'target/mips/tcg',
2876    'target/nios2',
2877    'target/ppc',
2878    'target/riscv',
2879    'target/s390x',
2880    'target/s390x/kvm',
2881    'target/sparc',
2882  ]
2883endif
2884
2885vhost_user = not_found
2886if targetos == 'linux' and 'CONFIG_VHOST_USER' in config_host
2887  libvhost_user = subproject('libvhost-user')
2888  vhost_user = libvhost_user.get_variable('vhost_user_dep')
2889endif
2890
2891# NOTE: the trace/ subdirectory needs the qapi_trace_events variable
2892# that is filled in by qapi/.
2893subdir('qapi')
2894subdir('qobject')
2895subdir('stubs')
2896subdir('trace')
2897subdir('util')
2898subdir('qom')
2899subdir('authz')
2900subdir('crypto')
2901subdir('ui')
2902
2903
2904if enable_modules
2905  libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
2906  modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
2907endif
2908
2909stub_ss = stub_ss.apply(config_all, strict: false)
2910
2911util_ss.add_all(trace_ss)
2912util_ss = util_ss.apply(config_all, strict: false)
2913libqemuutil = static_library('qemuutil',
2914                             sources: util_ss.sources() + stub_ss.sources() + genh,
2915                             dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc, pixman])
2916qemuutil = declare_dependency(link_with: libqemuutil,
2917                              sources: genh + version_res)
2918
2919if have_system or have_user
2920  decodetree = generator(find_program('scripts/decodetree.py'),
2921                         output: 'decode-@BASENAME@.c.inc',
2922                         arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
2923  subdir('libdecnumber')
2924  subdir('target')
2925endif
2926
2927subdir('audio')
2928subdir('io')
2929subdir('chardev')
2930subdir('fsdev')
2931subdir('dump')
2932
2933if have_block
2934  block_ss.add(files(
2935    'block.c',
2936    'blockjob.c',
2937    'job.c',
2938    'qemu-io-cmds.c',
2939  ))
2940  if config_host_data.get('CONFIG_REPLICATION')
2941    block_ss.add(files('replication.c'))
2942  endif
2943
2944  subdir('nbd')
2945  subdir('scsi')
2946  subdir('block')
2947
2948  blockdev_ss.add(files(
2949    'blockdev.c',
2950    'blockdev-nbd.c',
2951    'iothread.c',
2952    'job-qmp.c',
2953  ), gnutls)
2954
2955  # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
2956  # os-win32.c does not
2957  blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
2958  softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
2959endif
2960
2961common_ss.add(files('cpus-common.c'))
2962
2963subdir('softmmu')
2964
2965common_ss.add(capstone)
2966specific_ss.add(files('cpu.c', 'disas.c', 'gdbstub.c'), capstone)
2967
2968# Work around a gcc bug/misfeature wherein constant propagation looks
2969# through an alias:
2970#   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99696
2971# to guess that a const variable is always zero.  Without lto, this is
2972# impossible, as the alias is restricted to page-vary-common.c.  Indeed,
2973# without lto, not even the alias is required -- we simply use different
2974# declarations in different compilation units.
2975pagevary = files('page-vary-common.c')
2976if get_option('b_lto')
2977  pagevary_flags = ['-fno-lto']
2978  if get_option('cfi')
2979    pagevary_flags += '-fno-sanitize=cfi-icall'
2980  endif
2981  pagevary = static_library('page-vary-common', sources: pagevary + genh,
2982                            c_args: pagevary_flags)
2983  pagevary = declare_dependency(link_with: pagevary)
2984endif
2985common_ss.add(pagevary)
2986specific_ss.add(files('page-vary.c'))
2987
2988subdir('backends')
2989subdir('disas')
2990subdir('migration')
2991subdir('monitor')
2992subdir('net')
2993subdir('replay')
2994subdir('semihosting')
2995subdir('hw')
2996subdir('tcg')
2997subdir('fpu')
2998subdir('accel')
2999subdir('plugins')
3000subdir('ebpf')
3001
3002common_user_inc = []
3003
3004subdir('common-user')
3005subdir('bsd-user')
3006subdir('linux-user')
3007
3008# needed for fuzzing binaries
3009subdir('tests/qtest/libqos')
3010subdir('tests/qtest/fuzz')
3011
3012# accel modules
3013tcg_real_module_ss = ss.source_set()
3014tcg_real_module_ss.add_all(when: 'CONFIG_TCG_MODULAR', if_true: tcg_module_ss)
3015specific_ss.add_all(when: 'CONFIG_TCG_BUILTIN', if_true: tcg_module_ss)
3016target_modules += { 'accel' : { 'qtest': qtest_module_ss,
3017                                'tcg': tcg_real_module_ss }}
3018
3019########################
3020# Library dependencies #
3021########################
3022
3023modinfo_collect = find_program('scripts/modinfo-collect.py')
3024modinfo_generate = find_program('scripts/modinfo-generate.py')
3025modinfo_files = []
3026
3027block_mods = []
3028softmmu_mods = []
3029foreach d, list : modules
3030  foreach m, module_ss : list
3031    if enable_modules and targetos != 'windows'
3032      module_ss = module_ss.apply(config_all, strict: false)
3033      sl = static_library(d + '-' + m, [genh, module_ss.sources()],
3034                          dependencies: [modulecommon, module_ss.dependencies()], pic: true)
3035      if d == 'block'
3036        block_mods += sl
3037      else
3038        softmmu_mods += sl
3039      endif
3040      if module_ss.sources() != []
3041        # FIXME: Should use sl.extract_all_objects(recursive: true) as
3042        # input. Sources can be used multiple times but objects are
3043        # unique when it comes to lookup in compile_commands.json.
3044        # Depnds on a mesion version with
3045        # https://github.com/mesonbuild/meson/pull/8900
3046        modinfo_files += custom_target(d + '-' + m + '.modinfo',
3047                                       output: d + '-' + m + '.modinfo',
3048                                       input: module_ss.sources() + genh,
3049                                       capture: true,
3050                                       command: [modinfo_collect, module_ss.sources()])
3051      endif
3052    else
3053      if d == 'block'
3054        block_ss.add_all(module_ss)
3055      else
3056        softmmu_ss.add_all(module_ss)
3057      endif
3058    endif
3059  endforeach
3060endforeach
3061
3062foreach d, list : target_modules
3063  foreach m, module_ss : list
3064    if enable_modules and targetos != 'windows'
3065      foreach target : target_dirs
3066        if target.endswith('-softmmu')
3067          config_target = config_target_mak[target]
3068          config_target += config_host
3069          target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3070          c_args = ['-DNEED_CPU_H',
3071                    '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3072                    '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3073          target_module_ss = module_ss.apply(config_target, strict: false)
3074          if target_module_ss.sources() != []
3075            module_name = d + '-' + m + '-' + config_target['TARGET_NAME']
3076            sl = static_library(module_name,
3077                                [genh, target_module_ss.sources()],
3078                                dependencies: [modulecommon, target_module_ss.dependencies()],
3079                                include_directories: target_inc,
3080                                c_args: c_args,
3081                                pic: true)
3082            softmmu_mods += sl
3083            # FIXME: Should use sl.extract_all_objects(recursive: true) too.
3084            modinfo_files += custom_target(module_name + '.modinfo',
3085                                           output: module_name + '.modinfo',
3086                                           input: target_module_ss.sources() + genh,
3087                                           capture: true,
3088                                           command: [modinfo_collect, '--target', target, target_module_ss.sources()])
3089          endif
3090        endif
3091      endforeach
3092    else
3093      specific_ss.add_all(module_ss)
3094    endif
3095  endforeach
3096endforeach
3097
3098if enable_modules
3099  modinfo_src = custom_target('modinfo.c',
3100                              output: 'modinfo.c',
3101                              input: modinfo_files,
3102                              command: [modinfo_generate, '@INPUT@'],
3103                              capture: true)
3104  modinfo_lib = static_library('modinfo', modinfo_src)
3105  modinfo_dep = declare_dependency(link_whole: modinfo_lib)
3106  softmmu_ss.add(modinfo_dep)
3107endif
3108
3109nm = find_program('nm')
3110undefsym = find_program('scripts/undefsym.py')
3111block_syms = custom_target('block.syms', output: 'block.syms',
3112                             input: [libqemuutil, block_mods],
3113                             capture: true,
3114                             command: [undefsym, nm, '@INPUT@'])
3115qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
3116                             input: [libqemuutil, softmmu_mods],
3117                             capture: true,
3118                             command: [undefsym, nm, '@INPUT@'])
3119
3120qom_ss = qom_ss.apply(config_host, strict: false)
3121libqom = static_library('qom', qom_ss.sources() + genh,
3122                        dependencies: [qom_ss.dependencies()],
3123                        name_suffix: 'fa')
3124
3125qom = declare_dependency(link_whole: libqom)
3126
3127authz_ss = authz_ss.apply(config_host, strict: false)
3128libauthz = static_library('authz', authz_ss.sources() + genh,
3129                          dependencies: [authz_ss.dependencies()],
3130                          name_suffix: 'fa',
3131                          build_by_default: false)
3132
3133authz = declare_dependency(link_whole: libauthz,
3134                           dependencies: qom)
3135
3136crypto_ss = crypto_ss.apply(config_host, strict: false)
3137libcrypto = static_library('crypto', crypto_ss.sources() + genh,
3138                           dependencies: [crypto_ss.dependencies()],
3139                           name_suffix: 'fa',
3140                           build_by_default: false)
3141
3142crypto = declare_dependency(link_whole: libcrypto,
3143                            dependencies: [authz, qom])
3144
3145io_ss = io_ss.apply(config_host, strict: false)
3146libio = static_library('io', io_ss.sources() + genh,
3147                       dependencies: [io_ss.dependencies()],
3148                       link_with: libqemuutil,
3149                       name_suffix: 'fa',
3150                       build_by_default: false)
3151
3152io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
3153
3154libmigration = static_library('migration', sources: migration_files + genh,
3155                              name_suffix: 'fa',
3156                              build_by_default: false)
3157migration = declare_dependency(link_with: libmigration,
3158                               dependencies: [zlib, qom, io])
3159softmmu_ss.add(migration)
3160
3161block_ss = block_ss.apply(config_host, strict: false)
3162libblock = static_library('block', block_ss.sources() + genh,
3163                          dependencies: block_ss.dependencies(),
3164                          link_depends: block_syms,
3165                          name_suffix: 'fa',
3166                          build_by_default: false)
3167
3168block = declare_dependency(link_whole: [libblock],
3169                           link_args: '@block.syms',
3170                           dependencies: [crypto, io])
3171
3172blockdev_ss = blockdev_ss.apply(config_host, strict: false)
3173libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
3174                             dependencies: blockdev_ss.dependencies(),
3175                             name_suffix: 'fa',
3176                             build_by_default: false)
3177
3178blockdev = declare_dependency(link_whole: [libblockdev],
3179                              dependencies: [block])
3180
3181qmp_ss = qmp_ss.apply(config_host, strict: false)
3182libqmp = static_library('qmp', qmp_ss.sources() + genh,
3183                        dependencies: qmp_ss.dependencies(),
3184                        name_suffix: 'fa',
3185                        build_by_default: false)
3186
3187qmp = declare_dependency(link_whole: [libqmp])
3188
3189libchardev = static_library('chardev', chardev_ss.sources() + genh,
3190                            name_suffix: 'fa',
3191                            dependencies: chardev_ss.dependencies(),
3192                            build_by_default: false)
3193
3194chardev = declare_dependency(link_whole: libchardev)
3195
3196hwcore_ss = hwcore_ss.apply(config_host, strict: false)
3197libhwcore = static_library('hwcore', sources: hwcore_ss.sources() + genh,
3198                           name_suffix: 'fa',
3199                           build_by_default: false)
3200hwcore = declare_dependency(link_whole: libhwcore)
3201common_ss.add(hwcore)
3202
3203###########
3204# Targets #
3205###########
3206
3207emulator_modules = []
3208foreach m : block_mods + softmmu_mods
3209  emulator_modules += shared_module(m.name(),
3210                build_by_default: true,
3211                name_prefix: '',
3212                link_whole: m,
3213                install: true,
3214                install_dir: qemu_moddir)
3215endforeach
3216
3217softmmu_ss.add(authz, blockdev, chardev, crypto, io, qmp)
3218common_ss.add(qom, qemuutil)
3219
3220common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
3221common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
3222
3223common_all = common_ss.apply(config_all, strict: false)
3224common_all = static_library('common',
3225                            build_by_default: false,
3226                            sources: common_all.sources() + genh,
3227                            include_directories: common_user_inc,
3228                            implicit_include_directories: false,
3229                            dependencies: common_all.dependencies(),
3230                            name_suffix: 'fa')
3231
3232feature_to_c = find_program('scripts/feature_to_c.sh')
3233
3234if targetos == 'darwin'
3235  entitlement = find_program('scripts/entitlement.sh')
3236endif
3237
3238emulators = {}
3239foreach target : target_dirs
3240  config_target = config_target_mak[target]
3241  target_name = config_target['TARGET_NAME']
3242  target_base_arch = config_target['TARGET_BASE_ARCH']
3243  arch_srcs = [config_target_h[target]]
3244  arch_deps = []
3245  c_args = ['-DNEED_CPU_H',
3246            '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3247            '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3248  link_args = emulator_link_args
3249
3250  config_target += config_host
3251  target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3252  if targetos == 'linux'
3253    target_inc += include_directories('linux-headers', is_system: true)
3254  endif
3255  if target.endswith('-softmmu')
3256    qemu_target_name = 'qemu-system-' + target_name
3257    target_type='system'
3258    t = target_softmmu_arch[target_base_arch].apply(config_target, strict: false)
3259    arch_srcs += t.sources()
3260    arch_deps += t.dependencies()
3261
3262    hw_dir = target_name == 'sparc64' ? 'sparc64' : target_base_arch
3263    hw = hw_arch[hw_dir].apply(config_target, strict: false)
3264    arch_srcs += hw.sources()
3265    arch_deps += hw.dependencies()
3266
3267    arch_srcs += config_devices_h[target]
3268    link_args += ['@block.syms', '@qemu.syms']
3269  else
3270    abi = config_target['TARGET_ABI_DIR']
3271    target_type='user'
3272    target_inc += common_user_inc
3273    qemu_target_name = 'qemu-' + target_name
3274    if target_base_arch in target_user_arch
3275      t = target_user_arch[target_base_arch].apply(config_target, strict: false)
3276      arch_srcs += t.sources()
3277      arch_deps += t.dependencies()
3278    endif
3279    if 'CONFIG_LINUX_USER' in config_target
3280      base_dir = 'linux-user'
3281    endif
3282    if 'CONFIG_BSD_USER' in config_target
3283      base_dir = 'bsd-user'
3284      target_inc += include_directories('bsd-user/' / targetos)
3285      target_inc += include_directories('bsd-user/host/' / host_arch)
3286      dir = base_dir / abi
3287      arch_srcs += files(dir / 'signal.c', dir / 'target_arch_cpu.c')
3288    endif
3289    target_inc += include_directories(
3290      base_dir,
3291      base_dir / abi,
3292    )
3293    if 'CONFIG_LINUX_USER' in config_target
3294      dir = base_dir / abi
3295      arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
3296      if config_target.has_key('TARGET_SYSTBL_ABI')
3297        arch_srcs += \
3298          syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
3299                                             extra_args : config_target['TARGET_SYSTBL_ABI'])
3300      endif
3301    endif
3302  endif
3303
3304  if 'TARGET_XML_FILES' in config_target
3305    gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
3306                                output: target + '-gdbstub-xml.c',
3307                                input: files(config_target['TARGET_XML_FILES'].split()),
3308                                command: [feature_to_c, '@INPUT@'],
3309                                capture: true)
3310    arch_srcs += gdbstub_xml
3311  endif
3312
3313  t = target_arch[target_base_arch].apply(config_target, strict: false)
3314  arch_srcs += t.sources()
3315  arch_deps += t.dependencies()
3316
3317  target_common = common_ss.apply(config_target, strict: false)
3318  objects = common_all.extract_objects(target_common.sources())
3319  deps = target_common.dependencies()
3320
3321  target_specific = specific_ss.apply(config_target, strict: false)
3322  arch_srcs += target_specific.sources()
3323  arch_deps += target_specific.dependencies()
3324
3325  lib = static_library('qemu-' + target,
3326                 sources: arch_srcs + genh,
3327                 dependencies: arch_deps,
3328                 objects: objects,
3329                 include_directories: target_inc,
3330                 c_args: c_args,
3331                 build_by_default: false,
3332                 name_suffix: 'fa')
3333
3334  if target.endswith('-softmmu')
3335    execs = [{
3336      'name': 'qemu-system-' + target_name,
3337      'win_subsystem': 'console',
3338      'sources': files('softmmu/main.c'),
3339      'dependencies': []
3340    }]
3341    if targetos == 'windows' and (sdl.found() or gtk.found())
3342      execs += [{
3343        'name': 'qemu-system-' + target_name + 'w',
3344        'win_subsystem': 'windows',
3345        'sources': files('softmmu/main.c'),
3346        'dependencies': []
3347      }]
3348    endif
3349    if get_option('fuzzing')
3350      specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
3351      execs += [{
3352        'name': 'qemu-fuzz-' + target_name,
3353        'win_subsystem': 'console',
3354        'sources': specific_fuzz.sources(),
3355        'dependencies': specific_fuzz.dependencies(),
3356      }]
3357    endif
3358  else
3359    execs = [{
3360      'name': 'qemu-' + target_name,
3361      'win_subsystem': 'console',
3362      'sources': [],
3363      'dependencies': []
3364    }]
3365  endif
3366  foreach exe: execs
3367    exe_name = exe['name']
3368    if targetos == 'darwin'
3369      exe_name += '-unsigned'
3370    endif
3371
3372    emulator = executable(exe_name, exe['sources'],
3373               install: true,
3374               c_args: c_args,
3375               dependencies: arch_deps + deps + exe['dependencies'],
3376               objects: lib.extract_all_objects(recursive: true),
3377               link_language: link_language,
3378               link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
3379               link_args: link_args,
3380               win_subsystem: exe['win_subsystem'])
3381
3382    if targetos == 'darwin'
3383      icon = 'pc-bios/qemu.rsrc'
3384      build_input = [emulator, files(icon)]
3385      install_input = [
3386        get_option('bindir') / exe_name,
3387        meson.current_source_dir() / icon
3388      ]
3389      if 'CONFIG_HVF' in config_target
3390        entitlements = 'accel/hvf/entitlements.plist'
3391        build_input += files(entitlements)
3392        install_input += meson.current_source_dir() / entitlements
3393      endif
3394
3395      emulators += {exe['name'] : custom_target(exe['name'],
3396                   input: build_input,
3397                   output: exe['name'],
3398                   command: [entitlement, '@OUTPUT@', '@INPUT@'])
3399      }
3400
3401      meson.add_install_script(entitlement, '--install',
3402                               get_option('bindir') / exe['name'],
3403                               install_input)
3404    else
3405      emulators += {exe['name']: emulator}
3406    endif
3407
3408    if stap.found()
3409      foreach stp: [
3410        {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
3411        {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
3412        {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
3413        {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
3414      ]
3415        custom_target(exe['name'] + stp['ext'],
3416                      input: trace_events_all,
3417                      output: exe['name'] + stp['ext'],
3418                      install: stp['install'],
3419                      install_dir: get_option('datadir') / 'systemtap/tapset',
3420                      command: [
3421                        tracetool, '--group=all', '--format=' + stp['fmt'],
3422                        '--binary=' + stp['bin'],
3423                        '--target-name=' + target_name,
3424                        '--target-type=' + target_type,
3425                        '--probe-prefix=qemu.' + target_type + '.' + target_name,
3426                        '@INPUT@', '@OUTPUT@'
3427                      ],
3428                      depend_files: tracetool_depends)
3429      endforeach
3430    endif
3431  endforeach
3432endforeach
3433
3434# Other build targets
3435
3436if 'CONFIG_PLUGIN' in config_host
3437  install_headers('include/qemu/qemu-plugin.h')
3438endif
3439
3440subdir('qga')
3441
3442# Don't build qemu-keymap if xkbcommon is not explicitly enabled
3443# when we don't build tools or system
3444if xkbcommon.found()
3445  # used for the update-keymaps target, so include rules even if !have_tools
3446  qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
3447                           dependencies: [qemuutil, xkbcommon], install: have_tools)
3448endif
3449
3450if have_tools
3451  qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
3452             dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
3453  qemu_io = executable('qemu-io', files('qemu-io.c'),
3454             dependencies: [block, qemuutil], install: true)
3455  qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
3456               dependencies: [blockdev, qemuutil, gnutls, selinux],
3457               install: true)
3458
3459  subdir('storage-daemon')
3460  subdir('contrib/rdmacm-mux')
3461  subdir('contrib/elf2dmp')
3462
3463  executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
3464             dependencies: qemuutil,
3465             install: true)
3466
3467  if 'CONFIG_VHOST_USER' in config_host
3468    subdir('contrib/vhost-user-blk')
3469    subdir('contrib/vhost-user-gpu')
3470    subdir('contrib/vhost-user-input')
3471    subdir('contrib/vhost-user-scsi')
3472  endif
3473
3474  if targetos == 'linux'
3475    executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
3476               dependencies: [qemuutil, libcap_ng],
3477               install: true,
3478               install_dir: get_option('libexecdir'))
3479
3480    executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
3481               dependencies: [authz, crypto, io, qom, qemuutil,
3482                              libcap_ng, mpathpersist],
3483               install: true)
3484  endif
3485
3486  if have_ivshmem
3487    subdir('contrib/ivshmem-client')
3488    subdir('contrib/ivshmem-server')
3489  endif
3490endif
3491
3492subdir('scripts')
3493subdir('tools')
3494subdir('pc-bios')
3495subdir('docs')
3496subdir('tests')
3497if gtk.found()
3498  subdir('po')
3499endif
3500
3501if host_machine.system() == 'windows'
3502  nsis_cmd = [
3503    find_program('scripts/nsis.py'),
3504    '@OUTPUT@',
3505    get_option('prefix'),
3506    meson.current_source_dir(),
3507    host_machine.cpu(),
3508    '--',
3509    '-DDISPLAYVERSION=' + meson.project_version(),
3510  ]
3511  if build_docs
3512    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
3513  endif
3514  if gtk.found()
3515    nsis_cmd += '-DCONFIG_GTK=y'
3516  endif
3517
3518  nsis = custom_target('nsis',
3519                       output: 'qemu-setup-' + meson.project_version() + '.exe',
3520                       input: files('qemu.nsi'),
3521                       build_always_stale: true,
3522                       command: nsis_cmd + ['@INPUT@'])
3523  alias_target('installer', nsis)
3524endif
3525
3526#########################
3527# Configuration summary #
3528#########################
3529
3530# Directories
3531summary_info = {}
3532summary_info += {'Install prefix':    get_option('prefix')}
3533summary_info += {'BIOS directory':    qemu_datadir}
3534summary_info += {'firmware path':     get_option('qemu_firmwarepath')}
3535summary_info += {'binary directory':  get_option('bindir')}
3536summary_info += {'library directory': get_option('libdir')}
3537summary_info += {'module directory':  qemu_moddir}
3538summary_info += {'libexec directory': get_option('libexecdir')}
3539summary_info += {'include directory': get_option('includedir')}
3540summary_info += {'config directory':  get_option('sysconfdir')}
3541if targetos != 'windows'
3542  summary_info += {'local state directory': get_option('localstatedir')}
3543  summary_info += {'Manual directory':      get_option('mandir')}
3544else
3545  summary_info += {'local state directory': 'queried at runtime'}
3546endif
3547summary_info += {'Doc directory':     get_option('docdir')}
3548summary_info += {'Build directory':   meson.current_build_dir()}
3549summary_info += {'Source path':       meson.current_source_dir()}
3550summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
3551summary(summary_info, bool_yn: true, section: 'Directories')
3552
3553# Host binaries
3554summary_info = {}
3555summary_info += {'git':               config_host['GIT']}
3556summary_info += {'make':              config_host['MAKE']}
3557summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
3558summary_info += {'sphinx-build':      sphinx_build}
3559if config_host.has_key('HAVE_GDB_BIN')
3560  summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
3561endif
3562if get_option('iasl') != ''
3563  summary_info += {'iasl':            get_option('iasl')}
3564else
3565  summary_info += {'iasl':            false}
3566endif
3567summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
3568if targetos == 'windows' and have_ga
3569  summary_info += {'wixl':            wixl}
3570endif
3571if slirp_opt != 'disabled' and have_system
3572  summary_info += {'smbd':            have_slirp_smbd ? smbd_path : false}
3573endif
3574summary(summary_info, bool_yn: true, section: 'Host binaries')
3575
3576# Configurable features
3577summary_info = {}
3578summary_info += {'Documentation':     build_docs}
3579summary_info += {'system-mode emulation': have_system}
3580summary_info += {'user-mode emulation': have_user}
3581summary_info += {'block layer':       have_block}
3582summary_info += {'Install blobs':     get_option('install_blobs')}
3583summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
3584if config_host.has_key('CONFIG_MODULES')
3585  summary_info += {'alternative module path': get_option('module_upgrades')}
3586endif
3587summary_info += {'fuzzing support':   get_option('fuzzing')}
3588if have_system
3589  summary_info += {'Audio drivers':     ' '.join(audio_drivers_selected)}
3590endif
3591summary_info += {'Trace backends':    ','.join(get_option('trace_backends'))}
3592if 'simple' in get_option('trace_backends')
3593  summary_info += {'Trace output file': get_option('trace_file') + '-<pid>'}
3594endif
3595summary_info += {'D-Bus display':     dbus_display}
3596summary_info += {'QOM debugging':     get_option('qom_cast_debug')}
3597summary_info += {'vhost-kernel support': config_host.has_key('CONFIG_VHOST_KERNEL')}
3598summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')}
3599summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')}
3600summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')}
3601summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')}
3602summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_USER')}
3603summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
3604summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')}
3605summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')}
3606summary_info += {'build guest agent': have_ga}
3607summary(summary_info, bool_yn: true, section: 'Configurable features')
3608
3609# Compilation information
3610summary_info = {}
3611summary_info += {'host CPU':          cpu}
3612summary_info += {'host endianness':   build_machine.endian()}
3613summary_info += {'C compiler':        ' '.join(meson.get_compiler('c').cmd_array())}
3614summary_info += {'Host C compiler':   ' '.join(meson.get_compiler('c', native: true).cmd_array())}
3615if link_language == 'cpp'
3616  summary_info += {'C++ compiler':    ' '.join(meson.get_compiler('cpp').cmd_array())}
3617else
3618  summary_info += {'C++ compiler':      false}
3619endif
3620if targetos == 'darwin'
3621  summary_info += {'Objective-C compiler': ' '.join(meson.get_compiler('objc').cmd_array())}
3622endif
3623summary_info += {'CFLAGS':            ' '.join(get_option('c_args')
3624                                               + ['-O' + get_option('optimization')]
3625                                               + (get_option('debug') ? ['-g'] : []))}
3626if link_language == 'cpp'
3627  summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args')
3628                                               + ['-O' + get_option('optimization')]
3629                                               + (get_option('debug') ? ['-g'] : []))}
3630endif
3631if targetos == 'darwin'
3632  summary_info += {'OBJCFLAGS':       ' '.join(get_option('objc_args')
3633                                               + ['-O' + get_option('optimization')]
3634                                               + (get_option('debug') ? ['-g'] : []))}
3635endif
3636link_args = get_option(link_language + '_link_args')
3637if link_args.length() > 0
3638  summary_info += {'LDFLAGS':         ' '.join(link_args)}
3639endif
3640summary_info += {'QEMU_CFLAGS':       ' '.join(qemu_cflags)}
3641summary_info += {'QEMU_CXXFLAGS':     ' '.join(qemu_cxxflags)}
3642summary_info += {'QEMU_OBJCFLAGS':    ' '.join(qemu_objcflags)}
3643summary_info += {'QEMU_LDFLAGS':      ' '.join(qemu_ldflags)}
3644summary_info += {'profiler':          get_option('profiler')}
3645summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
3646summary_info += {'PIE':               get_option('b_pie')}
3647summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
3648summary_info += {'malloc trim support': has_malloc_trim}
3649summary_info += {'membarrier':        have_membarrier}
3650summary_info += {'debug stack usage': get_option('debug_stack_usage')}
3651summary_info += {'mutex debugging':   get_option('debug_mutex')}
3652summary_info += {'memory allocator':  get_option('malloc')}
3653summary_info += {'avx2 optimization': config_host_data.get('CONFIG_AVX2_OPT')}
3654summary_info += {'avx512f optimization': config_host_data.get('CONFIG_AVX512F_OPT')}
3655summary_info += {'gprof enabled':     get_option('gprof')}
3656summary_info += {'gcov':              get_option('b_coverage')}
3657summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
3658summary_info += {'CFI support':       get_option('cfi')}
3659if get_option('cfi')
3660  summary_info += {'CFI debug support': get_option('cfi_debug')}
3661endif
3662summary_info += {'strip binaries':    get_option('strip')}
3663summary_info += {'sparse':            sparse}
3664summary_info += {'mingw32 support':   targetos == 'windows'}
3665
3666# snarf the cross-compilation information for tests
3667foreach target: target_dirs
3668  tcg_mak = meson.current_build_dir() / 'tests/tcg' / 'config-' + target + '.mak'
3669  if fs.exists(tcg_mak)
3670    config_cross_tcg = keyval.load(tcg_mak)
3671    target = config_cross_tcg['TARGET_NAME']
3672    compiler = ''
3673    if 'DOCKER_CROSS_CC_GUEST' in config_cross_tcg
3674      summary_info += {target + ' tests': config_cross_tcg['DOCKER_CROSS_CC_GUEST'] +
3675                                          ' via ' + config_cross_tcg['DOCKER_IMAGE']}
3676    elif 'CROSS_CC_GUEST' in config_cross_tcg
3677      summary_info += {target + ' tests'
3678                                : config_cross_tcg['CROSS_CC_GUEST'] }
3679    endif
3680   endif
3681endforeach
3682
3683summary(summary_info, bool_yn: true, section: 'Compilation')
3684
3685# Targets and accelerators
3686summary_info = {}
3687if have_system
3688  summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
3689  summary_info += {'HAX support':       config_all.has_key('CONFIG_HAX')}
3690  summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
3691  summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
3692  summary_info += {'NVMM support':      config_all.has_key('CONFIG_NVMM')}
3693  summary_info += {'Xen support':       config_host.has_key('CONFIG_XEN_BACKEND')}
3694  if config_host.has_key('CONFIG_XEN_BACKEND')
3695    summary_info += {'xen ctrl version':  config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
3696  endif
3697endif
3698summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
3699if config_all.has_key('CONFIG_TCG')
3700  if get_option('tcg_interpreter')
3701    summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, slow)'}
3702  else
3703    summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
3704  endif
3705  summary_info += {'TCG plugins': config_host.has_key('CONFIG_PLUGIN')}
3706  summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
3707endif
3708summary_info += {'target list':       ' '.join(target_dirs)}
3709if have_system
3710  summary_info += {'default devices':   get_option('default_devices')}
3711  summary_info += {'out of process emulation': multiprocess_allowed}
3712endif
3713summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
3714
3715# Block layer
3716summary_info = {}
3717summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
3718summary_info += {'coroutine pool':    have_coroutine_pool}
3719if have_block
3720  summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']}
3721  summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']}
3722  summary_info += {'Use block whitelist in tools': get_option('block_drv_whitelist_in_tools')}
3723  summary_info += {'VirtFS support':    have_virtfs}
3724  summary_info += {'build virtiofs daemon': have_virtiofsd}
3725  summary_info += {'Live block migration': config_host_data.get('CONFIG_LIVE_BLOCK_MIGRATION')}
3726  summary_info += {'replication support': config_host_data.get('CONFIG_REPLICATION')}
3727  summary_info += {'bochs support':     get_option('bochs').allowed()}
3728  summary_info += {'cloop support':     get_option('cloop').allowed()}
3729  summary_info += {'dmg support':       get_option('dmg').allowed()}
3730  summary_info += {'qcow v1 support':   get_option('qcow1').allowed()}
3731  summary_info += {'vdi support':       get_option('vdi').allowed()}
3732  summary_info += {'vvfat support':     get_option('vvfat').allowed()}
3733  summary_info += {'qed support':       get_option('qed').allowed()}
3734  summary_info += {'parallels support': get_option('parallels').allowed()}
3735  summary_info += {'FUSE exports':      fuse}
3736endif
3737summary(summary_info, bool_yn: true, section: 'Block layer support')
3738
3739# Crypto
3740summary_info = {}
3741summary_info += {'TLS priority':      config_host['CONFIG_TLS_PRIORITY']}
3742summary_info += {'GNUTLS support':    gnutls}
3743if gnutls.found()
3744  summary_info += {'  GNUTLS crypto':   gnutls_crypto.found()}
3745endif
3746summary_info += {'libgcrypt':         gcrypt}
3747summary_info += {'nettle':            nettle}
3748if nettle.found()
3749   summary_info += {'  XTS':             xts != 'private'}
3750endif
3751summary_info += {'AF_ALG support':    have_afalg}
3752summary_info += {'rng-none':          get_option('rng_none')}
3753summary_info += {'Linux keyring':     have_keyring}
3754summary(summary_info, bool_yn: true, section: 'Crypto')
3755
3756# Libraries
3757summary_info = {}
3758if targetos == 'darwin'
3759  summary_info += {'Cocoa support':   cocoa}
3760endif
3761summary_info += {'SDL support':       sdl}
3762summary_info += {'SDL image support': sdl_image}
3763summary_info += {'GTK support':       gtk}
3764summary_info += {'pixman':            pixman}
3765summary_info += {'VTE support':       vte}
3766summary_info += {'slirp support':     slirp_opt == 'internal' ? slirp_opt : slirp}
3767summary_info += {'libtasn1':          tasn1}
3768summary_info += {'PAM':               pam}
3769summary_info += {'iconv support':     iconv}
3770summary_info += {'curses support':    curses}
3771summary_info += {'virgl support':     virgl}
3772summary_info += {'curl support':      curl}
3773summary_info += {'Multipath support': mpathpersist}
3774summary_info += {'PNG support':       png}
3775summary_info += {'VNC support':       vnc}
3776if vnc.found()
3777  summary_info += {'VNC SASL support':  sasl}
3778  summary_info += {'VNC JPEG support':  jpeg}
3779endif
3780if targetos not in ['darwin', 'haiku', 'windows']
3781  summary_info += {'OSS support':     oss}
3782elif targetos == 'darwin'
3783  summary_info += {'CoreAudio support': coreaudio}
3784elif targetos == 'windows'
3785  summary_info += {'DirectSound support': dsound}
3786endif
3787if targetos == 'linux'
3788  summary_info += {'ALSA support':    alsa}
3789  summary_info += {'PulseAudio support': pulse}
3790endif
3791summary_info += {'JACK support':      jack}
3792summary_info += {'brlapi support':    brlapi}
3793summary_info += {'vde support':       vde}
3794summary_info += {'netmap support':    have_netmap}
3795summary_info += {'l2tpv3 support':    have_l2tpv3}
3796summary_info += {'Linux AIO support': libaio}
3797summary_info += {'Linux io_uring support': linux_io_uring}
3798summary_info += {'ATTR/XATTR support': libattr}
3799summary_info += {'RDMA support':      rdma}
3800summary_info += {'PVRDMA support':    have_pvrdma}
3801summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
3802summary_info += {'libcap-ng support': libcap_ng}
3803summary_info += {'bpf support':       libbpf}
3804summary_info += {'spice protocol support': spice_protocol}
3805if spice_protocol.found()
3806  summary_info += {'  spice server support': spice}
3807endif
3808summary_info += {'rbd support':       rbd}
3809summary_info += {'smartcard support': cacard}
3810summary_info += {'U2F support':       u2f}
3811summary_info += {'libusb':            libusb}
3812summary_info += {'usb net redir':     usbredir}
3813summary_info += {'OpenGL support (epoxy)': opengl}
3814summary_info += {'GBM':               gbm}
3815summary_info += {'libiscsi support':  libiscsi}
3816summary_info += {'libnfs support':    libnfs}
3817if targetos == 'windows'
3818  if have_ga
3819    summary_info += {'QGA VSS support':   have_qga_vss}
3820  endif
3821endif
3822summary_info += {'seccomp support':   seccomp}
3823summary_info += {'GlusterFS support': glusterfs}
3824summary_info += {'TPM support':       have_tpm}
3825summary_info += {'libssh support':    libssh}
3826summary_info += {'lzo support':       lzo}
3827summary_info += {'snappy support':    snappy}
3828summary_info += {'bzip2 support':     libbzip2}
3829summary_info += {'lzfse support':     liblzfse}
3830summary_info += {'zstd support':      zstd}
3831summary_info += {'NUMA host support': numa}
3832summary_info += {'capstone':          capstone_opt == 'internal' ? capstone_opt : capstone}
3833summary_info += {'libpmem support':   libpmem}
3834summary_info += {'libdaxctl support': libdaxctl}
3835summary_info += {'libudev':           libudev}
3836# Dummy dependency, keep .found()
3837summary_info += {'FUSE lseek':        fuse_lseek.found()}
3838summary_info += {'selinux':           selinux}
3839summary(summary_info, bool_yn: true, section: 'Dependencies')
3840
3841if not supported_cpus.contains(cpu)
3842  message()
3843  warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
3844  message()
3845  message('CPU host architecture ' + cpu + ' support is not currently maintained.')
3846  message('The QEMU project intends to remove support for this host CPU in')
3847  message('a future release if nobody volunteers to maintain it and to')
3848  message('provide a build host for our continuous integration setup.')
3849  message('configure has succeeded and you can continue to build, but')
3850  message('if you care about QEMU on this platform you should contact')
3851  message('us upstream at qemu-devel@nongnu.org.')
3852endif
3853
3854if not supported_oses.contains(targetos)
3855  message()
3856  warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
3857  message()
3858  message('Host OS ' + targetos + 'support is not currently maintained.')
3859  message('The QEMU project intends to remove support for this host OS in')
3860  message('a future release if nobody volunteers to maintain it and to')
3861  message('provide a build host for our continuous integration setup.')
3862  message('configure has succeeded and you can continue to build, but')
3863  message('if you care about QEMU on this platform you should contact')
3864  message('us upstream at qemu-devel@nongnu.org.')
3865endif
3866