xref: /openbmc/qemu/meson.build (revision cc1838c2)
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_h += {target: configure_file(output: target + '-config-target.h',
1629                                               configuration: config_target_data)}
1630
1631  if target.endswith('-softmmu')
1632    config_input = meson.get_external_property(target, 'default')
1633    config_devices_mak = target + '-config-devices.mak'
1634    config_devices_mak = configure_file(
1635      input: ['configs/devices' / target / config_input + '.mak', 'Kconfig'],
1636      output: config_devices_mak,
1637      depfile: config_devices_mak + '.d',
1638      capture: true,
1639      command: [minikconf,
1640                get_option('default_devices') ? '--defconfig' : '--allnoconfig',
1641                config_devices_mak, '@DEPFILE@', '@INPUT@',
1642                host_kconfig, accel_kconfig,
1643                'CONFIG_' + config_target['TARGET_ARCH'].to_upper() + '=y'])
1644
1645    config_devices_data = configuration_data()
1646    config_devices = keyval.load(config_devices_mak)
1647    foreach k, v: config_devices
1648      config_devices_data.set(k, 1)
1649    endforeach
1650    config_devices_mak_list += config_devices_mak
1651    config_devices_h += {target: configure_file(output: target + '-config-devices.h',
1652                                                configuration: config_devices_data)}
1653    config_target += config_devices
1654    config_all_devices += config_devices
1655  endif
1656  config_target_mak += {target: config_target}
1657endforeach
1658target_dirs = actual_target_dirs
1659
1660# This configuration is used to build files that are shared by
1661# multiple binaries, and then extracted out of the "common"
1662# static_library target.
1663#
1664# We do not use all_sources()/all_dependencies(), because it would
1665# build literally all source files, including devices only used by
1666# targets that are not built for this compilation.  The CONFIG_ALL
1667# pseudo symbol replaces it.
1668
1669config_all += config_all_devices
1670config_all += config_host
1671config_all += config_all_disas
1672config_all += {
1673  'CONFIG_XEN': config_host.has_key('CONFIG_XEN_BACKEND'),
1674  'CONFIG_SOFTMMU': have_system,
1675  'CONFIG_USER_ONLY': have_user,
1676  'CONFIG_ALL': true,
1677}
1678
1679##############
1680# Submodules #
1681##############
1682
1683capstone = not_found
1684capstone_opt = get_option('capstone')
1685if capstone_opt in ['enabled', 'auto', 'system']
1686  have_internal = fs.exists(meson.current_source_dir() / 'capstone/Makefile')
1687  capstone = dependency('capstone', version: '>=4.0',
1688                        kwargs: static_kwargs, method: 'pkg-config',
1689                        required: capstone_opt == 'system' or
1690                                  capstone_opt == 'enabled' and not have_internal)
1691
1692  # Some versions of capstone have broken pkg-config file
1693  # that reports a wrong -I path, causing the #include to
1694  # fail later. If the system has such a broken version
1695  # do not use it.
1696  if capstone.found() and not cc.compiles('#include <capstone.h>',
1697                                          dependencies: [capstone])
1698    capstone = not_found
1699    if capstone_opt == 'system'
1700      error('system capstone requested, it does not appear to work')
1701    endif
1702  endif
1703
1704  if capstone.found()
1705    capstone_opt = 'system'
1706  elif have_internal
1707    capstone_opt = 'internal'
1708  else
1709    capstone_opt = 'disabled'
1710  endif
1711endif
1712if capstone_opt == 'internal'
1713  capstone_data = configuration_data()
1714  capstone_data.set('CAPSTONE_USE_SYS_DYN_MEM', '1')
1715
1716  capstone_files = files(
1717    'capstone/cs.c',
1718    'capstone/MCInst.c',
1719    'capstone/MCInstrDesc.c',
1720    'capstone/MCRegisterInfo.c',
1721    'capstone/SStream.c',
1722    'capstone/utils.c'
1723  )
1724
1725  if 'CONFIG_ARM_DIS' in config_all_disas
1726    capstone_data.set('CAPSTONE_HAS_ARM', '1')
1727    capstone_files += files(
1728      'capstone/arch/ARM/ARMDisassembler.c',
1729      'capstone/arch/ARM/ARMInstPrinter.c',
1730      'capstone/arch/ARM/ARMMapping.c',
1731      'capstone/arch/ARM/ARMModule.c'
1732    )
1733  endif
1734
1735  # FIXME: This config entry currently depends on a c++ compiler.
1736  # Which is needed for building libvixl, but not for capstone.
1737  if 'CONFIG_ARM_A64_DIS' in config_all_disas
1738    capstone_data.set('CAPSTONE_HAS_ARM64', '1')
1739    capstone_files += files(
1740      'capstone/arch/AArch64/AArch64BaseInfo.c',
1741      'capstone/arch/AArch64/AArch64Disassembler.c',
1742      'capstone/arch/AArch64/AArch64InstPrinter.c',
1743      'capstone/arch/AArch64/AArch64Mapping.c',
1744      'capstone/arch/AArch64/AArch64Module.c'
1745    )
1746  endif
1747
1748  if 'CONFIG_PPC_DIS' in config_all_disas
1749    capstone_data.set('CAPSTONE_HAS_POWERPC', '1')
1750    capstone_files += files(
1751      'capstone/arch/PowerPC/PPCDisassembler.c',
1752      'capstone/arch/PowerPC/PPCInstPrinter.c',
1753      'capstone/arch/PowerPC/PPCMapping.c',
1754      'capstone/arch/PowerPC/PPCModule.c'
1755    )
1756  endif
1757
1758  if 'CONFIG_S390_DIS' in config_all_disas
1759    capstone_data.set('CAPSTONE_HAS_SYSZ', '1')
1760    capstone_files += files(
1761      'capstone/arch/SystemZ/SystemZDisassembler.c',
1762      'capstone/arch/SystemZ/SystemZInstPrinter.c',
1763      'capstone/arch/SystemZ/SystemZMapping.c',
1764      'capstone/arch/SystemZ/SystemZModule.c',
1765      'capstone/arch/SystemZ/SystemZMCTargetDesc.c'
1766    )
1767  endif
1768
1769  if 'CONFIG_I386_DIS' in config_all_disas
1770    capstone_data.set('CAPSTONE_HAS_X86', 1)
1771    capstone_files += files(
1772      'capstone/arch/X86/X86Disassembler.c',
1773      'capstone/arch/X86/X86DisassemblerDecoder.c',
1774      'capstone/arch/X86/X86ATTInstPrinter.c',
1775      'capstone/arch/X86/X86IntelInstPrinter.c',
1776      'capstone/arch/X86/X86InstPrinterCommon.c',
1777      'capstone/arch/X86/X86Mapping.c',
1778      'capstone/arch/X86/X86Module.c'
1779    )
1780  endif
1781
1782  configure_file(output: 'capstone-defs.h', configuration: capstone_data)
1783
1784  capstone_cargs = [
1785    # FIXME: There does not seem to be a way to completely replace the c_args
1786    # that come from add_project_arguments() -- we can only add to them.
1787    # So: disable all warnings with a big hammer.
1788    '-Wno-error', '-w',
1789
1790    # Include all configuration defines via a header file, which will wind up
1791    # as a dependency on the object file, and thus changes here will result
1792    # in a rebuild.
1793    '-include', 'capstone-defs.h'
1794  ]
1795
1796  libcapstone = static_library('capstone',
1797                               build_by_default: false,
1798                               sources: capstone_files,
1799                               c_args: capstone_cargs,
1800                               include_directories: 'capstone/include')
1801  capstone = declare_dependency(link_with: libcapstone,
1802                                include_directories: 'capstone/include/capstone')
1803endif
1804
1805slirp = not_found
1806slirp_opt = 'disabled'
1807if have_system
1808  slirp_opt = get_option('slirp')
1809  if slirp_opt in ['enabled', 'auto', 'system']
1810    have_internal = fs.exists(meson.current_source_dir() / 'slirp/meson.build')
1811    slirp = dependency('slirp', kwargs: static_kwargs,
1812                       method: 'pkg-config',
1813                       required: slirp_opt == 'system' or
1814                                 slirp_opt == 'enabled' and not have_internal)
1815    if slirp.found()
1816      slirp_opt = 'system'
1817    elif have_internal
1818      slirp_opt = 'internal'
1819    else
1820      slirp_opt = 'disabled'
1821    endif
1822  endif
1823  if slirp_opt == 'internal'
1824    slirp_deps = []
1825    if targetos == 'windows'
1826      slirp_deps = cc.find_library('iphlpapi')
1827    elif targetos == 'darwin'
1828      slirp_deps = cc.find_library('resolv')
1829    endif
1830    slirp_conf = configuration_data()
1831    slirp_conf.set('SLIRP_MAJOR_VERSION', meson.project_version().split('.')[0])
1832    slirp_conf.set('SLIRP_MINOR_VERSION', meson.project_version().split('.')[1])
1833    slirp_conf.set('SLIRP_MICRO_VERSION', meson.project_version().split('.')[2])
1834    slirp_conf.set_quoted('SLIRP_VERSION_STRING', meson.project_version())
1835    slirp_cargs = ['-DG_LOG_DOMAIN="Slirp"']
1836    slirp_files = [
1837      'slirp/src/arp_table.c',
1838      'slirp/src/bootp.c',
1839      'slirp/src/cksum.c',
1840      'slirp/src/dhcpv6.c',
1841      'slirp/src/dnssearch.c',
1842      'slirp/src/if.c',
1843      'slirp/src/ip6_icmp.c',
1844      'slirp/src/ip6_input.c',
1845      'slirp/src/ip6_output.c',
1846      'slirp/src/ip_icmp.c',
1847      'slirp/src/ip_input.c',
1848      'slirp/src/ip_output.c',
1849      'slirp/src/mbuf.c',
1850      'slirp/src/misc.c',
1851      'slirp/src/ncsi.c',
1852      'slirp/src/ndp_table.c',
1853      'slirp/src/sbuf.c',
1854      'slirp/src/slirp.c',
1855      'slirp/src/socket.c',
1856      'slirp/src/state.c',
1857      'slirp/src/stream.c',
1858      'slirp/src/tcp_input.c',
1859      'slirp/src/tcp_output.c',
1860      'slirp/src/tcp_subr.c',
1861      'slirp/src/tcp_timer.c',
1862      'slirp/src/tftp.c',
1863      'slirp/src/udp.c',
1864      'slirp/src/udp6.c',
1865      'slirp/src/util.c',
1866      'slirp/src/version.c',
1867      'slirp/src/vmstate.c',
1868    ]
1869
1870    configure_file(
1871      input : 'slirp/src/libslirp-version.h.in',
1872      output : 'libslirp-version.h',
1873      configuration: slirp_conf)
1874
1875    slirp_inc = include_directories('slirp', 'slirp/src')
1876    libslirp = static_library('slirp',
1877                              build_by_default: false,
1878                              sources: slirp_files,
1879                              c_args: slirp_cargs,
1880                              include_directories: slirp_inc)
1881    slirp = declare_dependency(link_with: libslirp,
1882                               dependencies: slirp_deps,
1883                               include_directories: slirp_inc)
1884  endif
1885endif
1886
1887# For CFI, we need to compile slirp as a static library together with qemu.
1888# This is because we register slirp functions as callbacks for QEMU Timers.
1889# When using a system-wide shared libslirp, the type information for the
1890# callback is missing and the timer call produces a false positive with CFI.
1891#
1892# Now that slirp_opt has been defined, check if the selected slirp is compatible
1893# with control-flow integrity.
1894if get_option('cfi') and slirp_opt == 'system'
1895  error('Control-Flow Integrity is not compatible with system-wide slirp.' \
1896         + ' Please configure with --enable-slirp=git')
1897endif
1898
1899fdt = not_found
1900fdt_opt = get_option('fdt')
1901if have_system
1902  if fdt_opt in ['enabled', 'auto', 'system']
1903    have_internal = fs.exists(meson.current_source_dir() / 'dtc/libfdt/Makefile.libfdt')
1904    fdt = cc.find_library('fdt', kwargs: static_kwargs,
1905                          required: fdt_opt == 'system' or
1906                                    fdt_opt == 'enabled' and not have_internal)
1907    if fdt.found() and cc.links('''
1908       #include <libfdt.h>
1909       #include <libfdt_env.h>
1910       int main(void) { fdt_check_full(NULL, 0); return 0; }''',
1911         dependencies: fdt)
1912      fdt_opt = 'system'
1913    elif have_internal
1914      fdt_opt = 'internal'
1915    else
1916      fdt_opt = 'disabled'
1917    endif
1918  endif
1919  if fdt_opt == 'internal'
1920    fdt_files = files(
1921      'dtc/libfdt/fdt.c',
1922      'dtc/libfdt/fdt_ro.c',
1923      'dtc/libfdt/fdt_wip.c',
1924      'dtc/libfdt/fdt_sw.c',
1925      'dtc/libfdt/fdt_rw.c',
1926      'dtc/libfdt/fdt_strerror.c',
1927      'dtc/libfdt/fdt_empty_tree.c',
1928      'dtc/libfdt/fdt_addresses.c',
1929      'dtc/libfdt/fdt_overlay.c',
1930      'dtc/libfdt/fdt_check.c',
1931    )
1932
1933    fdt_inc = include_directories('dtc/libfdt')
1934    libfdt = static_library('fdt',
1935                            build_by_default: false,
1936                            sources: fdt_files,
1937                            include_directories: fdt_inc)
1938    fdt = declare_dependency(link_with: libfdt,
1939                             include_directories: fdt_inc)
1940  endif
1941endif
1942if not fdt.found() and fdt_required.length() > 0
1943  error('fdt not available but required by targets ' + ', '.join(fdt_required))
1944endif
1945
1946config_host_data.set('CONFIG_CAPSTONE', capstone.found())
1947config_host_data.set('CONFIG_FDT', fdt.found())
1948config_host_data.set('CONFIG_SLIRP', slirp.found())
1949
1950#####################
1951# Generated sources #
1952#####################
1953
1954genh += configure_file(output: 'config-host.h', configuration: config_host_data)
1955
1956hxtool = find_program('scripts/hxtool')
1957shaderinclude = find_program('scripts/shaderinclude.pl')
1958qapi_gen = find_program('scripts/qapi-gen.py')
1959qapi_gen_depends = [ meson.source_root() / 'scripts/qapi/__init__.py',
1960                     meson.source_root() / 'scripts/qapi/commands.py',
1961                     meson.source_root() / 'scripts/qapi/common.py',
1962                     meson.source_root() / 'scripts/qapi/error.py',
1963                     meson.source_root() / 'scripts/qapi/events.py',
1964                     meson.source_root() / 'scripts/qapi/expr.py',
1965                     meson.source_root() / 'scripts/qapi/gen.py',
1966                     meson.source_root() / 'scripts/qapi/introspect.py',
1967                     meson.source_root() / 'scripts/qapi/parser.py',
1968                     meson.source_root() / 'scripts/qapi/schema.py',
1969                     meson.source_root() / 'scripts/qapi/source.py',
1970                     meson.source_root() / 'scripts/qapi/types.py',
1971                     meson.source_root() / 'scripts/qapi/visit.py',
1972                     meson.source_root() / 'scripts/qapi/common.py',
1973                     meson.source_root() / 'scripts/qapi-gen.py'
1974]
1975
1976tracetool = [
1977  python, files('scripts/tracetool.py'),
1978   '--backend=' + config_host['TRACE_BACKENDS']
1979]
1980tracetool_depends = files(
1981  'scripts/tracetool/backend/log.py',
1982  'scripts/tracetool/backend/__init__.py',
1983  'scripts/tracetool/backend/dtrace.py',
1984  'scripts/tracetool/backend/ftrace.py',
1985  'scripts/tracetool/backend/simple.py',
1986  'scripts/tracetool/backend/syslog.py',
1987  'scripts/tracetool/backend/ust.py',
1988  'scripts/tracetool/format/tcg_h.py',
1989  'scripts/tracetool/format/ust_events_c.py',
1990  'scripts/tracetool/format/ust_events_h.py',
1991  'scripts/tracetool/format/__init__.py',
1992  'scripts/tracetool/format/d.py',
1993  'scripts/tracetool/format/tcg_helper_c.py',
1994  'scripts/tracetool/format/simpletrace_stap.py',
1995  'scripts/tracetool/format/c.py',
1996  'scripts/tracetool/format/h.py',
1997  'scripts/tracetool/format/tcg_helper_h.py',
1998  'scripts/tracetool/format/log_stap.py',
1999  'scripts/tracetool/format/stap.py',
2000  'scripts/tracetool/format/tcg_helper_wrapper_h.py',
2001  'scripts/tracetool/__init__.py',
2002  'scripts/tracetool/transform.py',
2003  'scripts/tracetool/vcpu.py'
2004)
2005
2006qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
2007                    meson.current_source_dir(),
2008                    config_host['PKGVERSION'], meson.project_version()]
2009qemu_version = custom_target('qemu-version.h',
2010                             output: 'qemu-version.h',
2011                             command: qemu_version_cmd,
2012                             capture: true,
2013                             build_by_default: true,
2014                             build_always_stale: true)
2015genh += qemu_version
2016
2017hxdep = []
2018hx_headers = [
2019  ['qemu-options.hx', 'qemu-options.def'],
2020  ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
2021]
2022if have_system
2023  hx_headers += [
2024    ['hmp-commands.hx', 'hmp-commands.h'],
2025    ['hmp-commands-info.hx', 'hmp-commands-info.h'],
2026  ]
2027endif
2028foreach d : hx_headers
2029  hxdep += custom_target(d[1],
2030                input: files(d[0]),
2031                output: d[1],
2032                capture: true,
2033                build_by_default: true, # to be removed when added to a target
2034                command: [hxtool, '-h', '@INPUT0@'])
2035endforeach
2036genh += hxdep
2037
2038###################
2039# Collect sources #
2040###################
2041
2042authz_ss = ss.source_set()
2043blockdev_ss = ss.source_set()
2044block_ss = ss.source_set()
2045bsd_user_ss = ss.source_set()
2046chardev_ss = ss.source_set()
2047common_ss = ss.source_set()
2048crypto_ss = ss.source_set()
2049io_ss = ss.source_set()
2050linux_user_ss = ss.source_set()
2051qmp_ss = ss.source_set()
2052qom_ss = ss.source_set()
2053softmmu_ss = ss.source_set()
2054specific_fuzz_ss = ss.source_set()
2055specific_ss = ss.source_set()
2056stub_ss = ss.source_set()
2057trace_ss = ss.source_set()
2058user_ss = ss.source_set()
2059util_ss = ss.source_set()
2060
2061# accel modules
2062qtest_module_ss = ss.source_set()
2063tcg_module_ss = ss.source_set()
2064
2065modules = {}
2066target_modules = {}
2067hw_arch = {}
2068target_arch = {}
2069target_softmmu_arch = {}
2070target_user_arch = {}
2071
2072###############
2073# Trace files #
2074###############
2075
2076# TODO: add each directory to the subdirs from its own meson.build, once
2077# we have those
2078trace_events_subdirs = [
2079  'crypto',
2080  'qapi',
2081  'qom',
2082  'monitor',
2083  'util',
2084]
2085if have_user
2086  trace_events_subdirs += [ 'linux-user' ]
2087endif
2088if have_block
2089  trace_events_subdirs += [
2090    'authz',
2091    'block',
2092    'io',
2093    'nbd',
2094    'scsi',
2095  ]
2096endif
2097if have_system
2098  trace_events_subdirs += [
2099    'accel/kvm',
2100    'audio',
2101    'backends',
2102    'backends/tpm',
2103    'chardev',
2104    'ebpf',
2105    'hw/9pfs',
2106    'hw/acpi',
2107    'hw/adc',
2108    'hw/alpha',
2109    'hw/arm',
2110    'hw/audio',
2111    'hw/block',
2112    'hw/block/dataplane',
2113    'hw/char',
2114    'hw/display',
2115    'hw/dma',
2116    'hw/hppa',
2117    'hw/hyperv',
2118    'hw/i2c',
2119    'hw/i386',
2120    'hw/i386/xen',
2121    'hw/ide',
2122    'hw/input',
2123    'hw/intc',
2124    'hw/isa',
2125    'hw/mem',
2126    'hw/mips',
2127    'hw/misc',
2128    'hw/misc/macio',
2129    'hw/net',
2130    'hw/net/can',
2131    'hw/nvme',
2132    'hw/nvram',
2133    'hw/pci',
2134    'hw/pci-host',
2135    'hw/ppc',
2136    'hw/rdma',
2137    'hw/rdma/vmw',
2138    'hw/rtc',
2139    'hw/s390x',
2140    'hw/scsi',
2141    'hw/sd',
2142    'hw/sparc',
2143    'hw/sparc64',
2144    'hw/ssi',
2145    'hw/timer',
2146    'hw/tpm',
2147    'hw/usb',
2148    'hw/vfio',
2149    'hw/virtio',
2150    'hw/watchdog',
2151    'hw/xen',
2152    'hw/gpio',
2153    'migration',
2154    'net',
2155    'softmmu',
2156    'ui',
2157    'hw/remote',
2158  ]
2159endif
2160if have_system or have_user
2161  trace_events_subdirs += [
2162    'accel/tcg',
2163    'hw/core',
2164    'target/arm',
2165    'target/hppa',
2166    'target/i386',
2167    'target/i386/kvm',
2168    'target/mips/tcg',
2169    'target/ppc',
2170    'target/riscv',
2171    'target/s390x',
2172    'target/s390x/kvm',
2173    'target/sparc',
2174  ]
2175endif
2176
2177vhost_user = not_found
2178if 'CONFIG_VHOST_USER' in config_host
2179  libvhost_user = subproject('libvhost-user')
2180  vhost_user = libvhost_user.get_variable('vhost_user_dep')
2181endif
2182
2183subdir('qapi')
2184subdir('qobject')
2185subdir('stubs')
2186subdir('trace')
2187subdir('util')
2188subdir('qom')
2189subdir('authz')
2190subdir('crypto')
2191subdir('ui')
2192
2193
2194if enable_modules
2195  libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
2196  modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
2197endif
2198
2199stub_ss = stub_ss.apply(config_all, strict: false)
2200
2201util_ss.add_all(trace_ss)
2202util_ss = util_ss.apply(config_all, strict: false)
2203libqemuutil = static_library('qemuutil',
2204                             sources: util_ss.sources() + stub_ss.sources() + genh,
2205                             dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc, pixman])
2206qemuutil = declare_dependency(link_with: libqemuutil,
2207                              sources: genh + version_res)
2208
2209if have_system or have_user
2210  decodetree = generator(find_program('scripts/decodetree.py'),
2211                         output: 'decode-@BASENAME@.c.inc',
2212                         arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
2213  subdir('libdecnumber')
2214  subdir('target')
2215endif
2216
2217subdir('audio')
2218subdir('io')
2219subdir('chardev')
2220subdir('fsdev')
2221subdir('dump')
2222
2223if have_block
2224  block_ss.add(files(
2225    'block.c',
2226    'blockjob.c',
2227    'job.c',
2228    'qemu-io-cmds.c',
2229  ))
2230  block_ss.add(when: 'CONFIG_REPLICATION', if_true: files('replication.c'))
2231
2232  subdir('nbd')
2233  subdir('scsi')
2234  subdir('block')
2235
2236  blockdev_ss.add(files(
2237    'blockdev.c',
2238    'blockdev-nbd.c',
2239    'iothread.c',
2240    'job-qmp.c',
2241  ), gnutls)
2242
2243  # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
2244  # os-win32.c does not
2245  blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
2246  softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
2247endif
2248
2249common_ss.add(files('cpus-common.c'))
2250
2251subdir('softmmu')
2252
2253common_ss.add(capstone)
2254specific_ss.add(files('cpu.c', 'disas.c', 'gdbstub.c'), capstone)
2255
2256# Work around a gcc bug/misfeature wherein constant propagation looks
2257# through an alias:
2258#   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99696
2259# to guess that a const variable is always zero.  Without lto, this is
2260# impossible, as the alias is restricted to page-vary-common.c.  Indeed,
2261# without lto, not even the alias is required -- we simply use different
2262# declarations in different compilation units.
2263pagevary = files('page-vary-common.c')
2264if get_option('b_lto')
2265  pagevary_flags = ['-fno-lto']
2266  if get_option('cfi')
2267    pagevary_flags += '-fno-sanitize=cfi-icall'
2268  endif
2269  pagevary = static_library('page-vary-common', sources: pagevary,
2270                            c_args: pagevary_flags)
2271  pagevary = declare_dependency(link_with: pagevary)
2272endif
2273common_ss.add(pagevary)
2274specific_ss.add(files('page-vary.c'))
2275
2276subdir('backends')
2277subdir('disas')
2278subdir('migration')
2279subdir('monitor')
2280subdir('net')
2281subdir('replay')
2282subdir('semihosting')
2283subdir('hw')
2284subdir('tcg')
2285subdir('fpu')
2286subdir('accel')
2287subdir('plugins')
2288subdir('bsd-user')
2289subdir('linux-user')
2290subdir('ebpf')
2291
2292common_ss.add(libbpf)
2293
2294bsd_user_ss.add(files('gdbstub.c'))
2295specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss)
2296
2297linux_user_ss.add(files('gdbstub.c', 'thunk.c'))
2298specific_ss.add_all(when: 'CONFIG_LINUX_USER', if_true: linux_user_ss)
2299
2300# needed for fuzzing binaries
2301subdir('tests/qtest/libqos')
2302subdir('tests/qtest/fuzz')
2303
2304# accel modules
2305tcg_real_module_ss = ss.source_set()
2306tcg_real_module_ss.add_all(when: 'CONFIG_TCG_MODULAR', if_true: tcg_module_ss)
2307specific_ss.add_all(when: 'CONFIG_TCG_BUILTIN', if_true: tcg_module_ss)
2308target_modules += { 'accel' : { 'qtest': qtest_module_ss,
2309                                'tcg': tcg_real_module_ss }}
2310
2311########################
2312# Library dependencies #
2313########################
2314
2315modinfo_collect = find_program('scripts/modinfo-collect.py')
2316modinfo_generate = find_program('scripts/modinfo-generate.py')
2317modinfo_files = []
2318
2319block_mods = []
2320softmmu_mods = []
2321foreach d, list : modules
2322  foreach m, module_ss : list
2323    if enable_modules and targetos != 'windows'
2324      module_ss = module_ss.apply(config_all, strict: false)
2325      sl = static_library(d + '-' + m, [genh, module_ss.sources()],
2326                          dependencies: [modulecommon, module_ss.dependencies()], pic: true)
2327      if d == 'block'
2328        block_mods += sl
2329      else
2330        softmmu_mods += sl
2331      endif
2332      if module_ss.sources() != []
2333        # FIXME: Should use sl.extract_all_objects(recursive: true) as
2334        # input. Sources can be used multiple times but objects are
2335        # unique when it comes to lookup in compile_commands.json.
2336        # Depnds on a mesion version with
2337        # https://github.com/mesonbuild/meson/pull/8900
2338        modinfo_files += custom_target(d + '-' + m + '.modinfo',
2339                                       output: d + '-' + m + '.modinfo',
2340                                       input: module_ss.sources() + genh,
2341                                       capture: true,
2342                                       command: [modinfo_collect, module_ss.sources()])
2343      endif
2344    else
2345      if d == 'block'
2346        block_ss.add_all(module_ss)
2347      else
2348        softmmu_ss.add_all(module_ss)
2349      endif
2350    endif
2351  endforeach
2352endforeach
2353
2354foreach d, list : target_modules
2355  foreach m, module_ss : list
2356    if enable_modules and targetos != 'windows'
2357      foreach target : target_dirs
2358        if target.endswith('-softmmu')
2359          config_target = config_target_mak[target]
2360          config_target += config_host
2361          target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
2362          c_args = ['-DNEED_CPU_H',
2363                    '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
2364                    '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
2365          target_module_ss = module_ss.apply(config_target, strict: false)
2366          if target_module_ss.sources() != []
2367            module_name = d + '-' + m + '-' + config_target['TARGET_NAME']
2368            sl = static_library(module_name,
2369                                [genh, target_module_ss.sources()],
2370                                dependencies: [modulecommon, target_module_ss.dependencies()],
2371                                include_directories: target_inc,
2372                                c_args: c_args,
2373                                pic: true)
2374            softmmu_mods += sl
2375            # FIXME: Should use sl.extract_all_objects(recursive: true) too.
2376            modinfo_files += custom_target(module_name + '.modinfo',
2377                                           output: module_name + '.modinfo',
2378                                           input: target_module_ss.sources() + genh,
2379                                           capture: true,
2380                                           command: [modinfo_collect, '--target', target, target_module_ss.sources()])
2381          endif
2382        endif
2383      endforeach
2384    else
2385      specific_ss.add_all(module_ss)
2386    endif
2387  endforeach
2388endforeach
2389
2390if enable_modules
2391  modinfo_src = custom_target('modinfo.c',
2392                              output: 'modinfo.c',
2393                              input: modinfo_files,
2394                              command: [modinfo_generate, '@INPUT@'],
2395                              capture: true)
2396  modinfo_lib = static_library('modinfo', modinfo_src)
2397  modinfo_dep = declare_dependency(link_whole: modinfo_lib)
2398  softmmu_ss.add(modinfo_dep)
2399endif
2400
2401nm = find_program('nm')
2402undefsym = find_program('scripts/undefsym.py')
2403block_syms = custom_target('block.syms', output: 'block.syms',
2404                             input: [libqemuutil, block_mods],
2405                             capture: true,
2406                             command: [undefsym, nm, '@INPUT@'])
2407qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
2408                             input: [libqemuutil, softmmu_mods],
2409                             capture: true,
2410                             command: [undefsym, nm, '@INPUT@'])
2411
2412qom_ss = qom_ss.apply(config_host, strict: false)
2413libqom = static_library('qom', qom_ss.sources() + genh,
2414                        dependencies: [qom_ss.dependencies()],
2415                        name_suffix: 'fa')
2416
2417qom = declare_dependency(link_whole: libqom)
2418
2419authz_ss = authz_ss.apply(config_host, strict: false)
2420libauthz = static_library('authz', authz_ss.sources() + genh,
2421                          dependencies: [authz_ss.dependencies()],
2422                          name_suffix: 'fa',
2423                          build_by_default: false)
2424
2425authz = declare_dependency(link_whole: libauthz,
2426                           dependencies: qom)
2427
2428crypto_ss = crypto_ss.apply(config_host, strict: false)
2429libcrypto = static_library('crypto', crypto_ss.sources() + genh,
2430                           dependencies: [crypto_ss.dependencies()],
2431                           name_suffix: 'fa',
2432                           build_by_default: false)
2433
2434crypto = declare_dependency(link_whole: libcrypto,
2435                            dependencies: [authz, qom])
2436
2437io_ss = io_ss.apply(config_host, strict: false)
2438libio = static_library('io', io_ss.sources() + genh,
2439                       dependencies: [io_ss.dependencies()],
2440                       link_with: libqemuutil,
2441                       name_suffix: 'fa',
2442                       build_by_default: false)
2443
2444io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
2445
2446libmigration = static_library('migration', sources: migration_files + genh,
2447                              name_suffix: 'fa',
2448                              build_by_default: false)
2449migration = declare_dependency(link_with: libmigration,
2450                               dependencies: [zlib, qom, io])
2451softmmu_ss.add(migration)
2452
2453block_ss = block_ss.apply(config_host, strict: false)
2454libblock = static_library('block', block_ss.sources() + genh,
2455                          dependencies: block_ss.dependencies(),
2456                          link_depends: block_syms,
2457                          name_suffix: 'fa',
2458                          build_by_default: false)
2459
2460block = declare_dependency(link_whole: [libblock],
2461                           link_args: '@block.syms',
2462                           dependencies: [crypto, io])
2463
2464blockdev_ss = blockdev_ss.apply(config_host, strict: false)
2465libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
2466                             dependencies: blockdev_ss.dependencies(),
2467                             name_suffix: 'fa',
2468                             build_by_default: false)
2469
2470blockdev = declare_dependency(link_whole: [libblockdev],
2471                              dependencies: [block])
2472
2473qmp_ss = qmp_ss.apply(config_host, strict: false)
2474libqmp = static_library('qmp', qmp_ss.sources() + genh,
2475                        dependencies: qmp_ss.dependencies(),
2476                        name_suffix: 'fa',
2477                        build_by_default: false)
2478
2479qmp = declare_dependency(link_whole: [libqmp])
2480
2481libchardev = static_library('chardev', chardev_ss.sources() + genh,
2482                            name_suffix: 'fa',
2483                            dependencies: [gnutls],
2484                            build_by_default: false)
2485
2486chardev = declare_dependency(link_whole: libchardev)
2487
2488libhwcore = static_library('hwcore', sources: hwcore_files + genh,
2489                           name_suffix: 'fa',
2490                           build_by_default: false)
2491hwcore = declare_dependency(link_whole: libhwcore)
2492common_ss.add(hwcore)
2493
2494###########
2495# Targets #
2496###########
2497
2498foreach m : block_mods + softmmu_mods
2499  shared_module(m.name(),
2500                name_prefix: '',
2501                link_whole: m,
2502                install: true,
2503                install_dir: qemu_moddir)
2504endforeach
2505
2506softmmu_ss.add(authz, blockdev, chardev, crypto, io, qmp)
2507common_ss.add(qom, qemuutil)
2508
2509common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
2510common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
2511
2512common_all = common_ss.apply(config_all, strict: false)
2513common_all = static_library('common',
2514                            build_by_default: false,
2515                            sources: common_all.sources() + genh,
2516                            implicit_include_directories: false,
2517                            dependencies: common_all.dependencies(),
2518                            name_suffix: 'fa')
2519
2520feature_to_c = find_program('scripts/feature_to_c.sh')
2521
2522emulators = {}
2523foreach target : target_dirs
2524  config_target = config_target_mak[target]
2525  target_name = config_target['TARGET_NAME']
2526  arch = config_target['TARGET_BASE_ARCH']
2527  arch_srcs = [config_target_h[target]]
2528  arch_deps = []
2529  c_args = ['-DNEED_CPU_H',
2530            '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
2531            '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
2532  link_args = emulator_link_args
2533
2534  config_target += config_host
2535  target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
2536  if targetos == 'linux'
2537    target_inc += include_directories('linux-headers', is_system: true)
2538  endif
2539  if target.endswith('-softmmu')
2540    qemu_target_name = 'qemu-system-' + target_name
2541    target_type='system'
2542    t = target_softmmu_arch[arch].apply(config_target, strict: false)
2543    arch_srcs += t.sources()
2544    arch_deps += t.dependencies()
2545
2546    hw_dir = target_name == 'sparc64' ? 'sparc64' : arch
2547    hw = hw_arch[hw_dir].apply(config_target, strict: false)
2548    arch_srcs += hw.sources()
2549    arch_deps += hw.dependencies()
2550
2551    arch_srcs += config_devices_h[target]
2552    link_args += ['@block.syms', '@qemu.syms']
2553  else
2554    abi = config_target['TARGET_ABI_DIR']
2555    target_type='user'
2556    qemu_target_name = 'qemu-' + target_name
2557    if arch in target_user_arch
2558      t = target_user_arch[arch].apply(config_target, strict: false)
2559      arch_srcs += t.sources()
2560      arch_deps += t.dependencies()
2561    endif
2562    if 'CONFIG_LINUX_USER' in config_target
2563      base_dir = 'linux-user'
2564      target_inc += include_directories('linux-user/host/' / config_host['ARCH'])
2565    else
2566      base_dir = 'bsd-user'
2567      target_inc += include_directories('bsd-user/freebsd')
2568    endif
2569    target_inc += include_directories(
2570      base_dir,
2571      base_dir / abi,
2572    )
2573    if 'CONFIG_LINUX_USER' in config_target
2574      dir = base_dir / abi
2575      arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
2576      if config_target.has_key('TARGET_SYSTBL_ABI')
2577        arch_srcs += \
2578          syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
2579                                             extra_args : config_target['TARGET_SYSTBL_ABI'])
2580      endif
2581    endif
2582  endif
2583
2584  if 'TARGET_XML_FILES' in config_target
2585    gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
2586                                output: target + '-gdbstub-xml.c',
2587                                input: files(config_target['TARGET_XML_FILES'].split()),
2588                                command: [feature_to_c, '@INPUT@'],
2589                                capture: true)
2590    arch_srcs += gdbstub_xml
2591  endif
2592
2593  t = target_arch[arch].apply(config_target, strict: false)
2594  arch_srcs += t.sources()
2595  arch_deps += t.dependencies()
2596
2597  target_common = common_ss.apply(config_target, strict: false)
2598  objects = common_all.extract_objects(target_common.sources())
2599  deps = target_common.dependencies()
2600
2601  target_specific = specific_ss.apply(config_target, strict: false)
2602  arch_srcs += target_specific.sources()
2603  arch_deps += target_specific.dependencies()
2604
2605  lib = static_library('qemu-' + target,
2606                 sources: arch_srcs + genh,
2607                 dependencies: arch_deps,
2608                 objects: objects,
2609                 include_directories: target_inc,
2610                 c_args: c_args,
2611                 build_by_default: false,
2612                 name_suffix: 'fa')
2613
2614  if target.endswith('-softmmu')
2615    execs = [{
2616      'name': 'qemu-system-' + target_name,
2617      'gui': false,
2618      'sources': files('softmmu/main.c'),
2619      'dependencies': []
2620    }]
2621    if targetos == 'windows' and (sdl.found() or gtk.found())
2622      execs += [{
2623        'name': 'qemu-system-' + target_name + 'w',
2624        'gui': true,
2625        'sources': files('softmmu/main.c'),
2626        'dependencies': []
2627      }]
2628    endif
2629    if config_host.has_key('CONFIG_FUZZ')
2630      specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
2631      execs += [{
2632        'name': 'qemu-fuzz-' + target_name,
2633        'gui': false,
2634        'sources': specific_fuzz.sources(),
2635        'dependencies': specific_fuzz.dependencies(),
2636      }]
2637    endif
2638  else
2639    execs = [{
2640      'name': 'qemu-' + target_name,
2641      'gui': false,
2642      'sources': [],
2643      'dependencies': []
2644    }]
2645  endif
2646  foreach exe: execs
2647    exe_name = exe['name']
2648    if targetos == 'darwin'
2649      exe_name += '-unsigned'
2650    endif
2651
2652    emulator = executable(exe_name, exe['sources'],
2653               install: true,
2654               c_args: c_args,
2655               dependencies: arch_deps + deps + exe['dependencies'],
2656               objects: lib.extract_all_objects(recursive: true),
2657               link_language: link_language,
2658               link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
2659               link_args: link_args,
2660               gui_app: exe['gui'])
2661
2662    if targetos == 'darwin'
2663      icon = 'pc-bios/qemu.rsrc'
2664      build_input = [emulator, files(icon)]
2665      install_input = [
2666        get_option('bindir') / exe_name,
2667        meson.current_source_dir() / icon
2668      ]
2669      if 'CONFIG_HVF' in config_target
2670        entitlements = 'accel/hvf/entitlements.plist'
2671        build_input += files(entitlements)
2672        install_input += meson.current_source_dir() / entitlements
2673      endif
2674
2675      emulators += {exe['name'] : custom_target(exe['name'],
2676                   input: build_input,
2677                   output: exe['name'],
2678                   command: [
2679                     files('scripts/entitlement.sh'),
2680                     '@OUTPUT@',
2681                     '@INPUT@'
2682                   ])
2683      }
2684
2685      meson.add_install_script('scripts/entitlement.sh', '--install',
2686                               get_option('bindir') / exe['name'],
2687                               install_input)
2688    else
2689      emulators += {exe['name']: emulator}
2690    endif
2691
2692    if 'CONFIG_TRACE_SYSTEMTAP' in config_host
2693      foreach stp: [
2694        {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
2695        {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
2696        {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
2697        {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
2698      ]
2699        custom_target(exe['name'] + stp['ext'],
2700                      input: trace_events_all,
2701                      output: exe['name'] + stp['ext'],
2702                      install: stp['install'],
2703                      install_dir: get_option('datadir') / 'systemtap/tapset',
2704                      command: [
2705                        tracetool, '--group=all', '--format=' + stp['fmt'],
2706                        '--binary=' + stp['bin'],
2707                        '--target-name=' + target_name,
2708                        '--target-type=' + target_type,
2709                        '--probe-prefix=qemu.' + target_type + '.' + target_name,
2710                        '@INPUT@', '@OUTPUT@'
2711                      ],
2712                      depend_files: tracetool_depends)
2713      endforeach
2714    endif
2715  endforeach
2716endforeach
2717
2718# Other build targets
2719
2720if 'CONFIG_PLUGIN' in config_host
2721  install_headers('include/qemu/qemu-plugin.h')
2722endif
2723
2724if 'CONFIG_GUEST_AGENT' in config_host
2725  subdir('qga')
2726elif get_option('guest_agent_msi').enabled()
2727  error('Guest agent MSI requested, but the guest agent is not being built')
2728endif
2729
2730# Don't build qemu-keymap if xkbcommon is not explicitly enabled
2731# when we don't build tools or system
2732if xkbcommon.found()
2733  # used for the update-keymaps target, so include rules even if !have_tools
2734  qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
2735                           dependencies: [qemuutil, xkbcommon], install: have_tools)
2736endif
2737
2738if have_tools
2739  qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
2740             dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
2741  qemu_io = executable('qemu-io', files('qemu-io.c'),
2742             dependencies: [block, qemuutil], install: true)
2743  qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
2744               dependencies: [blockdev, qemuutil, gnutls], install: true)
2745
2746  subdir('storage-daemon')
2747  subdir('contrib/rdmacm-mux')
2748  subdir('contrib/elf2dmp')
2749
2750  executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
2751             dependencies: qemuutil,
2752             install: true)
2753
2754  if 'CONFIG_VHOST_USER' in config_host
2755    subdir('contrib/vhost-user-blk')
2756    subdir('contrib/vhost-user-gpu')
2757    subdir('contrib/vhost-user-input')
2758    subdir('contrib/vhost-user-scsi')
2759  endif
2760
2761  if targetos == 'linux'
2762    executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
2763               dependencies: [qemuutil, libcap_ng],
2764               install: true,
2765               install_dir: get_option('libexecdir'))
2766
2767    executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
2768               dependencies: [authz, crypto, io, qom, qemuutil,
2769                              libcap_ng, mpathpersist],
2770               install: true)
2771  endif
2772
2773  if have_ivshmem
2774    subdir('contrib/ivshmem-client')
2775    subdir('contrib/ivshmem-server')
2776  endif
2777endif
2778
2779subdir('scripts')
2780subdir('tools')
2781subdir('pc-bios')
2782subdir('docs')
2783subdir('tests')
2784if gtk.found()
2785  subdir('po')
2786endif
2787
2788if host_machine.system() == 'windows'
2789  nsis_cmd = [
2790    find_program('scripts/nsis.py'),
2791    '@OUTPUT@',
2792    get_option('prefix'),
2793    meson.current_source_dir(),
2794    host_machine.cpu(),
2795    '--',
2796    '-DDISPLAYVERSION=' + meson.project_version(),
2797  ]
2798  if build_docs
2799    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
2800  endif
2801  if gtk.found()
2802    nsis_cmd += '-DCONFIG_GTK=y'
2803  endif
2804
2805  nsis = custom_target('nsis',
2806                       output: 'qemu-setup-' + meson.project_version() + '.exe',
2807                       input: files('qemu.nsi'),
2808                       build_always_stale: true,
2809                       command: nsis_cmd + ['@INPUT@'])
2810  alias_target('installer', nsis)
2811endif
2812
2813#########################
2814# Configuration summary #
2815#########################
2816
2817# Directories
2818summary_info = {}
2819summary_info += {'Install prefix':    get_option('prefix')}
2820summary_info += {'BIOS directory':    qemu_datadir}
2821summary_info += {'firmware path':     get_option('qemu_firmwarepath')}
2822summary_info += {'binary directory':  get_option('bindir')}
2823summary_info += {'library directory': get_option('libdir')}
2824summary_info += {'module directory':  qemu_moddir}
2825summary_info += {'libexec directory': get_option('libexecdir')}
2826summary_info += {'include directory': get_option('includedir')}
2827summary_info += {'config directory':  get_option('sysconfdir')}
2828if targetos != 'windows'
2829  summary_info += {'local state directory': get_option('localstatedir')}
2830  summary_info += {'Manual directory':      get_option('mandir')}
2831else
2832  summary_info += {'local state directory': 'queried at runtime'}
2833endif
2834summary_info += {'Doc directory':     get_option('docdir')}
2835summary_info += {'Build directory':   meson.current_build_dir()}
2836summary_info += {'Source path':       meson.current_source_dir()}
2837summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
2838summary(summary_info, bool_yn: true, section: 'Directories')
2839
2840# Host binaries
2841summary_info = {}
2842summary_info += {'git':               config_host['GIT']}
2843summary_info += {'make':              config_host['MAKE']}
2844summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
2845summary_info += {'sphinx-build':      sphinx_build.found()}
2846if config_host.has_key('HAVE_GDB_BIN')
2847  summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
2848endif
2849summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
2850if targetos == 'windows' and config_host.has_key('CONFIG_GUEST_AGENT')
2851  summary_info += {'wixl':            wixl.found() ? wixl.full_path() : false}
2852endif
2853if slirp_opt != 'disabled' and 'CONFIG_SLIRP_SMBD' in config_host
2854  summary_info += {'smbd':            config_host['CONFIG_SMBD_COMMAND']}
2855endif
2856summary(summary_info, bool_yn: true, section: 'Host binaries')
2857
2858# Configurable features
2859summary_info = {}
2860summary_info += {'Documentation':     build_docs}
2861summary_info += {'system-mode emulation': have_system}
2862summary_info += {'user-mode emulation': have_user}
2863summary_info += {'block layer':       have_block}
2864summary_info += {'Install blobs':     get_option('install_blobs')}
2865summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
2866if config_host.has_key('CONFIG_MODULES')
2867  summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')}
2868endif
2869summary_info += {'fuzzing support':   config_host.has_key('CONFIG_FUZZ')}
2870if have_system
2871  summary_info += {'Audio drivers':     config_host['CONFIG_AUDIO_DRIVERS']}
2872endif
2873summary_info += {'Trace backends':    config_host['TRACE_BACKENDS']}
2874if config_host['TRACE_BACKENDS'].split().contains('simple')
2875  summary_info += {'Trace output file': config_host['CONFIG_TRACE_FILE'] + '-<pid>'}
2876endif
2877summary_info += {'QOM debugging':     config_host.has_key('CONFIG_QOM_CAST_DEBUG')}
2878summary_info += {'vhost-kernel support': config_host.has_key('CONFIG_VHOST_KERNEL')}
2879summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')}
2880summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')}
2881summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')}
2882summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')}
2883summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_USER')}
2884summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
2885summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')}
2886summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')}
2887summary_info += {'build guest agent': config_host.has_key('CONFIG_GUEST_AGENT')}
2888summary(summary_info, bool_yn: true, section: 'Configurable features')
2889
2890# Compilation information
2891summary_info = {}
2892summary_info += {'host CPU':          cpu}
2893summary_info += {'host endianness':   build_machine.endian()}
2894summary_info += {'C compiler':        ' '.join(meson.get_compiler('c').cmd_array())}
2895summary_info += {'Host C compiler':   ' '.join(meson.get_compiler('c', native: true).cmd_array())}
2896if link_language == 'cpp'
2897  summary_info += {'C++ compiler':    ' '.join(meson.get_compiler('cpp').cmd_array())}
2898else
2899  summary_info += {'C++ compiler':      false}
2900endif
2901if targetos == 'darwin'
2902  summary_info += {'Objective-C compiler': ' '.join(meson.get_compiler('objc').cmd_array())}
2903endif
2904if targetos == 'windows'
2905  if 'WIN_SDK' in config_host
2906    summary_info += {'Windows SDK':   config_host['WIN_SDK']}
2907  endif
2908endif
2909summary_info += {'CFLAGS':            ' '.join(get_option('c_args')
2910                                               + ['-O' + get_option('optimization')]
2911                                               + (get_option('debug') ? ['-g'] : []))}
2912if link_language == 'cpp'
2913  summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args')
2914                                               + ['-O' + get_option('optimization')]
2915                                               + (get_option('debug') ? ['-g'] : []))}
2916endif
2917link_args = get_option(link_language + '_link_args')
2918if link_args.length() > 0
2919  summary_info += {'LDFLAGS':         ' '.join(link_args)}
2920endif
2921summary_info += {'QEMU_CFLAGS':       config_host['QEMU_CFLAGS']}
2922summary_info += {'QEMU_LDFLAGS':      config_host['QEMU_LDFLAGS']}
2923summary_info += {'profiler':          config_host.has_key('CONFIG_PROFILER')}
2924summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
2925summary_info += {'PIE':               get_option('b_pie')}
2926summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
2927summary_info += {'malloc trim support': has_malloc_trim}
2928summary_info += {'membarrier':        config_host.has_key('CONFIG_MEMBARRIER')}
2929summary_info += {'debug stack usage': config_host.has_key('CONFIG_DEBUG_STACK_USAGE')}
2930summary_info += {'mutex debugging':   config_host.has_key('CONFIG_DEBUG_MUTEX')}
2931summary_info += {'memory allocator':  get_option('malloc')}
2932summary_info += {'avx2 optimization': config_host.has_key('CONFIG_AVX2_OPT')}
2933summary_info += {'avx512f optimization': config_host.has_key('CONFIG_AVX512F_OPT')}
2934summary_info += {'gprof enabled':     config_host.has_key('CONFIG_GPROF')}
2935summary_info += {'gcov':              get_option('b_coverage')}
2936summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
2937summary_info += {'CFI support':       get_option('cfi')}
2938if get_option('cfi')
2939  summary_info += {'CFI debug support': get_option('cfi_debug')}
2940endif
2941summary_info += {'strip binaries':    get_option('strip')}
2942summary_info += {'sparse':            sparse.found() ? sparse.full_path() : false}
2943summary_info += {'mingw32 support':   targetos == 'windows'}
2944
2945# snarf the cross-compilation information for tests
2946foreach target: target_dirs
2947  tcg_mak = meson.current_build_dir() / 'tests/tcg' / 'config-' + target + '.mak'
2948  if fs.exists(tcg_mak)
2949    config_cross_tcg = keyval.load(tcg_mak)
2950    target = config_cross_tcg['TARGET_NAME']
2951    compiler = ''
2952    if 'DOCKER_CROSS_CC_GUEST' in config_cross_tcg
2953      summary_info += {target + ' tests': config_cross_tcg['DOCKER_CROSS_CC_GUEST'] +
2954                                          ' via ' + config_cross_tcg['DOCKER_IMAGE']}
2955    elif 'CROSS_CC_GUEST' in config_cross_tcg
2956      summary_info += {target + ' tests'
2957                                : config_cross_tcg['CROSS_CC_GUEST'] }
2958    endif
2959   endif
2960endforeach
2961
2962summary(summary_info, bool_yn: true, section: 'Compilation')
2963
2964# Targets and accelerators
2965summary_info = {}
2966if have_system
2967  summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
2968  summary_info += {'HAX support':       config_all.has_key('CONFIG_HAX')}
2969  summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
2970  summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
2971  summary_info += {'NVMM support':      config_all.has_key('CONFIG_NVMM')}
2972  summary_info += {'Xen support':       config_host.has_key('CONFIG_XEN_BACKEND')}
2973  if config_host.has_key('CONFIG_XEN_BACKEND')
2974    summary_info += {'xen ctrl version':  config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
2975  endif
2976endif
2977summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
2978if config_all.has_key('CONFIG_TCG')
2979  if get_option('tcg_interpreter')
2980    summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, experimental and slow)'}
2981  else
2982    summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
2983  endif
2984  summary_info += {'TCG plugins': config_host.has_key('CONFIG_PLUGIN')}
2985  summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
2986endif
2987summary_info += {'target list':       ' '.join(target_dirs)}
2988if have_system
2989  summary_info += {'default devices':   get_option('default_devices')}
2990  summary_info += {'out of process emulation': multiprocess_allowed}
2991endif
2992summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
2993
2994# Block layer
2995summary_info = {}
2996summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
2997summary_info += {'coroutine pool':    config_host['CONFIG_COROUTINE_POOL'] == '1'}
2998if have_block
2999  summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']}
3000  summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']}
3001  summary_info += {'Use block whitelist in tools': config_host.has_key('CONFIG_BDRV_WHITELIST_TOOLS')}
3002  summary_info += {'VirtFS support':    have_virtfs}
3003  summary_info += {'build virtiofs daemon': have_virtiofsd}
3004  summary_info += {'Live block migration': config_host.has_key('CONFIG_LIVE_BLOCK_MIGRATION')}
3005  summary_info += {'replication support': config_host.has_key('CONFIG_REPLICATION')}
3006  summary_info += {'bochs support':     config_host.has_key('CONFIG_BOCHS')}
3007  summary_info += {'cloop support':     config_host.has_key('CONFIG_CLOOP')}
3008  summary_info += {'dmg support':       config_host.has_key('CONFIG_DMG')}
3009  summary_info += {'qcow v1 support':   config_host.has_key('CONFIG_QCOW1')}
3010  summary_info += {'vdi support':       config_host.has_key('CONFIG_VDI')}
3011  summary_info += {'vvfat support':     config_host.has_key('CONFIG_VVFAT')}
3012  summary_info += {'qed support':       config_host.has_key('CONFIG_QED')}
3013  summary_info += {'parallels support': config_host.has_key('CONFIG_PARALLELS')}
3014  summary_info += {'FUSE exports':      fuse.found()}
3015endif
3016summary(summary_info, bool_yn: true, section: 'Block layer support')
3017
3018# Crypto
3019summary_info = {}
3020summary_info += {'TLS priority':      config_host['CONFIG_TLS_PRIORITY']}
3021summary_info += {'GNUTLS support':    gnutls.found()}
3022summary_info += {'GNUTLS crypto':     gnutls_crypto.found()}
3023# TODO: add back version
3024summary_info += {'libgcrypt':         gcrypt.found()}
3025# TODO: add back version
3026summary_info += {'nettle':            nettle.found()}
3027if nettle.found()
3028   summary_info += {'  XTS':             xts != 'private'}
3029endif
3030summary_info += {'crypto afalg':      config_host.has_key('CONFIG_AF_ALG')}
3031summary_info += {'rng-none':          config_host.has_key('CONFIG_RNG_NONE')}
3032summary_info += {'Linux keyring':     config_host.has_key('CONFIG_SECRET_KEYRING')}
3033summary(summary_info, bool_yn: true, section: 'Crypto')
3034
3035# Libraries
3036summary_info = {}
3037if targetos == 'darwin'
3038  summary_info += {'Cocoa support':   cocoa.found()}
3039endif
3040# TODO: add back version
3041summary_info += {'SDL support':       sdl.found()}
3042summary_info += {'SDL image support': sdl_image.found()}
3043# TODO: add back version
3044summary_info += {'GTK support':       gtk.found()}
3045summary_info += {'pixman':            pixman.found()}
3046# TODO: add back version
3047summary_info += {'VTE support':       vte.found()}
3048# TODO: add back version
3049summary_info += {'slirp support':     slirp_opt == 'disabled' ? false : slirp_opt}
3050summary_info += {'libtasn1':          tasn1.found()}
3051summary_info += {'PAM':               pam.found()}
3052summary_info += {'iconv support':     iconv.found()}
3053summary_info += {'curses support':    curses.found()}
3054# TODO: add back version
3055summary_info += {'virgl support':     virgl.found()}
3056summary_info += {'curl support':      curl.found()}
3057summary_info += {'Multipath support': mpathpersist.found()}
3058summary_info += {'VNC support':       vnc.found()}
3059if vnc.found()
3060  summary_info += {'VNC SASL support':  sasl.found()}
3061  summary_info += {'VNC JPEG support':  jpeg.found()}
3062  summary_info += {'VNC PNG support':   png.found()}
3063endif
3064summary_info += {'brlapi support':    brlapi.found()}
3065summary_info += {'vde support':       config_host.has_key('CONFIG_VDE')}
3066summary_info += {'netmap support':    config_host.has_key('CONFIG_NETMAP')}
3067summary_info += {'Linux AIO support': config_host.has_key('CONFIG_LINUX_AIO')}
3068summary_info += {'Linux io_uring support': linux_io_uring.found()}
3069summary_info += {'ATTR/XATTR support': libattr.found()}
3070summary_info += {'RDMA support':      config_host.has_key('CONFIG_RDMA')}
3071summary_info += {'PVRDMA support':    config_host.has_key('CONFIG_PVRDMA')}
3072summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
3073summary_info += {'libcap-ng support': libcap_ng.found()}
3074summary_info += {'bpf support': libbpf.found()}
3075# TODO: add back protocol and server version
3076summary_info += {'spice support':     config_host.has_key('CONFIG_SPICE')}
3077summary_info += {'rbd support':       rbd.found()}
3078summary_info += {'xfsctl support':    config_host.has_key('CONFIG_XFS')}
3079summary_info += {'smartcard support': cacard.found()}
3080summary_info += {'U2F support':       u2f.found()}
3081summary_info += {'libusb':            libusb.found()}
3082summary_info += {'usb net redir':     usbredir.found()}
3083summary_info += {'OpenGL support':    config_host.has_key('CONFIG_OPENGL')}
3084summary_info += {'GBM':               config_host.has_key('CONFIG_GBM')}
3085summary_info += {'libiscsi support':  libiscsi.found()}
3086summary_info += {'libnfs support':    libnfs.found()}
3087if targetos == 'windows'
3088  if config_host.has_key('CONFIG_GUEST_AGENT')
3089    summary_info += {'QGA VSS support':   config_host.has_key('CONFIG_QGA_VSS')}
3090    summary_info += {'QGA w32 disk info': config_host.has_key('CONFIG_QGA_NTDDSCSI')}
3091  endif
3092endif
3093summary_info += {'seccomp support':   seccomp.found()}
3094summary_info += {'GlusterFS support': glusterfs.found()}
3095summary_info += {'TPM support':       config_host.has_key('CONFIG_TPM')}
3096summary_info += {'libssh support':    config_host.has_key('CONFIG_LIBSSH')}
3097summary_info += {'lzo support':       lzo.found()}
3098summary_info += {'snappy support':    snappy.found()}
3099summary_info += {'bzip2 support':     libbzip2.found()}
3100summary_info += {'lzfse support':     liblzfse.found()}
3101summary_info += {'zstd support':      zstd.found()}
3102summary_info += {'NUMA host support': config_host.has_key('CONFIG_NUMA')}
3103summary_info += {'libxml2':           libxml2.found()}
3104summary_info += {'capstone':          capstone_opt == 'disabled' ? false : capstone_opt}
3105summary_info += {'libpmem support':   libpmem.found()}
3106summary_info += {'libdaxctl support': libdaxctl.found()}
3107summary_info += {'libudev':           libudev.found()}
3108summary_info += {'FUSE lseek':        fuse_lseek.found()}
3109summary(summary_info, bool_yn: true, section: 'Dependencies')
3110
3111if not supported_cpus.contains(cpu)
3112  message()
3113  warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
3114  message()
3115  message('CPU host architecture ' + cpu + ' support is not currently maintained.')
3116  message('The QEMU project intends to remove support for this host CPU in')
3117  message('a future release if nobody volunteers to maintain it and to')
3118  message('provide a build host for our continuous integration setup.')
3119  message('configure has succeeded and you can continue to build, but')
3120  message('if you care about QEMU on this platform you should contact')
3121  message('us upstream at qemu-devel@nongnu.org.')
3122endif
3123
3124if not supported_oses.contains(targetos)
3125  message()
3126  warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
3127  message()
3128  message('Host OS ' + targetos + 'support is not currently maintained.')
3129  message('The QEMU project intends to remove support for this host OS in')
3130  message('a future release if nobody volunteers to maintain it and to')
3131  message('provide a build host for our continuous integration setup.')
3132  message('configure has succeeded and you can continue to build, but')
3133  message('if you care about QEMU on this platform you should contact')
3134  message('us upstream at qemu-devel@nongnu.org.')
3135endif
3136