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