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