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