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