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