xref: /openbmc/qemu/meson.build (revision e28ab096bf897310fc7a37fdc087e66a24e6e977)
1project('qemu', ['c'], meson_version: '>=0.55.0',
2        default_options: ['warning_level=1', 'c_std=gnu99', 'cpp_std=gnu++11',
3                          'b_colorout=auto'],
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
20build_docs = 'BUILD_DOCS' in config_host
21
22if get_option('qemu_suffix').startswith('/')
23  error('qemu_suffix cannot start with a /')
24endif
25
26qemu_datadir = get_option('datadir') / get_option('qemu_suffix')
27qemu_docdir = get_option('docdir') / get_option('qemu_suffix')
28config_host_data = configuration_data()
29genh = []
30
31target_dirs = config_host['TARGET_DIRS'].split()
32have_user = false
33have_system = false
34foreach target : target_dirs
35  have_user = have_user or target.endswith('-user')
36  have_system = have_system or target.endswith('-softmmu')
37endforeach
38have_tools = 'CONFIG_TOOLS' in config_host
39have_block = have_system or have_tools
40
41python = import('python').find_installation()
42
43supported_oses = ['windows', 'freebsd', 'netbsd', 'openbsd', 'darwin', 'sunos', 'linux']
44supported_cpus = ['ppc', 'ppc64', 's390x', 'sparc64', 'riscv32', 'riscv64', 'x86', 'x86_64',
45  'arm', 'aarch64', 'mips', 'mips64', 'sparc', 'sparc64']
46
47cpu = host_machine.cpu_family()
48targetos = host_machine.system()
49
50configure_file(input: files('scripts/ninjatool.py'),
51               output: 'ninjatool',
52               configuration: config_host)
53
54if cpu in ['x86', 'x86_64']
55  kvm_targets = ['i386-softmmu', 'x86_64-softmmu']
56elif cpu == 'aarch64'
57  kvm_targets = ['aarch64-softmmu']
58elif cpu == 's390x'
59  kvm_targets = ['s390x-softmmu']
60elif cpu in ['ppc', 'ppc64']
61  kvm_targets = ['ppc-softmmu', 'ppc64-softmmu']
62else
63  kvm_targets = []
64endif
65
66accelerator_targets = { 'CONFIG_KVM': kvm_targets }
67if cpu in ['x86', 'x86_64']
68  accelerator_targets += {
69    'CONFIG_HAX': ['i386-softmmu', 'x86_64-softmmu'],
70    'CONFIG_XEN': ['i386-softmmu', 'x86_64-softmmu'],
71    'CONFIG_HVF': ['x86_64-softmmu'],
72    'CONFIG_WHPX': ['i386-softmmu', 'x86_64-softmmu'],
73  }
74endif
75
76##################
77# Compiler flags #
78##################
79
80# Specify linker-script with add_project_link_arguments so that it is not placed
81# within a linker --start-group/--end-group pair
82if 'CONFIG_FUZZ' in config_host
83   add_project_link_arguments(['-Wl,-T,',
84                               (meson.current_source_dir() / 'tests/qtest/fuzz/fork_fuzz.ld')],
85                              native: false, language: ['c', 'cpp', 'objc'])
86endif
87
88add_project_arguments(config_host['QEMU_CFLAGS'].split(),
89                      native: false, language: ['c', 'objc'])
90add_project_arguments(config_host['QEMU_CXXFLAGS'].split(),
91                      native: false, language: 'cpp')
92add_project_link_arguments(config_host['QEMU_LDFLAGS'].split(),
93                           native: false, language: ['c', 'cpp', 'objc'])
94add_project_arguments(config_host['QEMU_INCLUDES'].split(),
95                      language: ['c', 'cpp', 'objc'])
96
97
98link_language = meson.get_external_property('link_language', 'cpp')
99if link_language == 'cpp'
100  add_languages('cpp', required: true, native: false)
101endif
102if host_machine.system() == 'darwin'
103  add_languages('objc', required: false, native: false)
104endif
105
106sparse = find_program('cgcc', required: get_option('sparse'))
107if sparse.found()
108  run_target('sparse',
109             command: [find_program('scripts/check_sparse.py'),
110                       'compile_commands.json', sparse.full_path(), '-Wbitwise',
111                       '-Wno-transparent-union', '-Wno-old-initializer',
112                       '-Wno-non-pointer-null'])
113endif
114
115###########################################
116# Target-specific checks and dependencies #
117###########################################
118
119if targetos != 'linux' and get_option('mpath').enabled()
120  error('Multipath is supported only on Linux')
121endif
122
123m = cc.find_library('m', required: false)
124util = cc.find_library('util', required: false)
125winmm = []
126socket = []
127version_res = []
128coref = []
129iokit = []
130emulator_link_args = []
131cocoa = not_found
132hvf = not_found
133if targetos == 'windows'
134  socket = cc.find_library('ws2_32')
135  winmm = cc.find_library('winmm')
136
137  win = import('windows')
138  version_res = win.compile_resources('version.rc',
139                                      depend_files: files('pc-bios/qemu-nsis.ico'),
140                                      include_directories: include_directories('.'))
141elif targetos == 'darwin'
142  coref = dependency('appleframeworks', modules: 'CoreFoundation')
143  iokit = dependency('appleframeworks', modules: 'IOKit')
144  cocoa = dependency('appleframeworks', modules: 'Cocoa', required: get_option('cocoa'))
145elif targetos == 'sunos'
146  socket = [cc.find_library('socket'),
147            cc.find_library('nsl'),
148            cc.find_library('resolv')]
149elif targetos == 'haiku'
150  socket = [cc.find_library('posix_error_mapper'),
151            cc.find_library('network'),
152            cc.find_library('bsd')]
153elif targetos == 'openbsd'
154  if not get_option('tcg').disabled() and target_dirs.length() > 0
155    # Disable OpenBSD W^X if available
156    emulator_link_args = cc.get_supported_link_arguments('-Wl,-z,wxneeded')
157  endif
158endif
159
160accelerators = []
161if not get_option('kvm').disabled() and targetos == 'linux'
162  accelerators += 'CONFIG_KVM'
163endif
164if not get_option('xen').disabled() and 'CONFIG_XEN_BACKEND' in config_host
165  accelerators += 'CONFIG_XEN'
166  have_xen_pci_passthrough = not get_option('xen_pci_passthrough').disabled() and targetos == 'linux'
167else
168  have_xen_pci_passthrough = false
169endif
170if not get_option('whpx').disabled() and targetos == 'windows'
171  if get_option('whpx').enabled() and cpu != 'x86_64'
172    error('WHPX requires 64-bit host')
173  elif cc.has_header('WinHvPlatform.h', required: get_option('whpx')) and \
174       cc.has_header('WinHvEmulation.h', required: get_option('whpx'))
175    accelerators += 'CONFIG_WHPX'
176  endif
177endif
178if not get_option('hvf').disabled()
179  hvf = dependency('appleframeworks', modules: 'Hypervisor',
180                   required: get_option('hvf'))
181  if hvf.found()
182    accelerators += 'CONFIG_HVF'
183  endif
184endif
185if not get_option('hax').disabled()
186  if get_option('hax').enabled() or targetos in ['windows', 'darwin', 'netbsd']
187    accelerators += 'CONFIG_HAX'
188  endif
189endif
190if not get_option('tcg').disabled()
191  if cpu not in supported_cpus
192    if 'CONFIG_TCG_INTERPRETER' in config_host
193      warning('Unsupported CPU @0@, will use TCG with TCI (experimental)'.format(cpu))
194    else
195      error('Unsupported CPU @0@, try --enable-tcg-interpreter'.format(cpu))
196    endif
197  endif
198  accelerators += 'CONFIG_TCG'
199  config_host += { 'CONFIG_TCG': 'y' }
200endif
201
202if 'CONFIG_KVM' not in accelerators and get_option('kvm').enabled()
203  error('KVM not available on this platform')
204endif
205if 'CONFIG_HVF' not in accelerators and get_option('hvf').enabled()
206  error('HVF not available on this platform')
207endif
208if 'CONFIG_WHPX' not in accelerators and get_option('whpx').enabled()
209  error('WHPX not available on this platform')
210endif
211if not have_xen_pci_passthrough and get_option('xen_pci_passthrough').enabled()
212  if 'CONFIG_XEN' in accelerators
213    error('Xen PCI passthrough not available on this platform')
214  else
215    error('Xen PCI passthrough requested but Xen not enabled')
216  endif
217endif
218if not cocoa.found() and get_option('cocoa').enabled()
219  error('Cocoa not available on this platform')
220endif
221
222################
223# Dependencies #
224################
225
226# The path to glib.h is added to all compilation commands.  This was
227# grandfathered in from the QEMU Makefiles.
228add_project_arguments(config_host['GLIB_CFLAGS'].split(),
229                      native: false, language: ['c', 'cpp', 'objc'])
230glib = declare_dependency(link_args: config_host['GLIB_LIBS'].split())
231gio = not_found
232if 'CONFIG_GIO' in config_host
233  gio = declare_dependency(compile_args: config_host['GIO_CFLAGS'].split(),
234                           link_args: config_host['GIO_LIBS'].split())
235endif
236lttng = not_found
237if 'CONFIG_TRACE_UST' in config_host
238  lttng = declare_dependency(link_args: config_host['LTTNG_UST_LIBS'].split())
239endif
240urcubp = not_found
241if 'CONFIG_TRACE_UST' in config_host
242  urcubp = declare_dependency(link_args: config_host['URCU_BP_LIBS'].split())
243endif
244gcrypt = not_found
245if 'CONFIG_GCRYPT' in config_host
246  gcrypt = declare_dependency(compile_args: config_host['GCRYPT_CFLAGS'].split(),
247                              link_args: config_host['GCRYPT_LIBS'].split())
248endif
249nettle = not_found
250if 'CONFIG_NETTLE' in config_host
251  nettle = declare_dependency(compile_args: config_host['NETTLE_CFLAGS'].split(),
252                              link_args: config_host['NETTLE_LIBS'].split())
253endif
254gnutls = not_found
255if 'CONFIG_GNUTLS' in config_host
256  gnutls = declare_dependency(compile_args: config_host['GNUTLS_CFLAGS'].split(),
257                              link_args: config_host['GNUTLS_LIBS'].split())
258endif
259pixman = not_found
260if have_system or have_tools
261  pixman = dependency('pixman-1', required: have_system, version:'>=0.21.8',
262                      method: 'pkg-config', static: enable_static)
263endif
264pam = not_found
265if 'CONFIG_AUTH_PAM' in config_host
266  pam = cc.find_library('pam')
267endif
268libaio = cc.find_library('aio', required: false)
269zlib = dependency('zlib', required: true, static: enable_static)
270linux_io_uring = not_found
271if 'CONFIG_LINUX_IO_URING' in config_host
272  linux_io_uring = declare_dependency(compile_args: config_host['LINUX_IO_URING_CFLAGS'].split(),
273                                      link_args: config_host['LINUX_IO_URING_LIBS'].split())
274endif
275libxml2 = not_found
276if 'CONFIG_LIBXML2' in config_host
277  libxml2 = declare_dependency(compile_args: config_host['LIBXML2_CFLAGS'].split(),
278                               link_args: config_host['LIBXML2_LIBS'].split())
279endif
280libnfs = not_found
281if 'CONFIG_LIBNFS' in config_host
282  libnfs = declare_dependency(link_args: config_host['LIBNFS_LIBS'].split())
283endif
284libattr = not_found
285if 'CONFIG_ATTR' in config_host
286  libattr = declare_dependency(link_args: config_host['LIBATTR_LIBS'].split())
287endif
288seccomp = not_found
289if 'CONFIG_SECCOMP' in config_host
290  seccomp = declare_dependency(compile_args: config_host['SECCOMP_CFLAGS'].split(),
291                               link_args: config_host['SECCOMP_LIBS'].split())
292endif
293libcap_ng = not_found
294if 'CONFIG_LIBCAP_NG' in config_host
295  libcap_ng = declare_dependency(link_args: config_host['LIBCAP_NG_LIBS'].split())
296endif
297if get_option('xkbcommon').auto() and not have_system and not have_tools
298  xkbcommon = not_found
299else
300  xkbcommon = dependency('xkbcommon', required: get_option('xkbcommon'),
301                         method: 'pkg-config', static: enable_static)
302endif
303vde = not_found
304if config_host.has_key('CONFIG_VDE')
305  vde = declare_dependency(link_args: config_host['VDE_LIBS'].split())
306endif
307pulse = not_found
308if 'CONFIG_LIBPULSE' in config_host
309  pulse = declare_dependency(compile_args: config_host['PULSE_CFLAGS'].split(),
310                             link_args: config_host['PULSE_LIBS'].split())
311endif
312alsa = not_found
313if 'CONFIG_ALSA' in config_host
314  alsa = declare_dependency(compile_args: config_host['ALSA_CFLAGS'].split(),
315                            link_args: config_host['ALSA_LIBS'].split())
316endif
317jack = not_found
318if 'CONFIG_LIBJACK' in config_host
319  jack = declare_dependency(link_args: config_host['JACK_LIBS'].split())
320endif
321spice = not_found
322if 'CONFIG_SPICE' in config_host
323  spice = declare_dependency(compile_args: config_host['SPICE_CFLAGS'].split(),
324                             link_args: config_host['SPICE_LIBS'].split())
325endif
326rt = cc.find_library('rt', required: false)
327libdl = not_found
328if 'CONFIG_PLUGIN' in config_host
329  libdl = cc.find_library('dl', required: true)
330endif
331libiscsi = not_found
332if 'CONFIG_LIBISCSI' in config_host
333  libiscsi = declare_dependency(compile_args: config_host['LIBISCSI_CFLAGS'].split(),
334                                link_args: config_host['LIBISCSI_LIBS'].split())
335endif
336zstd = not_found
337if 'CONFIG_ZSTD' in config_host
338  zstd = declare_dependency(compile_args: config_host['ZSTD_CFLAGS'].split(),
339                            link_args: config_host['ZSTD_LIBS'].split())
340endif
341gbm = not_found
342if 'CONFIG_GBM' in config_host
343  gbm = declare_dependency(compile_args: config_host['GBM_CFLAGS'].split(),
344                           link_args: config_host['GBM_LIBS'].split())
345endif
346virgl = not_found
347if 'CONFIG_VIRGL' in config_host
348  virgl = declare_dependency(compile_args: config_host['VIRGL_CFLAGS'].split(),
349                             link_args: config_host['VIRGL_LIBS'].split())
350endif
351curl = not_found
352if 'CONFIG_CURL' in config_host
353  curl = declare_dependency(compile_args: config_host['CURL_CFLAGS'].split(),
354                            link_args: config_host['CURL_LIBS'].split())
355endif
356libudev = not_found
357if targetos == 'linux' and (have_system or have_tools)
358  libudev = dependency('libudev',
359                       required: get_option('mpath').enabled(),
360                       static: enable_static)
361endif
362
363mpathpersist = not_found
364mpathpersist_new_api = false
365if targetos == 'linux' and have_tools and not get_option('mpath').disabled()
366  mpath_test_source_new = '''
367    #include <libudev.h>
368    #include <mpath_persist.h>
369    unsigned mpath_mx_alloc_len = 1024;
370    int logsink;
371    static struct config *multipath_conf;
372    extern struct udev *udev;
373    extern struct config *get_multipath_config(void);
374    extern void put_multipath_config(struct config *conf);
375    struct udev *udev;
376    struct config *get_multipath_config(void) { return multipath_conf; }
377    void put_multipath_config(struct config *conf) { }
378    int main(void) {
379        udev = udev_new();
380        multipath_conf = mpath_lib_init();
381        return 0;
382    }'''
383  mpath_test_source_old = '''
384      #include <libudev.h>
385      #include <mpath_persist.h>
386      unsigned mpath_mx_alloc_len = 1024;
387      int logsink;
388      int main(void) {
389          struct udev *udev = udev_new();
390          mpath_lib_init(udev);
391          return 0;
392      }'''
393  mpathlibs = [libudev]
394  if enable_static
395    mpathlibs += cc.find_library('devmapper',
396                                   required: get_option('mpath'),
397                                   static: enable_static)
398  endif
399  mpathlibs += cc.find_library('multipath',
400                               required: get_option('mpath'),
401                               static: enable_static)
402  mpathlibs += cc.find_library('mpathpersist',
403                               required: get_option('mpath'),
404                               static: enable_static)
405  foreach lib: mpathlibs
406    if not lib.found()
407      mpathlibs = []
408      break
409    endif
410  endforeach
411  if mpathlibs.length() > 0
412    if cc.links(mpath_test_source_new, dependencies: mpathlibs)
413      mpathpersist = declare_dependency(dependencies: mpathlibs)
414      mpathpersist_new_api = true
415    elif cc.links(mpath_test_source_old, dependencies: mpathlibs)
416      mpathpersist = declare_dependency(dependencies: mpathlibs)
417    else
418      if get_option('mpath').enabled()
419        error('Cannot detect libmpathpersist API')
420      else
421        warning('Cannot detect libmpathpersist API, disabling')
422      endif
423    endif
424  endif
425endif
426
427brlapi = not_found
428if 'CONFIG_BRLAPI' in config_host
429  brlapi = declare_dependency(link_args: config_host['BRLAPI_LIBS'].split())
430endif
431
432sdl = not_found
433if have_system
434  sdl = dependency('sdl2', required: get_option('sdl'), static: enable_static)
435  sdl_image = not_found
436endif
437if sdl.found()
438  # work around 2.0.8 bug
439  sdl = declare_dependency(compile_args: '-Wno-undef',
440                           dependencies: sdl)
441  sdl_image = dependency('SDL2_image', required: get_option('sdl_image'),
442                         method: 'pkg-config', static: enable_static)
443else
444  if get_option('sdl_image').enabled()
445    error('sdl-image required, but SDL was @0@'.format(
446          get_option('sdl').disabled() ? 'disabled' : 'not found'))
447  endif
448  sdl_image = not_found
449endif
450
451rbd = not_found
452if 'CONFIG_RBD' in config_host
453  rbd = declare_dependency(link_args: config_host['RBD_LIBS'].split())
454endif
455glusterfs = not_found
456if 'CONFIG_GLUSTERFS' in config_host
457  glusterfs = declare_dependency(compile_args: config_host['GLUSTERFS_CFLAGS'].split(),
458                                 link_args: config_host['GLUSTERFS_LIBS'].split())
459endif
460libssh = not_found
461if 'CONFIG_LIBSSH' in config_host
462  libssh = declare_dependency(compile_args: config_host['LIBSSH_CFLAGS'].split(),
463                              link_args: config_host['LIBSSH_LIBS'].split())
464endif
465libbzip2 = not_found
466if 'CONFIG_BZIP2' in config_host
467  libbzip2 = declare_dependency(link_args: config_host['BZIP2_LIBS'].split())
468endif
469liblzfse = not_found
470if 'CONFIG_LZFSE' in config_host
471  liblzfse = declare_dependency(link_args: config_host['LZFSE_LIBS'].split())
472endif
473oss = not_found
474if 'CONFIG_AUDIO_OSS' in config_host
475  oss = declare_dependency(link_args: config_host['OSS_LIBS'].split())
476endif
477dsound = not_found
478if 'CONFIG_AUDIO_DSOUND' in config_host
479  dsound = declare_dependency(link_args: config_host['DSOUND_LIBS'].split())
480endif
481coreaudio = not_found
482if 'CONFIG_AUDIO_COREAUDIO' in config_host
483  coreaudio = declare_dependency(link_args: config_host['COREAUDIO_LIBS'].split())
484endif
485opengl = not_found
486if 'CONFIG_OPENGL' in config_host
487  opengl = declare_dependency(compile_args: config_host['OPENGL_CFLAGS'].split(),
488                              link_args: config_host['OPENGL_LIBS'].split())
489endif
490gtk = not_found
491if 'CONFIG_GTK' in config_host
492  gtk = declare_dependency(compile_args: config_host['GTK_CFLAGS'].split(),
493                              link_args: config_host['GTK_LIBS'].split())
494endif
495vte = not_found
496if 'CONFIG_VTE' in config_host
497  vte = declare_dependency(compile_args: config_host['VTE_CFLAGS'].split(),
498                           link_args: config_host['VTE_LIBS'].split())
499endif
500x11 = not_found
501if 'CONFIG_X11' in config_host
502  x11 = declare_dependency(compile_args: config_host['X11_CFLAGS'].split(),
503                           link_args: config_host['X11_LIBS'].split())
504endif
505curses = not_found
506if 'CONFIG_CURSES' in config_host
507  curses = declare_dependency(compile_args: config_host['CURSES_CFLAGS'].split(),
508                              link_args: config_host['CURSES_LIBS'].split())
509endif
510iconv = not_found
511if 'CONFIG_ICONV' in config_host
512  iconv = declare_dependency(compile_args: config_host['ICONV_CFLAGS'].split(),
513                             link_args: config_host['ICONV_LIBS'].split())
514endif
515vnc = not_found
516png = not_found
517jpeg = not_found
518sasl = not_found
519if get_option('vnc').enabled()
520  vnc = declare_dependency() # dummy dependency
521  png = dependency('libpng', required: get_option('vnc_png'),
522                   method: 'pkg-config', static: enable_static)
523  jpeg = cc.find_library('jpeg', has_headers: ['jpeglib.h'],
524                         required: get_option('vnc_jpeg'),
525                         static: enable_static)
526  sasl = cc.find_library('sasl2', has_headers: ['sasl/sasl.h'],
527                         required: get_option('vnc_sasl'),
528                         static: enable_static)
529  if sasl.found()
530    sasl = declare_dependency(dependencies: sasl,
531                              compile_args: '-DSTRUCT_IOVEC_DEFINED')
532  endif
533endif
534snappy = not_found
535if 'CONFIG_SNAPPY' in config_host
536  snappy = declare_dependency(link_args: config_host['SNAPPY_LIBS'].split())
537endif
538lzo = not_found
539if 'CONFIG_LZO' in config_host
540  lzo = declare_dependency(link_args: config_host['LZO_LIBS'].split())
541endif
542rdma = not_found
543if 'CONFIG_RDMA' in config_host
544  rdma = declare_dependency(link_args: config_host['RDMA_LIBS'].split())
545endif
546numa = not_found
547if 'CONFIG_NUMA' in config_host
548  numa = declare_dependency(link_args: config_host['NUMA_LIBS'].split())
549endif
550xen = not_found
551if 'CONFIG_XEN_BACKEND' in config_host
552  xen = declare_dependency(compile_args: config_host['XEN_CFLAGS'].split(),
553                           link_args: config_host['XEN_LIBS'].split())
554endif
555cacard = not_found
556if 'CONFIG_SMARTCARD' in config_host
557  cacard = declare_dependency(compile_args: config_host['SMARTCARD_CFLAGS'].split(),
558                              link_args: config_host['SMARTCARD_LIBS'].split())
559endif
560u2f = not_found
561if have_system
562  u2f = dependency('u2f-emu', required: get_option('u2f'),
563                   method: 'pkg-config',
564                   static: enable_static)
565endif
566usbredir = not_found
567if 'CONFIG_USB_REDIR' in config_host
568  usbredir = declare_dependency(compile_args: config_host['USB_REDIR_CFLAGS'].split(),
569                                link_args: config_host['USB_REDIR_LIBS'].split())
570endif
571libusb = not_found
572if 'CONFIG_USB_LIBUSB' in config_host
573  libusb = declare_dependency(compile_args: config_host['LIBUSB_CFLAGS'].split(),
574                              link_args: config_host['LIBUSB_LIBS'].split())
575endif
576libpmem = not_found
577if 'CONFIG_LIBPMEM' in config_host
578  libpmem = declare_dependency(compile_args: config_host['LIBPMEM_CFLAGS'].split(),
579                               link_args: config_host['LIBPMEM_LIBS'].split())
580endif
581libdaxctl = not_found
582if 'CONFIG_LIBDAXCTL' in config_host
583  libdaxctl = declare_dependency(link_args: config_host['LIBDAXCTL_LIBS'].split())
584endif
585tasn1 = not_found
586if 'CONFIG_TASN1' in config_host
587  tasn1 = declare_dependency(compile_args: config_host['TASN1_CFLAGS'].split(),
588                             link_args: config_host['TASN1_LIBS'].split())
589endif
590keyutils = dependency('libkeyutils', required: false,
591                      method: 'pkg-config', static: enable_static)
592
593has_gettid = cc.has_function('gettid')
594
595# Malloc tests
596
597malloc = []
598if get_option('malloc') == 'system'
599  has_malloc_trim = \
600    not get_option('malloc_trim').disabled() and \
601    cc.links('''#include <malloc.h>
602                int main(void) { malloc_trim(0); return 0; }''')
603else
604  has_malloc_trim = false
605  malloc = cc.find_library(get_option('malloc'), required: true)
606endif
607if not has_malloc_trim and get_option('malloc_trim').enabled()
608  if get_option('malloc') == 'system'
609    error('malloc_trim not available on this platform.')
610  else
611    error('malloc_trim not available with non-libc memory allocator')
612  endif
613endif
614
615# Create config-host.h
616
617config_host_data.set('CONFIG_COCOA', cocoa.found())
618config_host_data.set('CONFIG_LIBUDEV', libudev.found())
619config_host_data.set('CONFIG_MPATH', mpathpersist.found())
620config_host_data.set('CONFIG_MPATH_NEW_API', mpathpersist_new_api)
621config_host_data.set('CONFIG_SDL', sdl.found())
622config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found())
623config_host_data.set('CONFIG_VNC', vnc.found())
624config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
625config_host_data.set('CONFIG_VNC_PNG', png.found())
626config_host_data.set('CONFIG_VNC_SASL', sasl.found())
627config_host_data.set('CONFIG_XKBCOMMON', xkbcommon.found())
628config_host_data.set('CONFIG_KEYUTILS', keyutils.found())
629config_host_data.set('CONFIG_GETTID', has_gettid)
630config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim)
631config_host_data.set('QEMU_VERSION', '"@0@"'.format(meson.project_version()))
632config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0])
633config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1])
634config_host_data.set('QEMU_VERSION_MICRO', meson.project_version().split('.')[2])
635
636ignored = ['CONFIG_QEMU_INTERP_PREFIX'] # actually per-target
637arrays = ['CONFIG_AUDIO_DRIVERS', 'CONFIG_BDRV_RW_WHITELIST', 'CONFIG_BDRV_RO_WHITELIST']
638strings = ['HOST_DSOSUF', 'CONFIG_IASL', 'bindir', 'prefix', 'qemu_confdir', 'qemu_datadir',
639           'qemu_moddir', 'qemu_localstatedir', 'qemu_helperdir', 'qemu_localedir',
640           'qemu_icondir', 'qemu_desktopdir', 'qemu_firmwarepath', 'sysconfdir']
641foreach k, v: config_host
642  if ignored.contains(k)
643    # do nothing
644  elif arrays.contains(k)
645    if v != ''
646      v = '"' + '", "'.join(v.split()) + '", '
647    endif
648    config_host_data.set(k, v)
649  elif k == 'ARCH'
650    config_host_data.set('HOST_' + v.to_upper(), 1)
651  elif strings.contains(k)
652    if not k.startswith('CONFIG_')
653      k = 'CONFIG_' + k.to_upper()
654    endif
655    config_host_data.set_quoted(k, v)
656  elif k.startswith('CONFIG_') or k.startswith('HAVE_') or k.startswith('HOST_')
657    config_host_data.set(k, v == 'y' ? 1 : v)
658  endif
659endforeach
660
661minikconf = find_program('scripts/minikconf.py')
662config_all = {}
663config_all_devices = {}
664config_all_disas = {}
665config_devices_mak_list = []
666config_devices_h = {}
667config_target_h = {}
668config_target_mak = {}
669
670disassemblers = {
671  'alpha' : ['CONFIG_ALPHA_DIS'],
672  'arm' : ['CONFIG_ARM_DIS'],
673  'avr' : ['CONFIG_AVR_DIS'],
674  'cris' : ['CONFIG_CRIS_DIS'],
675  'hppa' : ['CONFIG_HPPA_DIS'],
676  'i386' : ['CONFIG_I386_DIS'],
677  'x86_64' : ['CONFIG_I386_DIS'],
678  'x32' : ['CONFIG_I386_DIS'],
679  'lm32' : ['CONFIG_LM32_DIS'],
680  'm68k' : ['CONFIG_M68K_DIS'],
681  'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
682  'mips' : ['CONFIG_MIPS_DIS'],
683  'moxie' : ['CONFIG_MOXIE_DIS'],
684  'nios2' : ['CONFIG_NIOS2_DIS'],
685  'or1k' : ['CONFIG_OPENRISC_DIS'],
686  'ppc' : ['CONFIG_PPC_DIS'],
687  'riscv' : ['CONFIG_RISCV_DIS'],
688  'rx' : ['CONFIG_RX_DIS'],
689  's390' : ['CONFIG_S390_DIS'],
690  'sh4' : ['CONFIG_SH4_DIS'],
691  'sparc' : ['CONFIG_SPARC_DIS'],
692  'xtensa' : ['CONFIG_XTENSA_DIS'],
693}
694if link_language == 'cpp'
695  disassemblers += {
696    'aarch64' : [ 'CONFIG_ARM_A64_DIS'],
697    'arm' : [ 'CONFIG_ARM_DIS', 'CONFIG_ARM_A64_DIS'],
698    'mips' : [ 'CONFIG_MIPS_DIS', 'CONFIG_NANOMIPS_DIS'],
699  }
700endif
701
702kconfig_external_symbols = [
703  'CONFIG_KVM',
704  'CONFIG_XEN',
705  'CONFIG_TPM',
706  'CONFIG_SPICE',
707  'CONFIG_IVSHMEM',
708  'CONFIG_OPENGL',
709  'CONFIG_X11',
710  'CONFIG_VHOST_USER',
711  'CONFIG_VHOST_VDPA',
712  'CONFIG_VHOST_KERNEL',
713  'CONFIG_VIRTFS',
714  'CONFIG_LINUX',
715  'CONFIG_PVRDMA',
716]
717ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ]
718
719default_targets = 'CONFIG_DEFAULT_TARGETS' in config_host
720actual_target_dirs = []
721fdt_required = []
722foreach target : target_dirs
723  config_target = { 'TARGET_NAME': target.split('-')[0] }
724  if target.endswith('linux-user')
725    if targetos != 'linux'
726      if default_targets
727        continue
728      endif
729      error('Target @0@ is only available on a Linux host'.format(target))
730    endif
731    config_target += { 'CONFIG_LINUX_USER': 'y' }
732  elif target.endswith('bsd-user')
733    if 'CONFIG_BSD' not in config_host
734      if default_targets
735        continue
736      endif
737      error('Target @0@ is only available on a BSD host'.format(target))
738    endif
739    config_target += { 'CONFIG_BSD_USER': 'y' }
740  elif target.endswith('softmmu')
741    config_target += { 'CONFIG_SOFTMMU': 'y' }
742  endif
743  if target.endswith('-user')
744    config_target += {
745      'CONFIG_USER_ONLY': 'y',
746      'CONFIG_QEMU_INTERP_PREFIX':
747        config_host['CONFIG_QEMU_INTERP_PREFIX'].format(config_target['TARGET_NAME'])
748    }
749  endif
750
751  have_accel = false
752  foreach sym: accelerators
753    if sym == 'CONFIG_TCG' or target in accelerator_targets.get(sym, [])
754      config_target += { sym: 'y' }
755      config_all += { sym: 'y' }
756      if sym == 'CONFIG_XEN' and have_xen_pci_passthrough
757        config_target += { 'CONFIG_XEN_PCI_PASSTHROUGH': 'y' }
758      endif
759      have_accel = true
760    endif
761  endforeach
762  if not have_accel
763    if default_targets
764      continue
765    endif
766    error('No accelerator available for target @0@'.format(target))
767  endif
768
769  actual_target_dirs += target
770  config_target += keyval.load('default-configs/targets' / target + '.mak')
771  config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
772
773  if 'TARGET_NEED_FDT' in config_target
774    fdt_required += target
775  endif
776
777  # Add default keys
778  if 'TARGET_BASE_ARCH' not in config_target
779    config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
780  endif
781  if 'TARGET_ABI_DIR' not in config_target
782    config_target += {'TARGET_ABI_DIR': config_target['TARGET_ARCH']}
783  endif
784
785  foreach k, v: disassemblers
786    if config_host['ARCH'].startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k)
787      foreach sym: v
788        config_target += { sym: 'y' }
789        config_all_disas += { sym: 'y' }
790      endforeach
791    endif
792  endforeach
793
794  config_target_data = configuration_data()
795  foreach k, v: config_target
796    if not k.startswith('TARGET_') and not k.startswith('CONFIG_')
797      # do nothing
798    elif ignored.contains(k)
799      # do nothing
800    elif k == 'TARGET_BASE_ARCH'
801      # Note that TARGET_BASE_ARCH ends up in config-target.h but it is
802      # not used to select files from sourcesets.
803      config_target_data.set('TARGET_' + v.to_upper(), 1)
804    elif k == 'TARGET_NAME' or k == 'CONFIG_QEMU_INTERP_PREFIX'
805      config_target_data.set_quoted(k, v)
806    elif v == 'y'
807      config_target_data.set(k, 1)
808    else
809      config_target_data.set(k, v)
810    endif
811  endforeach
812  config_target_h += {target: configure_file(output: target + '-config-target.h',
813                                               configuration: config_target_data)}
814
815  if target.endswith('-softmmu')
816    base_kconfig = []
817    foreach sym : kconfig_external_symbols
818      if sym in config_target or sym in config_host
819        base_kconfig += '@0@=y'.format(sym)
820      endif
821    endforeach
822
823    config_devices_mak = target + '-config-devices.mak'
824    config_devices_mak = configure_file(
825      input: ['default-configs/devices' / target + '.mak', 'Kconfig'],
826      output: config_devices_mak,
827      depfile: config_devices_mak + '.d',
828      capture: true,
829      command: [minikconf, config_host['CONFIG_MINIKCONF_MODE'],
830                config_devices_mak, '@DEPFILE@', '@INPUT@',
831                base_kconfig])
832
833    config_devices_data = configuration_data()
834    config_devices = keyval.load(config_devices_mak)
835    foreach k, v: config_devices
836      config_devices_data.set(k, 1)
837    endforeach
838    config_devices_mak_list += config_devices_mak
839    config_devices_h += {target: configure_file(output: target + '-config-devices.h',
840                                                configuration: config_devices_data)}
841    config_target += config_devices
842    config_all_devices += config_devices
843  endif
844  config_target_mak += {target: config_target}
845endforeach
846target_dirs = actual_target_dirs
847
848# This configuration is used to build files that are shared by
849# multiple binaries, and then extracted out of the "common"
850# static_library target.
851#
852# We do not use all_sources()/all_dependencies(), because it would
853# build literally all source files, including devices only used by
854# targets that are not built for this compilation.  The CONFIG_ALL
855# pseudo symbol replaces it.
856
857config_all += config_all_devices
858config_all += config_host
859config_all += config_all_disas
860config_all += {
861  'CONFIG_XEN': config_host.has_key('CONFIG_XEN_BACKEND'),
862  'CONFIG_SOFTMMU': have_system,
863  'CONFIG_USER_ONLY': have_user,
864  'CONFIG_ALL': true,
865}
866
867# Submodules
868
869capstone = not_found
870capstone_opt = get_option('capstone')
871if capstone_opt in ['enabled', 'auto', 'system']
872  have_internal = fs.exists(meson.current_source_dir() / 'capstone/Makefile')
873  capstone = dependency('capstone', version: '>=4.0',
874                        static: enable_static, method: 'pkg-config',
875                        required: capstone_opt == 'system' or
876                                  capstone_opt == 'enabled' and not have_internal)
877  if capstone.found()
878    capstone_opt = 'system'
879  elif have_internal
880    capstone_opt = 'internal'
881  else
882    capstone_opt = 'disabled'
883  endif
884endif
885if capstone_opt == 'internal'
886  capstone_data = configuration_data()
887  capstone_data.set('CAPSTONE_USE_SYS_DYN_MEM', '1')
888
889  capstone_files = files(
890    'capstone/cs.c',
891    'capstone/MCInst.c',
892    'capstone/MCInstrDesc.c',
893    'capstone/MCRegisterInfo.c',
894    'capstone/SStream.c',
895    'capstone/utils.c'
896  )
897
898  if 'CONFIG_ARM_DIS' in config_all_disas
899    capstone_data.set('CAPSTONE_HAS_ARM', '1')
900    capstone_files += files(
901      'capstone/arch/ARM/ARMDisassembler.c',
902      'capstone/arch/ARM/ARMInstPrinter.c',
903      'capstone/arch/ARM/ARMMapping.c',
904      'capstone/arch/ARM/ARMModule.c'
905    )
906  endif
907
908  # FIXME: This config entry currently depends on a c++ compiler.
909  # Which is needed for building libvixl, but not for capstone.
910  if 'CONFIG_ARM_A64_DIS' in config_all_disas
911    capstone_data.set('CAPSTONE_HAS_ARM64', '1')
912    capstone_files += files(
913      'capstone/arch/AArch64/AArch64BaseInfo.c',
914      'capstone/arch/AArch64/AArch64Disassembler.c',
915      'capstone/arch/AArch64/AArch64InstPrinter.c',
916      'capstone/arch/AArch64/AArch64Mapping.c',
917      'capstone/arch/AArch64/AArch64Module.c'
918    )
919  endif
920
921  if 'CONFIG_PPC_DIS' in config_all_disas
922    capstone_data.set('CAPSTONE_HAS_POWERPC', '1')
923    capstone_files += files(
924      'capstone/arch/PowerPC/PPCDisassembler.c',
925      'capstone/arch/PowerPC/PPCInstPrinter.c',
926      'capstone/arch/PowerPC/PPCMapping.c',
927      'capstone/arch/PowerPC/PPCModule.c'
928    )
929  endif
930
931  if 'CONFIG_S390_DIS' in config_all_disas
932    capstone_data.set('CAPSTONE_HAS_SYSZ', '1')
933    capstone_files += files(
934      'capstone/arch/SystemZ/SystemZDisassembler.c',
935      'capstone/arch/SystemZ/SystemZInstPrinter.c',
936      'capstone/arch/SystemZ/SystemZMapping.c',
937      'capstone/arch/SystemZ/SystemZModule.c',
938      'capstone/arch/SystemZ/SystemZMCTargetDesc.c'
939    )
940  endif
941
942  if 'CONFIG_I386_DIS' in config_all_disas
943    capstone_data.set('CAPSTONE_HAS_X86', 1)
944    capstone_files += files(
945      'capstone/arch/X86/X86Disassembler.c',
946      'capstone/arch/X86/X86DisassemblerDecoder.c',
947      'capstone/arch/X86/X86ATTInstPrinter.c',
948      'capstone/arch/X86/X86IntelInstPrinter.c',
949      'capstone/arch/X86/X86InstPrinterCommon.c',
950      'capstone/arch/X86/X86Mapping.c',
951      'capstone/arch/X86/X86Module.c'
952    )
953  endif
954
955  configure_file(output: 'capstone-defs.h', configuration: capstone_data)
956
957  capstone_cargs = [
958    # FIXME: There does not seem to be a way to completely replace the c_args
959    # that come from add_project_arguments() -- we can only add to them.
960    # So: disable all warnings with a big hammer.
961    '-Wno-error', '-w',
962
963    # Include all configuration defines via a header file, which will wind up
964    # as a dependency on the object file, and thus changes here will result
965    # in a rebuild.
966    '-include', 'capstone-defs.h'
967  ]
968
969  libcapstone = static_library('capstone',
970                               sources: capstone_files,
971                               c_args: capstone_cargs,
972                               include_directories: 'capstone/include')
973  capstone = declare_dependency(link_with: libcapstone,
974                                include_directories: 'capstone/include/capstone')
975endif
976
977slirp = not_found
978slirp_opt = 'disabled'
979if have_system
980  slirp_opt = get_option('slirp')
981  if slirp_opt in ['enabled', 'auto', 'system']
982    have_internal = fs.exists(meson.current_source_dir() / 'slirp/meson.build')
983    slirp = dependency('slirp', static: enable_static,
984                       method: 'pkg-config',
985                       required: slirp_opt == 'system' or
986                                 slirp_opt == 'enabled' and not have_internal)
987    if slirp.found()
988      slirp_opt = 'system'
989    elif have_internal
990      slirp_opt = 'internal'
991    else
992      slirp_opt = 'disabled'
993    endif
994  endif
995  if slirp_opt == 'internal'
996    slirp_deps = []
997    if targetos == 'windows'
998      slirp_deps = cc.find_library('iphlpapi')
999    endif
1000    slirp_conf = configuration_data()
1001    slirp_conf.set('SLIRP_MAJOR_VERSION', meson.project_version().split('.')[0])
1002    slirp_conf.set('SLIRP_MINOR_VERSION', meson.project_version().split('.')[1])
1003    slirp_conf.set('SLIRP_MICRO_VERSION', meson.project_version().split('.')[2])
1004    slirp_conf.set_quoted('SLIRP_VERSION_STRING', meson.project_version())
1005    slirp_cargs = ['-DG_LOG_DOMAIN="Slirp"']
1006    slirp_files = [
1007      'slirp/src/arp_table.c',
1008      'slirp/src/bootp.c',
1009      'slirp/src/cksum.c',
1010      'slirp/src/dhcpv6.c',
1011      'slirp/src/dnssearch.c',
1012      'slirp/src/if.c',
1013      'slirp/src/ip6_icmp.c',
1014      'slirp/src/ip6_input.c',
1015      'slirp/src/ip6_output.c',
1016      'slirp/src/ip_icmp.c',
1017      'slirp/src/ip_input.c',
1018      'slirp/src/ip_output.c',
1019      'slirp/src/mbuf.c',
1020      'slirp/src/misc.c',
1021      'slirp/src/ncsi.c',
1022      'slirp/src/ndp_table.c',
1023      'slirp/src/sbuf.c',
1024      'slirp/src/slirp.c',
1025      'slirp/src/socket.c',
1026      'slirp/src/state.c',
1027      'slirp/src/stream.c',
1028      'slirp/src/tcp_input.c',
1029      'slirp/src/tcp_output.c',
1030      'slirp/src/tcp_subr.c',
1031      'slirp/src/tcp_timer.c',
1032      'slirp/src/tftp.c',
1033      'slirp/src/udp.c',
1034      'slirp/src/udp6.c',
1035      'slirp/src/util.c',
1036      'slirp/src/version.c',
1037      'slirp/src/vmstate.c',
1038    ]
1039
1040    configure_file(
1041      input : 'slirp/src/libslirp-version.h.in',
1042      output : 'libslirp-version.h',
1043      configuration: slirp_conf)
1044
1045    slirp_inc = include_directories('slirp', 'slirp/src')
1046    libslirp = static_library('slirp',
1047                              sources: slirp_files,
1048                              c_args: slirp_cargs,
1049                              include_directories: slirp_inc)
1050    slirp = declare_dependency(link_with: libslirp,
1051                               dependencies: slirp_deps,
1052                               include_directories: slirp_inc)
1053  endif
1054endif
1055
1056fdt = not_found
1057fdt_opt = get_option('fdt')
1058if have_system
1059  if fdt_opt in ['enabled', 'auto', 'system']
1060    have_internal = fs.exists(meson.current_source_dir() / 'dtc/libfdt/Makefile.libfdt')
1061    fdt = cc.find_library('fdt', static: enable_static,
1062                          required: fdt_opt == 'system' or
1063                                    fdt_opt == 'enabled' and not have_internal)
1064    if fdt.found() and cc.links('''
1065       #include <libfdt.h>
1066       #include <libfdt_env.h>
1067       int main(void) { fdt_check_full(NULL, 0); return 0; }''',
1068         dependencies: fdt)
1069      fdt_opt = 'system'
1070    elif have_internal
1071      fdt_opt = 'internal'
1072    else
1073      fdt_opt = 'disabled'
1074    endif
1075  endif
1076  if fdt_opt == 'internal'
1077    fdt_files = files(
1078      'dtc/libfdt/fdt.c',
1079      'dtc/libfdt/fdt_ro.c',
1080      'dtc/libfdt/fdt_wip.c',
1081      'dtc/libfdt/fdt_sw.c',
1082      'dtc/libfdt/fdt_rw.c',
1083      'dtc/libfdt/fdt_strerror.c',
1084      'dtc/libfdt/fdt_empty_tree.c',
1085      'dtc/libfdt/fdt_addresses.c',
1086      'dtc/libfdt/fdt_overlay.c',
1087      'dtc/libfdt/fdt_check.c',
1088    )
1089
1090    fdt_inc = include_directories('dtc/libfdt')
1091    libfdt = static_library('fdt',
1092                            sources: fdt_files,
1093                            include_directories: fdt_inc)
1094    fdt = declare_dependency(link_with: libfdt,
1095                             include_directories: fdt_inc)
1096  endif
1097endif
1098if not fdt.found() and fdt_required.length() > 0
1099  error('fdt not available but required by targets ' + ', '.join(fdt_required))
1100endif
1101
1102config_host_data.set('CONFIG_CAPSTONE', capstone.found())
1103config_host_data.set('CONFIG_FDT', fdt.found())
1104config_host_data.set('CONFIG_SLIRP', slirp.found())
1105
1106genh += configure_file(output: 'config-host.h', configuration: config_host_data)
1107
1108# Generators
1109
1110hxtool = find_program('scripts/hxtool')
1111shaderinclude = find_program('scripts/shaderinclude.pl')
1112qapi_gen = find_program('scripts/qapi-gen.py')
1113qapi_gen_depends = [ meson.source_root() / 'scripts/qapi/__init__.py',
1114                     meson.source_root() / 'scripts/qapi/commands.py',
1115                     meson.source_root() / 'scripts/qapi/common.py',
1116                     meson.source_root() / 'scripts/qapi/error.py',
1117                     meson.source_root() / 'scripts/qapi/events.py',
1118                     meson.source_root() / 'scripts/qapi/expr.py',
1119                     meson.source_root() / 'scripts/qapi/gen.py',
1120                     meson.source_root() / 'scripts/qapi/introspect.py',
1121                     meson.source_root() / 'scripts/qapi/parser.py',
1122                     meson.source_root() / 'scripts/qapi/schema.py',
1123                     meson.source_root() / 'scripts/qapi/source.py',
1124                     meson.source_root() / 'scripts/qapi/types.py',
1125                     meson.source_root() / 'scripts/qapi/visit.py',
1126                     meson.source_root() / 'scripts/qapi/common.py',
1127                     meson.source_root() / 'scripts/qapi-gen.py'
1128]
1129
1130tracetool = [
1131  python, files('scripts/tracetool.py'),
1132   '--backend=' + config_host['TRACE_BACKENDS']
1133]
1134
1135qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
1136                    meson.current_source_dir(),
1137                    config_host['PKGVERSION'], meson.project_version()]
1138qemu_version = custom_target('qemu-version.h',
1139                             output: 'qemu-version.h',
1140                             command: qemu_version_cmd,
1141                             capture: true,
1142                             build_by_default: true,
1143                             build_always_stale: true)
1144genh += qemu_version
1145
1146hxdep = []
1147hx_headers = [
1148  ['qemu-options.hx', 'qemu-options.def'],
1149  ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
1150]
1151if have_system
1152  hx_headers += [
1153    ['hmp-commands.hx', 'hmp-commands.h'],
1154    ['hmp-commands-info.hx', 'hmp-commands-info.h'],
1155  ]
1156endif
1157foreach d : hx_headers
1158  hxdep += custom_target(d[1],
1159                input: files(d[0]),
1160                output: d[1],
1161                capture: true,
1162                build_by_default: true, # to be removed when added to a target
1163                command: [hxtool, '-h', '@INPUT0@'])
1164endforeach
1165genh += hxdep
1166
1167SPHINX_ARGS = [config_host['SPHINX_BUILD'],
1168               '-Dversion=' + meson.project_version(),
1169               '-Drelease=' + config_host['PKGVERSION']]
1170
1171if get_option('werror')
1172  SPHINX_ARGS += [ '-W' ]
1173endif
1174
1175sphinx_extn_depends = [ meson.source_root() / 'docs/sphinx/depfile.py',
1176                        meson.source_root() / 'docs/sphinx/hxtool.py',
1177                        meson.source_root() / 'docs/sphinx/kerneldoc.py',
1178                        meson.source_root() / 'docs/sphinx/kernellog.py',
1179                        meson.source_root() / 'docs/sphinx/qapidoc.py',
1180                        meson.source_root() / 'docs/sphinx/qmp_lexer.py',
1181                        qapi_gen_depends ]
1182
1183# Collect sourcesets.
1184
1185blockdev_ss = ss.source_set()
1186block_ss = ss.source_set()
1187bsd_user_ss = ss.source_set()
1188common_ss = ss.source_set()
1189linux_user_ss = ss.source_set()
1190qmp_ss = ss.source_set()
1191softmmu_ss = ss.source_set()
1192specific_fuzz_ss = ss.source_set()
1193specific_ss = ss.source_set()
1194stub_ss = ss.source_set()
1195trace_ss = ss.source_set()
1196user_ss = ss.source_set()
1197util_ss = ss.source_set()
1198
1199modules = {}
1200hw_arch = {}
1201target_arch = {}
1202target_softmmu_arch = {}
1203
1204###############
1205# Trace files #
1206###############
1207
1208# TODO: add each directory to the subdirs from its own meson.build, once
1209# we have those
1210trace_events_subdirs = [
1211  'accel/kvm',
1212  'accel/tcg',
1213  'crypto',
1214  'monitor',
1215]
1216if have_user
1217  trace_events_subdirs += [ 'linux-user' ]
1218endif
1219if have_block
1220  trace_events_subdirs += [
1221    'authz',
1222    'block',
1223    'io',
1224    'nbd',
1225    'scsi',
1226  ]
1227endif
1228if have_system
1229  trace_events_subdirs += [
1230    'audio',
1231    'backends',
1232    'backends/tpm',
1233    'chardev',
1234    'hw/9pfs',
1235    'hw/acpi',
1236    'hw/alpha',
1237    'hw/arm',
1238    'hw/audio',
1239    'hw/block',
1240    'hw/block/dataplane',
1241    'hw/char',
1242    'hw/display',
1243    'hw/dma',
1244    'hw/hppa',
1245    'hw/hyperv',
1246    'hw/i2c',
1247    'hw/i386',
1248    'hw/i386/xen',
1249    'hw/ide',
1250    'hw/input',
1251    'hw/intc',
1252    'hw/isa',
1253    'hw/mem',
1254    'hw/mips',
1255    'hw/misc',
1256    'hw/misc/macio',
1257    'hw/net',
1258    'hw/nvram',
1259    'hw/pci',
1260    'hw/pci-host',
1261    'hw/ppc',
1262    'hw/rdma',
1263    'hw/rdma/vmw',
1264    'hw/rtc',
1265    'hw/s390x',
1266    'hw/scsi',
1267    'hw/sd',
1268    'hw/sparc',
1269    'hw/sparc64',
1270    'hw/ssi',
1271    'hw/timer',
1272    'hw/tpm',
1273    'hw/usb',
1274    'hw/vfio',
1275    'hw/virtio',
1276    'hw/watchdog',
1277    'hw/xen',
1278    'hw/gpio',
1279    'migration',
1280    'net',
1281    'softmmu',
1282    'ui',
1283  ]
1284endif
1285trace_events_subdirs += [
1286  'hw/core',
1287  'qapi',
1288  'qom',
1289  'target/arm',
1290  'target/hppa',
1291  'target/i386',
1292  'target/mips',
1293  'target/ppc',
1294  'target/riscv',
1295  'target/s390x',
1296  'target/sparc',
1297  'util',
1298]
1299
1300subdir('qapi')
1301subdir('qobject')
1302subdir('stubs')
1303subdir('trace')
1304subdir('util')
1305subdir('qom')
1306subdir('authz')
1307subdir('crypto')
1308subdir('ui')
1309
1310
1311if enable_modules
1312  libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
1313  modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
1314endif
1315
1316# Build targets from sourcesets
1317
1318stub_ss = stub_ss.apply(config_all, strict: false)
1319
1320util_ss.add_all(trace_ss)
1321util_ss = util_ss.apply(config_all, strict: false)
1322libqemuutil = static_library('qemuutil',
1323                             sources: util_ss.sources() + stub_ss.sources() + genh,
1324                             dependencies: [util_ss.dependencies(), m, glib, socket, malloc])
1325qemuutil = declare_dependency(link_with: libqemuutil,
1326                              sources: genh + version_res)
1327
1328decodetree = generator(find_program('scripts/decodetree.py'),
1329                       output: 'decode-@BASENAME@.c.inc',
1330                       arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
1331
1332subdir('audio')
1333subdir('io')
1334subdir('chardev')
1335subdir('fsdev')
1336subdir('libdecnumber')
1337subdir('target')
1338subdir('dump')
1339
1340block_ss.add(files(
1341  'block.c',
1342  'blockdev-nbd.c',
1343  'blockjob.c',
1344  'job.c',
1345  'qemu-io-cmds.c',
1346))
1347block_ss.add(when: 'CONFIG_REPLICATION', if_true: files('replication.c'))
1348
1349subdir('nbd')
1350subdir('scsi')
1351subdir('block')
1352
1353blockdev_ss.add(files(
1354  'blockdev.c',
1355  'iothread.c',
1356  'job-qmp.c',
1357))
1358
1359# os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
1360# os-win32.c does not
1361blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
1362softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
1363
1364softmmu_ss.add_all(blockdev_ss)
1365softmmu_ss.add(files(
1366  'bootdevice.c',
1367  'dma-helpers.c',
1368  'qdev-monitor.c',
1369), sdl)
1370
1371softmmu_ss.add(when: 'CONFIG_TPM', if_true: files('tpm.c'))
1372softmmu_ss.add(when: 'CONFIG_SECCOMP', if_true: [files('qemu-seccomp.c'), seccomp])
1373softmmu_ss.add(when: fdt, if_true: files('device_tree.c'))
1374
1375common_ss.add(files('cpus-common.c'))
1376
1377subdir('softmmu')
1378
1379common_ss.add(capstone)
1380specific_ss.add(files('disas.c', 'exec.c', 'gdbstub.c'), capstone, libpmem, libdaxctl)
1381specific_ss.add(files('exec-vary.c'))
1382specific_ss.add(when: 'CONFIG_TCG', if_true: files(
1383  'fpu/softfloat.c',
1384  'tcg/optimize.c',
1385  'tcg/tcg-common.c',
1386  'tcg/tcg-op-gvec.c',
1387  'tcg/tcg-op-vec.c',
1388  'tcg/tcg-op.c',
1389  'tcg/tcg.c',
1390))
1391specific_ss.add(when: 'CONFIG_TCG_INTERPRETER', if_true: files('disas/tci.c', 'tcg/tci.c'))
1392
1393subdir('backends')
1394subdir('disas')
1395subdir('migration')
1396subdir('monitor')
1397subdir('net')
1398subdir('replay')
1399subdir('hw')
1400subdir('accel')
1401subdir('plugins')
1402subdir('bsd-user')
1403subdir('linux-user')
1404
1405bsd_user_ss.add(files('gdbstub.c'))
1406specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss)
1407
1408linux_user_ss.add(files('gdbstub.c', 'thunk.c'))
1409specific_ss.add_all(when: 'CONFIG_LINUX_USER', if_true: linux_user_ss)
1410
1411# needed for fuzzing binaries
1412subdir('tests/qtest/libqos')
1413subdir('tests/qtest/fuzz')
1414
1415block_mods = []
1416softmmu_mods = []
1417foreach d, list : modules
1418  foreach m, module_ss : list
1419    if enable_modules and targetos != 'windows'
1420      module_ss = module_ss.apply(config_all, strict: false)
1421      sl = static_library(d + '-' + m, [genh, module_ss.sources()],
1422                          dependencies: [modulecommon, module_ss.dependencies()], pic: true)
1423      if d == 'block'
1424        block_mods += sl
1425      else
1426        softmmu_mods += sl
1427      endif
1428    else
1429      if d == 'block'
1430        block_ss.add_all(module_ss)
1431      else
1432        softmmu_ss.add_all(module_ss)
1433      endif
1434    endif
1435  endforeach
1436endforeach
1437
1438nm = find_program('nm')
1439undefsym = find_program('scripts/undefsym.py')
1440block_syms = custom_target('block.syms', output: 'block.syms',
1441                             input: [libqemuutil, block_mods],
1442                             capture: true,
1443                             command: [undefsym, nm, '@INPUT@'])
1444qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
1445                             input: [libqemuutil, softmmu_mods],
1446                             capture: true,
1447                             command: [undefsym, nm, '@INPUT@'])
1448
1449########################
1450# Library dependencies #
1451########################
1452
1453block_ss = block_ss.apply(config_host, strict: false)
1454libblock = static_library('block', block_ss.sources() + genh,
1455                          dependencies: block_ss.dependencies(),
1456                          link_depends: block_syms,
1457                          name_suffix: 'fa',
1458                          build_by_default: false)
1459
1460block = declare_dependency(link_whole: [libblock],
1461                           link_args: '@block.syms',
1462                           dependencies: [crypto, io])
1463
1464qmp_ss = qmp_ss.apply(config_host, strict: false)
1465libqmp = static_library('qmp', qmp_ss.sources() + genh,
1466                        dependencies: qmp_ss.dependencies(),
1467                        name_suffix: 'fa',
1468                        build_by_default: false)
1469
1470qmp = declare_dependency(link_whole: [libqmp])
1471
1472libhwcore = static_library('hwcore', sources: hwcore_files + genh,
1473                           name_suffix: 'fa',
1474                           build_by_default: false)
1475hwcore = declare_dependency(link_whole: libhwcore)
1476common_ss.add(hwcore)
1477
1478###########
1479# Targets #
1480###########
1481
1482foreach m : block_mods + softmmu_mods
1483  shared_module(m.name(),
1484                name_prefix: '',
1485                link_whole: m,
1486                install: true,
1487                install_dir: config_host['qemu_moddir'])
1488endforeach
1489
1490softmmu_ss.add(authz, block, chardev, crypto, io, qmp)
1491common_ss.add(qom, qemuutil)
1492
1493common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
1494common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
1495
1496common_all = common_ss.apply(config_all, strict: false)
1497common_all = static_library('common',
1498                            build_by_default: false,
1499                            sources: common_all.sources() + genh,
1500                            dependencies: common_all.dependencies(),
1501                            name_suffix: 'fa')
1502
1503feature_to_c = find_program('scripts/feature_to_c.sh')
1504
1505emulators = {}
1506foreach target : target_dirs
1507  config_target = config_target_mak[target]
1508  target_name = config_target['TARGET_NAME']
1509  arch = config_target['TARGET_BASE_ARCH']
1510  arch_srcs = [config_target_h[target]]
1511  arch_deps = []
1512  c_args = ['-DNEED_CPU_H',
1513            '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
1514            '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
1515  link_args = emulator_link_args
1516
1517  config_target += config_host
1518  target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
1519  if targetos == 'linux'
1520    target_inc += include_directories('linux-headers', is_system: true)
1521  endif
1522  if target.endswith('-softmmu')
1523    qemu_target_name = 'qemu-system-' + target_name
1524    target_type='system'
1525    t = target_softmmu_arch[arch].apply(config_target, strict: false)
1526    arch_srcs += t.sources()
1527    arch_deps += t.dependencies()
1528
1529    hw_dir = target_name == 'sparc64' ? 'sparc64' : arch
1530    hw = hw_arch[hw_dir].apply(config_target, strict: false)
1531    arch_srcs += hw.sources()
1532    arch_deps += hw.dependencies()
1533
1534    arch_srcs += config_devices_h[target]
1535    link_args += ['@block.syms', '@qemu.syms']
1536  else
1537    abi = config_target['TARGET_ABI_DIR']
1538    target_type='user'
1539    qemu_target_name = 'qemu-' + target_name
1540    if 'CONFIG_LINUX_USER' in config_target
1541      base_dir = 'linux-user'
1542      target_inc += include_directories('linux-user/host/' / config_host['ARCH'])
1543    else
1544      base_dir = 'bsd-user'
1545    endif
1546    target_inc += include_directories(
1547      base_dir,
1548      base_dir / abi,
1549    )
1550    if 'CONFIG_LINUX_USER' in config_target
1551      dir = base_dir / abi
1552      arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
1553      if config_target.has_key('TARGET_SYSTBL_ABI')
1554        arch_srcs += \
1555          syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
1556                                             extra_args : config_target['TARGET_SYSTBL_ABI'])
1557      endif
1558    endif
1559  endif
1560
1561  if 'TARGET_XML_FILES' in config_target
1562    gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
1563                                output: target + '-gdbstub-xml.c',
1564                                input: files(config_target['TARGET_XML_FILES'].split()),
1565                                command: [feature_to_c, '@INPUT@'],
1566                                capture: true)
1567    arch_srcs += gdbstub_xml
1568  endif
1569
1570  t = target_arch[arch].apply(config_target, strict: false)
1571  arch_srcs += t.sources()
1572  arch_deps += t.dependencies()
1573
1574  target_common = common_ss.apply(config_target, strict: false)
1575  objects = common_all.extract_objects(target_common.sources())
1576  deps = target_common.dependencies()
1577
1578  target_specific = specific_ss.apply(config_target, strict: false)
1579  arch_srcs += target_specific.sources()
1580  arch_deps += target_specific.dependencies()
1581
1582  lib = static_library('qemu-' + target,
1583                 sources: arch_srcs + genh,
1584                 dependencies: arch_deps,
1585                 objects: objects,
1586                 include_directories: target_inc,
1587                 c_args: c_args,
1588                 build_by_default: false,
1589                 name_suffix: 'fa')
1590
1591  if target.endswith('-softmmu')
1592    execs = [{
1593      'name': 'qemu-system-' + target_name,
1594      'gui': false,
1595      'sources': files('softmmu/main.c'),
1596      'dependencies': []
1597    }]
1598    if targetos == 'windows' and (sdl.found() or gtk.found())
1599      execs += [{
1600        'name': 'qemu-system-' + target_name + 'w',
1601        'gui': true,
1602        'sources': files('softmmu/main.c'),
1603        'dependencies': []
1604      }]
1605    endif
1606    if config_host.has_key('CONFIG_FUZZ')
1607      specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
1608      execs += [{
1609        'name': 'qemu-fuzz-' + target_name,
1610        'gui': false,
1611        'sources': specific_fuzz.sources(),
1612        'dependencies': specific_fuzz.dependencies(),
1613      }]
1614    endif
1615  else
1616    execs = [{
1617      'name': 'qemu-' + target_name,
1618      'gui': false,
1619      'sources': [],
1620      'dependencies': []
1621    }]
1622  endif
1623  foreach exe: execs
1624    emulators += {exe['name']:
1625         executable(exe['name'], exe['sources'],
1626               install: true,
1627               c_args: c_args,
1628               dependencies: arch_deps + deps + exe['dependencies'],
1629               objects: lib.extract_all_objects(recursive: true),
1630               link_language: link_language,
1631               link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
1632               link_args: link_args,
1633               gui_app: exe['gui'])
1634    }
1635
1636    if 'CONFIG_TRACE_SYSTEMTAP' in config_host
1637      foreach stp: [
1638        {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
1639        {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
1640        {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
1641        {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
1642      ]
1643        custom_target(exe['name'] + stp['ext'],
1644                      input: trace_events_all,
1645                      output: exe['name'] + stp['ext'],
1646                      capture: true,
1647                      install: stp['install'],
1648                      install_dir: qemu_datadir / '../systemtap/tapset',
1649                      command: [
1650                        tracetool, '--group=all', '--format=' + stp['fmt'],
1651                        '--binary=' + stp['bin'],
1652                        '--target-name=' + target_name,
1653                        '--target-type=' + target_type,
1654                        '--probe-prefix=qemu.' + target_type + '.' + target_name,
1655                        '@INPUT@',
1656                      ])
1657      endforeach
1658    endif
1659  endforeach
1660endforeach
1661
1662# Other build targets
1663
1664if 'CONFIG_PLUGIN' in config_host
1665  install_headers('include/qemu/qemu-plugin.h')
1666endif
1667
1668if 'CONFIG_GUEST_AGENT' in config_host
1669  subdir('qga')
1670endif
1671
1672# Don't build qemu-keymap if xkbcommon is not explicitly enabled
1673# when we don't build tools or system
1674if xkbcommon.found()
1675  # used for the update-keymaps target, so include rules even if !have_tools
1676  qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
1677                           dependencies: [qemuutil, xkbcommon], install: have_tools)
1678endif
1679
1680if have_tools
1681  qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
1682             dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
1683  qemu_io = executable('qemu-io', files('qemu-io.c'),
1684             dependencies: [block, qemuutil], install: true)
1685  qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
1686               dependencies: [block, qemuutil], install: true)
1687
1688  subdir('storage-daemon')
1689  subdir('contrib/rdmacm-mux')
1690  subdir('contrib/elf2dmp')
1691
1692  executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
1693             dependencies: qemuutil,
1694             install: true)
1695
1696  if 'CONFIG_VHOST_USER' in config_host
1697    subdir('contrib/libvhost-user')
1698    subdir('contrib/vhost-user-blk')
1699    subdir('contrib/vhost-user-gpu')
1700    subdir('contrib/vhost-user-input')
1701    subdir('contrib/vhost-user-scsi')
1702  endif
1703
1704  if targetos == 'linux'
1705    executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
1706               dependencies: [qemuutil, libcap_ng],
1707               install: true,
1708               install_dir: get_option('libexecdir'))
1709
1710    executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
1711               dependencies: [authz, crypto, io, qom, qemuutil,
1712                              libcap_ng, mpathpersist],
1713               install: true)
1714  endif
1715
1716  if 'CONFIG_IVSHMEM' in config_host
1717    subdir('contrib/ivshmem-client')
1718    subdir('contrib/ivshmem-server')
1719  endif
1720endif
1721
1722subdir('scripts')
1723subdir('tools')
1724subdir('pc-bios')
1725subdir('tests')
1726subdir('docs')
1727if 'CONFIG_GTK' in config_host
1728  subdir('po')
1729endif
1730
1731if host_machine.system() == 'windows'
1732  nsis_cmd = [
1733    find_program('scripts/nsis.py'),
1734    '@OUTPUT@',
1735    get_option('prefix'),
1736    meson.current_source_dir(),
1737    host_machine.cpu_family(),
1738    '--',
1739    '-DDISPLAYVERSION=' + meson.project_version(),
1740  ]
1741  if build_docs
1742    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
1743  endif
1744  if 'CONFIG_GTK' in config_host
1745    nsis_cmd += '-DCONFIG_GTK=y'
1746  endif
1747
1748  nsis = custom_target('nsis',
1749                       output: 'qemu-setup-' + meson.project_version() + '.exe',
1750                       input: files('qemu.nsi'),
1751                       build_always_stale: true,
1752                       command: nsis_cmd + ['@INPUT@'])
1753  alias_target('installer', nsis)
1754endif
1755
1756summary_info = {}
1757summary_info += {'Install prefix':    config_host['prefix']}
1758summary_info += {'BIOS directory':    config_host['qemu_datadir']}
1759summary_info += {'firmware path':     config_host['qemu_firmwarepath']}
1760summary_info += {'binary directory':  config_host['bindir']}
1761summary_info += {'library directory': config_host['libdir']}
1762summary_info += {'module directory':  config_host['qemu_moddir']}
1763summary_info += {'libexec directory': config_host['libexecdir']}
1764summary_info += {'include directory': config_host['includedir']}
1765summary_info += {'config directory':  config_host['sysconfdir']}
1766if targetos != 'windows'
1767  summary_info += {'local state directory': config_host['qemu_localstatedir']}
1768  summary_info += {'Manual directory':      get_option('mandir')}
1769else
1770  summary_info += {'local state directory': 'queried at runtime'}
1771endif
1772summary_info += {'Doc directory':     get_option('docdir')}
1773summary_info += {'Build directory':   meson.current_build_dir()}
1774summary_info += {'Source path':       meson.current_source_dir()}
1775summary_info += {'GIT binary':        config_host['GIT']}
1776summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
1777summary_info += {'C compiler':        meson.get_compiler('c').cmd_array()[0]}
1778summary_info += {'Host C compiler':   meson.get_compiler('c', native: true).cmd_array()[0]}
1779if link_language == 'cpp'
1780  summary_info += {'C++ compiler':      meson.get_compiler('cpp').cmd_array()[0]}
1781else
1782  summary_info += {'C++ compiler':      false}
1783endif
1784if targetos == 'darwin'
1785  summary_info += {'Objective-C compiler': meson.get_compiler('objc').cmd_array()[0]}
1786endif
1787summary_info += {'ARFLAGS':           config_host['ARFLAGS']}
1788summary_info += {'CFLAGS':            ' '.join(get_option('c_args')
1789                                               + ['-O' + get_option('optimization')]
1790                                               + (get_option('debug') ? ['-g'] : []))}
1791if link_language == 'cpp'
1792  summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args')
1793                                               + ['-O' + get_option('optimization')]
1794                                               + (get_option('debug') ? ['-g'] : []))}
1795endif
1796link_args = get_option(link_language + '_link_args')
1797if link_args.length() > 0
1798  summary_info += {'LDFLAGS':         ' '.join(link_args)}
1799endif
1800summary_info += {'QEMU_CFLAGS':       config_host['QEMU_CFLAGS']}
1801summary_info += {'QEMU_LDFLAGS':      config_host['QEMU_LDFLAGS']}
1802summary_info += {'make':              config_host['MAKE']}
1803summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
1804summary_info += {'sphinx-build':      config_host['SPHINX_BUILD']}
1805summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
1806# TODO: add back version
1807summary_info += {'slirp support':     slirp_opt == 'disabled' ? false : slirp_opt}
1808if slirp_opt != 'disabled'
1809  summary_info += {'smbd':            config_host['CONFIG_SMBD_COMMAND']}
1810endif
1811summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
1812if config_host.has_key('CONFIG_MODULES')
1813  summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')}
1814endif
1815summary_info += {'host CPU':          cpu}
1816summary_info += {'host endianness':   build_machine.endian()}
1817summary_info += {'target list':       ' '.join(target_dirs)}
1818summary_info += {'gprof enabled':     config_host.has_key('CONFIG_GPROF')}
1819summary_info += {'sparse enabled':    sparse.found()}
1820summary_info += {'strip binaries':    get_option('strip')}
1821summary_info += {'profiler':          config_host.has_key('CONFIG_PROFILER')}
1822summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
1823if targetos == 'darwin'
1824  summary_info += {'Cocoa support': config_host.has_key('CONFIG_COCOA')}
1825endif
1826# TODO: add back version
1827summary_info += {'SDL support':       sdl.found()}
1828summary_info += {'SDL image support': sdl_image.found()}
1829# TODO: add back version
1830summary_info += {'GTK support':       config_host.has_key('CONFIG_GTK')}
1831summary_info += {'GTK GL support':    config_host.has_key('CONFIG_GTK_GL')}
1832summary_info += {'pixman':            pixman.found()}
1833# TODO: add back version
1834summary_info += {'VTE support':       config_host.has_key('CONFIG_VTE')}
1835summary_info += {'TLS priority':      config_host['CONFIG_TLS_PRIORITY']}
1836summary_info += {'GNUTLS support':    config_host.has_key('CONFIG_GNUTLS')}
1837# TODO: add back version
1838summary_info += {'libgcrypt':         config_host.has_key('CONFIG_GCRYPT')}
1839if config_host.has_key('CONFIG_GCRYPT')
1840   summary_info += {'  hmac':            config_host.has_key('CONFIG_GCRYPT_HMAC')}
1841   summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
1842endif
1843# TODO: add back version
1844summary_info += {'nettle':            config_host.has_key('CONFIG_NETTLE')}
1845if config_host.has_key('CONFIG_NETTLE')
1846   summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
1847endif
1848summary_info += {'libtasn1':          config_host.has_key('CONFIG_TASN1')}
1849summary_info += {'PAM':               config_host.has_key('CONFIG_AUTH_PAM')}
1850summary_info += {'iconv support':     config_host.has_key('CONFIG_ICONV')}
1851summary_info += {'curses support':    config_host.has_key('CONFIG_CURSES')}
1852# TODO: add back version
1853summary_info += {'virgl support':     config_host.has_key('CONFIG_VIRGL')}
1854summary_info += {'curl support':      config_host.has_key('CONFIG_CURL')}
1855summary_info += {'mingw32 support':   targetos == 'windows'}
1856summary_info += {'Audio drivers':     config_host['CONFIG_AUDIO_DRIVERS']}
1857summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']}
1858summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']}
1859summary_info += {'VirtFS support':    config_host.has_key('CONFIG_VIRTFS')}
1860summary_info += {'Multipath support': mpathpersist.found()}
1861summary_info += {'VNC support':       vnc.found()}
1862if vnc.found()
1863  summary_info += {'VNC SASL support':  sasl.found()}
1864  summary_info += {'VNC JPEG support':  jpeg.found()}
1865  summary_info += {'VNC PNG support':   png.found()}
1866endif
1867summary_info += {'xen support':       config_host.has_key('CONFIG_XEN_BACKEND')}
1868if config_host.has_key('CONFIG_XEN_BACKEND')
1869  summary_info += {'xen ctrl version':  config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
1870endif
1871summary_info += {'brlapi support':    config_host.has_key('CONFIG_BRLAPI')}
1872summary_info += {'Documentation':     config_host.has_key('BUILD_DOCS')}
1873summary_info += {'PIE':               get_option('b_pie')}
1874summary_info += {'vde support':       config_host.has_key('CONFIG_VDE')}
1875summary_info += {'netmap support':    config_host.has_key('CONFIG_NETMAP')}
1876summary_info += {'Linux AIO support': config_host.has_key('CONFIG_LINUX_AIO')}
1877summary_info += {'Linux io_uring support': config_host.has_key('CONFIG_LINUX_IO_URING')}
1878summary_info += {'ATTR/XATTR support': config_host.has_key('CONFIG_ATTR')}
1879summary_info += {'Install blobs':     config_host.has_key('INSTALL_BLOBS')}
1880summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
1881summary_info += {'HAX support':       config_all.has_key('CONFIG_HAX')}
1882summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
1883summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
1884summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
1885if config_all.has_key('CONFIG_TCG')
1886  summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
1887  summary_info += {'TCG interpreter':   config_host.has_key('CONFIG_TCG_INTERPRETER')}
1888endif
1889summary_info += {'malloc trim support': has_malloc_trim}
1890summary_info += {'RDMA support':      config_host.has_key('CONFIG_RDMA')}
1891summary_info += {'PVRDMA support':    config_host.has_key('CONFIG_PVRDMA')}
1892summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
1893summary_info += {'membarrier':        config_host.has_key('CONFIG_MEMBARRIER')}
1894summary_info += {'preadv support':    config_host.has_key('CONFIG_PREADV')}
1895summary_info += {'fdatasync':         config_host.has_key('CONFIG_FDATASYNC')}
1896summary_info += {'madvise':           config_host.has_key('CONFIG_MADVISE')}
1897summary_info += {'posix_madvise':     config_host.has_key('CONFIG_POSIX_MADVISE')}
1898summary_info += {'posix_memalign':    config_host.has_key('CONFIG_POSIX_MEMALIGN')}
1899summary_info += {'libcap-ng support': config_host.has_key('CONFIG_LIBCAP_NG')}
1900summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')}
1901summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')}
1902summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')}
1903summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')}
1904summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_KERNEL')}
1905summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')}
1906summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')}
1907summary_info += {'Trace backends':    config_host['TRACE_BACKENDS']}
1908if config_host['TRACE_BACKENDS'].split().contains('simple')
1909  summary_info += {'Trace output file': config_host['CONFIG_TRACE_FILE'] + '-<pid>'}
1910endif
1911# TODO: add back protocol and server version
1912summary_info += {'spice support':     config_host.has_key('CONFIG_SPICE')}
1913summary_info += {'rbd support':       config_host.has_key('CONFIG_RBD')}
1914summary_info += {'xfsctl support':    config_host.has_key('CONFIG_XFS')}
1915summary_info += {'smartcard support': config_host.has_key('CONFIG_SMARTCARD')}
1916summary_info += {'U2F support':       u2f.found()}
1917summary_info += {'libusb':            config_host.has_key('CONFIG_USB_LIBUSB')}
1918summary_info += {'usb net redir':     config_host.has_key('CONFIG_USB_REDIR')}
1919summary_info += {'OpenGL support':    config_host.has_key('CONFIG_OPENGL')}
1920summary_info += {'OpenGL dmabufs':    config_host.has_key('CONFIG_OPENGL_DMABUF')}
1921summary_info += {'libiscsi support':  config_host.has_key('CONFIG_LIBISCSI')}
1922summary_info += {'libnfs support':    config_host.has_key('CONFIG_LIBNFS')}
1923summary_info += {'build guest agent': config_host.has_key('CONFIG_GUEST_AGENT')}
1924if targetos == 'windows'
1925  if 'WIN_SDK' in config_host
1926    summary_info += {'Windows SDK':       config_host['WIN_SDK']}
1927  endif
1928  summary_info += {'QGA VSS support':   config_host.has_key('CONFIG_QGA_VSS')}
1929  summary_info += {'QGA w32 disk info': config_host.has_key('CONFIG_QGA_NTDDSCSI')}
1930  summary_info += {'QGA MSI support':   config_host.has_key('CONFIG_QGA_MSI')}
1931endif
1932summary_info += {'seccomp support':   config_host.has_key('CONFIG_SECCOMP')}
1933summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
1934summary_info += {'coroutine pool':    config_host['CONFIG_COROUTINE_POOL'] == '1'}
1935summary_info += {'debug stack usage': config_host.has_key('CONFIG_DEBUG_STACK_USAGE')}
1936summary_info += {'mutex debugging':   config_host.has_key('CONFIG_DEBUG_MUTEX')}
1937summary_info += {'crypto afalg':      config_host.has_key('CONFIG_AF_ALG')}
1938summary_info += {'GlusterFS support': config_host.has_key('CONFIG_GLUSTERFS')}
1939summary_info += {'gcov':              get_option('b_coverage')}
1940summary_info += {'TPM support':       config_host.has_key('CONFIG_TPM')}
1941summary_info += {'libssh support':    config_host.has_key('CONFIG_LIBSSH')}
1942summary_info += {'QOM debugging':     config_host.has_key('CONFIG_QOM_CAST_DEBUG')}
1943summary_info += {'Live block migration': config_host.has_key('CONFIG_LIVE_BLOCK_MIGRATION')}
1944summary_info += {'lzo support':       config_host.has_key('CONFIG_LZO')}
1945summary_info += {'snappy support':    config_host.has_key('CONFIG_SNAPPY')}
1946summary_info += {'bzip2 support':     config_host.has_key('CONFIG_BZIP2')}
1947summary_info += {'lzfse support':     config_host.has_key('CONFIG_LZFSE')}
1948summary_info += {'zstd support':      config_host.has_key('CONFIG_ZSTD')}
1949summary_info += {'NUMA host support': config_host.has_key('CONFIG_NUMA')}
1950summary_info += {'libxml2':           config_host.has_key('CONFIG_LIBXML2')}
1951summary_info += {'memory allocator':  get_option('malloc')}
1952summary_info += {'avx2 optimization': config_host.has_key('CONFIG_AVX2_OPT')}
1953summary_info += {'avx512f optimization': config_host.has_key('CONFIG_AVX512F_OPT')}
1954summary_info += {'replication support': config_host.has_key('CONFIG_REPLICATION')}
1955summary_info += {'bochs support':     config_host.has_key('CONFIG_BOCHS')}
1956summary_info += {'cloop support':     config_host.has_key('CONFIG_CLOOP')}
1957summary_info += {'dmg support':       config_host.has_key('CONFIG_DMG')}
1958summary_info += {'qcow v1 support':   config_host.has_key('CONFIG_QCOW1')}
1959summary_info += {'vdi support':       config_host.has_key('CONFIG_VDI')}
1960summary_info += {'vvfat support':     config_host.has_key('CONFIG_VVFAT')}
1961summary_info += {'qed support':       config_host.has_key('CONFIG_QED')}
1962summary_info += {'parallels support': config_host.has_key('CONFIG_PARALLELS')}
1963summary_info += {'sheepdog support':  config_host.has_key('CONFIG_SHEEPDOG')}
1964summary_info += {'capstone':          capstone_opt == 'disabled' ? false : capstone_opt}
1965summary_info += {'libpmem support':   config_host.has_key('CONFIG_LIBPMEM')}
1966summary_info += {'libdaxctl support': config_host.has_key('CONFIG_LIBDAXCTL')}
1967summary_info += {'libudev':           libudev.found()}
1968summary_info += {'default devices':   config_host['CONFIG_MINIKCONF_MODE'] == '--defconfig'}
1969summary_info += {'plugin support':    config_host.has_key('CONFIG_PLUGIN')}
1970summary_info += {'fuzzing support':   config_host.has_key('CONFIG_FUZZ')}
1971if config_host.has_key('HAVE_GDB_BIN')
1972  summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
1973endif
1974summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
1975summary_info += {'rng-none':          config_host.has_key('CONFIG_RNG_NONE')}
1976summary_info += {'Linux keyring':     config_host.has_key('CONFIG_SECRET_KEYRING')}
1977summary(summary_info, bool_yn: true)
1978
1979if not supported_cpus.contains(cpu)
1980  message()
1981  warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
1982  message()
1983  message('CPU host architecture ' + cpu + ' support is not currently maintained.')
1984  message('The QEMU project intends to remove support for this host CPU in')
1985  message('a future release if nobody volunteers to maintain it and to')
1986  message('provide a build host for our continuous integration setup.')
1987  message('configure has succeeded and you can continue to build, but')
1988  message('if you care about QEMU on this platform you should contact')
1989  message('us upstream at qemu-devel@nongnu.org.')
1990endif
1991
1992if not supported_oses.contains(targetos)
1993  message()
1994  warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
1995  message()
1996  message('Host OS ' + targetos + 'support is not currently maintained.')
1997  message('The QEMU project intends to remove support for this host OS in')
1998  message('a future release if nobody volunteers to maintain it and to')
1999  message('provide a build host for our continuous integration setup.')
2000  message('configure has succeeded and you can continue to build, but')
2001  message('if you care about QEMU on this platform you should contact')
2002  message('us upstream at qemu-devel@nongnu.org.')
2003endif
2004