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