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