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