meson: report accelerator support
[qemu.git] / meson.build
1 project('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
6 not_found = dependency('', required: false)
7 if meson.version().version_compare('>=0.56.0')
8   keyval = import('keyval')
9 else
10   keyval = import('unstable-keyval')
11 endif
12 ss = import('sourceset')
13
14 sh = find_program('sh')
15 cc = meson.get_compiler('c')
16 config_host = keyval.load(meson.current_build_dir() / 'config-host.mak')
17 enable_modules = 'CONFIG_MODULES' in config_host
18 enable_static = 'CONFIG_STATIC' in config_host
19 build_docs = 'BUILD_DOCS' in config_host
20
21 if get_option('qemu_suffix').startswith('/')
22   error('qemu_suffix cannot start with a /')
23 endif
24
25 qemu_datadir = get_option('datadir') / get_option('qemu_suffix')
26 qemu_docdir = get_option('docdir') / get_option('qemu_suffix')
27 config_host_data = configuration_data()
28 genh = []
29
30 target_dirs = config_host['TARGET_DIRS'].split()
31 have_user = false
32 have_system = false
33 foreach target : target_dirs
34   have_user = have_user or target.endswith('-user')
35   have_system = have_system or target.endswith('-softmmu')
36 endforeach
37 have_tools = 'CONFIG_TOOLS' in config_host
38 have_block = have_system or have_tools
39
40 python = import('python').find_installation()
41
42 supported_oses = ['windows', 'freebsd', 'netbsd', 'openbsd', 'darwin', 'sunos', 'linux']
43 supported_cpus = ['ppc', 'ppc64', 's390x', 'sparc64', 'riscv32', 'riscv64', 'x86', 'x86_64',
44   'arm', 'aarch64', 'mips', 'mips64', 'sparc', 'sparc64']
45
46 cpu = host_machine.cpu_family()
47 targetos = host_machine.system()
48
49 configure_file(input: files('scripts/ninjatool.py'),
50                output: 'ninjatool',
51                configuration: config_host)
52
53 ##################
54 # Compiler flags #
55 ##################
56
57 add_project_arguments(config_host['QEMU_CFLAGS'].split(),
58                       native: false, language: ['c', 'objc'])
59 add_project_arguments(config_host['QEMU_CXXFLAGS'].split(),
60                       native: false, language: 'cpp')
61 add_project_link_arguments(config_host['QEMU_LDFLAGS'].split(),
62                            native: false, language: ['c', 'cpp', 'objc'])
63 add_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
68 if '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'])
72 endif
73
74 link_language = meson.get_external_property('link_language', 'cpp')
75 if link_language == 'cpp'
76   add_languages('cpp', required: true, native: false)
77 endif
78 if host_machine.system() == 'darwin'
79   add_languages('objc', required: false, native: false)
80 endif
81
82 if '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'])
87 endif
88
89 ###########################################
90 # Target-specific checks and dependencies #
91 ###########################################
92
93 if targetos != 'linux' and get_option('mpath').enabled()
94   error('Multipath is supported only on Linux')
95 endif
96
97 m = cc.find_library('m', required: false)
98 util = cc.find_library('util', required: false)
99 winmm = []
100 socket = []
101 version_res = []
102 coref = []
103 iokit = []
104 cocoa = not_found
105 hvf = []
106 if 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('.'))
114 elif 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')
119 elif targetos == 'sunos'
120   socket = [cc.find_library('socket'),
121             cc.find_library('nsl'),
122             cc.find_library('resolv')]
123 elif targetos == 'haiku'
124   socket = [cc.find_library('posix_error_mapper'),
125             cc.find_library('network'),
126             cc.find_library('bsd')]
127 endif
128
129 if not cocoa.found() and get_option('cocoa').enabled()
130   error('Cocoa not available on this platform')
131 endif
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.
139 add_project_arguments(config_host['GLIB_CFLAGS'].split(),
140                       native: false, language: ['c', 'cpp', 'objc'])
141 glib = declare_dependency(link_args: config_host['GLIB_LIBS'].split())
142 gio = not_found
143 if 'CONFIG_GIO' in config_host
144   gio = declare_dependency(compile_args: config_host['GIO_CFLAGS'].split(),
145                            link_args: config_host['GIO_LIBS'].split())
146 endif
147 lttng = not_found
148 if 'CONFIG_TRACE_UST' in config_host
149   lttng = declare_dependency(link_args: config_host['LTTNG_UST_LIBS'].split())
150 endif
151 urcubp = not_found
152 if 'CONFIG_TRACE_UST' in config_host
153   urcubp = declare_dependency(link_args: config_host['URCU_BP_LIBS'].split())
154 endif
155 gcrypt = not_found
156 if 'CONFIG_GCRYPT' in config_host
157   gcrypt = declare_dependency(compile_args: config_host['GCRYPT_CFLAGS'].split(),
158                               link_args: config_host['GCRYPT_LIBS'].split())
159 endif
160 nettle = not_found
161 if 'CONFIG_NETTLE' in config_host
162   nettle = declare_dependency(compile_args: config_host['NETTLE_CFLAGS'].split(),
163                               link_args: config_host['NETTLE_LIBS'].split())
164 endif
165 gnutls = not_found
166 if 'CONFIG_GNUTLS' in config_host
167   gnutls = declare_dependency(compile_args: config_host['GNUTLS_CFLAGS'].split(),
168                               link_args: config_host['GNUTLS_LIBS'].split())
169 endif
170 pixman = not_found
171 if have_system or have_tools
172   pixman = dependency('pixman-1', required: have_system, version:'>=0.21.8',
173                       method: 'pkg-config', static: enable_static)
174 endif
175 pam = not_found
176 if 'CONFIG_AUTH_PAM' in config_host
177   pam = cc.find_library('pam')
178 endif
179 libaio = cc.find_library('aio', required: false)
180 zlib = dependency('zlib', required: true, static: enable_static)
181 linux_io_uring = not_found
182 if '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())
185 endif
186 libxml2 = not_found
187 if 'CONFIG_LIBXML2' in config_host
188   libxml2 = declare_dependency(compile_args: config_host['LIBXML2_CFLAGS'].split(),
189                                link_args: config_host['LIBXML2_LIBS'].split())
190 endif
191 libnfs = not_found
192 if 'CONFIG_LIBNFS' in config_host
193   libnfs = declare_dependency(link_args: config_host['LIBNFS_LIBS'].split())
194 endif
195 libattr = not_found
196 if 'CONFIG_ATTR' in config_host
197   libattr = declare_dependency(link_args: config_host['LIBATTR_LIBS'].split())
198 endif
199 seccomp = not_found
200 if 'CONFIG_SECCOMP' in config_host
201   seccomp = declare_dependency(compile_args: config_host['SECCOMP_CFLAGS'].split(),
202                                link_args: config_host['SECCOMP_LIBS'].split())
203 endif
204 libcap_ng = not_found
205 if 'CONFIG_LIBCAP_NG' in config_host
206   libcap_ng = declare_dependency(link_args: config_host['LIBCAP_NG_LIBS'].split())
207 endif
208 if get_option('xkbcommon').auto() and not have_system and not have_tools
209   xkbcommon = not_found
210 else
211   xkbcommon = dependency('xkbcommon', required: get_option('xkbcommon'),
212                          method: 'pkg-config', static: enable_static)
213 endif
214 slirp = not_found
215 if 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())
218 endif
219 vde = not_found
220 if config_host.has_key('CONFIG_VDE')
221   vde = declare_dependency(link_args: config_host['VDE_LIBS'].split())
222 endif
223 pulse = not_found
224 if 'CONFIG_LIBPULSE' in config_host
225   pulse = declare_dependency(compile_args: config_host['PULSE_CFLAGS'].split(),
226                              link_args: config_host['PULSE_LIBS'].split())
227 endif
228 alsa = not_found
229 if 'CONFIG_ALSA' in config_host
230   alsa = declare_dependency(compile_args: config_host['ALSA_CFLAGS'].split(),
231                             link_args: config_host['ALSA_LIBS'].split())
232 endif
233 jack = not_found
234 if 'CONFIG_LIBJACK' in config_host
235   jack = declare_dependency(link_args: config_host['JACK_LIBS'].split())
236 endif
237 spice = not_found
238 if 'CONFIG_SPICE' in config_host
239   spice = declare_dependency(compile_args: config_host['SPICE_CFLAGS'].split(),
240                              link_args: config_host['SPICE_LIBS'].split())
241 endif
242 rt = cc.find_library('rt', required: false)
243 libdl = not_found
244 if 'CONFIG_PLUGIN' in config_host
245   libdl = cc.find_library('dl', required: true)
246 endif
247 libiscsi = not_found
248 if 'CONFIG_LIBISCSI' in config_host
249   libiscsi = declare_dependency(compile_args: config_host['LIBISCSI_CFLAGS'].split(),
250                                 link_args: config_host['LIBISCSI_LIBS'].split())
251 endif
252 zstd = not_found
253 if 'CONFIG_ZSTD' in config_host
254   zstd = declare_dependency(compile_args: config_host['ZSTD_CFLAGS'].split(),
255                             link_args: config_host['ZSTD_LIBS'].split())
256 endif
257 gbm = not_found
258 if 'CONFIG_GBM' in config_host
259   gbm = declare_dependency(compile_args: config_host['GBM_CFLAGS'].split(),
260                            link_args: config_host['GBM_LIBS'].split())
261 endif
262 virgl = not_found
263 if 'CONFIG_VIRGL' in config_host
264   virgl = declare_dependency(compile_args: config_host['VIRGL_CFLAGS'].split(),
265                              link_args: config_host['VIRGL_LIBS'].split())
266 endif
267 curl = not_found
268 if 'CONFIG_CURL' in config_host
269   curl = declare_dependency(compile_args: config_host['CURL_CFLAGS'].split(),
270                             link_args: config_host['CURL_LIBS'].split())
271 endif
272 libudev = not_found
273 if targetos == 'linux' and (have_system or have_tools)
274   libudev = dependency('libudev',
275                        required: get_option('mpath').enabled(),
276                        static: enable_static)
277 endif
278
279 mpathpersist = not_found
280 mpathpersist_new_api = false
281 if 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
341 endif
342
343 brlapi = not_found
344 if 'CONFIG_BRLAPI' in config_host
345   brlapi = declare_dependency(link_args: config_host['BRLAPI_LIBS'].split())
346 endif
347
348 sdl = not_found
349 if have_system
350   sdl = dependency('sdl2', required: get_option('sdl'), static: enable_static)
351   sdl_image = not_found
352 endif
353 if 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)
359 else
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
365 endif
366
367 rbd = not_found
368 if 'CONFIG_RBD' in config_host
369   rbd = declare_dependency(link_args: config_host['RBD_LIBS'].split())
370 endif
371 glusterfs = not_found
372 if 'CONFIG_GLUSTERFS' in config_host
373   glusterfs = declare_dependency(compile_args: config_host['GLUSTERFS_CFLAGS'].split(),
374                                  link_args: config_host['GLUSTERFS_LIBS'].split())
375 endif
376 libssh = not_found
377 if 'CONFIG_LIBSSH' in config_host
378   libssh = declare_dependency(compile_args: config_host['LIBSSH_CFLAGS'].split(),
379                               link_args: config_host['LIBSSH_LIBS'].split())
380 endif
381 libbzip2 = not_found
382 if 'CONFIG_BZIP2' in config_host
383   libbzip2 = declare_dependency(link_args: config_host['BZIP2_LIBS'].split())
384 endif
385 liblzfse = not_found
386 if 'CONFIG_LZFSE' in config_host
387   liblzfse = declare_dependency(link_args: config_host['LZFSE_LIBS'].split())
388 endif
389 oss = not_found
390 if 'CONFIG_AUDIO_OSS' in config_host
391   oss = declare_dependency(link_args: config_host['OSS_LIBS'].split())
392 endif
393 dsound = not_found
394 if 'CONFIG_AUDIO_DSOUND' in config_host
395   dsound = declare_dependency(link_args: config_host['DSOUND_LIBS'].split())
396 endif
397 coreaudio = not_found
398 if 'CONFIG_AUDIO_COREAUDIO' in config_host
399   coreaudio = declare_dependency(link_args: config_host['COREAUDIO_LIBS'].split())
400 endif
401 opengl = not_found
402 if 'CONFIG_OPENGL' in config_host
403   opengl = declare_dependency(compile_args: config_host['OPENGL_CFLAGS'].split(),
404                               link_args: config_host['OPENGL_LIBS'].split())
405 endif
406 gtk = not_found
407 if 'CONFIG_GTK' in config_host
408   gtk = declare_dependency(compile_args: config_host['GTK_CFLAGS'].split(),
409                               link_args: config_host['GTK_LIBS'].split())
410 endif
411 vte = not_found
412 if 'CONFIG_VTE' in config_host
413   vte = declare_dependency(compile_args: config_host['VTE_CFLAGS'].split(),
414                            link_args: config_host['VTE_LIBS'].split())
415 endif
416 x11 = not_found
417 if 'CONFIG_X11' in config_host
418   x11 = declare_dependency(compile_args: config_host['X11_CFLAGS'].split(),
419                            link_args: config_host['X11_LIBS'].split())
420 endif
421 curses = not_found
422 if 'CONFIG_CURSES' in config_host
423   curses = declare_dependency(compile_args: config_host['CURSES_CFLAGS'].split(),
424                               link_args: config_host['CURSES_LIBS'].split())
425 endif
426 iconv = not_found
427 if 'CONFIG_ICONV' in config_host
428   iconv = declare_dependency(compile_args: config_host['ICONV_CFLAGS'].split(),
429                              link_args: config_host['ICONV_LIBS'].split())
430 endif
431 vnc = not_found
432 png = not_found
433 jpeg = not_found
434 sasl = not_found
435 if 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
449 endif
450 fdt = not_found
451 if 'CONFIG_FDT' in config_host
452   fdt = declare_dependency(compile_args: config_host['FDT_CFLAGS'].split(),
453                            link_args: config_host['FDT_LIBS'].split())
454 endif
455 snappy = not_found
456 if 'CONFIG_SNAPPY' in config_host
457   snappy = declare_dependency(link_args: config_host['SNAPPY_LIBS'].split())
458 endif
459 lzo = not_found
460 if 'CONFIG_LZO' in config_host
461   lzo = declare_dependency(link_args: config_host['LZO_LIBS'].split())
462 endif
463 rdma = not_found
464 if 'CONFIG_RDMA' in config_host
465   rdma = declare_dependency(link_args: config_host['RDMA_LIBS'].split())
466 endif
467 numa = not_found
468 if 'CONFIG_NUMA' in config_host
469   numa = declare_dependency(link_args: config_host['NUMA_LIBS'].split())
470 endif
471 xen = not_found
472 if '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())
475 endif
476 cacard = not_found
477 if 'CONFIG_SMARTCARD' in config_host
478   cacard = declare_dependency(compile_args: config_host['SMARTCARD_CFLAGS'].split(),
479                               link_args: config_host['SMARTCARD_LIBS'].split())
480 endif
481 u2f = not_found
482 if have_system
483   u2f = dependency('u2f-emu', required: get_option('u2f'),
484                    method: 'pkg-config',
485                    static: enable_static)
486 endif
487 usbredir = not_found
488 if '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())
491 endif
492 libusb = not_found
493 if '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())
496 endif
497 capstone = not_found
498 if 'CONFIG_CAPSTONE' in config_host
499   capstone = declare_dependency(compile_args: config_host['CAPSTONE_CFLAGS'].split(),
500                                 link_args: config_host['CAPSTONE_LIBS'].split())
501 endif
502 libpmem = not_found
503 if 'CONFIG_LIBPMEM' in config_host
504   libpmem = declare_dependency(compile_args: config_host['LIBPMEM_CFLAGS'].split(),
505                                link_args: config_host['LIBPMEM_LIBS'].split())
506 endif
507 libdaxctl = not_found
508 if 'CONFIG_LIBDAXCTL' in config_host
509   libdaxctl = declare_dependency(link_args: config_host['LIBDAXCTL_LIBS'].split())
510 endif
511 tasn1 = not_found
512 if 'CONFIG_TASN1' in config_host
513   tasn1 = declare_dependency(compile_args: config_host['TASN1_CFLAGS'].split(),
514                              link_args: config_host['TASN1_LIBS'].split())
515 endif
516 keyutils = dependency('libkeyutils', required: false,
517                       method: 'pkg-config', static: enable_static)
518
519 has_gettid = cc.has_function('gettid')
520
521 # Malloc tests
522
523 malloc = []
524 if 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; }''')
529 else
530   has_malloc_trim = false
531   malloc = cc.find_library(get_option('malloc'), required: true)
532 endif
533 if 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
539 endif
540
541 # Create config-host.h
542
543 config_host_data.set('CONFIG_COCOA', cocoa.found())
544 config_host_data.set('CONFIG_LIBUDEV', libudev.found())
545 config_host_data.set('CONFIG_MPATH', mpathpersist.found())
546 config_host_data.set('CONFIG_MPATH_NEW_API', mpathpersist_new_api)
547 config_host_data.set('CONFIG_SDL', sdl.found())
548 config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found())
549 config_host_data.set('CONFIG_VNC', vnc.found())
550 config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
551 config_host_data.set('CONFIG_VNC_PNG', png.found())
552 config_host_data.set('CONFIG_VNC_SASL', sasl.found())
553 config_host_data.set('CONFIG_XKBCOMMON', xkbcommon.found())
554 config_host_data.set('CONFIG_KEYUTILS', keyutils.found())
555 config_host_data.set('CONFIG_GETTID', has_gettid)
556 config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim)
557 config_host_data.set('QEMU_VERSION', '"@0@"'.format(meson.project_version()))
558 config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0])
559 config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1])
560 config_host_data.set('QEMU_VERSION_MICRO', meson.project_version().split('.')[2])
561
562 arrays = ['CONFIG_AUDIO_DRIVERS', 'CONFIG_BDRV_RW_WHITELIST', 'CONFIG_BDRV_RO_WHITELIST']
563 strings = ['HOST_DSOSUF', 'CONFIG_IASL', 'qemu_confdir', 'qemu_datadir',
564            'qemu_moddir', 'qemu_localstatedir', 'qemu_helperdir', 'qemu_localedir',
565            'qemu_icondir', 'qemu_desktopdir', 'qemu_firmwarepath']
566 foreach 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
582 endforeach
583 genh += configure_file(output: 'config-host.h', configuration: config_host_data)
584
585 minikconf = find_program('scripts/minikconf.py')
586 config_all = {}
587 config_all_devices = {}
588 config_all_disas = {}
589 config_devices_mak_list = []
590 config_devices_h = {}
591 config_target_h = {}
592 config_target_mak = {}
593
594 disassemblers = {
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 }
618 if 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   }
624 endif
625
626 kconfig_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 ]
641 ignored = ['TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_DIRS']
642
643 accel_symbols = [
644   'CONFIG_KVM',
645   'CONFIG_HAX',
646   'CONFIG_HVF',
647   'CONFIG_TCG',
648   'CONFIG_WHPX'
649 ]
650
651 foreach 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}
717 endforeach
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
728 config_all += config_all_devices
729 config_all += config_host
730 config_all += config_all_disas
731 config_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
740 hxtool = find_program('scripts/hxtool')
741 shaderinclude = find_program('scripts/shaderinclude.pl')
742 qapi_gen = find_program('scripts/qapi-gen.py')
743 qapi_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
760 tracetool = [
761   python, files('scripts/tracetool.py'),
762    '--backend=' + config_host['TRACE_BACKENDS']
763 ]
764
765 qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
766                     meson.current_source_dir(),
767                     config_host['PKGVERSION'], meson.project_version()]
768 qemu_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)
774 genh += qemu_version
775
776 hxdep = []
777 hx_headers = [
778   ['qemu-options.hx', 'qemu-options.def'],
779   ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
780 ]
781 if have_system
782   hx_headers += [
783     ['hmp-commands.hx', 'hmp-commands.h'],
784     ['hmp-commands-info.hx', 'hmp-commands-info.h'],
785   ]
786 endif
787 foreach 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@'])
794 endforeach
795 genh += hxdep
796
797 SPHINX_ARGS = [config_host['SPHINX_BUILD'],
798                '-Dversion=' + meson.project_version(),
799                '-Drelease=' + config_host['PKGVERSION']]
800
801 if get_option('werror')
802   SPHINX_ARGS += [ '-W' ]
803 endif
804
805 sphinx_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
815 util_ss = ss.source_set()
816 stub_ss = ss.source_set()
817 trace_ss = ss.source_set()
818 block_ss = ss.source_set()
819 blockdev_ss = ss.source_set()
820 qmp_ss = ss.source_set()
821 common_ss = ss.source_set()
822 softmmu_ss = ss.source_set()
823 user_ss = ss.source_set()
824 bsd_user_ss = ss.source_set()
825 linux_user_ss = ss.source_set()
826 specific_ss = ss.source_set()
827 specific_fuzz_ss = ss.source_set()
828
829 modules = {}
830 hw_arch = {}
831 target_arch = {}
832 target_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
840 trace_events_subdirs = [
841   'accel/kvm',
842   'accel/tcg',
843   'crypto',
844   'monitor',
845 ]
846 if have_user
847   trace_events_subdirs += [ 'linux-user' ]
848 endif
849 if have_block
850   trace_events_subdirs += [
851     'authz',
852     'block',
853     'io',
854     'nbd',
855     'scsi',
856   ]
857 endif
858 if 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   ]
914 endif
915 trace_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
930 subdir('qapi')
931 subdir('qobject')
932 subdir('stubs')
933 subdir('trace')
934 subdir('util')
935 subdir('qom')
936 subdir('authz')
937 subdir('crypto')
938 subdir('ui')
939
940
941 if 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')
944 endif
945
946 # Build targets from sourcesets
947
948 stub_ss = stub_ss.apply(config_all, strict: false)
949
950 util_ss.add_all(trace_ss)
951 util_ss = util_ss.apply(config_all, strict: false)
952 libqemuutil = static_library('qemuutil',
953                              sources: util_ss.sources() + stub_ss.sources() + genh,
954                              dependencies: [util_ss.dependencies(), m, glib, socket, malloc])
955 qemuutil = declare_dependency(link_with: libqemuutil,
956                               sources: genh + version_res)
957
958 decodetree = generator(find_program('scripts/decodetree.py'),
959                        output: 'decode-@BASENAME@.c.inc',
960                        arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
961
962 subdir('audio')
963 subdir('io')
964 subdir('chardev')
965 subdir('fsdev')
966 subdir('libdecnumber')
967 subdir('target')
968 subdir('dump')
969
970 block_ss.add(files(
971   'block.c',
972   'blockjob.c',
973   'job.c',
974   'qemu-io-cmds.c',
975 ))
976 block_ss.add(when: 'CONFIG_REPLICATION', if_true: files('replication.c'))
977
978 subdir('nbd')
979 subdir('scsi')
980 subdir('block')
981
982 blockdev_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
991 blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
992 softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
993
994 softmmu_ss.add_all(blockdev_ss)
995 softmmu_ss.add(files(
996   'bootdevice.c',
997   'dma-helpers.c',
998   'qdev-monitor.c',
999 ), sdl)
1000
1001 softmmu_ss.add(when: 'CONFIG_TPM', if_true: files('tpm.c'))
1002 softmmu_ss.add(when: 'CONFIG_SECCOMP', if_true: [files('qemu-seccomp.c'), seccomp])
1003 softmmu_ss.add(when: ['CONFIG_FDT', fdt],  if_true: [files('device_tree.c')])
1004
1005 common_ss.add(files('cpus-common.c'))
1006
1007 subdir('softmmu')
1008
1009 specific_ss.add(files('disas.c', 'exec.c', 'gdbstub.c'), capstone, libpmem, libdaxctl)
1010 specific_ss.add(files('exec-vary.c'))
1011 specific_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 ))
1020 specific_ss.add(when: 'CONFIG_TCG_INTERPRETER', if_true: files('disas/tci.c', 'tcg/tci.c'))
1021
1022 subdir('backends')
1023 subdir('disas')
1024 subdir('migration')
1025 subdir('monitor')
1026 subdir('net')
1027 subdir('replay')
1028 subdir('hw')
1029 subdir('accel')
1030 subdir('plugins')
1031 subdir('bsd-user')
1032 subdir('linux-user')
1033
1034 bsd_user_ss.add(files('gdbstub.c'))
1035 specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss)
1036
1037 linux_user_ss.add(files('gdbstub.c', 'thunk.c'))
1038 specific_ss.add_all(when: 'CONFIG_LINUX_USER', if_true: linux_user_ss)
1039
1040 # needed for fuzzing binaries
1041 subdir('tests/qtest/libqos')
1042 subdir('tests/qtest/fuzz')
1043
1044 block_mods = []
1045 softmmu_mods = []
1046 foreach 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
1065 endforeach
1066
1067 nm = find_program('nm')
1068 undefsym = find_program('scripts/undefsym.py')
1069 block_syms = custom_target('block.syms', output: 'block.syms',
1070                              input: [libqemuutil, block_mods],
1071                              capture: true,
1072                              command: [undefsym, nm, '@INPUT@'])
1073 qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
1074                              input: [libqemuutil, softmmu_mods],
1075                              capture: true,
1076                              command: [undefsym, nm, '@INPUT@'])
1077
1078 block_ss = block_ss.apply(config_host, strict: false)
1079 libblock = 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
1085 block = declare_dependency(link_whole: [libblock],
1086                            link_args: '@block.syms',
1087                            dependencies: [crypto, io])
1088
1089 qmp_ss = qmp_ss.apply(config_host, strict: false)
1090 libqmp = static_library('qmp', qmp_ss.sources() + genh,
1091                         dependencies: qmp_ss.dependencies(),
1092                         name_suffix: 'fa',
1093                         build_by_default: false)
1094
1095 qmp = declare_dependency(link_whole: [libqmp])
1096
1097 foreach 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'])
1103 endforeach
1104
1105 softmmu_ss.add(authz, block, chardev, crypto, io, qmp)
1106 common_ss.add(qom, qemuutil)
1107
1108 common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
1109 common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
1110
1111 common_all = common_ss.apply(config_all, strict: false)
1112 common_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
1118 feature_to_c = find_program('scripts/feature_to_c.sh')
1119
1120 emulators = {}
1121 foreach 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
1275 endforeach
1276
1277 # Other build targets
1278
1279 if 'CONFIG_PLUGIN' in config_host
1280   install_headers('include/qemu/qemu-plugin.h')
1281 endif
1282
1283 if 'CONFIG_GUEST_AGENT' in config_host
1284   subdir('qga')
1285 endif
1286
1287 # Don't build qemu-keymap if xkbcommon is not explicitly enabled
1288 # when we don't build tools or system
1289 if 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)
1293 endif
1294
1295 if 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
1335 endif
1336
1337 subdir('scripts')
1338 subdir('tools')
1339 subdir('pc-bios')
1340 subdir('tests')
1341 subdir('docs')
1342 if 'CONFIG_GTK' in config_host
1343   subdir('po')
1344 endif
1345
1346 if 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)
1369 endif
1370
1371 summary_info = {}
1372 summary_info += {'Install prefix':    config_host['prefix']}
1373 summary_info += {'BIOS directory':    config_host['qemu_datadir']}
1374 summary_info += {'firmware path':     config_host['qemu_firmwarepath']}
1375 summary_info += {'binary directory':  config_host['bindir']}
1376 summary_info += {'library directory': config_host['libdir']}
1377 summary_info += {'module directory':  config_host['qemu_moddir']}
1378 summary_info += {'libexec directory': config_host['libexecdir']}
1379 summary_info += {'include directory': config_host['includedir']}
1380 summary_info += {'config directory':  config_host['sysconfdir']}
1381 if targetos != 'windows'
1382   summary_info += {'local state directory': config_host['qemu_localstatedir']}
1383   summary_info += {'Manual directory':      get_option('mandir')}
1384 else
1385   summary_info += {'local state directory': 'queried at runtime'}
1386 endif
1387 summary_info += {'Doc directory':     get_option('docdir')}
1388 summary_info += {'Build directory':   meson.current_build_dir()}
1389 summary_info += {'Source path':       meson.current_source_dir()}
1390 summary_info += {'GIT binary':        config_host['GIT']}
1391 summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
1392 summary_info += {'C compiler':        meson.get_compiler('c').cmd_array()[0]}
1393 summary_info += {'Host C compiler':   meson.get_compiler('c', native: true).cmd_array()[0]}
1394 if link_language == 'cpp'
1395   summary_info += {'C++ compiler':      meson.get_compiler('cpp').cmd_array()[0]}
1396 else
1397   summary_info += {'C++ compiler':      false}
1398 endif
1399 if targetos == 'darwin'
1400   summary_info += {'Objective-C compiler': meson.get_compiler('objc').cmd_array()[0]}
1401 endif
1402 summary_info += {'ARFLAGS':           config_host['ARFLAGS']}
1403 summary_info += {'CFLAGS':            config_host['CFLAGS']}
1404 summary_info += {'QEMU_CFLAGS':       config_host['QEMU_CFLAGS']}
1405 summary_info += {'QEMU_LDFLAGS':      config_host['QEMU_LDFLAGS']}
1406 summary_info += {'make':              config_host['MAKE']}
1407 summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
1408 summary_info += {'sphinx-build':      config_host['SPHINX_BUILD']}
1409 summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
1410 # TODO: add back version
1411 summary_info += {'slirp support':     config_host.has_key('CONFIG_SLIRP')}
1412 if config_host.has_key('CONFIG_SLIRP')
1413   summary_info += {'smbd':            config_host['CONFIG_SMBD_COMMAND']}
1414 endif
1415 summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
1416 if config_host.has_key('CONFIG_MODULES')
1417   summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')}
1418 endif
1419 summary_info += {'host CPU':          cpu}
1420 summary_info += {'host endianness':   build_machine.endian()}
1421 summary_info += {'target list':       config_host['TARGET_DIRS']}
1422 summary_info += {'gprof enabled':     config_host.has_key('CONFIG_GPROF')}
1423 summary_info += {'sparse enabled':    meson.get_compiler('c').cmd_array().contains('cgcc')}
1424 summary_info += {'strip binaries':    get_option('strip')}
1425 summary_info += {'profiler':          config_host.has_key('CONFIG_PROFILER')}
1426 summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
1427 if targetos == 'darwin'
1428   summary_info += {'Cocoa support': config_host.has_key('CONFIG_COCOA')}
1429 endif
1430 # TODO: add back version
1431 summary_info += {'SDL support':       sdl.found()}
1432 summary_info += {'SDL image support': sdl_image.found()}
1433 # TODO: add back version
1434 summary_info += {'GTK support':       config_host.has_key('CONFIG_GTK')}
1435 summary_info += {'GTK GL support':    config_host.has_key('CONFIG_GTK_GL')}
1436 summary_info += {'pixman':            pixman.found()}
1437 # TODO: add back version
1438 summary_info += {'VTE support':       config_host.has_key('CONFIG_VTE')}
1439 summary_info += {'TLS priority':      config_host['CONFIG_TLS_PRIORITY']}
1440 summary_info += {'GNUTLS support':    config_host.has_key('CONFIG_GNUTLS')}
1441 # TODO: add back version
1442 summary_info += {'libgcrypt':         config_host.has_key('CONFIG_GCRYPT')}
1443 if 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')}
1446 endif
1447 # TODO: add back version
1448 summary_info += {'nettle':            config_host.has_key('CONFIG_NETTLE')}
1449 if config_host.has_key('CONFIG_NETTLE')
1450    summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
1451 endif
1452 summary_info += {'libtasn1':          config_host.has_key('CONFIG_TASN1')}
1453 summary_info += {'PAM':               config_host.has_key('CONFIG_AUTH_PAM')}
1454 summary_info += {'iconv support':     config_host.has_key('CONFIG_ICONV')}
1455 summary_info += {'curses support':    config_host.has_key('CONFIG_CURSES')}
1456 # TODO: add back version
1457 summary_info += {'virgl support':     config_host.has_key('CONFIG_VIRGL')}
1458 summary_info += {'curl support':      config_host.has_key('CONFIG_CURL')}
1459 summary_info += {'mingw32 support':   targetos == 'windows'}
1460 summary_info += {'Audio drivers':     config_host['CONFIG_AUDIO_DRIVERS']}
1461 summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']}
1462 summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']}
1463 summary_info += {'VirtFS support':    config_host.has_key('CONFIG_VIRTFS')}
1464 summary_info += {'Multipath support': mpathpersist.found()}
1465 summary_info += {'VNC support':       vnc.found()}
1466 if 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()}
1470 endif
1471 summary_info += {'xen support':       config_host.has_key('CONFIG_XEN_BACKEND')}
1472 if config_host.has_key('CONFIG_XEN_BACKEND')
1473   summary_info += {'xen ctrl version':  config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
1474 endif
1475 summary_info += {'brlapi support':    config_host.has_key('CONFIG_BRLAPI')}
1476 summary_info += {'Documentation':     config_host.has_key('BUILD_DOCS')}
1477 summary_info += {'PIE':               get_option('b_pie')}
1478 summary_info += {'vde support':       config_host.has_key('CONFIG_VDE')}
1479 summary_info += {'netmap support':    config_host.has_key('CONFIG_NETMAP')}
1480 summary_info += {'Linux AIO support': config_host.has_key('CONFIG_LINUX_AIO')}
1481 summary_info += {'Linux io_uring support': config_host.has_key('CONFIG_LINUX_IO_URING')}
1482 summary_info += {'ATTR/XATTR support': config_host.has_key('CONFIG_ATTR')}
1483 summary_info += {'Install blobs':     config_host.has_key('INSTALL_BLOBS')}
1484 summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
1485 summary_info += {'HAX support':       config_all.has_key('CONFIG_HAX')}
1486 summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
1487 summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
1488 summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
1489 if 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')}
1492 endif
1493 summary_info += {'malloc trim support': has_malloc_trim}
1494 summary_info += {'RDMA support':      config_host.has_key('CONFIG_RDMA')}
1495 summary_info += {'PVRDMA support':    config_host.has_key('CONFIG_PVRDMA')}
1496 summary_info += {'fdt support':       config_host.has_key('CONFIG_FDT')}
1497 summary_info += {'membarrier':        config_host.has_key('CONFIG_MEMBARRIER')}
1498 summary_info += {'preadv support':    config_host.has_key('CONFIG_PREADV')}
1499 summary_info += {'fdatasync':         config_host.has_key('CONFIG_FDATASYNC')}
1500 summary_info += {'madvise':           config_host.has_key('CONFIG_MADVISE')}
1501 summary_info += {'posix_madvise':     config_host.has_key('CONFIG_POSIX_MADVISE')}
1502 summary_info += {'posix_memalign':    config_host.has_key('CONFIG_POSIX_MEMALIGN')}
1503 summary_info += {'libcap-ng support': config_host.has_key('CONFIG_LIBCAP_NG')}
1504 summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')}
1505 summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')}
1506 summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')}
1507 summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')}
1508 summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_KERNEL')}
1509 summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')}
1510 summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')}
1511 summary_info += {'Trace backends':    config_host['TRACE_BACKENDS']}
1512 if config_host['TRACE_BACKENDS'].split().contains('simple')
1513   summary_info += {'Trace output file': config_host['CONFIG_TRACE_FILE'] + '-<pid>'}
1514 endif
1515 # TODO: add back protocol and server version
1516 summary_info += {'spice support':     config_host.has_key('CONFIG_SPICE')}
1517 summary_info += {'rbd support':       config_host.has_key('CONFIG_RBD')}
1518 summary_info += {'xfsctl support':    config_host.has_key('CONFIG_XFS')}
1519 summary_info += {'smartcard support': config_host.has_key('CONFIG_SMARTCARD')}
1520 summary_info += {'U2F support':       u2f.found()}
1521 summary_info += {'libusb':            config_host.has_key('CONFIG_USB_LIBUSB')}
1522 summary_info += {'usb net redir':     config_host.has_key('CONFIG_USB_REDIR')}
1523 summary_info += {'OpenGL support':    config_host.has_key('CONFIG_OPENGL')}
1524 summary_info += {'OpenGL dmabufs':    config_host.has_key('CONFIG_OPENGL_DMABUF')}
1525 summary_info += {'libiscsi support':  config_host.has_key('CONFIG_LIBISCSI')}
1526 summary_info += {'libnfs support':    config_host.has_key('CONFIG_LIBNFS')}
1527 summary_info += {'build guest agent': config_host.has_key('CONFIG_GUEST_AGENT')}
1528 if 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')}
1535 endif
1536 summary_info += {'seccomp support':   config_host.has_key('CONFIG_SECCOMP')}
1537 summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
1538 summary_info += {'coroutine pool':    config_host['CONFIG_COROUTINE_POOL'] == '1'}
1539 summary_info += {'debug stack usage': config_host.has_key('CONFIG_DEBUG_STACK_USAGE')}
1540 summary_info += {'mutex debugging':   config_host.has_key('CONFIG_DEBUG_MUTEX')}
1541 summary_info += {'crypto afalg':      config_host.has_key('CONFIG_AF_ALG')}
1542 summary_info += {'GlusterFS support': config_host.has_key('CONFIG_GLUSTERFS')}
1543 summary_info += {'gcov':              get_option('b_coverage')}
1544 summary_info += {'TPM support':       config_host.has_key('CONFIG_TPM')}
1545 summary_info += {'libssh support':    config_host.has_key('CONFIG_LIBSSH')}
1546 summary_info += {'QOM debugging':     config_host.has_key('CONFIG_QOM_CAST_DEBUG')}
1547 summary_info += {'Live block migration': config_host.has_key('CONFIG_LIVE_BLOCK_MIGRATION')}
1548 summary_info += {'lzo support':       config_host.has_key('CONFIG_LZO')}
1549 summary_info += {'snappy support':    config_host.has_key('CONFIG_SNAPPY')}
1550 summary_info += {'bzip2 support':     config_host.has_key('CONFIG_BZIP2')}
1551 summary_info += {'lzfse support':     config_host.has_key('CONFIG_LZFSE')}
1552 summary_info += {'zstd support':      config_host.has_key('CONFIG_ZSTD')}
1553 summary_info += {'NUMA host support': config_host.has_key('CONFIG_NUMA')}
1554 summary_info += {'libxml2':           config_host.has_key('CONFIG_LIBXML2')}
1555 summary_info += {'memory allocator':  get_option('malloc')}
1556 summary_info += {'avx2 optimization': config_host.has_key('CONFIG_AVX2_OPT')}
1557 summary_info += {'avx512f optimization': config_host.has_key('CONFIG_AVX512F_OPT')}
1558 summary_info += {'replication support': config_host.has_key('CONFIG_REPLICATION')}
1559 summary_info += {'bochs support':     config_host.has_key('CONFIG_BOCHS')}
1560 summary_info += {'cloop support':     config_host.has_key('CONFIG_CLOOP')}
1561 summary_info += {'dmg support':       config_host.has_key('CONFIG_DMG')}
1562 summary_info += {'qcow v1 support':   config_host.has_key('CONFIG_QCOW1')}
1563 summary_info += {'vdi support':       config_host.has_key('CONFIG_VDI')}
1564 summary_info += {'vvfat support':     config_host.has_key('CONFIG_VVFAT')}
1565 summary_info += {'qed support':       config_host.has_key('CONFIG_QED')}
1566 summary_info += {'parallels support': config_host.has_key('CONFIG_PARALLELS')}
1567 summary_info += {'sheepdog support':  config_host.has_key('CONFIG_SHEEPDOG')}
1568 summary_info += {'capstone':          config_host.has_key('CONFIG_CAPSTONE')}
1569 summary_info += {'libpmem support':   config_host.has_key('CONFIG_LIBPMEM')}
1570 summary_info += {'libdaxctl support': config_host.has_key('CONFIG_LIBDAXCTL')}
1571 summary_info += {'libudev':           libudev.found()}
1572 summary_info += {'default devices':   config_host['CONFIG_MINIKCONF_MODE'] == '--defconfig'}
1573 summary_info += {'plugin support':    config_host.has_key('CONFIG_PLUGIN')}
1574 summary_info += {'fuzzing support':   config_host.has_key('CONFIG_FUZZ')}
1575 if config_host.has_key('HAVE_GDB_BIN')
1576   summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
1577 endif
1578 summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
1579 summary_info += {'rng-none':          config_host.has_key('CONFIG_RNG_NONE')}
1580 summary_info += {'Linux keyring':     config_host.has_key('CONFIG_SECRET_KEYRING')}
1581 summary(summary_info, bool_yn: true)
1582
1583 if 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.')
1594 endif
1595
1596 if 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.')
1607 endif