xref: /openbmc/qemu/meson.build (revision feabc71d)
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')
13
14sh = find_program('sh')
15cc = meson.get_compiler('c')
16config_host = keyval.load(meson.current_build_dir() / 'config-host.mak')
17enable_modules = 'CONFIG_MODULES' in config_host
18enable_static = 'CONFIG_STATIC' in config_host
19build_docs = 'BUILD_DOCS' in config_host
20qemu_datadir = get_option('datadir') / get_option('qemu_suffix')
21qemu_docdir = get_option('docdir') / get_option('qemu_suffix')
22config_host_data = configuration_data()
23genh = []
24
25target_dirs = config_host['TARGET_DIRS'].split()
26have_user = false
27have_system = false
28foreach target : target_dirs
29  have_user = have_user or target.endswith('-user')
30  have_system = have_system or target.endswith('-softmmu')
31endforeach
32have_tools = 'CONFIG_TOOLS' in config_host
33have_block = have_system or have_tools
34
35python = import('python').find_installation()
36
37supported_oses = ['windows', 'freebsd', 'netbsd', 'openbsd', 'darwin', 'sunos', 'linux']
38supported_cpus = ['ppc', 'ppc64', 's390x', 'sparc64', 'riscv32', 'riscv64', 'x86', 'x86_64',
39  'arm', 'aarch64', 'mips', 'mips64', 'sparc', 'sparc64']
40
41cpu = host_machine.cpu_family()
42targetos = host_machine.system()
43
44configure_file(input: files('scripts/ninjatool.py'),
45               output: 'ninjatool',
46               configuration: config_host)
47
48##################
49# Compiler flags #
50##################
51
52add_project_arguments(config_host['QEMU_CFLAGS'].split(),
53                      native: false, language: ['c', 'objc'])
54add_project_arguments(config_host['QEMU_CXXFLAGS'].split(),
55                      native: false, language: 'cpp')
56add_project_link_arguments(config_host['QEMU_LDFLAGS'].split(),
57                           native: false, language: ['c', 'cpp', 'objc'])
58add_project_arguments(config_host['QEMU_INCLUDES'].split(),
59                      language: ['c', 'cpp', 'objc'])
60
61link_language = meson.get_external_property('link_language', 'cpp')
62if link_language == 'cpp'
63  add_languages('cpp', required: true, native: false)
64endif
65if host_machine.system() == 'darwin'
66  add_languages('objc', required: false, native: false)
67endif
68
69if 'SPARSE_CFLAGS' in config_host
70  run_target('sparse',
71             command: [find_program('scripts/check_sparse.py'),
72                       config_host['SPARSE_CFLAGS'].split(),
73                       'compile_commands.json'])
74endif
75
76m = cc.find_library('m', required: false)
77util = cc.find_library('util', required: false)
78winmm = []
79socket = []
80version_res = []
81coref = []
82iokit = []
83cocoa = []
84hvf = []
85if targetos == 'windows'
86  socket = cc.find_library('ws2_32')
87  winmm = cc.find_library('winmm')
88
89  win = import('windows')
90  version_res = win.compile_resources('version.rc',
91                                      depend_files: files('pc-bios/qemu-nsis.ico'),
92                                      include_directories: include_directories('.'))
93elif targetos == 'darwin'
94  coref = dependency('appleframeworks', modules: 'CoreFoundation')
95  iokit = dependency('appleframeworks', modules: 'IOKit')
96  cocoa = dependency('appleframeworks', modules: 'Cocoa')
97  hvf = dependency('appleframeworks', modules: 'Hypervisor')
98elif targetos == 'sunos'
99  socket = [cc.find_library('socket'),
100            cc.find_library('nsl'),
101            cc.find_library('resolv')]
102elif targetos == 'haiku'
103  socket = [cc.find_library('posix_error_mapper'),
104            cc.find_library('network'),
105            cc.find_library('bsd')]
106endif
107# The path to glib.h is added to all compilation commands.  This was
108# grandfathered in from the QEMU Makefiles.
109add_project_arguments(config_host['GLIB_CFLAGS'].split(),
110                      native: false, language: ['c', 'cpp', 'objc'])
111glib = declare_dependency(link_args: config_host['GLIB_LIBS'].split())
112gio = not_found
113if 'CONFIG_GIO' in config_host
114  gio = declare_dependency(compile_args: config_host['GIO_CFLAGS'].split(),
115                           link_args: config_host['GIO_LIBS'].split())
116endif
117lttng = not_found
118if 'CONFIG_TRACE_UST' in config_host
119  lttng = declare_dependency(link_args: config_host['LTTNG_UST_LIBS'].split())
120endif
121urcubp = not_found
122if 'CONFIG_TRACE_UST' in config_host
123  urcubp = declare_dependency(link_args: config_host['URCU_BP_LIBS'].split())
124endif
125gcrypt = not_found
126if 'CONFIG_GCRYPT' in config_host
127  gcrypt = declare_dependency(compile_args: config_host['GCRYPT_CFLAGS'].split(),
128                              link_args: config_host['GCRYPT_LIBS'].split())
129endif
130nettle = not_found
131if 'CONFIG_NETTLE' in config_host
132  nettle = declare_dependency(compile_args: config_host['NETTLE_CFLAGS'].split(),
133                              link_args: config_host['NETTLE_LIBS'].split())
134endif
135gnutls = not_found
136if 'CONFIG_GNUTLS' in config_host
137  gnutls = declare_dependency(compile_args: config_host['GNUTLS_CFLAGS'].split(),
138                              link_args: config_host['GNUTLS_LIBS'].split())
139endif
140pixman = not_found
141if have_system or have_tools
142  pixman = dependency('pixman-1', required: have_system, version:'>=0.21.8',
143                      method: 'pkg-config', static: enable_static)
144endif
145pam = not_found
146if 'CONFIG_AUTH_PAM' in config_host
147  pam = cc.find_library('pam')
148endif
149libaio = cc.find_library('aio', required: false)
150zlib = dependency('zlib', required: true, static: enable_static)
151linux_io_uring = not_found
152if 'CONFIG_LINUX_IO_URING' in config_host
153  linux_io_uring = declare_dependency(compile_args: config_host['LINUX_IO_URING_CFLAGS'].split(),
154                                      link_args: config_host['LINUX_IO_URING_LIBS'].split())
155endif
156libxml2 = not_found
157if 'CONFIG_LIBXML2' in config_host
158  libxml2 = declare_dependency(compile_args: config_host['LIBXML2_CFLAGS'].split(),
159                               link_args: config_host['LIBXML2_LIBS'].split())
160endif
161libnfs = not_found
162if 'CONFIG_LIBNFS' in config_host
163  libnfs = declare_dependency(link_args: config_host['LIBNFS_LIBS'].split())
164endif
165libattr = not_found
166if 'CONFIG_ATTR' in config_host
167  libattr = declare_dependency(link_args: config_host['LIBATTR_LIBS'].split())
168endif
169seccomp = not_found
170if 'CONFIG_SECCOMP' in config_host
171  seccomp = declare_dependency(compile_args: config_host['SECCOMP_CFLAGS'].split(),
172                               link_args: config_host['SECCOMP_LIBS'].split())
173endif
174libcap_ng = not_found
175if 'CONFIG_LIBCAP_NG' in config_host
176  libcap_ng = declare_dependency(link_args: config_host['LIBCAP_NG_LIBS'].split())
177endif
178if get_option('xkbcommon').auto() and not have_system and not have_tools
179  xkbcommon = not_found
180else
181  xkbcommon = dependency('xkbcommon', required: get_option('xkbcommon'),
182                         method: 'pkg-config', static: enable_static)
183endif
184slirp = not_found
185if config_host.has_key('CONFIG_SLIRP')
186  slirp = declare_dependency(compile_args: config_host['SLIRP_CFLAGS'].split(),
187                             link_args: config_host['SLIRP_LIBS'].split())
188endif
189vde = not_found
190if config_host.has_key('CONFIG_VDE')
191  vde = declare_dependency(link_args: config_host['VDE_LIBS'].split())
192endif
193pulse = not_found
194if 'CONFIG_LIBPULSE' in config_host
195  pulse = declare_dependency(compile_args: config_host['PULSE_CFLAGS'].split(),
196                             link_args: config_host['PULSE_LIBS'].split())
197endif
198alsa = not_found
199if 'CONFIG_ALSA' in config_host
200  alsa = declare_dependency(compile_args: config_host['ALSA_CFLAGS'].split(),
201                            link_args: config_host['ALSA_LIBS'].split())
202endif
203jack = not_found
204if 'CONFIG_LIBJACK' in config_host
205  jack = declare_dependency(link_args: config_host['JACK_LIBS'].split())
206endif
207spice = not_found
208if 'CONFIG_SPICE' in config_host
209  spice = declare_dependency(compile_args: config_host['SPICE_CFLAGS'].split(),
210                             link_args: config_host['SPICE_LIBS'].split())
211endif
212rt = cc.find_library('rt', required: false)
213libmpathpersist = not_found
214if config_host.has_key('CONFIG_MPATH')
215  libmpathpersist = cc.find_library('mpathpersist')
216endif
217libdl = not_found
218if 'CONFIG_PLUGIN' in config_host
219  libdl = cc.find_library('dl', required: true)
220endif
221libiscsi = not_found
222if 'CONFIG_LIBISCSI' in config_host
223  libiscsi = declare_dependency(compile_args: config_host['LIBISCSI_CFLAGS'].split(),
224                                link_args: config_host['LIBISCSI_LIBS'].split())
225endif
226zstd = not_found
227if 'CONFIG_ZSTD' in config_host
228  zstd = declare_dependency(compile_args: config_host['ZSTD_CFLAGS'].split(),
229                            link_args: config_host['ZSTD_LIBS'].split())
230endif
231gbm = not_found
232if 'CONFIG_GBM' in config_host
233  gbm = declare_dependency(compile_args: config_host['GBM_CFLAGS'].split(),
234                           link_args: config_host['GBM_LIBS'].split())
235endif
236virgl = not_found
237if 'CONFIG_VIRGL' in config_host
238  virgl = declare_dependency(compile_args: config_host['VIRGL_CFLAGS'].split(),
239                             link_args: config_host['VIRGL_LIBS'].split())
240endif
241curl = not_found
242if 'CONFIG_CURL' in config_host
243  curl = declare_dependency(compile_args: config_host['CURL_CFLAGS'].split(),
244                            link_args: config_host['CURL_LIBS'].split())
245endif
246libudev = not_found
247if 'CONFIG_LIBUDEV' in config_host
248  libudev = declare_dependency(link_args: config_host['LIBUDEV_LIBS'].split())
249endif
250brlapi = not_found
251if 'CONFIG_BRLAPI' in config_host
252  brlapi = declare_dependency(link_args: config_host['BRLAPI_LIBS'].split())
253endif
254
255sdl = not_found
256if have_system
257  sdl = dependency('sdl2', required: get_option('sdl'), static: enable_static)
258  sdl_image = not_found
259endif
260if sdl.found()
261  # work around 2.0.8 bug
262  sdl = declare_dependency(compile_args: '-Wno-undef',
263                           dependencies: sdl)
264  sdl_image = dependency('SDL2_image', required: get_option('sdl_image'),
265                         method: 'pkg-config', static: enable_static)
266else
267  if get_option('sdl_image').enabled()
268    error('sdl-image required, but SDL was @0@',
269          get_option('sdl').disabled() ? 'disabled' : 'not found')
270  endif
271  sdl_image = not_found
272endif
273
274rbd = not_found
275if 'CONFIG_RBD' in config_host
276  rbd = declare_dependency(link_args: config_host['RBD_LIBS'].split())
277endif
278glusterfs = not_found
279if 'CONFIG_GLUSTERFS' in config_host
280  glusterfs = declare_dependency(compile_args: config_host['GLUSTERFS_CFLAGS'].split(),
281                                 link_args: config_host['GLUSTERFS_LIBS'].split())
282endif
283libssh = not_found
284if 'CONFIG_LIBSSH' in config_host
285  libssh = declare_dependency(compile_args: config_host['LIBSSH_CFLAGS'].split(),
286                              link_args: config_host['LIBSSH_LIBS'].split())
287endif
288libbzip2 = not_found
289if 'CONFIG_BZIP2' in config_host
290  libbzip2 = declare_dependency(link_args: config_host['BZIP2_LIBS'].split())
291endif
292liblzfse = not_found
293if 'CONFIG_LZFSE' in config_host
294  liblzfse = declare_dependency(link_args: config_host['LZFSE_LIBS'].split())
295endif
296oss = not_found
297if 'CONFIG_AUDIO_OSS' in config_host
298  oss = declare_dependency(link_args: config_host['OSS_LIBS'].split())
299endif
300dsound = not_found
301if 'CONFIG_AUDIO_DSOUND' in config_host
302  dsound = declare_dependency(link_args: config_host['DSOUND_LIBS'].split())
303endif
304coreaudio = not_found
305if 'CONFIG_AUDIO_COREAUDIO' in config_host
306  coreaudio = declare_dependency(link_args: config_host['COREAUDIO_LIBS'].split())
307endif
308opengl = not_found
309if 'CONFIG_OPENGL' in config_host
310  opengl = declare_dependency(compile_args: config_host['OPENGL_CFLAGS'].split(),
311                              link_args: config_host['OPENGL_LIBS'].split())
312else
313endif
314gtk = not_found
315if 'CONFIG_GTK' in config_host
316  gtk = declare_dependency(compile_args: config_host['GTK_CFLAGS'].split(),
317                              link_args: config_host['GTK_LIBS'].split())
318endif
319vte = not_found
320if 'CONFIG_VTE' in config_host
321  vte = declare_dependency(compile_args: config_host['VTE_CFLAGS'].split(),
322                           link_args: config_host['VTE_LIBS'].split())
323endif
324x11 = not_found
325if 'CONFIG_X11' in config_host
326  x11 = declare_dependency(compile_args: config_host['X11_CFLAGS'].split(),
327                           link_args: config_host['X11_LIBS'].split())
328endif
329curses = not_found
330if 'CONFIG_CURSES' in config_host
331  curses = declare_dependency(compile_args: config_host['CURSES_CFLAGS'].split(),
332                              link_args: config_host['CURSES_LIBS'].split())
333endif
334iconv = not_found
335if 'CONFIG_ICONV' in config_host
336  iconv = declare_dependency(compile_args: config_host['ICONV_CFLAGS'].split(),
337                             link_args: config_host['ICONV_LIBS'].split())
338endif
339gio = not_found
340if 'CONFIG_GIO' in config_host
341  gio = declare_dependency(compile_args: config_host['GIO_CFLAGS'].split(),
342                           link_args: config_host['GIO_LIBS'].split())
343endif
344vnc = not_found
345png = not_found
346jpeg = not_found
347sasl = not_found
348if get_option('vnc').enabled()
349  vnc = declare_dependency() # dummy dependency
350  png = dependency('libpng', required: get_option('vnc_png'),
351                   method: 'pkg-config', static: enable_static)
352  jpeg = cc.find_library('jpeg', has_headers: ['jpeglib.h'],
353                         required: get_option('vnc_jpeg'),
354                         static: enable_static)
355  sasl = cc.find_library('sasl2', has_headers: ['sasl/sasl.h'],
356                         required: get_option('vnc_sasl'),
357                         static: enable_static)
358  if sasl.found()
359    sasl = declare_dependency(dependencies: sasl,
360                              compile_args: '-DSTRUCT_IOVEC_DEFINED')
361  endif
362endif
363fdt = not_found
364if 'CONFIG_FDT' in config_host
365  fdt = declare_dependency(compile_args: config_host['FDT_CFLAGS'].split(),
366                           link_args: config_host['FDT_LIBS'].split())
367endif
368snappy = not_found
369if 'CONFIG_SNAPPY' in config_host
370  snappy = declare_dependency(link_args: config_host['SNAPPY_LIBS'].split())
371endif
372lzo = not_found
373if 'CONFIG_LZO' in config_host
374  lzo = declare_dependency(link_args: config_host['LZO_LIBS'].split())
375endif
376rdma = not_found
377if 'CONFIG_RDMA' in config_host
378  rdma = declare_dependency(link_args: config_host['RDMA_LIBS'].split())
379endif
380numa = not_found
381if 'CONFIG_NUMA' in config_host
382  numa = declare_dependency(link_args: config_host['NUMA_LIBS'].split())
383endif
384xen = not_found
385if 'CONFIG_XEN_BACKEND' in config_host
386  xen = declare_dependency(compile_args: config_host['XEN_CFLAGS'].split(),
387                           link_args: config_host['XEN_LIBS'].split())
388endif
389cacard = not_found
390if 'CONFIG_SMARTCARD' in config_host
391  cacard = declare_dependency(compile_args: config_host['SMARTCARD_CFLAGS'].split(),
392                              link_args: config_host['SMARTCARD_LIBS'].split())
393endif
394u2f = not_found
395if have_system
396  u2f = dependency('u2f-emu', required: get_option('u2f'),
397                   method: 'pkg-config',
398                   static: enable_static)
399endif
400usbredir = not_found
401if 'CONFIG_USB_REDIR' in config_host
402  usbredir = declare_dependency(compile_args: config_host['USB_REDIR_CFLAGS'].split(),
403                                link_args: config_host['USB_REDIR_LIBS'].split())
404endif
405libusb = not_found
406if 'CONFIG_USB_LIBUSB' in config_host
407  libusb = declare_dependency(compile_args: config_host['LIBUSB_CFLAGS'].split(),
408                              link_args: config_host['LIBUSB_LIBS'].split())
409endif
410capstone = not_found
411if 'CONFIG_CAPSTONE' in config_host
412  capstone = declare_dependency(compile_args: config_host['CAPSTONE_CFLAGS'].split(),
413                                link_args: config_host['CAPSTONE_LIBS'].split())
414endif
415libpmem = not_found
416if 'CONFIG_LIBPMEM' in config_host
417  libpmem = declare_dependency(compile_args: config_host['LIBPMEM_CFLAGS'].split(),
418                               link_args: config_host['LIBPMEM_LIBS'].split())
419endif
420libdaxctl = not_found
421if 'CONFIG_LIBDAXCTL' in config_host
422  libdaxctl = declare_dependency(link_args: config_host['LIBDAXCTL_LIBS'].split())
423endif
424tasn1 = not_found
425if 'CONFIG_TASN1' in config_host
426  tasn1 = declare_dependency(compile_args: config_host['TASN1_CFLAGS'].split(),
427                             link_args: config_host['TASN1_LIBS'].split())
428endif
429keyutils = dependency('libkeyutils', required: false,
430                      method: 'pkg-config', static: enable_static)
431
432has_gettid = cc.has_function('gettid')
433
434# Create config-host.h
435
436config_host_data.set('CONFIG_SDL', sdl.found())
437config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found())
438config_host_data.set('CONFIG_VNC', vnc.found())
439config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
440config_host_data.set('CONFIG_VNC_PNG', png.found())
441config_host_data.set('CONFIG_VNC_SASL', sasl.found())
442config_host_data.set('CONFIG_XKBCOMMON', xkbcommon.found())
443config_host_data.set('CONFIG_KEYUTILS', keyutils.found())
444config_host_data.set('CONFIG_GETTID', has_gettid)
445config_host_data.set('QEMU_VERSION', '"@0@"'.format(meson.project_version()))
446config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0])
447config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1])
448config_host_data.set('QEMU_VERSION_MICRO', meson.project_version().split('.')[2])
449
450arrays = ['CONFIG_AUDIO_DRIVERS', 'CONFIG_BDRV_RW_WHITELIST', 'CONFIG_BDRV_RO_WHITELIST']
451strings = ['HOST_DSOSUF', 'CONFIG_IASL', 'qemu_confdir', 'qemu_datadir',
452           'qemu_moddir', 'qemu_localstatedir', 'qemu_helperdir', 'qemu_localedir',
453           'qemu_icondir', 'qemu_desktopdir', 'qemu_firmwarepath']
454foreach k, v: config_host
455  if arrays.contains(k)
456    if v != ''
457      v = '"' + '", "'.join(v.split()) + '", '
458    endif
459    config_host_data.set(k, v)
460  elif k == 'ARCH'
461    config_host_data.set('HOST_' + v.to_upper(), 1)
462  elif strings.contains(k)
463    if not k.startswith('CONFIG_')
464      k = 'CONFIG_' + k.to_upper()
465    endif
466    config_host_data.set_quoted(k, v)
467  elif k.startswith('CONFIG_') or k.startswith('HAVE_') or k.startswith('HOST_')
468    config_host_data.set(k, v == 'y' ? 1 : v)
469  endif
470endforeach
471genh += configure_file(output: 'config-host.h', configuration: config_host_data)
472
473minikconf = find_program('scripts/minikconf.py')
474config_all_devices = {}
475config_all_disas = {}
476config_devices_mak_list = []
477config_devices_h = {}
478config_target_h = {}
479config_target_mak = {}
480
481disassemblers = {
482  'alpha' : ['CONFIG_ALPHA_DIS'],
483  'arm' : ['CONFIG_ARM_DIS'],
484  'avr' : ['CONFIG_AVR_DIS'],
485  'cris' : ['CONFIG_CRIS_DIS'],
486  'hppa' : ['CONFIG_HPPA_DIS'],
487  'i386' : ['CONFIG_I386_DIS'],
488  'x86_64' : ['CONFIG_I386_DIS'],
489  'x32' : ['CONFIG_I386_DIS'],
490  'lm32' : ['CONFIG_LM32_DIS'],
491  'm68k' : ['CONFIG_M68K_DIS'],
492  'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
493  'mips' : ['CONFIG_MIPS_DIS'],
494  'moxie' : ['CONFIG_MOXIE_DIS'],
495  'nios2' : ['CONFIG_NIOS2_DIS'],
496  'or1k' : ['CONFIG_OPENRISC_DIS'],
497  'ppc' : ['CONFIG_PPC_DIS'],
498  'riscv' : ['CONFIG_RISCV_DIS'],
499  'rx' : ['CONFIG_RX_DIS'],
500  's390' : ['CONFIG_S390_DIS'],
501  'sh4' : ['CONFIG_SH4_DIS'],
502  'sparc' : ['CONFIG_SPARC_DIS'],
503  'xtensa' : ['CONFIG_XTENSA_DIS'],
504}
505if link_language == 'cpp'
506  disassemblers += {
507    'aarch64' : [ 'CONFIG_ARM_A64_DIS'],
508    'arm' : [ 'CONFIG_ARM_DIS', 'CONFIG_ARM_A64_DIS'],
509    'mips' : [ 'CONFIG_MIPS_DIS', 'CONFIG_NANOMIPS_DIS'],
510  }
511endif
512
513kconfig_external_symbols = [
514  'CONFIG_KVM',
515  'CONFIG_XEN',
516  'CONFIG_TPM',
517  'CONFIG_SPICE',
518  'CONFIG_IVSHMEM',
519  'CONFIG_OPENGL',
520  'CONFIG_X11',
521  'CONFIG_VHOST_USER',
522  'CONFIG_VHOST_KERNEL',
523  'CONFIG_VIRTFS',
524  'CONFIG_LINUX',
525  'CONFIG_PVRDMA',
526]
527ignored = ['TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_DIRS']
528
529foreach target : target_dirs
530  config_target = keyval.load(meson.current_build_dir() / target / 'config-target.mak')
531
532  foreach k, v: disassemblers
533    if config_host['ARCH'].startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k)
534      foreach sym: v
535        config_target += { sym: 'y' }
536        config_all_disas += { sym: 'y' }
537      endforeach
538    endif
539  endforeach
540
541  config_target_data = configuration_data()
542  foreach k, v: config_target
543    if not k.startswith('TARGET_') and not k.startswith('CONFIG_')
544      # do nothing
545    elif ignored.contains(k)
546      # do nothing
547    elif k == 'TARGET_BASE_ARCH'
548      config_target_data.set('TARGET_' + v.to_upper(), 1)
549    elif k == 'TARGET_NAME'
550      config_target_data.set_quoted(k, v)
551    elif v == 'y'
552      config_target_data.set(k, 1)
553    else
554      config_target_data.set(k, v)
555    endif
556  endforeach
557  config_target_h += {target: configure_file(output: target + '-config-target.h',
558                                               configuration: config_target_data)}
559
560  if target.endswith('-softmmu')
561    base_kconfig = []
562    foreach sym : kconfig_external_symbols
563      if sym in config_target or sym in config_host
564        base_kconfig += '@0@=y'.format(sym)
565      endif
566    endforeach
567
568    config_devices_mak = target + '-config-devices.mak'
569    config_devices_mak = configure_file(
570      input: ['default-configs' / target + '.mak', 'Kconfig'],
571      output: config_devices_mak,
572      depfile: config_devices_mak + '.d',
573      capture: true,
574      command: [minikconf, config_host['CONFIG_MINIKCONF_MODE'],
575                config_devices_mak, '@DEPFILE@', '@INPUT@',
576                base_kconfig])
577
578    config_devices_data = configuration_data()
579    config_devices = keyval.load(config_devices_mak)
580    foreach k, v: config_devices
581      config_devices_data.set(k, 1)
582    endforeach
583    config_devices_mak_list += config_devices_mak
584    config_devices_h += {target: configure_file(output: target + '-config-devices.h',
585                                                configuration: config_devices_data)}
586    config_target += config_devices
587    config_all_devices += config_devices
588  endif
589  config_target_mak += {target: config_target}
590endforeach
591
592# This configuration is used to build files that are shared by
593# multiple binaries, and then extracted out of the "common"
594# static_library target.
595#
596# We do not use all_sources()/all_dependencies(), because it would
597# build literally all source files, including devices only used by
598# targets that are not built for this compilation.  The CONFIG_ALL
599# pseudo symbol replaces it.
600
601config_all = config_all_devices
602config_all += config_host
603config_all += config_all_disas
604config_all += {
605  'CONFIG_XEN': config_host.has_key('CONFIG_XEN_BACKEND'),
606  'CONFIG_SOFTMMU': have_system,
607  'CONFIG_USER_ONLY': have_user,
608  'CONFIG_ALL': true,
609}
610
611# Generators
612
613hxtool = find_program('scripts/hxtool')
614shaderinclude = find_program('scripts/shaderinclude.pl')
615qapi_gen = find_program('scripts/qapi-gen.py')
616qapi_gen_depends = [ meson.source_root() / 'scripts/qapi/__init__.py',
617                     meson.source_root() / 'scripts/qapi/commands.py',
618                     meson.source_root() / 'scripts/qapi/common.py',
619                     meson.source_root() / 'scripts/qapi/doc.py',
620                     meson.source_root() / 'scripts/qapi/error.py',
621                     meson.source_root() / 'scripts/qapi/events.py',
622                     meson.source_root() / 'scripts/qapi/expr.py',
623                     meson.source_root() / 'scripts/qapi/gen.py',
624                     meson.source_root() / 'scripts/qapi/introspect.py',
625                     meson.source_root() / 'scripts/qapi/parser.py',
626                     meson.source_root() / 'scripts/qapi/schema.py',
627                     meson.source_root() / 'scripts/qapi/source.py',
628                     meson.source_root() / 'scripts/qapi/types.py',
629                     meson.source_root() / 'scripts/qapi/visit.py',
630                     meson.source_root() / 'scripts/qapi/common.py',
631                     meson.source_root() / 'scripts/qapi/doc.py',
632                     meson.source_root() / 'scripts/qapi-gen.py'
633]
634
635tracetool = [
636  python, files('scripts/tracetool.py'),
637   '--backend=' + config_host['TRACE_BACKENDS']
638]
639
640qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
641                    meson.current_source_dir(),
642                    config_host['PKGVERSION'], meson.project_version()]
643qemu_version = custom_target('qemu-version.h',
644                             output: 'qemu-version.h',
645                             command: qemu_version_cmd,
646                             capture: true,
647                             build_by_default: true,
648                             build_always_stale: true)
649genh += qemu_version
650
651hxdep = []
652hx_headers = [
653  ['qemu-options.hx', 'qemu-options.def'],
654  ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
655]
656if have_system
657  hx_headers += [
658    ['hmp-commands.hx', 'hmp-commands.h'],
659    ['hmp-commands-info.hx', 'hmp-commands-info.h'],
660  ]
661endif
662foreach d : hx_headers
663  hxdep += custom_target(d[1],
664                input: files(d[0]),
665                output: d[1],
666                capture: true,
667                build_by_default: true, # to be removed when added to a target
668                command: [hxtool, '-h', '@INPUT0@'])
669endforeach
670genh += hxdep
671
672# Collect sourcesets.
673
674util_ss = ss.source_set()
675stub_ss = ss.source_set()
676trace_ss = ss.source_set()
677block_ss = ss.source_set()
678blockdev_ss = ss.source_set()
679qmp_ss = ss.source_set()
680common_ss = ss.source_set()
681softmmu_ss = ss.source_set()
682user_ss = ss.source_set()
683bsd_user_ss = ss.source_set()
684linux_user_ss = ss.source_set()
685specific_ss = ss.source_set()
686specific_fuzz_ss = ss.source_set()
687
688modules = {}
689hw_arch = {}
690target_arch = {}
691target_softmmu_arch = {}
692
693###############
694# Trace files #
695###############
696
697# TODO: add each directory to the subdirs from its own meson.build, once
698# we have those
699trace_events_subdirs = [
700  'accel/kvm',
701  'accel/tcg',
702  'crypto',
703  'monitor',
704]
705if have_user
706  trace_events_subdirs += [ 'linux-user' ]
707endif
708if have_block
709  trace_events_subdirs += [
710    'authz',
711    'block',
712    'io',
713    'nbd',
714    'scsi',
715  ]
716endif
717if have_system
718  trace_events_subdirs += [
719    'audio',
720    'backends',
721    'backends/tpm',
722    'chardev',
723    'hw/9pfs',
724    'hw/acpi',
725    'hw/alpha',
726    'hw/arm',
727    'hw/audio',
728    'hw/block',
729    'hw/block/dataplane',
730    'hw/char',
731    'hw/display',
732    'hw/dma',
733    'hw/hppa',
734    'hw/hyperv',
735    'hw/i2c',
736    'hw/i386',
737    'hw/i386/xen',
738    'hw/ide',
739    'hw/input',
740    'hw/intc',
741    'hw/isa',
742    'hw/mem',
743    'hw/mips',
744    'hw/misc',
745    'hw/misc/macio',
746    'hw/net',
747    'hw/nvram',
748    'hw/pci',
749    'hw/pci-host',
750    'hw/ppc',
751    'hw/rdma',
752    'hw/rdma/vmw',
753    'hw/rtc',
754    'hw/s390x',
755    'hw/scsi',
756    'hw/sd',
757    'hw/sparc',
758    'hw/sparc64',
759    'hw/ssi',
760    'hw/timer',
761    'hw/tpm',
762    'hw/usb',
763    'hw/vfio',
764    'hw/virtio',
765    'hw/watchdog',
766    'hw/xen',
767    'hw/gpio',
768    'hw/riscv',
769    'migration',
770    'net',
771    'ui',
772  ]
773endif
774trace_events_subdirs += [
775  'hw/core',
776  'qapi',
777  'qom',
778  'target/arm',
779  'target/hppa',
780  'target/i386',
781  'target/mips',
782  'target/ppc',
783  'target/riscv',
784  'target/s390x',
785  'target/sparc',
786  'util',
787]
788
789subdir('qapi')
790subdir('qobject')
791subdir('stubs')
792subdir('trace')
793subdir('util')
794subdir('qom')
795subdir('authz')
796subdir('crypto')
797subdir('ui')
798
799
800if enable_modules
801  libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
802  modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
803endif
804
805# Build targets from sourcesets
806
807stub_ss = stub_ss.apply(config_all, strict: false)
808
809util_ss.add_all(trace_ss)
810util_ss = util_ss.apply(config_all, strict: false)
811libqemuutil = static_library('qemuutil',
812                             sources: util_ss.sources() + stub_ss.sources() + genh,
813                             dependencies: [util_ss.dependencies(), m, glib, socket])
814qemuutil = declare_dependency(link_with: libqemuutil,
815                              sources: genh + version_res)
816
817decodetree = generator(find_program('scripts/decodetree.py'),
818                       output: 'decode-@BASENAME@.c.inc',
819                       arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
820
821subdir('audio')
822subdir('io')
823subdir('chardev')
824subdir('fsdev')
825subdir('libdecnumber')
826subdir('target')
827subdir('dump')
828
829block_ss.add(files(
830  'block.c',
831  'blockjob.c',
832  'job.c',
833  'qemu-io-cmds.c',
834))
835block_ss.add(when: 'CONFIG_REPLICATION', if_true: files('replication.c'))
836
837subdir('nbd')
838subdir('scsi')
839subdir('block')
840
841blockdev_ss.add(files(
842  'blockdev.c',
843  'blockdev-nbd.c',
844  'iothread.c',
845  'job-qmp.c',
846))
847
848# os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
849# os-win32.c does not
850blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
851softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
852
853softmmu_ss.add_all(blockdev_ss)
854softmmu_ss.add(files(
855  'bootdevice.c',
856  'dma-helpers.c',
857  'qdev-monitor.c',
858), sdl)
859
860softmmu_ss.add(when: 'CONFIG_TPM', if_true: files('tpm.c'))
861softmmu_ss.add(when: 'CONFIG_SECCOMP', if_true: [files('qemu-seccomp.c'), seccomp])
862softmmu_ss.add(when: ['CONFIG_FDT', fdt],  if_true: [files('device_tree.c')])
863
864common_ss.add(files('cpus-common.c'))
865
866subdir('softmmu')
867
868specific_ss.add(files('disas.c', 'exec.c', 'gdbstub.c'), capstone, libpmem, libdaxctl)
869specific_ss.add(files('exec-vary.c'))
870specific_ss.add(when: 'CONFIG_TCG', if_true: files(
871  'fpu/softfloat.c',
872  'tcg/optimize.c',
873  'tcg/tcg-common.c',
874  'tcg/tcg-op-gvec.c',
875  'tcg/tcg-op-vec.c',
876  'tcg/tcg-op.c',
877  'tcg/tcg.c',
878))
879specific_ss.add(when: 'CONFIG_TCG_INTERPRETER', if_true: files('disas/tci.c', 'tcg/tci.c'))
880
881subdir('backends')
882subdir('disas')
883subdir('migration')
884subdir('monitor')
885subdir('net')
886subdir('replay')
887subdir('hw')
888subdir('accel')
889subdir('plugins')
890subdir('bsd-user')
891subdir('linux-user')
892
893bsd_user_ss.add(files('gdbstub.c'))
894specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss)
895
896linux_user_ss.add(files('gdbstub.c', 'thunk.c'))
897specific_ss.add_all(when: 'CONFIG_LINUX_USER', if_true: linux_user_ss)
898
899# needed for fuzzing binaries
900subdir('tests/qtest/libqos')
901subdir('tests/qtest/fuzz')
902
903block_mods = []
904softmmu_mods = []
905foreach d, list : modules
906  foreach m, module_ss : list
907    if enable_modules and targetos != 'windows'
908      module_ss = module_ss.apply(config_host, strict: false)
909      sl = static_library(d + '-' + m, [genh, module_ss.sources()],
910                          dependencies: [modulecommon, module_ss.dependencies()], pic: true)
911      if d == 'block'
912        block_mods += sl
913      else
914        softmmu_mods += sl
915      endif
916    else
917      if d == 'block'
918        block_ss.add_all(module_ss)
919      else
920        softmmu_ss.add_all(module_ss)
921      endif
922    endif
923  endforeach
924endforeach
925
926nm = find_program('nm')
927undefsym = find_program('scripts/undefsym.sh')
928block_syms = custom_target('block.syms', output: 'block.syms',
929                             input: [libqemuutil, block_mods],
930                             capture: true,
931                             command: [undefsym, nm, '@INPUT@'])
932qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
933                             input: [libqemuutil, softmmu_mods],
934                             capture: true,
935                             command: [undefsym, nm, '@INPUT@'])
936
937block_ss = block_ss.apply(config_host, strict: false)
938libblock = static_library('block', block_ss.sources() + genh,
939                          dependencies: block_ss.dependencies(),
940                          link_depends: block_syms,
941                          name_suffix: 'fa',
942                          build_by_default: false)
943
944block = declare_dependency(link_whole: [libblock],
945                           link_args: '@block.syms',
946                           dependencies: [crypto, io])
947
948qmp_ss = qmp_ss.apply(config_host, strict: false)
949libqmp = static_library('qmp', qmp_ss.sources() + genh,
950                        dependencies: qmp_ss.dependencies(),
951                        name_suffix: 'fa',
952                        build_by_default: false)
953
954qmp = declare_dependency(link_whole: [libqmp])
955
956foreach m : block_mods + softmmu_mods
957  shared_module(m.name(),
958                name_prefix: '',
959                link_whole: m,
960                install: true,
961                install_dir: config_host['qemu_moddir'])
962endforeach
963
964softmmu_ss.add(authz, block, chardev, crypto, io, qmp)
965common_ss.add(qom, qemuutil)
966
967common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
968common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
969
970common_all = common_ss.apply(config_all, strict: false)
971common_all = static_library('common',
972                            build_by_default: false,
973                            sources: common_all.sources() + genh,
974                            dependencies: common_all.dependencies(),
975                            name_suffix: 'fa')
976
977feature_to_c = find_program('scripts/feature_to_c.sh')
978
979emulators = []
980foreach target : target_dirs
981  config_target = config_target_mak[target]
982  target_name = config_target['TARGET_NAME']
983  arch = config_target['TARGET_BASE_ARCH']
984  arch_srcs = [config_target_h[target]]
985  arch_deps = []
986  c_args = ['-DNEED_CPU_H',
987            '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
988            '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
989  link_args = []
990
991  config_target += config_host
992  target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
993  if targetos == 'linux'
994    target_inc += include_directories('linux-headers', is_system: true)
995  endif
996  if target.endswith('-softmmu')
997    qemu_target_name = 'qemu-system-' + target_name
998    target_type='system'
999    t = target_softmmu_arch[arch].apply(config_target, strict: false)
1000    arch_srcs += t.sources()
1001    arch_deps += t.dependencies()
1002
1003    hw_dir = target_name == 'sparc64' ? 'sparc64' : arch
1004    hw = hw_arch[hw_dir].apply(config_target, strict: false)
1005    arch_srcs += hw.sources()
1006    arch_deps += hw.dependencies()
1007
1008    arch_srcs += config_devices_h[target]
1009    link_args += ['@block.syms', '@qemu.syms']
1010  else
1011    abi = config_target['TARGET_ABI_DIR']
1012    target_type='user'
1013    qemu_target_name = 'qemu-' + target_name
1014    if 'CONFIG_LINUX_USER' in config_target
1015      base_dir = 'linux-user'
1016      target_inc += include_directories('linux-user/host/' / config_host['ARCH'])
1017    else
1018      base_dir = 'bsd-user'
1019    endif
1020    target_inc += include_directories(
1021      base_dir,
1022      base_dir / abi,
1023    )
1024    if 'CONFIG_LINUX_USER' in config_target
1025      dir = base_dir / abi
1026      arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
1027      if config_target.has_key('TARGET_SYSTBL_ABI')
1028        arch_srcs += \
1029          syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
1030                                             extra_args : config_target['TARGET_SYSTBL_ABI'])
1031      endif
1032    endif
1033  endif
1034
1035  if 'TARGET_XML_FILES' in config_target
1036    gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
1037                                output: target + '-gdbstub-xml.c',
1038                                input: files(config_target['TARGET_XML_FILES'].split()),
1039                                command: [feature_to_c, '@INPUT@'],
1040                                capture: true)
1041    arch_srcs += gdbstub_xml
1042  endif
1043
1044  t = target_arch[arch].apply(config_target, strict: false)
1045  arch_srcs += t.sources()
1046  arch_deps += t.dependencies()
1047
1048  target_common = common_ss.apply(config_target, strict: false)
1049  objects = common_all.extract_objects(target_common.sources())
1050  deps = target_common.dependencies()
1051
1052  target_specific = specific_ss.apply(config_target, strict: false)
1053  arch_srcs += target_specific.sources()
1054  arch_deps += target_specific.dependencies()
1055
1056  lib = static_library('qemu-' + target,
1057                 sources: arch_srcs + genh,
1058                 dependencies: arch_deps,
1059                 objects: objects,
1060                 include_directories: target_inc,
1061                 c_args: c_args,
1062                 build_by_default: false,
1063                 name_suffix: 'fa')
1064
1065  if target.endswith('-softmmu')
1066    execs = [{
1067      'name': 'qemu-system-' + target_name,
1068      'gui': false,
1069      'sources': files('softmmu/main.c'),
1070      'dependencies': []
1071    }]
1072    if targetos == 'windows' and (sdl.found() or gtk.found())
1073      execs += [{
1074        'name': 'qemu-system-' + target_name + 'w',
1075        'gui': true,
1076        'sources': files('softmmu/main.c'),
1077        'dependencies': []
1078      }]
1079    endif
1080    if config_host.has_key('CONFIG_FUZZ')
1081      specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
1082      execs += [{
1083        'name': 'qemu-fuzz-' + target_name,
1084        'gui': false,
1085        'sources': specific_fuzz.sources(),
1086        'dependencies': specific_fuzz.dependencies(),
1087        'link_depends': [files('tests/qtest/fuzz/fork_fuzz.ld')],
1088      }]
1089    endif
1090  else
1091    execs = [{
1092      'name': 'qemu-' + target_name,
1093      'gui': false,
1094      'sources': [],
1095      'dependencies': []
1096    }]
1097  endif
1098  foreach exe: execs
1099    emulators += executable(exe['name'], exe['sources'],
1100               install: true,
1101               c_args: c_args,
1102               dependencies: arch_deps + deps + exe['dependencies'],
1103               objects: lib.extract_all_objects(recursive: true),
1104               link_language: link_language,
1105               link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
1106               link_args: link_args,
1107               gui_app: exe['gui'])
1108
1109    if 'CONFIG_TRACE_SYSTEMTAP' in config_host
1110      foreach stp: [
1111        {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
1112        {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
1113        {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
1114        {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
1115      ]
1116        custom_target(exe['name'] + stp['ext'],
1117                      input: trace_events_all,
1118                      output: exe['name'] + stp['ext'],
1119                      capture: true,
1120                      install: stp['install'],
1121                      install_dir: qemu_datadir / '../systemtap/tapset',
1122                      command: [
1123                        tracetool, '--group=all', '--format=' + stp['fmt'],
1124                        '--binary=' + stp['bin'],
1125                        '--target-name=' + target_name,
1126                        '--target-type=' + target_type,
1127                        '--probe-prefix=qemu.' + target_type + '.' + target_name,
1128                        '@INPUT@',
1129                      ])
1130      endforeach
1131    endif
1132  endforeach
1133endforeach
1134
1135# Other build targets
1136
1137if 'CONFIG_PLUGIN' in config_host
1138  install_headers('include/qemu/qemu-plugin.h')
1139endif
1140
1141if 'CONFIG_GUEST_AGENT' in config_host
1142  subdir('qga')
1143endif
1144
1145# Don't build qemu-keymap if xkbcommon is not explicitly enabled
1146# when we don't build tools or system
1147if xkbcommon.found()
1148  # used for the update-keymaps target, so include rules even if !have_tools
1149  qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
1150                           dependencies: [qemuutil, xkbcommon], install: have_tools)
1151endif
1152
1153qemu_block_tools = []
1154if have_tools
1155  qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
1156             dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
1157  qemu_io = executable('qemu-io', files('qemu-io.c'),
1158             dependencies: [block, qemuutil], install: true)
1159  qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
1160               dependencies: [block, qemuutil], install: true)
1161
1162  subdir('storage-daemon')
1163  subdir('contrib/rdmacm-mux')
1164  subdir('contrib/elf2dmp')
1165
1166  executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
1167             dependencies: qemuutil,
1168             install: true)
1169
1170  if 'CONFIG_VHOST_USER' in config_host
1171    subdir('contrib/libvhost-user')
1172    subdir('contrib/vhost-user-blk')
1173    subdir('contrib/vhost-user-gpu')
1174    subdir('contrib/vhost-user-input')
1175    subdir('contrib/vhost-user-scsi')
1176  endif
1177
1178  if targetos == 'linux'
1179    executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
1180               dependencies: [qemuutil, libcap_ng],
1181               install: true,
1182               install_dir: get_option('libexecdir'))
1183
1184    executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
1185               dependencies: [authz, crypto, io, qom, qemuutil,
1186                              libcap_ng, libudev, libmpathpersist],
1187               install: true)
1188  endif
1189
1190  if 'CONFIG_IVSHMEM' in config_host
1191    subdir('contrib/ivshmem-client')
1192    subdir('contrib/ivshmem-server')
1193  endif
1194endif
1195
1196subdir('scripts')
1197subdir('tools')
1198subdir('pc-bios')
1199subdir('tests')
1200subdir('docs')
1201if 'CONFIG_GTK' in config_host
1202  subdir('po')
1203endif
1204
1205if build_docs
1206  makeinfo = find_program('makeinfo', required: build_docs)
1207
1208  docs_inc = [
1209    '-I', meson.current_source_dir(),
1210    '-I', meson.current_build_dir() / 'docs',
1211    '-I', '@OUTDIR@',
1212  ]
1213
1214  version_texi = configure_file(output: 'version.texi',
1215                              input: 'version.texi.in',
1216                              configuration: {'VERSION': meson.project_version(),
1217                                              'qemu_confdir': config_host['qemu_confdir']})
1218
1219  texi = {
1220    'qemu-qmp-ref': ['docs/interop/qemu-qmp-ref.texi', qapi_doc_texi, version_texi],
1221  }
1222  if 'CONFIG_GUEST_AGENT' in config_host
1223    texi += {'qemu-ga-ref': ['docs/interop/qemu-ga-ref.texi', qga_qapi_doc_texi, version_texi]}
1224  endif
1225
1226  if makeinfo.found()
1227    cmd = [
1228      'env', 'LC_ALL=C', makeinfo, '--no-split', '--number-sections', docs_inc,
1229      '@INPUT0@', '-o', '@OUTPUT@',
1230    ]
1231    foreach ext, args: {
1232        'info': [],
1233        'html': ['--no-headers', '--html'],
1234        'txt': ['--no-headers', '--plaintext'],
1235    }
1236      t = []
1237      foreach doc, input: texi
1238        output = doc + '.' + ext
1239        t += custom_target(output,
1240                      input: input,
1241                      output: output,
1242                      install: true,
1243                      install_dir: qemu_docdir / 'interop',
1244                      command: cmd + args)
1245      endforeach
1246      alias_target(ext, t)
1247    endforeach
1248  endif
1249
1250  texi2pdf = find_program('texi2pdf', required: false)
1251
1252  if texi2pdf.found()
1253    pdfs = []
1254    foreach doc, input: texi
1255      output = doc + '.pdf'
1256      pdfs += custom_target(output,
1257                    input: input,
1258                    output: output,
1259                    command: [texi2pdf, '-q', docs_inc, '@INPUT0@', '-o', '@OUTPUT@'],
1260                    build_by_default: false)
1261    endforeach
1262    alias_target('pdf', pdfs)
1263  endif
1264
1265  texi2pod = find_program('scripts/texi2pod.pl')
1266  pod2man = find_program('pod2man', required: build_docs)
1267
1268  if pod2man.found()
1269    foreach doc, input: texi
1270      man = doc + '.7'
1271      pod = custom_target(man + '.pod',
1272                          input: input,
1273                          output: man + '.pod',
1274                          command: [texi2pod,
1275                                    '-DVERSION="' + meson.project_version() + '"',
1276                                    '-DCONFDIR="' + config_host['qemu_confdir'] + '"',
1277                                    '@INPUT0@', '@OUTPUT@'])
1278      man = custom_target(man,
1279                          input: pod,
1280                          output: man,
1281                          capture: true,
1282                          install: true,
1283                          install_dir: get_option('mandir') / 'man7',
1284                          command: [pod2man, '--utf8', '--section=7', '--center=" "',
1285                                    '--release=" "', '@INPUT@'])
1286    endforeach
1287  endif
1288endif
1289
1290if host_machine.system() == 'windows'
1291  nsis_cmd = [
1292    find_program('scripts/nsis.py'),
1293    '@OUTPUT@',
1294    get_option('prefix'),
1295    meson.current_source_dir(),
1296    host_machine.cpu_family(),
1297    '--',
1298    '-DDISPLAYVERSION=' + meson.project_version(),
1299  ]
1300  if build_docs
1301    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
1302  endif
1303  if 'CONFIG_GTK' in config_host
1304    nsis_cmd += '-DCONFIG_GTK=y'
1305  endif
1306
1307  nsis = custom_target('nsis',
1308                       output: 'qemu-setup-' + meson.project_version() + '.exe',
1309                       input: files('qemu.nsi'),
1310                       build_always_stale: true,
1311                       command: nsis_cmd + ['@INPUT@'])
1312  alias_target('installer', nsis)
1313endif
1314
1315summary_info = {}
1316summary_info += {'Install prefix':    config_host['prefix']}
1317summary_info += {'BIOS directory':    config_host['qemu_datadir']}
1318summary_info += {'firmware path':     config_host['qemu_firmwarepath']}
1319summary_info += {'binary directory':  config_host['bindir']}
1320summary_info += {'library directory': config_host['libdir']}
1321summary_info += {'module directory':  config_host['qemu_moddir']}
1322summary_info += {'libexec directory': config_host['libexecdir']}
1323summary_info += {'include directory': config_host['includedir']}
1324summary_info += {'config directory':  config_host['sysconfdir']}
1325if targetos != 'windows'
1326  summary_info += {'local state directory': config_host['qemu_localstatedir']}
1327  summary_info += {'Manual directory':      get_option('mandir')}
1328else
1329  summary_info += {'local state directory': 'queried at runtime'}
1330endif
1331summary_info += {'Doc directory':     get_option('docdir')}
1332summary_info += {'Build directory':   meson.current_build_dir()}
1333summary_info += {'Source path':       meson.current_source_dir()}
1334summary_info += {'GIT binary':        config_host['GIT']}
1335summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
1336summary_info += {'C compiler':        meson.get_compiler('c').cmd_array()[0]}
1337summary_info += {'Host C compiler':   meson.get_compiler('c', native: true).cmd_array()[0]}
1338if link_language == 'cpp'
1339  summary_info += {'C++ compiler':      meson.get_compiler('cpp').cmd_array()[0]}
1340else
1341  summary_info += {'C++ compiler':      false}
1342endif
1343if targetos == 'darwin'
1344  summary_info += {'Objective-C compiler': meson.get_compiler('objc').cmd_array()[0]}
1345endif
1346summary_info += {'ARFLAGS':           config_host['ARFLAGS']}
1347summary_info += {'CFLAGS':            config_host['CFLAGS']}
1348summary_info += {'QEMU_CFLAGS':       config_host['QEMU_CFLAGS']}
1349summary_info += {'QEMU_LDFLAGS':      config_host['QEMU_LDFLAGS']}
1350summary_info += {'make':              config_host['MAKE']}
1351summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
1352summary_info += {'sphinx-build':      config_host['SPHINX_BUILD']}
1353summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
1354# TODO: add back version
1355summary_info += {'slirp support':     config_host.has_key('CONFIG_SLIRP')}
1356if config_host.has_key('CONFIG_SLIRP')
1357  summary_info += {'smbd':            config_host['CONFIG_SMBD_COMMAND']}
1358endif
1359summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
1360if config_host.has_key('CONFIG_MODULES')
1361  summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')}
1362endif
1363summary_info += {'host CPU':          cpu}
1364summary_info += {'host endianness':   build_machine.endian()}
1365summary_info += {'target list':       config_host['TARGET_DIRS']}
1366summary_info += {'gprof enabled':     config_host.has_key('CONFIG_GPROF')}
1367summary_info += {'sparse enabled':    meson.get_compiler('c').cmd_array().contains('cgcc')}
1368summary_info += {'strip binaries':    get_option('strip')}
1369summary_info += {'profiler':          config_host.has_key('CONFIG_PROFILER')}
1370summary_info += {'static build':      config_host.has_key('CONFIG_TOOLS')}
1371if targetos == 'darwin'
1372  summary_info += {'Cocoa support': config_host.has_key('CONFIG_COCOA')}
1373endif
1374# TODO: add back version
1375summary_info += {'SDL support':       sdl.found()}
1376summary_info += {'SDL image support': sdl_image.found()}
1377# TODO: add back version
1378summary_info += {'GTK support':       config_host.has_key('CONFIG_GTK')}
1379summary_info += {'GTK GL support':    config_host.has_key('CONFIG_GTK_GL')}
1380summary_info += {'pixman':            pixman.found()}
1381# TODO: add back version
1382summary_info += {'VTE support':       config_host.has_key('CONFIG_VTE')}
1383summary_info += {'TLS priority':      config_host['CONFIG_TLS_PRIORITY']}
1384summary_info += {'GNUTLS support':    config_host.has_key('CONFIG_GNUTLS')}
1385# TODO: add back version
1386summary_info += {'libgcrypt':         config_host.has_key('CONFIG_GCRYPT')}
1387if config_host.has_key('CONFIG_GCRYPT')
1388   summary_info += {'  hmac':            config_host.has_key('CONFIG_GCRYPT_HMAC')}
1389   summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
1390endif
1391# TODO: add back version
1392summary_info += {'nettle':            config_host.has_key('CONFIG_NETTLE')}
1393if config_host.has_key('CONFIG_NETTLE')
1394   summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
1395endif
1396summary_info += {'libtasn1':          config_host.has_key('CONFIG_TASN1')}
1397summary_info += {'PAM':               config_host.has_key('CONFIG_AUTH_PAM')}
1398summary_info += {'iconv support':     config_host.has_key('CONFIG_ICONV')}
1399summary_info += {'curses support':    config_host.has_key('CONFIG_CURSES')}
1400# TODO: add back version
1401summary_info += {'virgl support':     config_host.has_key('CONFIG_VIRGL')}
1402summary_info += {'curl support':      config_host.has_key('CONFIG_CURL')}
1403summary_info += {'mingw32 support':   targetos == 'windows'}
1404summary_info += {'Audio drivers':     config_host['CONFIG_AUDIO_DRIVERS']}
1405summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']}
1406summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']}
1407summary_info += {'VirtFS support':    config_host.has_key('CONFIG_VIRTFS')}
1408summary_info += {'Multipath support': config_host.has_key('CONFIG_MPATH')}
1409summary_info += {'VNC support':       vnc.found()}
1410if vnc.found()
1411  summary_info += {'VNC SASL support':  sasl.found()}
1412  summary_info += {'VNC JPEG support':  jpeg.found()}
1413  summary_info += {'VNC PNG support':   png.found()}
1414endif
1415summary_info += {'xen support':       config_host.has_key('CONFIG_XEN_BACKEND')}
1416if config_host.has_key('CONFIG_XEN_BACKEND')
1417  summary_info += {'xen ctrl version':  config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
1418endif
1419summary_info += {'brlapi support':    config_host.has_key('CONFIG_BRLAPI')}
1420summary_info += {'Documentation':     config_host.has_key('BUILD_DOCS')}
1421summary_info += {'PIE':               get_option('b_pie')}
1422summary_info += {'vde support':       config_host.has_key('CONFIG_VDE')}
1423summary_info += {'netmap support':    config_host.has_key('CONFIG_NETMAP')}
1424summary_info += {'Linux AIO support': config_host.has_key('CONFIG_LINUX_AIO')}
1425summary_info += {'Linux io_uring support': config_host.has_key('CONFIG_LINUX_IO_URING')}
1426summary_info += {'ATTR/XATTR support': config_host.has_key('CONFIG_ATTR')}
1427summary_info += {'Install blobs':     config_host.has_key('INSTALL_BLOBS')}
1428# TODO: add back KVM/HAX/HVF/WHPX/TCG
1429#summary_info += {'KVM support':       have_kvm'}
1430#summary_info += {'HAX support':       have_hax'}
1431#summary_info += {'HVF support':       have_hvf'}
1432#summary_info += {'WHPX support':      have_whpx'}
1433#summary_info += {'TCG support':       have_tcg'}
1434#if get_option('tcg')
1435#  summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
1436#  summary_info += {'TCG interpreter':   config_host.has_key('CONFIG_TCG_INTERPRETER')}
1437#endif
1438summary_info += {'malloc trim support': config_host.has_key('CONFIG_MALLOC_TRIM')}
1439summary_info += {'RDMA support':      config_host.has_key('CONFIG_RDMA')}
1440summary_info += {'PVRDMA support':    config_host.has_key('CONFIG_PVRDMA')}
1441summary_info += {'fdt support':       config_host.has_key('CONFIG_FDT')}
1442summary_info += {'membarrier':        config_host.has_key('CONFIG_MEMBARRIER')}
1443summary_info += {'preadv support':    config_host.has_key('CONFIG_PREADV')}
1444summary_info += {'fdatasync':         config_host.has_key('CONFIG_FDATASYNC')}
1445summary_info += {'madvise':           config_host.has_key('CONFIG_MADVISE')}
1446summary_info += {'posix_madvise':     config_host.has_key('CONFIG_POSIX_MADVISE')}
1447summary_info += {'posix_memalign':    config_host.has_key('CONFIG_POSIX_MEMALIGN')}
1448summary_info += {'libcap-ng support': config_host.has_key('CONFIG_LIBCAP_NG')}
1449summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')}
1450summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')}
1451summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')}
1452summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')}
1453summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_KERNEL')}
1454summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')}
1455summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')}
1456summary_info += {'Trace backends':    config_host['TRACE_BACKENDS']}
1457if config_host['TRACE_BACKENDS'].split().contains('simple')
1458  summary_info += {'Trace output file': config_host['CONFIG_TRACE_FILE'] + '-<pid>'}
1459endif
1460# TODO: add back protocol and server version
1461summary_info += {'spice support':     config_host.has_key('CONFIG_SPICE')}
1462summary_info += {'rbd support':       config_host.has_key('CONFIG_RBD')}
1463summary_info += {'xfsctl support':    config_host.has_key('CONFIG_XFS')}
1464summary_info += {'smartcard support': config_host.has_key('CONFIG_SMARTCARD')}
1465summary_info += {'U2F support':       u2f.found()}
1466summary_info += {'libusb':            config_host.has_key('CONFIG_USB_LIBUSB')}
1467summary_info += {'usb net redir':     config_host.has_key('CONFIG_USB_REDIR')}
1468summary_info += {'OpenGL support':    config_host.has_key('CONFIG_OPENGL')}
1469summary_info += {'OpenGL dmabufs':    config_host.has_key('CONFIG_OPENGL_DMABUF')}
1470summary_info += {'libiscsi support':  config_host.has_key('CONFIG_LIBISCSI')}
1471summary_info += {'libnfs support':    config_host.has_key('CONFIG_LIBNFS')}
1472summary_info += {'build guest agent': config_host.has_key('CONFIG_GUEST_AGENT')}
1473if targetos == 'windows'
1474  if 'WIN_SDK' in config_host
1475    summary_info += {'Windows SDK':       config_host['WIN_SDK']}
1476  endif
1477  summary_info += {'QGA VSS support':   config_host.has_key('CONFIG_QGA_VSS')}
1478  summary_info += {'QGA w32 disk info': config_host.has_key('CONFIG_QGA_NTDDSCSI')}
1479  summary_info += {'QGA MSI support':   config_host.has_key('CONFIG_QGA_MSI_ENABLED')}
1480endif
1481summary_info += {'seccomp support':   config_host.has_key('CONFIG_SECCOMP')}
1482summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
1483summary_info += {'coroutine pool':    config_host['CONFIG_COROUTINE_POOL'] == '1'}
1484summary_info += {'debug stack usage': config_host.has_key('CONFIG_DEBUG_STACK_USAGE')}
1485summary_info += {'mutex debugging':   config_host.has_key('CONFIG_DEBUG_MUTEX')}
1486summary_info += {'crypto afalg':      config_host.has_key('CONFIG_AF_ALG')}
1487summary_info += {'GlusterFS support': config_host.has_key('CONFIG_GLUSTERFS')}
1488summary_info += {'gcov':              get_option('b_coverage')}
1489summary_info += {'TPM support':       config_host.has_key('CONFIG_TPM')}
1490summary_info += {'libssh support':    config_host.has_key('CONFIG_LIBSSH')}
1491summary_info += {'QOM debugging':     config_host.has_key('CONFIG_QOM_CAST_DEBUG')}
1492summary_info += {'Live block migration': config_host.has_key('CONFIG_LIVE_BLOCK_MIGRATION')}
1493summary_info += {'lzo support':       config_host.has_key('CONFIG_LZO')}
1494summary_info += {'snappy support':    config_host.has_key('CONFIG_SNAPPY')}
1495summary_info += {'bzip2 support':     config_host.has_key('CONFIG_BZIP2')}
1496summary_info += {'lzfse support':     config_host.has_key('CONFIG_LZFSE')}
1497summary_info += {'zstd support':      config_host.has_key('CONFIG_ZSTD')}
1498summary_info += {'NUMA host support': config_host.has_key('CONFIG_NUMA')}
1499summary_info += {'libxml2':           config_host.has_key('CONFIG_LIBXML2')}
1500summary_info += {'tcmalloc support':  config_host.has_key('CONFIG_TCMALLOC')}
1501summary_info += {'jemalloc support':  config_host.has_key('CONFIG_JEMALLOC')}
1502summary_info += {'avx2 optimization': config_host.has_key('CONFIG_AVX2_OPT')}
1503summary_info += {'avx512f optimization': config_host.has_key('CONFIG_AVX512F_OPT')}
1504summary_info += {'replication support': config_host.has_key('CONFIG_REPLICATION')}
1505summary_info += {'bochs support':     config_host.has_key('CONFIG_BOCHS')}
1506summary_info += {'cloop support':     config_host.has_key('CONFIG_CLOOP')}
1507summary_info += {'dmg support':       config_host.has_key('CONFIG_DMG')}
1508summary_info += {'qcow v1 support':   config_host.has_key('CONFIG_QCOW1')}
1509summary_info += {'vdi support':       config_host.has_key('CONFIG_VDI')}
1510summary_info += {'vvfat support':     config_host.has_key('CONFIG_VVFAT')}
1511summary_info += {'qed support':       config_host.has_key('CONFIG_QED')}
1512summary_info += {'parallels support': config_host.has_key('CONFIG_PARALLELS')}
1513summary_info += {'sheepdog support':  config_host.has_key('CONFIG_SHEEPDOG')}
1514summary_info += {'capstone':          config_host.has_key('CONFIG_CAPSTONE')}
1515summary_info += {'libpmem support':   config_host.has_key('CONFIG_LIBPMEM')}
1516summary_info += {'libdaxctl support': config_host.has_key('CONFIG_LIBDAXCTL')}
1517summary_info += {'libudev':           config_host.has_key('CONFIG_LIBUDEV')}
1518summary_info += {'default devices':   config_host['CONFIG_MINIKCONF_MODE'] == '--defconfig'}
1519summary_info += {'plugin support':    config_host.has_key('CONFIG_PLUGIN')}
1520summary_info += {'fuzzing support':   config_host.has_key('CONFIG_FUZZ')}
1521if config_host.has_key('HAVE_GDB_BIN')
1522  summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
1523endif
1524summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
1525summary_info += {'rng-none':          config_host.has_key('CONFIG_RNG_NONE')}
1526summary_info += {'Linux keyring':     config_host.has_key('CONFIG_SECRET_KEYRING')}
1527summary(summary_info, bool_yn: true)
1528
1529if not supported_cpus.contains(cpu)
1530  message()
1531  warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
1532  message()
1533  message('CPU host architecture ' + cpu + ' support is not currently maintained.')
1534  message('The QEMU project intends to remove support for this host CPU in')
1535  message('a future release if nobody volunteers to maintain it and to')
1536  message('provide a build host for our continuous integration setup.')
1537  message('configure has succeeded and you can continue to build, but')
1538  message('if you care about QEMU on this platform you should contact')
1539  message('us upstream at qemu-devel@nongnu.org.')
1540endif
1541
1542if not supported_oses.contains(targetos)
1543  message()
1544  warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
1545  message()
1546  message('Host OS ' + targetos + 'support is not currently maintained.')
1547  message('The QEMU project intends to remove support for this host OS in')
1548  message('a future release if nobody volunteers to maintain it and to')
1549  message('provide a build host for our continuous integration setup.')
1550  message('configure has succeeded and you can continue to build, but')
1551  message('if you care about QEMU on this platform you should contact')
1552  message('us upstream at qemu-devel@nongnu.org.')
1553endif
1554