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