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