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