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