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