configure: move cocoa option 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 = 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_devices = {}
587 config_all_disas = {}
588 config_devices_mak_list = []
589 config_devices_h = {}
590 config_target_h = {}
591 config_target_mak = {}
592
593 disassemblers = {
594   'alpha' : ['CONFIG_ALPHA_DIS'],
595   'arm' : ['CONFIG_ARM_DIS'],
596   'avr' : ['CONFIG_AVR_DIS'],
597   'cris' : ['CONFIG_CRIS_DIS'],
598   'hppa' : ['CONFIG_HPPA_DIS'],
599   'i386' : ['CONFIG_I386_DIS'],
600   'x86_64' : ['CONFIG_I386_DIS'],
601   'x32' : ['CONFIG_I386_DIS'],
602   'lm32' : ['CONFIG_LM32_DIS'],
603   'm68k' : ['CONFIG_M68K_DIS'],
604   'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
605   'mips' : ['CONFIG_MIPS_DIS'],
606   'moxie' : ['CONFIG_MOXIE_DIS'],
607   'nios2' : ['CONFIG_NIOS2_DIS'],
608   'or1k' : ['CONFIG_OPENRISC_DIS'],
609   'ppc' : ['CONFIG_PPC_DIS'],
610   'riscv' : ['CONFIG_RISCV_DIS'],
611   'rx' : ['CONFIG_RX_DIS'],
612   's390' : ['CONFIG_S390_DIS'],
613   'sh4' : ['CONFIG_SH4_DIS'],
614   'sparc' : ['CONFIG_SPARC_DIS'],
615   'xtensa' : ['CONFIG_XTENSA_DIS'],
616 }
617 if link_language == 'cpp'
618   disassemblers += {
619     'aarch64' : [ 'CONFIG_ARM_A64_DIS'],
620     'arm' : [ 'CONFIG_ARM_DIS', 'CONFIG_ARM_A64_DIS'],
621     'mips' : [ 'CONFIG_MIPS_DIS', 'CONFIG_NANOMIPS_DIS'],
622   }
623 endif
624
625 kconfig_external_symbols = [
626   'CONFIG_KVM',
627   'CONFIG_XEN',
628   'CONFIG_TPM',
629   'CONFIG_SPICE',
630   'CONFIG_IVSHMEM',
631   'CONFIG_OPENGL',
632   'CONFIG_X11',
633   'CONFIG_VHOST_USER',
634   'CONFIG_VHOST_VDPA',
635   'CONFIG_VHOST_KERNEL',
636   'CONFIG_VIRTFS',
637   'CONFIG_LINUX',
638   'CONFIG_PVRDMA',
639 ]
640 ignored = ['TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_DIRS']
641
642 foreach target : target_dirs
643   config_target = keyval.load(meson.current_build_dir() / target / 'config-target.mak')
644
645   foreach k, v: disassemblers
646     if config_host['ARCH'].startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k)
647       foreach sym: v
648         config_target += { sym: 'y' }
649         config_all_disas += { sym: 'y' }
650       endforeach
651     endif
652   endforeach
653
654   config_target_data = configuration_data()
655   foreach k, v: config_target
656     if not k.startswith('TARGET_') and not k.startswith('CONFIG_')
657       # do nothing
658     elif ignored.contains(k)
659       # do nothing
660     elif k == 'TARGET_BASE_ARCH'
661       config_target_data.set('TARGET_' + v.to_upper(), 1)
662     elif k == 'TARGET_NAME'
663       config_target_data.set_quoted(k, v)
664     elif v == 'y'
665       config_target_data.set(k, 1)
666     else
667       config_target_data.set(k, v)
668     endif
669   endforeach
670   config_target_h += {target: configure_file(output: target + '-config-target.h',
671                                                configuration: config_target_data)}
672
673   if target.endswith('-softmmu')
674     base_kconfig = []
675     foreach sym : kconfig_external_symbols
676       if sym in config_target or sym in config_host
677         base_kconfig += '@0@=y'.format(sym)
678       endif
679     endforeach
680
681     config_devices_mak = target + '-config-devices.mak'
682     config_devices_mak = configure_file(
683       input: ['default-configs' / target + '.mak', 'Kconfig'],
684       output: config_devices_mak,
685       depfile: config_devices_mak + '.d',
686       capture: true,
687       command: [minikconf, config_host['CONFIG_MINIKCONF_MODE'],
688                 config_devices_mak, '@DEPFILE@', '@INPUT@',
689                 base_kconfig])
690
691     config_devices_data = configuration_data()
692     config_devices = keyval.load(config_devices_mak)
693     foreach k, v: config_devices
694       config_devices_data.set(k, 1)
695     endforeach
696     config_devices_mak_list += config_devices_mak
697     config_devices_h += {target: configure_file(output: target + '-config-devices.h',
698                                                 configuration: config_devices_data)}
699     config_target += config_devices
700     config_all_devices += config_devices
701   endif
702   config_target_mak += {target: config_target}
703 endforeach
704
705 # This configuration is used to build files that are shared by
706 # multiple binaries, and then extracted out of the "common"
707 # static_library target.
708 #
709 # We do not use all_sources()/all_dependencies(), because it would
710 # build literally all source files, including devices only used by
711 # targets that are not built for this compilation.  The CONFIG_ALL
712 # pseudo symbol replaces it.
713
714 config_all = config_all_devices
715 config_all += config_host
716 config_all += config_all_disas
717 config_all += {
718   'CONFIG_XEN': config_host.has_key('CONFIG_XEN_BACKEND'),
719   'CONFIG_SOFTMMU': have_system,
720   'CONFIG_USER_ONLY': have_user,
721   'CONFIG_ALL': true,
722 }
723
724 # Generators
725
726 hxtool = find_program('scripts/hxtool')
727 shaderinclude = find_program('scripts/shaderinclude.pl')
728 qapi_gen = find_program('scripts/qapi-gen.py')
729 qapi_gen_depends = [ meson.source_root() / 'scripts/qapi/__init__.py',
730                      meson.source_root() / 'scripts/qapi/commands.py',
731                      meson.source_root() / 'scripts/qapi/common.py',
732                      meson.source_root() / 'scripts/qapi/error.py',
733                      meson.source_root() / 'scripts/qapi/events.py',
734                      meson.source_root() / 'scripts/qapi/expr.py',
735                      meson.source_root() / 'scripts/qapi/gen.py',
736                      meson.source_root() / 'scripts/qapi/introspect.py',
737                      meson.source_root() / 'scripts/qapi/parser.py',
738                      meson.source_root() / 'scripts/qapi/schema.py',
739                      meson.source_root() / 'scripts/qapi/source.py',
740                      meson.source_root() / 'scripts/qapi/types.py',
741                      meson.source_root() / 'scripts/qapi/visit.py',
742                      meson.source_root() / 'scripts/qapi/common.py',
743                      meson.source_root() / 'scripts/qapi-gen.py'
744 ]
745
746 tracetool = [
747   python, files('scripts/tracetool.py'),
748    '--backend=' + config_host['TRACE_BACKENDS']
749 ]
750
751 qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
752                     meson.current_source_dir(),
753                     config_host['PKGVERSION'], meson.project_version()]
754 qemu_version = custom_target('qemu-version.h',
755                              output: 'qemu-version.h',
756                              command: qemu_version_cmd,
757                              capture: true,
758                              build_by_default: true,
759                              build_always_stale: true)
760 genh += qemu_version
761
762 hxdep = []
763 hx_headers = [
764   ['qemu-options.hx', 'qemu-options.def'],
765   ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
766 ]
767 if have_system
768   hx_headers += [
769     ['hmp-commands.hx', 'hmp-commands.h'],
770     ['hmp-commands-info.hx', 'hmp-commands-info.h'],
771   ]
772 endif
773 foreach d : hx_headers
774   hxdep += custom_target(d[1],
775                 input: files(d[0]),
776                 output: d[1],
777                 capture: true,
778                 build_by_default: true, # to be removed when added to a target
779                 command: [hxtool, '-h', '@INPUT0@'])
780 endforeach
781 genh += hxdep
782
783 SPHINX_ARGS = [config_host['SPHINX_BUILD'],
784                '-Dversion=' + meson.project_version(),
785                '-Drelease=' + config_host['PKGVERSION']]
786
787 if get_option('werror')
788   SPHINX_ARGS += [ '-W' ]
789 endif
790
791 sphinx_extn_depends = [ meson.source_root() / 'docs/sphinx/depfile.py',
792                         meson.source_root() / 'docs/sphinx/hxtool.py',
793                         meson.source_root() / 'docs/sphinx/kerneldoc.py',
794                         meson.source_root() / 'docs/sphinx/kernellog.py',
795                         meson.source_root() / 'docs/sphinx/qapidoc.py',
796                         meson.source_root() / 'docs/sphinx/qmp_lexer.py',
797                         qapi_gen_depends ]
798
799 # Collect sourcesets.
800
801 util_ss = ss.source_set()
802 stub_ss = ss.source_set()
803 trace_ss = ss.source_set()
804 block_ss = ss.source_set()
805 blockdev_ss = ss.source_set()
806 qmp_ss = ss.source_set()
807 common_ss = ss.source_set()
808 softmmu_ss = ss.source_set()
809 user_ss = ss.source_set()
810 bsd_user_ss = ss.source_set()
811 linux_user_ss = ss.source_set()
812 specific_ss = ss.source_set()
813 specific_fuzz_ss = ss.source_set()
814
815 modules = {}
816 hw_arch = {}
817 target_arch = {}
818 target_softmmu_arch = {}
819
820 ###############
821 # Trace files #
822 ###############
823
824 # TODO: add each directory to the subdirs from its own meson.build, once
825 # we have those
826 trace_events_subdirs = [
827   'accel/kvm',
828   'accel/tcg',
829   'crypto',
830   'monitor',
831 ]
832 if have_user
833   trace_events_subdirs += [ 'linux-user' ]
834 endif
835 if have_block
836   trace_events_subdirs += [
837     'authz',
838     'block',
839     'io',
840     'nbd',
841     'scsi',
842   ]
843 endif
844 if have_system
845   trace_events_subdirs += [
846     'audio',
847     'backends',
848     'backends/tpm',
849     'chardev',
850     'hw/9pfs',
851     'hw/acpi',
852     'hw/alpha',
853     'hw/arm',
854     'hw/audio',
855     'hw/block',
856     'hw/block/dataplane',
857     'hw/char',
858     'hw/display',
859     'hw/dma',
860     'hw/hppa',
861     'hw/hyperv',
862     'hw/i2c',
863     'hw/i386',
864     'hw/i386/xen',
865     'hw/ide',
866     'hw/input',
867     'hw/intc',
868     'hw/isa',
869     'hw/mem',
870     'hw/mips',
871     'hw/misc',
872     'hw/misc/macio',
873     'hw/net',
874     'hw/nvram',
875     'hw/pci',
876     'hw/pci-host',
877     'hw/ppc',
878     'hw/rdma',
879     'hw/rdma/vmw',
880     'hw/rtc',
881     'hw/s390x',
882     'hw/scsi',
883     'hw/sd',
884     'hw/sparc',
885     'hw/sparc64',
886     'hw/ssi',
887     'hw/timer',
888     'hw/tpm',
889     'hw/usb',
890     'hw/vfio',
891     'hw/virtio',
892     'hw/watchdog',
893     'hw/xen',
894     'hw/gpio',
895     'migration',
896     'net',
897     'softmmu',
898     'ui',
899   ]
900 endif
901 trace_events_subdirs += [
902   'hw/core',
903   'qapi',
904   'qom',
905   'target/arm',
906   'target/hppa',
907   'target/i386',
908   'target/mips',
909   'target/ppc',
910   'target/riscv',
911   'target/s390x',
912   'target/sparc',
913   'util',
914 ]
915
916 subdir('qapi')
917 subdir('qobject')
918 subdir('stubs')
919 subdir('trace')
920 subdir('util')
921 subdir('qom')
922 subdir('authz')
923 subdir('crypto')
924 subdir('ui')
925
926
927 if enable_modules
928   libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
929   modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
930 endif
931
932 # Build targets from sourcesets
933
934 stub_ss = stub_ss.apply(config_all, strict: false)
935
936 util_ss.add_all(trace_ss)
937 util_ss = util_ss.apply(config_all, strict: false)
938 libqemuutil = static_library('qemuutil',
939                              sources: util_ss.sources() + stub_ss.sources() + genh,
940                              dependencies: [util_ss.dependencies(), m, glib, socket, malloc])
941 qemuutil = declare_dependency(link_with: libqemuutil,
942                               sources: genh + version_res)
943
944 decodetree = generator(find_program('scripts/decodetree.py'),
945                        output: 'decode-@BASENAME@.c.inc',
946                        arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
947
948 subdir('audio')
949 subdir('io')
950 subdir('chardev')
951 subdir('fsdev')
952 subdir('libdecnumber')
953 subdir('target')
954 subdir('dump')
955
956 block_ss.add(files(
957   'block.c',
958   'blockjob.c',
959   'job.c',
960   'qemu-io-cmds.c',
961 ))
962 block_ss.add(when: 'CONFIG_REPLICATION', if_true: files('replication.c'))
963
964 subdir('nbd')
965 subdir('scsi')
966 subdir('block')
967
968 blockdev_ss.add(files(
969   'blockdev.c',
970   'blockdev-nbd.c',
971   'iothread.c',
972   'job-qmp.c',
973 ))
974
975 # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
976 # os-win32.c does not
977 blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
978 softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
979
980 softmmu_ss.add_all(blockdev_ss)
981 softmmu_ss.add(files(
982   'bootdevice.c',
983   'dma-helpers.c',
984   'qdev-monitor.c',
985 ), sdl)
986
987 softmmu_ss.add(when: 'CONFIG_TPM', if_true: files('tpm.c'))
988 softmmu_ss.add(when: 'CONFIG_SECCOMP', if_true: [files('qemu-seccomp.c'), seccomp])
989 softmmu_ss.add(when: ['CONFIG_FDT', fdt],  if_true: [files('device_tree.c')])
990
991 common_ss.add(files('cpus-common.c'))
992
993 subdir('softmmu')
994
995 specific_ss.add(files('disas.c', 'exec.c', 'gdbstub.c'), capstone, libpmem, libdaxctl)
996 specific_ss.add(files('exec-vary.c'))
997 specific_ss.add(when: 'CONFIG_TCG', if_true: files(
998   'fpu/softfloat.c',
999   'tcg/optimize.c',
1000   'tcg/tcg-common.c',
1001   'tcg/tcg-op-gvec.c',
1002   'tcg/tcg-op-vec.c',
1003   'tcg/tcg-op.c',
1004   'tcg/tcg.c',
1005 ))
1006 specific_ss.add(when: 'CONFIG_TCG_INTERPRETER', if_true: files('disas/tci.c', 'tcg/tci.c'))
1007
1008 subdir('backends')
1009 subdir('disas')
1010 subdir('migration')
1011 subdir('monitor')
1012 subdir('net')
1013 subdir('replay')
1014 subdir('hw')
1015 subdir('accel')
1016 subdir('plugins')
1017 subdir('bsd-user')
1018 subdir('linux-user')
1019
1020 bsd_user_ss.add(files('gdbstub.c'))
1021 specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss)
1022
1023 linux_user_ss.add(files('gdbstub.c', 'thunk.c'))
1024 specific_ss.add_all(when: 'CONFIG_LINUX_USER', if_true: linux_user_ss)
1025
1026 # needed for fuzzing binaries
1027 subdir('tests/qtest/libqos')
1028 subdir('tests/qtest/fuzz')
1029
1030 block_mods = []
1031 softmmu_mods = []
1032 foreach d, list : modules
1033   foreach m, module_ss : list
1034     if enable_modules and targetos != 'windows'
1035       module_ss = module_ss.apply(config_all, strict: false)
1036       sl = static_library(d + '-' + m, [genh, module_ss.sources()],
1037                           dependencies: [modulecommon, module_ss.dependencies()], pic: true)
1038       if d == 'block'
1039         block_mods += sl
1040       else
1041         softmmu_mods += sl
1042       endif
1043     else
1044       if d == 'block'
1045         block_ss.add_all(module_ss)
1046       else
1047         softmmu_ss.add_all(module_ss)
1048       endif
1049     endif
1050   endforeach
1051 endforeach
1052
1053 nm = find_program('nm')
1054 undefsym = find_program('scripts/undefsym.py')
1055 block_syms = custom_target('block.syms', output: 'block.syms',
1056                              input: [libqemuutil, block_mods],
1057                              capture: true,
1058                              command: [undefsym, nm, '@INPUT@'])
1059 qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
1060                              input: [libqemuutil, softmmu_mods],
1061                              capture: true,
1062                              command: [undefsym, nm, '@INPUT@'])
1063
1064 block_ss = block_ss.apply(config_host, strict: false)
1065 libblock = static_library('block', block_ss.sources() + genh,
1066                           dependencies: block_ss.dependencies(),
1067                           link_depends: block_syms,
1068                           name_suffix: 'fa',
1069                           build_by_default: false)
1070
1071 block = declare_dependency(link_whole: [libblock],
1072                            link_args: '@block.syms',
1073                            dependencies: [crypto, io])
1074
1075 qmp_ss = qmp_ss.apply(config_host, strict: false)
1076 libqmp = static_library('qmp', qmp_ss.sources() + genh,
1077                         dependencies: qmp_ss.dependencies(),
1078                         name_suffix: 'fa',
1079                         build_by_default: false)
1080
1081 qmp = declare_dependency(link_whole: [libqmp])
1082
1083 foreach m : block_mods + softmmu_mods
1084   shared_module(m.name(),
1085                 name_prefix: '',
1086                 link_whole: m,
1087                 install: true,
1088                 install_dir: config_host['qemu_moddir'])
1089 endforeach
1090
1091 softmmu_ss.add(authz, block, chardev, crypto, io, qmp)
1092 common_ss.add(qom, qemuutil)
1093
1094 common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
1095 common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
1096
1097 common_all = common_ss.apply(config_all, strict: false)
1098 common_all = static_library('common',
1099                             build_by_default: false,
1100                             sources: common_all.sources() + genh,
1101                             dependencies: common_all.dependencies(),
1102                             name_suffix: 'fa')
1103
1104 feature_to_c = find_program('scripts/feature_to_c.sh')
1105
1106 emulators = []
1107 foreach target : target_dirs
1108   config_target = config_target_mak[target]
1109   target_name = config_target['TARGET_NAME']
1110   arch = config_target['TARGET_BASE_ARCH']
1111   arch_srcs = [config_target_h[target]]
1112   arch_deps = []
1113   c_args = ['-DNEED_CPU_H',
1114             '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
1115             '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
1116   link_args = []
1117
1118   config_target += config_host
1119   target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
1120   if targetos == 'linux'
1121     target_inc += include_directories('linux-headers', is_system: true)
1122   endif
1123   if target.endswith('-softmmu')
1124     qemu_target_name = 'qemu-system-' + target_name
1125     target_type='system'
1126     t = target_softmmu_arch[arch].apply(config_target, strict: false)
1127     arch_srcs += t.sources()
1128     arch_deps += t.dependencies()
1129
1130     hw_dir = target_name == 'sparc64' ? 'sparc64' : arch
1131     hw = hw_arch[hw_dir].apply(config_target, strict: false)
1132     arch_srcs += hw.sources()
1133     arch_deps += hw.dependencies()
1134
1135     arch_srcs += config_devices_h[target]
1136     link_args += ['@block.syms', '@qemu.syms']
1137   else
1138     abi = config_target['TARGET_ABI_DIR']
1139     target_type='user'
1140     qemu_target_name = 'qemu-' + target_name
1141     if 'CONFIG_LINUX_USER' in config_target
1142       base_dir = 'linux-user'
1143       target_inc += include_directories('linux-user/host/' / config_host['ARCH'])
1144     else
1145       base_dir = 'bsd-user'
1146     endif
1147     target_inc += include_directories(
1148       base_dir,
1149       base_dir / abi,
1150     )
1151     if 'CONFIG_LINUX_USER' in config_target
1152       dir = base_dir / abi
1153       arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
1154       if config_target.has_key('TARGET_SYSTBL_ABI')
1155         arch_srcs += \
1156           syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
1157                                              extra_args : config_target['TARGET_SYSTBL_ABI'])
1158       endif
1159     endif
1160   endif
1161
1162   if 'TARGET_XML_FILES' in config_target
1163     gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
1164                                 output: target + '-gdbstub-xml.c',
1165                                 input: files(config_target['TARGET_XML_FILES'].split()),
1166                                 command: [feature_to_c, '@INPUT@'],
1167                                 capture: true)
1168     arch_srcs += gdbstub_xml
1169   endif
1170
1171   t = target_arch[arch].apply(config_target, strict: false)
1172   arch_srcs += t.sources()
1173   arch_deps += t.dependencies()
1174
1175   target_common = common_ss.apply(config_target, strict: false)
1176   objects = common_all.extract_objects(target_common.sources())
1177   deps = target_common.dependencies()
1178
1179   target_specific = specific_ss.apply(config_target, strict: false)
1180   arch_srcs += target_specific.sources()
1181   arch_deps += target_specific.dependencies()
1182
1183   lib = static_library('qemu-' + target,
1184                  sources: arch_srcs + genh,
1185                  dependencies: arch_deps,
1186                  objects: objects,
1187                  include_directories: target_inc,
1188                  c_args: c_args,
1189                  build_by_default: false,
1190                  name_suffix: 'fa')
1191
1192   if target.endswith('-softmmu')
1193     execs = [{
1194       'name': 'qemu-system-' + target_name,
1195       'gui': false,
1196       'sources': files('softmmu/main.c'),
1197       'dependencies': []
1198     }]
1199     if targetos == 'windows' and (sdl.found() or gtk.found())
1200       execs += [{
1201         'name': 'qemu-system-' + target_name + 'w',
1202         'gui': true,
1203         'sources': files('softmmu/main.c'),
1204         'dependencies': []
1205       }]
1206     endif
1207     if config_host.has_key('CONFIG_FUZZ')
1208       specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
1209       execs += [{
1210         'name': 'qemu-fuzz-' + target_name,
1211         'gui': false,
1212         'sources': specific_fuzz.sources(),
1213         'dependencies': specific_fuzz.dependencies(),
1214       }]
1215     endif
1216   else
1217     execs = [{
1218       'name': 'qemu-' + target_name,
1219       'gui': false,
1220       'sources': [],
1221       'dependencies': []
1222     }]
1223   endif
1224   foreach exe: execs
1225     emulators += executable(exe['name'], exe['sources'],
1226                install: true,
1227                c_args: c_args,
1228                dependencies: arch_deps + deps + exe['dependencies'],
1229                objects: lib.extract_all_objects(recursive: true),
1230                link_language: link_language,
1231                link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
1232                link_args: link_args,
1233                gui_app: exe['gui'])
1234
1235     if 'CONFIG_TRACE_SYSTEMTAP' in config_host
1236       foreach stp: [
1237         {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
1238         {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
1239         {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
1240         {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
1241       ]
1242         custom_target(exe['name'] + stp['ext'],
1243                       input: trace_events_all,
1244                       output: exe['name'] + stp['ext'],
1245                       capture: true,
1246                       install: stp['install'],
1247                       install_dir: qemu_datadir / '../systemtap/tapset',
1248                       command: [
1249                         tracetool, '--group=all', '--format=' + stp['fmt'],
1250                         '--binary=' + stp['bin'],
1251                         '--target-name=' + target_name,
1252                         '--target-type=' + target_type,
1253                         '--probe-prefix=qemu.' + target_type + '.' + target_name,
1254                         '@INPUT@',
1255                       ])
1256       endforeach
1257     endif
1258   endforeach
1259 endforeach
1260
1261 # Other build targets
1262
1263 if 'CONFIG_PLUGIN' in config_host
1264   install_headers('include/qemu/qemu-plugin.h')
1265 endif
1266
1267 if 'CONFIG_GUEST_AGENT' in config_host
1268   subdir('qga')
1269 endif
1270
1271 # Don't build qemu-keymap if xkbcommon is not explicitly enabled
1272 # when we don't build tools or system
1273 if xkbcommon.found()
1274   # used for the update-keymaps target, so include rules even if !have_tools
1275   qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
1276                            dependencies: [qemuutil, xkbcommon], install: have_tools)
1277 endif
1278
1279 qemu_block_tools = []
1280 if have_tools
1281   qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
1282              dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
1283   qemu_io = executable('qemu-io', files('qemu-io.c'),
1284              dependencies: [block, qemuutil], install: true)
1285   qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
1286                dependencies: [block, qemuutil], install: true)
1287
1288   subdir('storage-daemon')
1289   subdir('contrib/rdmacm-mux')
1290   subdir('contrib/elf2dmp')
1291
1292   executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
1293              dependencies: qemuutil,
1294              install: true)
1295
1296   if 'CONFIG_VHOST_USER' in config_host
1297     subdir('contrib/libvhost-user')
1298     subdir('contrib/vhost-user-blk')
1299     subdir('contrib/vhost-user-gpu')
1300     subdir('contrib/vhost-user-input')
1301     subdir('contrib/vhost-user-scsi')
1302   endif
1303
1304   if targetos == 'linux'
1305     executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
1306                dependencies: [qemuutil, libcap_ng],
1307                install: true,
1308                install_dir: get_option('libexecdir'))
1309
1310     executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
1311                dependencies: [authz, crypto, io, qom, qemuutil,
1312                               libcap_ng, mpathpersist],
1313                install: true)
1314   endif
1315
1316   if 'CONFIG_IVSHMEM' in config_host
1317     subdir('contrib/ivshmem-client')
1318     subdir('contrib/ivshmem-server')
1319   endif
1320 endif
1321
1322 subdir('scripts')
1323 subdir('tools')
1324 subdir('pc-bios')
1325 subdir('tests')
1326 subdir('docs')
1327 if 'CONFIG_GTK' in config_host
1328   subdir('po')
1329 endif
1330
1331 if host_machine.system() == 'windows'
1332   nsis_cmd = [
1333     find_program('scripts/nsis.py'),
1334     '@OUTPUT@',
1335     get_option('prefix'),
1336     meson.current_source_dir(),
1337     host_machine.cpu_family(),
1338     '--',
1339     '-DDISPLAYVERSION=' + meson.project_version(),
1340   ]
1341   if build_docs
1342     nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
1343   endif
1344   if 'CONFIG_GTK' in config_host
1345     nsis_cmd += '-DCONFIG_GTK=y'
1346   endif
1347
1348   nsis = custom_target('nsis',
1349                        output: 'qemu-setup-' + meson.project_version() + '.exe',
1350                        input: files('qemu.nsi'),
1351                        build_always_stale: true,
1352                        command: nsis_cmd + ['@INPUT@'])
1353   alias_target('installer', nsis)
1354 endif
1355
1356 summary_info = {}
1357 summary_info += {'Install prefix':    config_host['prefix']}
1358 summary_info += {'BIOS directory':    config_host['qemu_datadir']}
1359 summary_info += {'firmware path':     config_host['qemu_firmwarepath']}
1360 summary_info += {'binary directory':  config_host['bindir']}
1361 summary_info += {'library directory': config_host['libdir']}
1362 summary_info += {'module directory':  config_host['qemu_moddir']}
1363 summary_info += {'libexec directory': config_host['libexecdir']}
1364 summary_info += {'include directory': config_host['includedir']}
1365 summary_info += {'config directory':  config_host['sysconfdir']}
1366 if targetos != 'windows'
1367   summary_info += {'local state directory': config_host['qemu_localstatedir']}
1368   summary_info += {'Manual directory':      get_option('mandir')}
1369 else
1370   summary_info += {'local state directory': 'queried at runtime'}
1371 endif
1372 summary_info += {'Doc directory':     get_option('docdir')}
1373 summary_info += {'Build directory':   meson.current_build_dir()}
1374 summary_info += {'Source path':       meson.current_source_dir()}
1375 summary_info += {'GIT binary':        config_host['GIT']}
1376 summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
1377 summary_info += {'C compiler':        meson.get_compiler('c').cmd_array()[0]}
1378 summary_info += {'Host C compiler':   meson.get_compiler('c', native: true).cmd_array()[0]}
1379 if link_language == 'cpp'
1380   summary_info += {'C++ compiler':      meson.get_compiler('cpp').cmd_array()[0]}
1381 else
1382   summary_info += {'C++ compiler':      false}
1383 endif
1384 if targetos == 'darwin'
1385   summary_info += {'Objective-C compiler': meson.get_compiler('objc').cmd_array()[0]}
1386 endif
1387 summary_info += {'ARFLAGS':           config_host['ARFLAGS']}
1388 summary_info += {'CFLAGS':            config_host['CFLAGS']}
1389 summary_info += {'QEMU_CFLAGS':       config_host['QEMU_CFLAGS']}
1390 summary_info += {'QEMU_LDFLAGS':      config_host['QEMU_LDFLAGS']}
1391 summary_info += {'make':              config_host['MAKE']}
1392 summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
1393 summary_info += {'sphinx-build':      config_host['SPHINX_BUILD']}
1394 summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
1395 # TODO: add back version
1396 summary_info += {'slirp support':     config_host.has_key('CONFIG_SLIRP')}
1397 if config_host.has_key('CONFIG_SLIRP')
1398   summary_info += {'smbd':            config_host['CONFIG_SMBD_COMMAND']}
1399 endif
1400 summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
1401 if config_host.has_key('CONFIG_MODULES')
1402   summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')}
1403 endif
1404 summary_info += {'host CPU':          cpu}
1405 summary_info += {'host endianness':   build_machine.endian()}
1406 summary_info += {'target list':       config_host['TARGET_DIRS']}
1407 summary_info += {'gprof enabled':     config_host.has_key('CONFIG_GPROF')}
1408 summary_info += {'sparse enabled':    meson.get_compiler('c').cmd_array().contains('cgcc')}
1409 summary_info += {'strip binaries':    get_option('strip')}
1410 summary_info += {'profiler':          config_host.has_key('CONFIG_PROFILER')}
1411 summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
1412 if targetos == 'darwin'
1413   summary_info += {'Cocoa support': config_host.has_key('CONFIG_COCOA')}
1414 endif
1415 # TODO: add back version
1416 summary_info += {'SDL support':       sdl.found()}
1417 summary_info += {'SDL image support': sdl_image.found()}
1418 # TODO: add back version
1419 summary_info += {'GTK support':       config_host.has_key('CONFIG_GTK')}
1420 summary_info += {'GTK GL support':    config_host.has_key('CONFIG_GTK_GL')}
1421 summary_info += {'pixman':            pixman.found()}
1422 # TODO: add back version
1423 summary_info += {'VTE support':       config_host.has_key('CONFIG_VTE')}
1424 summary_info += {'TLS priority':      config_host['CONFIG_TLS_PRIORITY']}
1425 summary_info += {'GNUTLS support':    config_host.has_key('CONFIG_GNUTLS')}
1426 # TODO: add back version
1427 summary_info += {'libgcrypt':         config_host.has_key('CONFIG_GCRYPT')}
1428 if config_host.has_key('CONFIG_GCRYPT')
1429    summary_info += {'  hmac':            config_host.has_key('CONFIG_GCRYPT_HMAC')}
1430    summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
1431 endif
1432 # TODO: add back version
1433 summary_info += {'nettle':            config_host.has_key('CONFIG_NETTLE')}
1434 if config_host.has_key('CONFIG_NETTLE')
1435    summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
1436 endif
1437 summary_info += {'libtasn1':          config_host.has_key('CONFIG_TASN1')}
1438 summary_info += {'PAM':               config_host.has_key('CONFIG_AUTH_PAM')}
1439 summary_info += {'iconv support':     config_host.has_key('CONFIG_ICONV')}
1440 summary_info += {'curses support':    config_host.has_key('CONFIG_CURSES')}
1441 # TODO: add back version
1442 summary_info += {'virgl support':     config_host.has_key('CONFIG_VIRGL')}
1443 summary_info += {'curl support':      config_host.has_key('CONFIG_CURL')}
1444 summary_info += {'mingw32 support':   targetos == 'windows'}
1445 summary_info += {'Audio drivers':     config_host['CONFIG_AUDIO_DRIVERS']}
1446 summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']}
1447 summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']}
1448 summary_info += {'VirtFS support':    config_host.has_key('CONFIG_VIRTFS')}
1449 summary_info += {'Multipath support': mpathpersist.found()}
1450 summary_info += {'VNC support':       vnc.found()}
1451 if vnc.found()
1452   summary_info += {'VNC SASL support':  sasl.found()}
1453   summary_info += {'VNC JPEG support':  jpeg.found()}
1454   summary_info += {'VNC PNG support':   png.found()}
1455 endif
1456 summary_info += {'xen support':       config_host.has_key('CONFIG_XEN_BACKEND')}
1457 if config_host.has_key('CONFIG_XEN_BACKEND')
1458   summary_info += {'xen ctrl version':  config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
1459 endif
1460 summary_info += {'brlapi support':    config_host.has_key('CONFIG_BRLAPI')}
1461 summary_info += {'Documentation':     config_host.has_key('BUILD_DOCS')}
1462 summary_info += {'PIE':               get_option('b_pie')}
1463 summary_info += {'vde support':       config_host.has_key('CONFIG_VDE')}
1464 summary_info += {'netmap support':    config_host.has_key('CONFIG_NETMAP')}
1465 summary_info += {'Linux AIO support': config_host.has_key('CONFIG_LINUX_AIO')}
1466 summary_info += {'Linux io_uring support': config_host.has_key('CONFIG_LINUX_IO_URING')}
1467 summary_info += {'ATTR/XATTR support': config_host.has_key('CONFIG_ATTR')}
1468 summary_info += {'Install blobs':     config_host.has_key('INSTALL_BLOBS')}
1469 # TODO: add back KVM/HAX/HVF/WHPX/TCG
1470 #summary_info += {'KVM support':       have_kvm'}
1471 #summary_info += {'HAX support':       have_hax'}
1472 #summary_info += {'HVF support':       have_hvf'}
1473 #summary_info += {'WHPX support':      have_whpx'}
1474 #summary_info += {'TCG support':       have_tcg'}
1475 #if get_option('tcg')
1476 #  summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
1477 #  summary_info += {'TCG interpreter':   config_host.has_key('CONFIG_TCG_INTERPRETER')}
1478 #endif
1479 summary_info += {'malloc trim support': has_malloc_trim}
1480 summary_info += {'RDMA support':      config_host.has_key('CONFIG_RDMA')}
1481 summary_info += {'PVRDMA support':    config_host.has_key('CONFIG_PVRDMA')}
1482 summary_info += {'fdt support':       config_host.has_key('CONFIG_FDT')}
1483 summary_info += {'membarrier':        config_host.has_key('CONFIG_MEMBARRIER')}
1484 summary_info += {'preadv support':    config_host.has_key('CONFIG_PREADV')}
1485 summary_info += {'fdatasync':         config_host.has_key('CONFIG_FDATASYNC')}
1486 summary_info += {'madvise':           config_host.has_key('CONFIG_MADVISE')}
1487 summary_info += {'posix_madvise':     config_host.has_key('CONFIG_POSIX_MADVISE')}
1488 summary_info += {'posix_memalign':    config_host.has_key('CONFIG_POSIX_MEMALIGN')}
1489 summary_info += {'libcap-ng support': config_host.has_key('CONFIG_LIBCAP_NG')}
1490 summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')}
1491 summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')}
1492 summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')}
1493 summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')}
1494 summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_KERNEL')}
1495 summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')}
1496 summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')}
1497 summary_info += {'Trace backends':    config_host['TRACE_BACKENDS']}
1498 if config_host['TRACE_BACKENDS'].split().contains('simple')
1499   summary_info += {'Trace output file': config_host['CONFIG_TRACE_FILE'] + '-<pid>'}
1500 endif
1501 # TODO: add back protocol and server version
1502 summary_info += {'spice support':     config_host.has_key('CONFIG_SPICE')}
1503 summary_info += {'rbd support':       config_host.has_key('CONFIG_RBD')}
1504 summary_info += {'xfsctl support':    config_host.has_key('CONFIG_XFS')}
1505 summary_info += {'smartcard support': config_host.has_key('CONFIG_SMARTCARD')}
1506 summary_info += {'U2F support':       u2f.found()}
1507 summary_info += {'libusb':            config_host.has_key('CONFIG_USB_LIBUSB')}
1508 summary_info += {'usb net redir':     config_host.has_key('CONFIG_USB_REDIR')}
1509 summary_info += {'OpenGL support':    config_host.has_key('CONFIG_OPENGL')}
1510 summary_info += {'OpenGL dmabufs':    config_host.has_key('CONFIG_OPENGL_DMABUF')}
1511 summary_info += {'libiscsi support':  config_host.has_key('CONFIG_LIBISCSI')}
1512 summary_info += {'libnfs support':    config_host.has_key('CONFIG_LIBNFS')}
1513 summary_info += {'build guest agent': config_host.has_key('CONFIG_GUEST_AGENT')}
1514 if targetos == 'windows'
1515   if 'WIN_SDK' in config_host
1516     summary_info += {'Windows SDK':       config_host['WIN_SDK']}
1517   endif
1518   summary_info += {'QGA VSS support':   config_host.has_key('CONFIG_QGA_VSS')}
1519   summary_info += {'QGA w32 disk info': config_host.has_key('CONFIG_QGA_NTDDSCSI')}
1520   summary_info += {'QGA MSI support':   config_host.has_key('CONFIG_QGA_MSI')}
1521 endif
1522 summary_info += {'seccomp support':   config_host.has_key('CONFIG_SECCOMP')}
1523 summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
1524 summary_info += {'coroutine pool':    config_host['CONFIG_COROUTINE_POOL'] == '1'}
1525 summary_info += {'debug stack usage': config_host.has_key('CONFIG_DEBUG_STACK_USAGE')}
1526 summary_info += {'mutex debugging':   config_host.has_key('CONFIG_DEBUG_MUTEX')}
1527 summary_info += {'crypto afalg':      config_host.has_key('CONFIG_AF_ALG')}
1528 summary_info += {'GlusterFS support': config_host.has_key('CONFIG_GLUSTERFS')}
1529 summary_info += {'gcov':              get_option('b_coverage')}
1530 summary_info += {'TPM support':       config_host.has_key('CONFIG_TPM')}
1531 summary_info += {'libssh support':    config_host.has_key('CONFIG_LIBSSH')}
1532 summary_info += {'QOM debugging':     config_host.has_key('CONFIG_QOM_CAST_DEBUG')}
1533 summary_info += {'Live block migration': config_host.has_key('CONFIG_LIVE_BLOCK_MIGRATION')}
1534 summary_info += {'lzo support':       config_host.has_key('CONFIG_LZO')}
1535 summary_info += {'snappy support':    config_host.has_key('CONFIG_SNAPPY')}
1536 summary_info += {'bzip2 support':     config_host.has_key('CONFIG_BZIP2')}
1537 summary_info += {'lzfse support':     config_host.has_key('CONFIG_LZFSE')}
1538 summary_info += {'zstd support':      config_host.has_key('CONFIG_ZSTD')}
1539 summary_info += {'NUMA host support': config_host.has_key('CONFIG_NUMA')}
1540 summary_info += {'libxml2':           config_host.has_key('CONFIG_LIBXML2')}
1541 summary_info += {'memory allocator':  get_option('malloc')}
1542 summary_info += {'avx2 optimization': config_host.has_key('CONFIG_AVX2_OPT')}
1543 summary_info += {'avx512f optimization': config_host.has_key('CONFIG_AVX512F_OPT')}
1544 summary_info += {'replication support': config_host.has_key('CONFIG_REPLICATION')}
1545 summary_info += {'bochs support':     config_host.has_key('CONFIG_BOCHS')}
1546 summary_info += {'cloop support':     config_host.has_key('CONFIG_CLOOP')}
1547 summary_info += {'dmg support':       config_host.has_key('CONFIG_DMG')}
1548 summary_info += {'qcow v1 support':   config_host.has_key('CONFIG_QCOW1')}
1549 summary_info += {'vdi support':       config_host.has_key('CONFIG_VDI')}
1550 summary_info += {'vvfat support':     config_host.has_key('CONFIG_VVFAT')}
1551 summary_info += {'qed support':       config_host.has_key('CONFIG_QED')}
1552 summary_info += {'parallels support': config_host.has_key('CONFIG_PARALLELS')}
1553 summary_info += {'sheepdog support':  config_host.has_key('CONFIG_SHEEPDOG')}
1554 summary_info += {'capstone':          config_host.has_key('CONFIG_CAPSTONE')}
1555 summary_info += {'libpmem support':   config_host.has_key('CONFIG_LIBPMEM')}
1556 summary_info += {'libdaxctl support': config_host.has_key('CONFIG_LIBDAXCTL')}
1557 summary_info += {'libudev':           libudev.found()}
1558 summary_info += {'default devices':   config_host['CONFIG_MINIKCONF_MODE'] == '--defconfig'}
1559 summary_info += {'plugin support':    config_host.has_key('CONFIG_PLUGIN')}
1560 summary_info += {'fuzzing support':   config_host.has_key('CONFIG_FUZZ')}
1561 if config_host.has_key('HAVE_GDB_BIN')
1562   summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
1563 endif
1564 summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
1565 summary_info += {'rng-none':          config_host.has_key('CONFIG_RNG_NONE')}
1566 summary_info += {'Linux keyring':     config_host.has_key('CONFIG_SECRET_KEYRING')}
1567 summary(summary_info, bool_yn: true)
1568
1569 if not supported_cpus.contains(cpu)
1570   message()
1571   warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
1572   message()
1573   message('CPU host architecture ' + cpu + ' support is not currently maintained.')
1574   message('The QEMU project intends to remove support for this host CPU in')
1575   message('a future release if nobody volunteers to maintain it and to')
1576   message('provide a build host for our continuous integration setup.')
1577   message('configure has succeeded and you can continue to build, but')
1578   message('if you care about QEMU on this platform you should contact')
1579   message('us upstream at qemu-devel@nongnu.org.')
1580 endif
1581
1582 if not supported_oses.contains(targetos)
1583   message()
1584   warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
1585   message()
1586   message('Host OS ' + targetos + 'support is not currently maintained.')
1587   message('The QEMU project intends to remove support for this host OS in')
1588   message('a future release if nobody volunteers to maintain it and to')
1589   message('provide a build host for our continuous integration setup.')
1590   message('configure has succeeded and you can continue to build, but')
1591   message('if you care about QEMU on this platform you should contact')
1592   message('us upstream at qemu-devel@nongnu.org.')
1593 endif