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