xref: /openbmc/qemu/meson.build (revision 59964b4f)
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('tcg/tci.c'))
1947
1948subdir('backends')
1949subdir('disas')
1950subdir('migration')
1951subdir('monitor')
1952subdir('net')
1953subdir('replay')
1954subdir('semihosting')
1955subdir('hw')
1956subdir('accel')
1957subdir('plugins')
1958subdir('bsd-user')
1959subdir('linux-user')
1960
1961bsd_user_ss.add(files('gdbstub.c'))
1962specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss)
1963
1964linux_user_ss.add(files('gdbstub.c', 'thunk.c'))
1965specific_ss.add_all(when: 'CONFIG_LINUX_USER', if_true: linux_user_ss)
1966
1967# needed for fuzzing binaries
1968subdir('tests/qtest/libqos')
1969subdir('tests/qtest/fuzz')
1970
1971########################
1972# Library dependencies #
1973########################
1974
1975block_mods = []
1976softmmu_mods = []
1977foreach d, list : modules
1978  foreach m, module_ss : list
1979    if enable_modules and targetos != 'windows'
1980      module_ss = module_ss.apply(config_all, strict: false)
1981      sl = static_library(d + '-' + m, [genh, module_ss.sources()],
1982                          dependencies: [modulecommon, module_ss.dependencies()], pic: true)
1983      if d == 'block'
1984        block_mods += sl
1985      else
1986        softmmu_mods += sl
1987      endif
1988    else
1989      if d == 'block'
1990        block_ss.add_all(module_ss)
1991      else
1992        softmmu_ss.add_all(module_ss)
1993      endif
1994    endif
1995  endforeach
1996endforeach
1997
1998nm = find_program('nm')
1999undefsym = find_program('scripts/undefsym.py')
2000block_syms = custom_target('block.syms', output: 'block.syms',
2001                             input: [libqemuutil, block_mods],
2002                             capture: true,
2003                             command: [undefsym, nm, '@INPUT@'])
2004qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
2005                             input: [libqemuutil, softmmu_mods],
2006                             capture: true,
2007                             command: [undefsym, nm, '@INPUT@'])
2008
2009qom_ss = qom_ss.apply(config_host, strict: false)
2010libqom = static_library('qom', qom_ss.sources() + genh,
2011                        dependencies: [qom_ss.dependencies()],
2012                        name_suffix: 'fa')
2013
2014qom = declare_dependency(link_whole: libqom)
2015
2016authz_ss = authz_ss.apply(config_host, strict: false)
2017libauthz = static_library('authz', authz_ss.sources() + genh,
2018                          dependencies: [authz_ss.dependencies()],
2019                          name_suffix: 'fa',
2020                          build_by_default: false)
2021
2022authz = declare_dependency(link_whole: libauthz,
2023                           dependencies: qom)
2024
2025crypto_ss = crypto_ss.apply(config_host, strict: false)
2026libcrypto = static_library('crypto', crypto_ss.sources() + genh,
2027                           dependencies: [crypto_ss.dependencies()],
2028                           name_suffix: 'fa',
2029                           build_by_default: false)
2030
2031crypto = declare_dependency(link_whole: libcrypto,
2032                            dependencies: [authz, qom])
2033
2034io_ss = io_ss.apply(config_host, strict: false)
2035libio = static_library('io', io_ss.sources() + genh,
2036                       dependencies: [io_ss.dependencies()],
2037                       link_with: libqemuutil,
2038                       name_suffix: 'fa',
2039                       build_by_default: false)
2040
2041io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
2042
2043libmigration = static_library('migration', sources: migration_files + genh,
2044                              name_suffix: 'fa',
2045                              build_by_default: false)
2046migration = declare_dependency(link_with: libmigration,
2047                               dependencies: [zlib, qom, io])
2048softmmu_ss.add(migration)
2049
2050block_ss = block_ss.apply(config_host, strict: false)
2051libblock = static_library('block', block_ss.sources() + genh,
2052                          dependencies: block_ss.dependencies(),
2053                          link_depends: block_syms,
2054                          name_suffix: 'fa',
2055                          build_by_default: false)
2056
2057block = declare_dependency(link_whole: [libblock],
2058                           link_args: '@block.syms',
2059                           dependencies: [crypto, io])
2060
2061blockdev_ss = blockdev_ss.apply(config_host, strict: false)
2062libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
2063                             dependencies: blockdev_ss.dependencies(),
2064                             name_suffix: 'fa',
2065                             build_by_default: false)
2066
2067blockdev = declare_dependency(link_whole: [libblockdev],
2068                              dependencies: [block])
2069
2070qmp_ss = qmp_ss.apply(config_host, strict: false)
2071libqmp = static_library('qmp', qmp_ss.sources() + genh,
2072                        dependencies: qmp_ss.dependencies(),
2073                        name_suffix: 'fa',
2074                        build_by_default: false)
2075
2076qmp = declare_dependency(link_whole: [libqmp])
2077
2078libchardev = static_library('chardev', chardev_ss.sources() + genh,
2079                            name_suffix: 'fa',
2080                            dependencies: [gnutls],
2081                            build_by_default: false)
2082
2083chardev = declare_dependency(link_whole: libchardev)
2084
2085libhwcore = static_library('hwcore', sources: hwcore_files + genh,
2086                           name_suffix: 'fa',
2087                           build_by_default: false)
2088hwcore = declare_dependency(link_whole: libhwcore)
2089common_ss.add(hwcore)
2090
2091###########
2092# Targets #
2093###########
2094
2095foreach m : block_mods + softmmu_mods
2096  shared_module(m.name(),
2097                name_prefix: '',
2098                link_whole: m,
2099                install: true,
2100                install_dir: qemu_moddir)
2101endforeach
2102
2103softmmu_ss.add(authz, blockdev, chardev, crypto, io, qmp)
2104common_ss.add(qom, qemuutil)
2105
2106common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
2107common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
2108
2109common_all = common_ss.apply(config_all, strict: false)
2110common_all = static_library('common',
2111                            build_by_default: false,
2112                            sources: common_all.sources() + genh,
2113                            dependencies: common_all.dependencies(),
2114                            name_suffix: 'fa')
2115
2116feature_to_c = find_program('scripts/feature_to_c.sh')
2117
2118emulators = {}
2119foreach target : target_dirs
2120  config_target = config_target_mak[target]
2121  target_name = config_target['TARGET_NAME']
2122  arch = config_target['TARGET_BASE_ARCH']
2123  arch_srcs = [config_target_h[target]]
2124  arch_deps = []
2125  c_args = ['-DNEED_CPU_H',
2126            '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
2127            '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
2128  link_args = emulator_link_args
2129
2130  config_target += config_host
2131  target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
2132  if targetos == 'linux'
2133    target_inc += include_directories('linux-headers', is_system: true)
2134  endif
2135  if target.endswith('-softmmu')
2136    qemu_target_name = 'qemu-system-' + target_name
2137    target_type='system'
2138    t = target_softmmu_arch[arch].apply(config_target, strict: false)
2139    arch_srcs += t.sources()
2140    arch_deps += t.dependencies()
2141
2142    hw_dir = target_name == 'sparc64' ? 'sparc64' : arch
2143    hw = hw_arch[hw_dir].apply(config_target, strict: false)
2144    arch_srcs += hw.sources()
2145    arch_deps += hw.dependencies()
2146
2147    arch_srcs += config_devices_h[target]
2148    link_args += ['@block.syms', '@qemu.syms']
2149  else
2150    abi = config_target['TARGET_ABI_DIR']
2151    target_type='user'
2152    qemu_target_name = 'qemu-' + target_name
2153    if 'CONFIG_LINUX_USER' in config_target
2154      base_dir = 'linux-user'
2155      target_inc += include_directories('linux-user/host/' / config_host['ARCH'])
2156    else
2157      base_dir = 'bsd-user'
2158      target_inc += include_directories('bsd-user/freebsd')
2159    endif
2160    target_inc += include_directories(
2161      base_dir,
2162      base_dir / abi,
2163    )
2164    if 'CONFIG_LINUX_USER' in config_target
2165      dir = base_dir / abi
2166      arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
2167      if config_target.has_key('TARGET_SYSTBL_ABI')
2168        arch_srcs += \
2169          syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
2170                                             extra_args : config_target['TARGET_SYSTBL_ABI'])
2171      endif
2172    endif
2173  endif
2174
2175  if 'TARGET_XML_FILES' in config_target
2176    gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
2177                                output: target + '-gdbstub-xml.c',
2178                                input: files(config_target['TARGET_XML_FILES'].split()),
2179                                command: [feature_to_c, '@INPUT@'],
2180                                capture: true)
2181    arch_srcs += gdbstub_xml
2182  endif
2183
2184  t = target_arch[arch].apply(config_target, strict: false)
2185  arch_srcs += t.sources()
2186  arch_deps += t.dependencies()
2187
2188  target_common = common_ss.apply(config_target, strict: false)
2189  objects = common_all.extract_objects(target_common.sources())
2190  deps = target_common.dependencies()
2191
2192  target_specific = specific_ss.apply(config_target, strict: false)
2193  arch_srcs += target_specific.sources()
2194  arch_deps += target_specific.dependencies()
2195
2196  lib = static_library('qemu-' + target,
2197                 sources: arch_srcs + genh,
2198                 dependencies: arch_deps,
2199                 objects: objects,
2200                 include_directories: target_inc,
2201                 c_args: c_args,
2202                 build_by_default: false,
2203                 name_suffix: 'fa')
2204
2205  if target.endswith('-softmmu')
2206    execs = [{
2207      'name': 'qemu-system-' + target_name,
2208      'gui': false,
2209      'sources': files('softmmu/main.c'),
2210      'dependencies': []
2211    }]
2212    if targetos == 'windows' and (sdl.found() or gtk.found())
2213      execs += [{
2214        'name': 'qemu-system-' + target_name + 'w',
2215        'gui': true,
2216        'sources': files('softmmu/main.c'),
2217        'dependencies': []
2218      }]
2219    endif
2220    if config_host.has_key('CONFIG_FUZZ')
2221      specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
2222      execs += [{
2223        'name': 'qemu-fuzz-' + target_name,
2224        'gui': false,
2225        'sources': specific_fuzz.sources(),
2226        'dependencies': specific_fuzz.dependencies(),
2227      }]
2228    endif
2229  else
2230    execs = [{
2231      'name': 'qemu-' + target_name,
2232      'gui': false,
2233      'sources': [],
2234      'dependencies': []
2235    }]
2236  endif
2237  foreach exe: execs
2238    exe_name = exe['name']
2239    exe_sign = 'CONFIG_HVF' in config_target
2240    if exe_sign
2241      exe_name += '-unsigned'
2242    endif
2243
2244    emulator = executable(exe_name, exe['sources'],
2245               install: true,
2246               c_args: c_args,
2247               dependencies: arch_deps + deps + exe['dependencies'],
2248               objects: lib.extract_all_objects(recursive: true),
2249               link_language: link_language,
2250               link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
2251               link_args: link_args,
2252               gui_app: exe['gui'])
2253
2254    if exe_sign
2255      emulators += {exe['name'] : custom_target(exe['name'],
2256                   depends: emulator,
2257                   output: exe['name'],
2258                   command: [
2259                     meson.current_source_dir() / 'scripts/entitlement.sh',
2260                     meson.current_build_dir() / exe_name,
2261                     meson.current_build_dir() / exe['name'],
2262                     meson.current_source_dir() / 'accel/hvf/entitlements.plist'
2263                   ])
2264      }
2265
2266      meson.add_install_script('scripts/entitlement.sh', '--install',
2267                               get_option('bindir') / exe_name,
2268                               get_option('bindir') / exe['name'],
2269                               meson.current_source_dir() / 'accel/hvf/entitlements.plist')
2270    else
2271      emulators += {exe['name']: emulator}
2272    endif
2273
2274    if 'CONFIG_TRACE_SYSTEMTAP' in config_host
2275      foreach stp: [
2276        {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
2277        {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
2278        {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
2279        {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
2280      ]
2281        custom_target(exe['name'] + stp['ext'],
2282                      input: trace_events_all,
2283                      output: exe['name'] + stp['ext'],
2284                      install: stp['install'],
2285                      install_dir: get_option('datadir') / 'systemtap/tapset',
2286                      command: [
2287                        tracetool, '--group=all', '--format=' + stp['fmt'],
2288                        '--binary=' + stp['bin'],
2289                        '--target-name=' + target_name,
2290                        '--target-type=' + target_type,
2291                        '--probe-prefix=qemu.' + target_type + '.' + target_name,
2292                        '@INPUT@', '@OUTPUT@'
2293                      ],
2294                      depend_files: tracetool_depends)
2295      endforeach
2296    endif
2297  endforeach
2298endforeach
2299
2300# Other build targets
2301
2302if 'CONFIG_PLUGIN' in config_host
2303  install_headers('include/qemu/qemu-plugin.h')
2304endif
2305
2306if 'CONFIG_GUEST_AGENT' in config_host
2307  subdir('qga')
2308elif get_option('guest_agent_msi').enabled()
2309  error('Guest agent MSI requested, but the guest agent is not being built')
2310endif
2311
2312# Don't build qemu-keymap if xkbcommon is not explicitly enabled
2313# when we don't build tools or system
2314if xkbcommon.found()
2315  # used for the update-keymaps target, so include rules even if !have_tools
2316  qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
2317                           dependencies: [qemuutil, xkbcommon], install: have_tools)
2318endif
2319
2320if have_tools
2321  qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
2322             dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
2323  qemu_io = executable('qemu-io', files('qemu-io.c'),
2324             dependencies: [block, qemuutil], install: true)
2325  qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
2326               dependencies: [blockdev, qemuutil, gnutls], install: true)
2327
2328  subdir('storage-daemon')
2329  subdir('contrib/rdmacm-mux')
2330  subdir('contrib/elf2dmp')
2331
2332  executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
2333             dependencies: qemuutil,
2334             install: true)
2335
2336  if 'CONFIG_VHOST_USER' in config_host
2337    subdir('contrib/vhost-user-blk')
2338    subdir('contrib/vhost-user-gpu')
2339    subdir('contrib/vhost-user-input')
2340    subdir('contrib/vhost-user-scsi')
2341  endif
2342
2343  if targetos == 'linux'
2344    executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
2345               dependencies: [qemuutil, libcap_ng],
2346               install: true,
2347               install_dir: get_option('libexecdir'))
2348
2349    executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
2350               dependencies: [authz, crypto, io, qom, qemuutil,
2351                              libcap_ng, mpathpersist],
2352               install: true)
2353  endif
2354
2355  if 'CONFIG_IVSHMEM' in config_host
2356    subdir('contrib/ivshmem-client')
2357    subdir('contrib/ivshmem-server')
2358  endif
2359endif
2360
2361subdir('scripts')
2362subdir('tools')
2363subdir('pc-bios')
2364subdir('docs')
2365subdir('tests')
2366if gtk.found()
2367  subdir('po')
2368endif
2369
2370if host_machine.system() == 'windows'
2371  nsis_cmd = [
2372    find_program('scripts/nsis.py'),
2373    '@OUTPUT@',
2374    get_option('prefix'),
2375    meson.current_source_dir(),
2376    host_machine.cpu(),
2377    '--',
2378    '-DDISPLAYVERSION=' + meson.project_version(),
2379  ]
2380  if build_docs
2381    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
2382  endif
2383  if gtk.found()
2384    nsis_cmd += '-DCONFIG_GTK=y'
2385  endif
2386
2387  nsis = custom_target('nsis',
2388                       output: 'qemu-setup-' + meson.project_version() + '.exe',
2389                       input: files('qemu.nsi'),
2390                       build_always_stale: true,
2391                       command: nsis_cmd + ['@INPUT@'])
2392  alias_target('installer', nsis)
2393endif
2394
2395#########################
2396# Configuration summary #
2397#########################
2398
2399# Directories
2400summary_info = {}
2401summary_info += {'Install prefix':    get_option('prefix')}
2402summary_info += {'BIOS directory':    qemu_datadir}
2403summary_info += {'firmware path':     get_option('qemu_firmwarepath')}
2404summary_info += {'binary directory':  get_option('bindir')}
2405summary_info += {'library directory': get_option('libdir')}
2406summary_info += {'module directory':  qemu_moddir}
2407summary_info += {'libexec directory': get_option('libexecdir')}
2408summary_info += {'include directory': get_option('includedir')}
2409summary_info += {'config directory':  get_option('sysconfdir')}
2410if targetos != 'windows'
2411  summary_info += {'local state directory': get_option('localstatedir')}
2412  summary_info += {'Manual directory':      get_option('mandir')}
2413else
2414  summary_info += {'local state directory': 'queried at runtime'}
2415endif
2416summary_info += {'Doc directory':     get_option('docdir')}
2417summary_info += {'Build directory':   meson.current_build_dir()}
2418summary_info += {'Source path':       meson.current_source_dir()}
2419summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
2420summary(summary_info, bool_yn: true, section: 'Directories')
2421
2422# Host binaries
2423summary_info = {}
2424summary_info += {'git':               config_host['GIT']}
2425summary_info += {'make':              config_host['MAKE']}
2426summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
2427summary_info += {'sphinx-build':      sphinx_build.found()}
2428if config_host.has_key('HAVE_GDB_BIN')
2429  summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
2430endif
2431summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
2432if targetos == 'windows' and config_host.has_key('CONFIG_GUEST_AGENT')
2433  summary_info += {'wixl':            wixl.found() ? wixl.full_path() : false}
2434endif
2435if slirp_opt != 'disabled'
2436  summary_info += {'smbd':            config_host['CONFIG_SMBD_COMMAND']}
2437endif
2438summary(summary_info, bool_yn: true, section: 'Host binaries')
2439
2440# Configurable features
2441summary_info = {}
2442summary_info += {'Documentation':     build_docs}
2443summary_info += {'system-mode emulation': have_system}
2444summary_info += {'user-mode emulation': have_user}
2445summary_info += {'block layer':       have_block}
2446summary_info += {'Install blobs':     get_option('install_blobs')}
2447summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
2448if config_host.has_key('CONFIG_MODULES')
2449  summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')}
2450endif
2451summary_info += {'plugin support':    config_host.has_key('CONFIG_PLUGIN')}
2452summary_info += {'fuzzing support':   config_host.has_key('CONFIG_FUZZ')}
2453if have_system
2454  summary_info += {'Audio drivers':     config_host['CONFIG_AUDIO_DRIVERS']}
2455endif
2456summary_info += {'Trace backends':    config_host['TRACE_BACKENDS']}
2457if config_host['TRACE_BACKENDS'].split().contains('simple')
2458  summary_info += {'Trace output file': config_host['CONFIG_TRACE_FILE'] + '-<pid>'}
2459endif
2460summary_info += {'QOM debugging':     config_host.has_key('CONFIG_QOM_CAST_DEBUG')}
2461summary_info += {'vhost-kernel support': config_host.has_key('CONFIG_VHOST_KERNEL')}
2462summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')}
2463summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')}
2464summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')}
2465summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')}
2466summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_USER')}
2467summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
2468summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')}
2469summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')}
2470summary_info += {'build guest agent': config_host.has_key('CONFIG_GUEST_AGENT')}
2471summary(summary_info, bool_yn: true, section: 'Configurable features')
2472
2473# Compilation information
2474summary_info = {}
2475summary_info += {'host CPU':          cpu}
2476summary_info += {'host endianness':   build_machine.endian()}
2477summary_info += {'C compiler':        meson.get_compiler('c').cmd_array()[0]}
2478summary_info += {'Host C compiler':   meson.get_compiler('c', native: true).cmd_array()[0]}
2479if link_language == 'cpp'
2480  summary_info += {'C++ compiler':      meson.get_compiler('cpp').cmd_array()[0]}
2481else
2482  summary_info += {'C++ compiler':      false}
2483endif
2484if targetos == 'darwin'
2485  summary_info += {'Objective-C compiler': meson.get_compiler('objc').cmd_array()[0]}
2486endif
2487if targetos == 'windows'
2488  if 'WIN_SDK' in config_host
2489    summary_info += {'Windows SDK':   config_host['WIN_SDK']}
2490  endif
2491endif
2492summary_info += {'ARFLAGS':           config_host['ARFLAGS']}
2493summary_info += {'CFLAGS':            ' '.join(get_option('c_args')
2494                                               + ['-O' + get_option('optimization')]
2495                                               + (get_option('debug') ? ['-g'] : []))}
2496if link_language == 'cpp'
2497  summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args')
2498                                               + ['-O' + get_option('optimization')]
2499                                               + (get_option('debug') ? ['-g'] : []))}
2500endif
2501link_args = get_option(link_language + '_link_args')
2502if link_args.length() > 0
2503  summary_info += {'LDFLAGS':         ' '.join(link_args)}
2504endif
2505summary_info += {'QEMU_CFLAGS':       config_host['QEMU_CFLAGS']}
2506summary_info += {'QEMU_LDFLAGS':      config_host['QEMU_LDFLAGS']}
2507summary_info += {'profiler':          config_host.has_key('CONFIG_PROFILER')}
2508summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
2509summary_info += {'PIE':               get_option('b_pie')}
2510summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
2511summary_info += {'malloc trim support': has_malloc_trim}
2512summary_info += {'membarrier':        config_host.has_key('CONFIG_MEMBARRIER')}
2513summary_info += {'preadv support':    config_host_data.get('CONFIG_PREADV')}
2514summary_info += {'fdatasync':         config_host.has_key('CONFIG_FDATASYNC')}
2515summary_info += {'madvise':           config_host.has_key('CONFIG_MADVISE')}
2516summary_info += {'posix_madvise':     config_host.has_key('CONFIG_POSIX_MADVISE')}
2517summary_info += {'posix_memalign':    config_host.has_key('CONFIG_POSIX_MEMALIGN')}
2518summary_info += {'debug stack usage': config_host.has_key('CONFIG_DEBUG_STACK_USAGE')}
2519summary_info += {'mutex debugging':   config_host.has_key('CONFIG_DEBUG_MUTEX')}
2520summary_info += {'memory allocator':  get_option('malloc')}
2521summary_info += {'avx2 optimization': config_host.has_key('CONFIG_AVX2_OPT')}
2522summary_info += {'avx512f optimization': config_host.has_key('CONFIG_AVX512F_OPT')}
2523summary_info += {'gprof enabled':     config_host.has_key('CONFIG_GPROF')}
2524summary_info += {'gcov':              get_option('b_coverage')}
2525summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
2526summary_info += {'CFI support':       get_option('cfi')}
2527if get_option('cfi')
2528  summary_info += {'CFI debug support': get_option('cfi_debug')}
2529endif
2530summary_info += {'strip binaries':    get_option('strip')}
2531summary_info += {'sparse':            sparse.found() ? sparse.full_path() : false}
2532summary_info += {'mingw32 support':   targetos == 'windows'}
2533
2534# snarf the cross-compilation information for tests
2535foreach target: target_dirs
2536  tcg_mak = meson.current_build_dir() / 'tests/tcg' / 'config-' + target + '.mak'
2537  if fs.exists(tcg_mak)
2538    config_cross_tcg = keyval.load(tcg_mak)
2539    target = config_cross_tcg['TARGET_NAME']
2540    compiler = ''
2541    if 'DOCKER_CROSS_CC_GUEST' in config_cross_tcg
2542      summary_info += {target + ' tests': config_cross_tcg['DOCKER_CROSS_CC_GUEST'] +
2543                                          ' via ' + config_cross_tcg['DOCKER_IMAGE']}
2544    elif 'CROSS_CC_GUEST' in config_cross_tcg
2545      summary_info += {target + ' tests'
2546                                : config_cross_tcg['CROSS_CC_GUEST'] }
2547    endif
2548   endif
2549endforeach
2550
2551summary(summary_info, bool_yn: true, section: 'Compilation')
2552
2553# Targets and accelerators
2554summary_info = {}
2555if have_system
2556  summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
2557  summary_info += {'HAX support':       config_all.has_key('CONFIG_HAX')}
2558  summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
2559  summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
2560  summary_info += {'Xen support':       config_host.has_key('CONFIG_XEN_BACKEND')}
2561  if config_host.has_key('CONFIG_XEN_BACKEND')
2562    summary_info += {'xen ctrl version':  config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
2563  endif
2564endif
2565summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
2566if config_all.has_key('CONFIG_TCG')
2567  if get_option('tcg_interpreter')
2568    summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, experimental and slow)'}
2569  else
2570    summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
2571  endif
2572  summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
2573endif
2574summary_info += {'target list':       ' '.join(target_dirs)}
2575if have_system
2576  summary_info += {'default devices':   get_option('default_devices')}
2577  summary_info += {'out of process emulation': multiprocess_allowed}
2578endif
2579summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
2580
2581# Block layer
2582summary_info = {}
2583summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
2584summary_info += {'coroutine pool':    config_host['CONFIG_COROUTINE_POOL'] == '1'}
2585if have_block
2586  summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']}
2587  summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']}
2588  summary_info += {'VirtFS support':    have_virtfs}
2589  summary_info += {'build virtiofs daemon': have_virtiofsd}
2590  summary_info += {'Live block migration': config_host.has_key('CONFIG_LIVE_BLOCK_MIGRATION')}
2591  summary_info += {'replication support': config_host.has_key('CONFIG_REPLICATION')}
2592  summary_info += {'bochs support':     config_host.has_key('CONFIG_BOCHS')}
2593  summary_info += {'cloop support':     config_host.has_key('CONFIG_CLOOP')}
2594  summary_info += {'dmg support':       config_host.has_key('CONFIG_DMG')}
2595  summary_info += {'qcow v1 support':   config_host.has_key('CONFIG_QCOW1')}
2596  summary_info += {'vdi support':       config_host.has_key('CONFIG_VDI')}
2597  summary_info += {'vvfat support':     config_host.has_key('CONFIG_VVFAT')}
2598  summary_info += {'qed support':       config_host.has_key('CONFIG_QED')}
2599  summary_info += {'parallels support': config_host.has_key('CONFIG_PARALLELS')}
2600  summary_info += {'sheepdog support':  config_host.has_key('CONFIG_SHEEPDOG')}
2601  summary_info += {'FUSE exports':      fuse.found()}
2602endif
2603summary(summary_info, bool_yn: true, section: 'Block layer support')
2604
2605# Crypto
2606summary_info = {}
2607summary_info += {'TLS priority':      config_host['CONFIG_TLS_PRIORITY']}
2608summary_info += {'GNUTLS support':    config_host.has_key('CONFIG_GNUTLS')}
2609# TODO: add back version
2610summary_info += {'libgcrypt':         config_host.has_key('CONFIG_GCRYPT')}
2611if config_host.has_key('CONFIG_GCRYPT')
2612   summary_info += {'  hmac':            config_host.has_key('CONFIG_GCRYPT_HMAC')}
2613   summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
2614endif
2615# TODO: add back version
2616summary_info += {'nettle':            config_host.has_key('CONFIG_NETTLE')}
2617if config_host.has_key('CONFIG_NETTLE')
2618   summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
2619endif
2620summary_info += {'crypto afalg':      config_host.has_key('CONFIG_AF_ALG')}
2621summary_info += {'rng-none':          config_host.has_key('CONFIG_RNG_NONE')}
2622summary_info += {'Linux keyring':     config_host.has_key('CONFIG_SECRET_KEYRING')}
2623summary(summary_info, bool_yn: true, section: 'Crypto')
2624
2625# Libraries
2626summary_info = {}
2627if targetos == 'darwin'
2628  summary_info += {'Cocoa support':   cocoa.found()}
2629endif
2630# TODO: add back version
2631summary_info += {'SDL support':       sdl.found()}
2632summary_info += {'SDL image support': sdl_image.found()}
2633# TODO: add back version
2634summary_info += {'GTK support':       gtk.found()}
2635summary_info += {'pixman':            pixman.found()}
2636# TODO: add back version
2637summary_info += {'VTE support':       config_host.has_key('CONFIG_VTE')}
2638# TODO: add back version
2639summary_info += {'slirp support':     slirp_opt == 'disabled' ? false : slirp_opt}
2640summary_info += {'libtasn1':          config_host.has_key('CONFIG_TASN1')}
2641summary_info += {'PAM':               config_host.has_key('CONFIG_AUTH_PAM')}
2642summary_info += {'iconv support':     iconv.found()}
2643summary_info += {'curses support':    curses.found()}
2644# TODO: add back version
2645summary_info += {'virgl support':     config_host.has_key('CONFIG_VIRGL')}
2646summary_info += {'curl support':      curl.found()}
2647summary_info += {'Multipath support': mpathpersist.found()}
2648summary_info += {'VNC support':       vnc.found()}
2649if vnc.found()
2650  summary_info += {'VNC SASL support':  sasl.found()}
2651  summary_info += {'VNC JPEG support':  jpeg.found()}
2652  summary_info += {'VNC PNG support':   png.found()}
2653endif
2654summary_info += {'brlapi support':    brlapi.found()}
2655summary_info += {'vde support':       config_host.has_key('CONFIG_VDE')}
2656summary_info += {'netmap support':    config_host.has_key('CONFIG_NETMAP')}
2657summary_info += {'Linux AIO support': config_host.has_key('CONFIG_LINUX_AIO')}
2658summary_info += {'Linux io_uring support': config_host.has_key('CONFIG_LINUX_IO_URING')}
2659summary_info += {'ATTR/XATTR support': libattr.found()}
2660summary_info += {'RDMA support':      config_host.has_key('CONFIG_RDMA')}
2661summary_info += {'PVRDMA support':    config_host.has_key('CONFIG_PVRDMA')}
2662summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
2663summary_info += {'libcap-ng support': libcap_ng.found()}
2664# TODO: add back protocol and server version
2665summary_info += {'spice support':     config_host.has_key('CONFIG_SPICE')}
2666summary_info += {'rbd support':       rbd.found()}
2667summary_info += {'xfsctl support':    config_host.has_key('CONFIG_XFS')}
2668summary_info += {'smartcard support': config_host.has_key('CONFIG_SMARTCARD')}
2669summary_info += {'U2F support':       u2f.found()}
2670summary_info += {'libusb':            config_host.has_key('CONFIG_USB_LIBUSB')}
2671summary_info += {'usb net redir':     config_host.has_key('CONFIG_USB_REDIR')}
2672summary_info += {'OpenGL support':    config_host.has_key('CONFIG_OPENGL')}
2673summary_info += {'GBM':               config_host.has_key('CONFIG_GBM')}
2674summary_info += {'libiscsi support':  libiscsi.found()}
2675summary_info += {'libnfs support':    libnfs.found()}
2676if targetos == 'windows'
2677  if config_host.has_key('CONFIG_GUEST_AGENT')
2678    summary_info += {'QGA VSS support':   config_host.has_key('CONFIG_QGA_VSS')}
2679    summary_info += {'QGA w32 disk info': config_host.has_key('CONFIG_QGA_NTDDSCSI')}
2680  endif
2681endif
2682summary_info += {'seccomp support':   seccomp.found()}
2683summary_info += {'GlusterFS support': glusterfs.found()}
2684summary_info += {'TPM support':       config_host.has_key('CONFIG_TPM')}
2685summary_info += {'libssh support':    config_host.has_key('CONFIG_LIBSSH')}
2686summary_info += {'lzo support':       lzo.found()}
2687summary_info += {'snappy support':    snappy.found()}
2688summary_info += {'bzip2 support':     libbzip2.found()}
2689summary_info += {'lzfse support':     liblzfse.found()}
2690summary_info += {'zstd support':      zstd.found()}
2691summary_info += {'NUMA host support': config_host.has_key('CONFIG_NUMA')}
2692summary_info += {'libxml2':           config_host.has_key('CONFIG_LIBXML2')}
2693summary_info += {'capstone':          capstone_opt == 'disabled' ? false : capstone_opt}
2694summary_info += {'libpmem support':   config_host.has_key('CONFIG_LIBPMEM')}
2695summary_info += {'libdaxctl support': config_host.has_key('CONFIG_LIBDAXCTL')}
2696summary_info += {'libudev':           libudev.found()}
2697summary_info += {'FUSE lseek':        fuse_lseek.found()}
2698summary(summary_info, bool_yn: true, section: 'Dependencies')
2699
2700if not supported_cpus.contains(cpu)
2701  message()
2702  warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
2703  message()
2704  message('CPU host architecture ' + cpu + ' support is not currently maintained.')
2705  message('The QEMU project intends to remove support for this host CPU in')
2706  message('a future release if nobody volunteers to maintain it and to')
2707  message('provide a build host for our continuous integration setup.')
2708  message('configure has succeeded and you can continue to build, but')
2709  message('if you care about QEMU on this platform you should contact')
2710  message('us upstream at qemu-devel@nongnu.org.')
2711endif
2712
2713if not supported_oses.contains(targetos)
2714  message()
2715  warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
2716  message()
2717  message('Host OS ' + targetos + 'support is not currently maintained.')
2718  message('The QEMU project intends to remove support for this host OS in')
2719  message('a future release if nobody volunteers to maintain it and to')
2720  message('provide a build host for our continuous integration setup.')
2721  message('configure has succeeded and you can continue to build, but')
2722  message('if you care about QEMU on this platform you should contact')
2723  message('us upstream at qemu-devel@nongnu.org.')
2724endif
2725