build: replace ninjatool with ninja
[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 fs = import('fs')
14
15 sh = find_program('sh')
16 cc = meson.get_compiler('c')
17 config_host = keyval.load(meson.current_build_dir() / 'config-host.mak')
18 enable_modules = 'CONFIG_MODULES' in config_host
19 enable_static = 'CONFIG_STATIC' in config_host
20 build_docs = 'BUILD_DOCS' in config_host
21
22 if get_option('qemu_suffix').startswith('/')
23   error('qemu_suffix cannot start with a /')
24 endif
25
26 qemu_datadir = get_option('datadir') / get_option('qemu_suffix')
27 qemu_docdir = get_option('docdir') / get_option('qemu_suffix')
28 config_host_data = configuration_data()
29 genh = []
30
31 target_dirs = config_host['TARGET_DIRS'].split()
32 have_user = false
33 have_system = false
34 foreach target : target_dirs
35   have_user = have_user or target.endswith('-user')
36   have_system = have_system or target.endswith('-softmmu')
37 endforeach
38 have_tools = 'CONFIG_TOOLS' in config_host
39 have_block = have_system or have_tools
40
41 python = import('python').find_installation()
42
43 supported_oses = ['windows', 'freebsd', 'netbsd', 'openbsd', 'darwin', 'sunos', 'linux']
44 supported_cpus = ['ppc', 'ppc64', 's390x', 'riscv32', 'riscv64', 'x86', 'x86_64',
45   'arm', 'aarch64', 'mips', 'mips64', 'sparc', 'sparc64']
46
47 cpu = host_machine.cpu_family()
48 targetos = host_machine.system()
49
50 if cpu in ['x86', 'x86_64']
51   kvm_targets = ['i386-softmmu', 'x86_64-softmmu']
52 elif cpu == 'aarch64'
53   kvm_targets = ['aarch64-softmmu']
54 elif cpu == 's390x'
55   kvm_targets = ['s390x-softmmu']
56 elif cpu in ['ppc', 'ppc64']
57   kvm_targets = ['ppc-softmmu', 'ppc64-softmmu']
58 elif cpu in ['mips', 'mips64']
59   kvm_targets = ['mips-softmmu', 'mipsel-softmmu', 'mips64-softmmu', 'mips64el-softmmu']
60 else
61   kvm_targets = []
62 endif
63
64 accelerator_targets = { 'CONFIG_KVM': kvm_targets }
65 if cpu in ['x86', 'x86_64']
66   accelerator_targets += {
67     'CONFIG_HAX': ['i386-softmmu', 'x86_64-softmmu'],
68     'CONFIG_XEN': ['i386-softmmu', 'x86_64-softmmu'],
69     'CONFIG_HVF': ['x86_64-softmmu'],
70     'CONFIG_WHPX': ['i386-softmmu', 'x86_64-softmmu'],
71   }
72 endif
73
74 ##################
75 # Compiler flags #
76 ##################
77
78 # Specify linker-script with add_project_link_arguments so that it is not placed
79 # within a linker --start-group/--end-group pair
80 if 'CONFIG_FUZZ' in config_host
81    add_project_link_arguments(['-Wl,-T,',
82                                (meson.current_source_dir() / 'tests/qtest/fuzz/fork_fuzz.ld')],
83                               native: false, language: ['c', 'cpp', 'objc'])
84 endif
85
86 add_project_arguments(config_host['QEMU_CFLAGS'].split(),
87                       native: false, language: ['c', 'objc'])
88 add_project_arguments(config_host['QEMU_CXXFLAGS'].split(),
89                       native: false, language: 'cpp')
90 add_project_link_arguments(config_host['QEMU_LDFLAGS'].split(),
91                            native: false, language: ['c', 'cpp', 'objc'])
92
93 if targetos == 'linux'
94   add_project_arguments('-isystem', meson.current_source_dir() / 'linux-headers',
95                         '-isystem', 'linux-headers',
96                         language: ['c', 'cpp'])
97 endif
98
99 if 'CONFIG_TCG_INTERPRETER' in config_host
100   tcg_arch = 'tci'
101 elif config_host['ARCH'] == 'sparc64'
102   tcg_arch = 'sparc'
103 elif config_host['ARCH'] == 's390x'
104   tcg_arch = 's390'
105 elif config_host['ARCH'] in ['x86_64', 'x32']
106   tcg_arch = 'i386'
107 elif config_host['ARCH'] == 'ppc64'
108   tcg_arch = 'ppc'
109 elif config_host['ARCH'] in ['riscv32', 'riscv64']
110   tcg_arch = 'riscv'
111 else
112   tcg_arch = config_host['ARCH']
113 endif
114 add_project_arguments('-iquote', meson.current_source_dir() / 'tcg' / tcg_arch,
115                       '-iquote', '.',
116                       '-iquote', meson.current_source_dir(),
117                       '-iquote', meson.current_source_dir() / 'accel/tcg',
118                       '-iquote', meson.current_source_dir() / 'include',
119                       '-iquote', meson.current_source_dir() / 'disas/libvixl',
120                       language: ['c', 'cpp', 'objc'])
121
122 link_language = meson.get_external_property('link_language', 'cpp')
123 if link_language == 'cpp'
124   add_languages('cpp', required: true, native: false)
125 endif
126 if host_machine.system() == 'darwin'
127   add_languages('objc', required: false, native: false)
128 endif
129
130 sparse = find_program('cgcc', required: get_option('sparse'))
131 if sparse.found()
132   run_target('sparse',
133              command: [find_program('scripts/check_sparse.py'),
134                        'compile_commands.json', sparse.full_path(), '-Wbitwise',
135                        '-Wno-transparent-union', '-Wno-old-initializer',
136                        '-Wno-non-pointer-null'])
137 endif
138
139 ###########################################
140 # Target-specific checks and dependencies #
141 ###########################################
142
143 if targetos != 'linux' and get_option('mpath').enabled()
144   error('Multipath is supported only on Linux')
145 endif
146
147 m = cc.find_library('m', required: false)
148 util = cc.find_library('util', required: false)
149 winmm = []
150 socket = []
151 version_res = []
152 coref = []
153 iokit = []
154 emulator_link_args = []
155 cocoa = not_found
156 hvf = not_found
157 if targetos == 'windows'
158   socket = cc.find_library('ws2_32')
159   winmm = cc.find_library('winmm')
160
161   win = import('windows')
162   version_res = win.compile_resources('version.rc',
163                                       depend_files: files('pc-bios/qemu-nsis.ico'),
164                                       include_directories: include_directories('.'))
165 elif targetos == 'darwin'
166   coref = dependency('appleframeworks', modules: 'CoreFoundation')
167   iokit = dependency('appleframeworks', modules: 'IOKit')
168   cocoa = dependency('appleframeworks', modules: 'Cocoa', required: get_option('cocoa'))
169 elif targetos == 'sunos'
170   socket = [cc.find_library('socket'),
171             cc.find_library('nsl'),
172             cc.find_library('resolv')]
173 elif targetos == 'haiku'
174   socket = [cc.find_library('posix_error_mapper'),
175             cc.find_library('network'),
176             cc.find_library('bsd')]
177 elif targetos == 'openbsd'
178   if not get_option('tcg').disabled() and target_dirs.length() > 0
179     # Disable OpenBSD W^X if available
180     emulator_link_args = cc.get_supported_link_arguments('-Wl,-z,wxneeded')
181   endif
182 endif
183
184 accelerators = []
185 if not get_option('kvm').disabled() and targetos == 'linux'
186   accelerators += 'CONFIG_KVM'
187 endif
188 if not get_option('xen').disabled() and 'CONFIG_XEN_BACKEND' in config_host
189   accelerators += 'CONFIG_XEN'
190   have_xen_pci_passthrough = not get_option('xen_pci_passthrough').disabled() and targetos == 'linux'
191 else
192   have_xen_pci_passthrough = false
193 endif
194 if not get_option('whpx').disabled() and targetos == 'windows'
195   if get_option('whpx').enabled() and cpu != 'x86_64'
196     error('WHPX requires 64-bit host')
197   elif cc.has_header('WinHvPlatform.h', required: get_option('whpx')) and \
198        cc.has_header('WinHvEmulation.h', required: get_option('whpx'))
199     accelerators += 'CONFIG_WHPX'
200   endif
201 endif
202 if not get_option('hvf').disabled()
203   hvf = dependency('appleframeworks', modules: 'Hypervisor',
204                    required: get_option('hvf'))
205   if hvf.found()
206     accelerators += 'CONFIG_HVF'
207   endif
208 endif
209 if not get_option('hax').disabled()
210   if get_option('hax').enabled() or targetos in ['windows', 'darwin', 'netbsd']
211     accelerators += 'CONFIG_HAX'
212   endif
213 endif
214 if not get_option('tcg').disabled()
215   if cpu not in supported_cpus
216     if 'CONFIG_TCG_INTERPRETER' in config_host
217       warning('Unsupported CPU @0@, will use TCG with TCI (experimental)'.format(cpu))
218     else
219       error('Unsupported CPU @0@, try --enable-tcg-interpreter'.format(cpu))
220     endif
221   endif
222   accelerators += 'CONFIG_TCG'
223   config_host += { 'CONFIG_TCG': 'y' }
224 endif
225
226 if 'CONFIG_KVM' not in accelerators and get_option('kvm').enabled()
227   error('KVM not available on this platform')
228 endif
229 if 'CONFIG_HVF' not in accelerators and get_option('hvf').enabled()
230   error('HVF not available on this platform')
231 endif
232 if 'CONFIG_WHPX' not in accelerators and get_option('whpx').enabled()
233   error('WHPX not available on this platform')
234 endif
235 if not have_xen_pci_passthrough and get_option('xen_pci_passthrough').enabled()
236   if 'CONFIG_XEN' in accelerators
237     error('Xen PCI passthrough not available on this platform')
238   else
239     error('Xen PCI passthrough requested but Xen not enabled')
240   endif
241 endif
242 if not cocoa.found() and get_option('cocoa').enabled()
243   error('Cocoa not available on this platform')
244 endif
245
246 ################
247 # Dependencies #
248 ################
249
250 # The path to glib.h is added to all compilation commands.  This was
251 # grandfathered in from the QEMU Makefiles.
252 add_project_arguments(config_host['GLIB_CFLAGS'].split(),
253                       native: false, language: ['c', 'cpp', 'objc'])
254 glib = declare_dependency(link_args: config_host['GLIB_LIBS'].split())
255 gio = not_found
256 if 'CONFIG_GIO' in config_host
257   gio = declare_dependency(compile_args: config_host['GIO_CFLAGS'].split(),
258                            link_args: config_host['GIO_LIBS'].split())
259 endif
260 lttng = not_found
261 if 'CONFIG_TRACE_UST' in config_host
262   lttng = declare_dependency(link_args: config_host['LTTNG_UST_LIBS'].split())
263 endif
264 urcubp = not_found
265 if 'CONFIG_TRACE_UST' in config_host
266   urcubp = declare_dependency(link_args: config_host['URCU_BP_LIBS'].split())
267 endif
268 gcrypt = not_found
269 if 'CONFIG_GCRYPT' in config_host
270   gcrypt = declare_dependency(compile_args: config_host['GCRYPT_CFLAGS'].split(),
271                               link_args: config_host['GCRYPT_LIBS'].split())
272 endif
273 nettle = not_found
274 if 'CONFIG_NETTLE' in config_host
275   nettle = declare_dependency(compile_args: config_host['NETTLE_CFLAGS'].split(),
276                               link_args: config_host['NETTLE_LIBS'].split())
277 endif
278 gnutls = not_found
279 if 'CONFIG_GNUTLS' in config_host
280   gnutls = declare_dependency(compile_args: config_host['GNUTLS_CFLAGS'].split(),
281                               link_args: config_host['GNUTLS_LIBS'].split())
282 endif
283 pixman = not_found
284 if have_system or have_tools
285   pixman = dependency('pixman-1', required: have_system, version:'>=0.21.8',
286                       method: 'pkg-config', static: enable_static)
287 endif
288 pam = not_found
289 if 'CONFIG_AUTH_PAM' in config_host
290   pam = cc.find_library('pam')
291 endif
292 libaio = cc.find_library('aio', required: false)
293 zlib = dependency('zlib', required: true, static: enable_static)
294 linux_io_uring = not_found
295 if 'CONFIG_LINUX_IO_URING' in config_host
296   linux_io_uring = declare_dependency(compile_args: config_host['LINUX_IO_URING_CFLAGS'].split(),
297                                       link_args: config_host['LINUX_IO_URING_LIBS'].split())
298 endif
299 libxml2 = not_found
300 if 'CONFIG_LIBXML2' in config_host
301   libxml2 = declare_dependency(compile_args: config_host['LIBXML2_CFLAGS'].split(),
302                                link_args: config_host['LIBXML2_LIBS'].split())
303 endif
304 libnfs = not_found
305 if 'CONFIG_LIBNFS' in config_host
306   libnfs = declare_dependency(link_args: config_host['LIBNFS_LIBS'].split())
307 endif
308 libattr = not_found
309 if 'CONFIG_ATTR' in config_host
310   libattr = declare_dependency(link_args: config_host['LIBATTR_LIBS'].split())
311 endif
312 seccomp = not_found
313 if 'CONFIG_SECCOMP' in config_host
314   seccomp = declare_dependency(compile_args: config_host['SECCOMP_CFLAGS'].split(),
315                                link_args: config_host['SECCOMP_LIBS'].split())
316 endif
317 libcap_ng = not_found
318 if 'CONFIG_LIBCAP_NG' in config_host
319   libcap_ng = declare_dependency(link_args: config_host['LIBCAP_NG_LIBS'].split())
320 endif
321 if get_option('xkbcommon').auto() and not have_system and not have_tools
322   xkbcommon = not_found
323 else
324   xkbcommon = dependency('xkbcommon', required: get_option('xkbcommon'),
325                          method: 'pkg-config', static: enable_static)
326 endif
327 vde = not_found
328 if config_host.has_key('CONFIG_VDE')
329   vde = declare_dependency(link_args: config_host['VDE_LIBS'].split())
330 endif
331 pulse = not_found
332 if 'CONFIG_LIBPULSE' in config_host
333   pulse = declare_dependency(compile_args: config_host['PULSE_CFLAGS'].split(),
334                              link_args: config_host['PULSE_LIBS'].split())
335 endif
336 alsa = not_found
337 if 'CONFIG_ALSA' in config_host
338   alsa = declare_dependency(compile_args: config_host['ALSA_CFLAGS'].split(),
339                             link_args: config_host['ALSA_LIBS'].split())
340 endif
341 jack = not_found
342 if 'CONFIG_LIBJACK' in config_host
343   jack = declare_dependency(link_args: config_host['JACK_LIBS'].split())
344 endif
345 spice = not_found
346 if 'CONFIG_SPICE' in config_host
347   spice = declare_dependency(compile_args: config_host['SPICE_CFLAGS'].split(),
348                              link_args: config_host['SPICE_LIBS'].split())
349 endif
350 rt = cc.find_library('rt', required: false)
351 libdl = not_found
352 if 'CONFIG_PLUGIN' in config_host
353   libdl = cc.find_library('dl', required: true)
354 endif
355 libiscsi = not_found
356 if 'CONFIG_LIBISCSI' in config_host
357   libiscsi = declare_dependency(compile_args: config_host['LIBISCSI_CFLAGS'].split(),
358                                 link_args: config_host['LIBISCSI_LIBS'].split())
359 endif
360 zstd = not_found
361 if 'CONFIG_ZSTD' in config_host
362   zstd = declare_dependency(compile_args: config_host['ZSTD_CFLAGS'].split(),
363                             link_args: config_host['ZSTD_LIBS'].split())
364 endif
365 gbm = not_found
366 if 'CONFIG_GBM' in config_host
367   gbm = declare_dependency(compile_args: config_host['GBM_CFLAGS'].split(),
368                            link_args: config_host['GBM_LIBS'].split())
369 endif
370 virgl = not_found
371 if 'CONFIG_VIRGL' in config_host
372   virgl = declare_dependency(compile_args: config_host['VIRGL_CFLAGS'].split(),
373                              link_args: config_host['VIRGL_LIBS'].split())
374 endif
375 curl = not_found
376 if 'CONFIG_CURL' in config_host
377   curl = declare_dependency(compile_args: config_host['CURL_CFLAGS'].split(),
378                             link_args: config_host['CURL_LIBS'].split())
379 endif
380 libudev = not_found
381 if targetos == 'linux' and (have_system or have_tools)
382   libudev = dependency('libudev',
383                        required: get_option('mpath').enabled(),
384                        static: enable_static)
385 endif
386
387 mpathpersist = not_found
388 mpathpersist_new_api = false
389 if targetos == 'linux' and have_tools and not get_option('mpath').disabled()
390   mpath_test_source_new = '''
391     #include <libudev.h>
392     #include <mpath_persist.h>
393     unsigned mpath_mx_alloc_len = 1024;
394     int logsink;
395     static struct config *multipath_conf;
396     extern struct udev *udev;
397     extern struct config *get_multipath_config(void);
398     extern void put_multipath_config(struct config *conf);
399     struct udev *udev;
400     struct config *get_multipath_config(void) { return multipath_conf; }
401     void put_multipath_config(struct config *conf) { }
402     int main(void) {
403         udev = udev_new();
404         multipath_conf = mpath_lib_init();
405         return 0;
406     }'''
407   mpath_test_source_old = '''
408       #include <libudev.h>
409       #include <mpath_persist.h>
410       unsigned mpath_mx_alloc_len = 1024;
411       int logsink;
412       int main(void) {
413           struct udev *udev = udev_new();
414           mpath_lib_init(udev);
415           return 0;
416       }'''
417   mpathlibs = [libudev]
418   if enable_static
419     mpathlibs += cc.find_library('devmapper',
420                                    required: get_option('mpath'),
421                                    static: enable_static)
422   endif
423   mpathlibs += cc.find_library('multipath',
424                                required: get_option('mpath'),
425                                static: enable_static)
426   mpathlibs += cc.find_library('mpathpersist',
427                                required: get_option('mpath'),
428                                static: enable_static)
429   foreach lib: mpathlibs
430     if not lib.found()
431       mpathlibs = []
432       break
433     endif
434   endforeach
435   if mpathlibs.length() > 0
436     if cc.links(mpath_test_source_new, dependencies: mpathlibs)
437       mpathpersist = declare_dependency(dependencies: mpathlibs)
438       mpathpersist_new_api = true
439     elif cc.links(mpath_test_source_old, dependencies: mpathlibs)
440       mpathpersist = declare_dependency(dependencies: mpathlibs)
441     else
442       if get_option('mpath').enabled()
443         error('Cannot detect libmpathpersist API')
444       else
445         warning('Cannot detect libmpathpersist API, disabling')
446       endif
447     endif
448   endif
449 endif
450
451 iconv = not_found
452 if not get_option('iconv').disabled()
453   libiconv = cc.find_library('iconv',
454                              required: false,
455                              static: enable_static)
456   if libiconv.found()
457     if cc.links('''
458       #include <iconv.h>
459       int main(void) {
460         iconv_t conv = iconv_open("WCHAR_T", "UCS-2");
461         return conv != (iconv_t) -1;
462       }''', dependencies: [libiconv])
463       iconv = declare_dependency(dependencies: [libiconv])
464     endif
465   endif
466 endif
467 if get_option('iconv').enabled() and not iconv.found()
468   error('Cannot detect iconv API')
469 endif
470
471 curses = not_found
472 if iconv.found() and not get_option('curses').disabled()
473   curses_libname_list = ['ncursesw', 'ncurses', 'cursesw', 'pdcurses']
474   curses_test = '''
475     #include <locale.h>
476     #include <curses.h>
477     #include <wchar.h>
478     int main(void) {
479       wchar_t wch = L'w';
480       setlocale(LC_ALL, "");
481       resize_term(0, 0);
482       addwstr(L"wide chars\n");
483       addnwstr(&wch, 1);
484       add_wch(WACS_DEGREE);
485       return 0;
486     }'''
487   foreach curses_libname : curses_libname_list
488       libcurses = dependency(curses_libname,
489                              required: false,
490                              method: 'pkg-config',
491                              static: enable_static)
492
493       if not libcurses.found()
494         dirs = ['/usr/include/ncursesw']
495         if targetos == 'windows'
496           dirs = []
497         endif
498         libcurses = cc.find_library(curses_libname,
499                                     required: false,
500                                     dirs: dirs,
501                                     static: enable_static)
502       endif
503       if libcurses.found()
504         if cc.links(curses_test, dependencies: [libcurses])
505           curses = declare_dependency(compile_args: '-DNCURSES_WIDECHAR', dependencies: [libcurses])
506           break
507         endif
508       endif
509   endforeach
510 endif
511 if get_option('curses').enabled() and not curses.found()
512   if not iconv.found()
513     error('Cannot detect iconv API')
514   else
515     error('Cannot detect curses API')
516   endif
517 endif
518
519 brlapi = not_found
520 if 'CONFIG_BRLAPI' in config_host
521   brlapi = declare_dependency(link_args: config_host['BRLAPI_LIBS'].split())
522 endif
523
524 sdl = not_found
525 if have_system
526   sdl = dependency('sdl2', required: get_option('sdl'), static: enable_static)
527   sdl_image = not_found
528 endif
529 if sdl.found()
530   # work around 2.0.8 bug
531   sdl = declare_dependency(compile_args: '-Wno-undef',
532                            dependencies: sdl)
533   sdl_image = dependency('SDL2_image', required: get_option('sdl_image'),
534                          method: 'pkg-config', static: enable_static)
535 else
536   if get_option('sdl_image').enabled()
537     error('sdl-image required, but SDL was @0@'.format(
538           get_option('sdl').disabled() ? 'disabled' : 'not found'))
539   endif
540   sdl_image = not_found
541 endif
542
543 rbd = not_found
544 if 'CONFIG_RBD' in config_host
545   rbd = declare_dependency(link_args: config_host['RBD_LIBS'].split())
546 endif
547 glusterfs = not_found
548 if 'CONFIG_GLUSTERFS' in config_host
549   glusterfs = declare_dependency(compile_args: config_host['GLUSTERFS_CFLAGS'].split(),
550                                  link_args: config_host['GLUSTERFS_LIBS'].split())
551 endif
552 libssh = not_found
553 if 'CONFIG_LIBSSH' in config_host
554   libssh = declare_dependency(compile_args: config_host['LIBSSH_CFLAGS'].split(),
555                               link_args: config_host['LIBSSH_LIBS'].split())
556 endif
557 libbzip2 = not_found
558 if 'CONFIG_BZIP2' in config_host
559   libbzip2 = declare_dependency(link_args: config_host['BZIP2_LIBS'].split())
560 endif
561 liblzfse = not_found
562 if 'CONFIG_LZFSE' in config_host
563   liblzfse = declare_dependency(link_args: config_host['LZFSE_LIBS'].split())
564 endif
565 oss = not_found
566 if 'CONFIG_AUDIO_OSS' in config_host
567   oss = declare_dependency(link_args: config_host['OSS_LIBS'].split())
568 endif
569 dsound = not_found
570 if 'CONFIG_AUDIO_DSOUND' in config_host
571   dsound = declare_dependency(link_args: config_host['DSOUND_LIBS'].split())
572 endif
573 coreaudio = not_found
574 if 'CONFIG_AUDIO_COREAUDIO' in config_host
575   coreaudio = declare_dependency(link_args: config_host['COREAUDIO_LIBS'].split())
576 endif
577 opengl = not_found
578 if 'CONFIG_OPENGL' in config_host
579   opengl = declare_dependency(compile_args: config_host['OPENGL_CFLAGS'].split(),
580                               link_args: config_host['OPENGL_LIBS'].split())
581 endif
582 gtk = not_found
583 if 'CONFIG_GTK' in config_host
584   gtk = declare_dependency(compile_args: config_host['GTK_CFLAGS'].split(),
585                               link_args: config_host['GTK_LIBS'].split())
586 endif
587 vte = not_found
588 if 'CONFIG_VTE' in config_host
589   vte = declare_dependency(compile_args: config_host['VTE_CFLAGS'].split(),
590                            link_args: config_host['VTE_LIBS'].split())
591 endif
592 x11 = not_found
593 if 'CONFIG_X11' in config_host
594   x11 = declare_dependency(compile_args: config_host['X11_CFLAGS'].split(),
595                            link_args: config_host['X11_LIBS'].split())
596 endif
597 vnc = not_found
598 png = not_found
599 jpeg = not_found
600 sasl = not_found
601 if get_option('vnc').enabled()
602   vnc = declare_dependency() # dummy dependency
603   png = dependency('libpng', required: get_option('vnc_png'),
604                    method: 'pkg-config', static: enable_static)
605   jpeg = cc.find_library('jpeg', has_headers: ['jpeglib.h'],
606                          required: get_option('vnc_jpeg'),
607                          static: enable_static)
608   sasl = cc.find_library('sasl2', has_headers: ['sasl/sasl.h'],
609                          required: get_option('vnc_sasl'),
610                          static: enable_static)
611   if sasl.found()
612     sasl = declare_dependency(dependencies: sasl,
613                               compile_args: '-DSTRUCT_IOVEC_DEFINED')
614   endif
615 endif
616 snappy = not_found
617 if 'CONFIG_SNAPPY' in config_host
618   snappy = declare_dependency(link_args: config_host['SNAPPY_LIBS'].split())
619 endif
620 lzo = not_found
621 if 'CONFIG_LZO' in config_host
622   lzo = declare_dependency(link_args: config_host['LZO_LIBS'].split())
623 endif
624 rdma = not_found
625 if 'CONFIG_RDMA' in config_host
626   rdma = declare_dependency(link_args: config_host['RDMA_LIBS'].split())
627 endif
628 numa = not_found
629 if 'CONFIG_NUMA' in config_host
630   numa = declare_dependency(link_args: config_host['NUMA_LIBS'].split())
631 endif
632 xen = not_found
633 if 'CONFIG_XEN_BACKEND' in config_host
634   xen = declare_dependency(compile_args: config_host['XEN_CFLAGS'].split(),
635                            link_args: config_host['XEN_LIBS'].split())
636 endif
637 cacard = not_found
638 if 'CONFIG_SMARTCARD' in config_host
639   cacard = declare_dependency(compile_args: config_host['SMARTCARD_CFLAGS'].split(),
640                               link_args: config_host['SMARTCARD_LIBS'].split())
641 endif
642 u2f = not_found
643 if have_system
644   u2f = dependency('u2f-emu', required: get_option('u2f'),
645                    method: 'pkg-config',
646                    static: enable_static)
647 endif
648 usbredir = not_found
649 if 'CONFIG_USB_REDIR' in config_host
650   usbredir = declare_dependency(compile_args: config_host['USB_REDIR_CFLAGS'].split(),
651                                 link_args: config_host['USB_REDIR_LIBS'].split())
652 endif
653 libusb = not_found
654 if 'CONFIG_USB_LIBUSB' in config_host
655   libusb = declare_dependency(compile_args: config_host['LIBUSB_CFLAGS'].split(),
656                               link_args: config_host['LIBUSB_LIBS'].split())
657 endif
658 libpmem = not_found
659 if 'CONFIG_LIBPMEM' in config_host
660   libpmem = declare_dependency(compile_args: config_host['LIBPMEM_CFLAGS'].split(),
661                                link_args: config_host['LIBPMEM_LIBS'].split())
662 endif
663 libdaxctl = not_found
664 if 'CONFIG_LIBDAXCTL' in config_host
665   libdaxctl = declare_dependency(link_args: config_host['LIBDAXCTL_LIBS'].split())
666 endif
667 tasn1 = not_found
668 if 'CONFIG_TASN1' in config_host
669   tasn1 = declare_dependency(compile_args: config_host['TASN1_CFLAGS'].split(),
670                              link_args: config_host['TASN1_LIBS'].split())
671 endif
672 keyutils = dependency('libkeyutils', required: false,
673                       method: 'pkg-config', static: enable_static)
674
675 has_gettid = cc.has_function('gettid')
676
677 # Malloc tests
678
679 malloc = []
680 if get_option('malloc') == 'system'
681   has_malloc_trim = \
682     not get_option('malloc_trim').disabled() and \
683     cc.links('''#include <malloc.h>
684                 int main(void) { malloc_trim(0); return 0; }''')
685 else
686   has_malloc_trim = false
687   malloc = cc.find_library(get_option('malloc'), required: true)
688 endif
689 if not has_malloc_trim and get_option('malloc_trim').enabled()
690   if get_option('malloc') == 'system'
691     error('malloc_trim not available on this platform.')
692   else
693     error('malloc_trim not available with non-libc memory allocator')
694   endif
695 endif
696
697 #################
698 # config-host.h #
699 #################
700
701 config_host_data.set('CONFIG_COCOA', cocoa.found())
702 config_host_data.set('CONFIG_LIBUDEV', libudev.found())
703 config_host_data.set('CONFIG_MPATH', mpathpersist.found())
704 config_host_data.set('CONFIG_MPATH_NEW_API', mpathpersist_new_api)
705 config_host_data.set('CONFIG_CURSES', curses.found())
706 config_host_data.set('CONFIG_SDL', sdl.found())
707 config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found())
708 config_host_data.set('CONFIG_VNC', vnc.found())
709 config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
710 config_host_data.set('CONFIG_VNC_PNG', png.found())
711 config_host_data.set('CONFIG_VNC_SASL', sasl.found())
712 config_host_data.set('CONFIG_XKBCOMMON', xkbcommon.found())
713 config_host_data.set('CONFIG_KEYUTILS', keyutils.found())
714 config_host_data.set('CONFIG_GETTID', has_gettid)
715 config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim)
716 config_host_data.set('QEMU_VERSION', '"@0@"'.format(meson.project_version()))
717 config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0])
718 config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1])
719 config_host_data.set('QEMU_VERSION_MICRO', meson.project_version().split('.')[2])
720
721 ignored = ['CONFIG_QEMU_INTERP_PREFIX'] # actually per-target
722 arrays = ['CONFIG_AUDIO_DRIVERS', 'CONFIG_BDRV_RW_WHITELIST', 'CONFIG_BDRV_RO_WHITELIST']
723 strings = ['HOST_DSOSUF', 'CONFIG_IASL', 'bindir', 'prefix', 'qemu_confdir', 'qemu_datadir',
724            'qemu_moddir', 'qemu_localstatedir', 'qemu_helperdir', 'qemu_localedir',
725            'qemu_icondir', 'qemu_desktopdir', 'qemu_firmwarepath', 'sysconfdir']
726 foreach k, v: config_host
727   if ignored.contains(k)
728     # do nothing
729   elif arrays.contains(k)
730     if v != ''
731       v = '"' + '", "'.join(v.split()) + '", '
732     endif
733     config_host_data.set(k, v)
734   elif k == 'ARCH'
735     config_host_data.set('HOST_' + v.to_upper(), 1)
736   elif strings.contains(k)
737     if not k.startswith('CONFIG_')
738       k = 'CONFIG_' + k.to_upper()
739     endif
740     config_host_data.set_quoted(k, v)
741   elif k.startswith('CONFIG_') or k.startswith('HAVE_') or k.startswith('HOST_')
742     config_host_data.set(k, v == 'y' ? 1 : v)
743   endif
744 endforeach
745
746 ########################
747 # Target configuration #
748 ########################
749
750 minikconf = find_program('scripts/minikconf.py')
751 config_all = {}
752 config_all_devices = {}
753 config_all_disas = {}
754 config_devices_mak_list = []
755 config_devices_h = {}
756 config_target_h = {}
757 config_target_mak = {}
758
759 disassemblers = {
760   'alpha' : ['CONFIG_ALPHA_DIS'],
761   'arm' : ['CONFIG_ARM_DIS'],
762   'avr' : ['CONFIG_AVR_DIS'],
763   'cris' : ['CONFIG_CRIS_DIS'],
764   'hppa' : ['CONFIG_HPPA_DIS'],
765   'i386' : ['CONFIG_I386_DIS'],
766   'x86_64' : ['CONFIG_I386_DIS'],
767   'x32' : ['CONFIG_I386_DIS'],
768   'lm32' : ['CONFIG_LM32_DIS'],
769   'm68k' : ['CONFIG_M68K_DIS'],
770   'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
771   'mips' : ['CONFIG_MIPS_DIS'],
772   'moxie' : ['CONFIG_MOXIE_DIS'],
773   'nios2' : ['CONFIG_NIOS2_DIS'],
774   'or1k' : ['CONFIG_OPENRISC_DIS'],
775   'ppc' : ['CONFIG_PPC_DIS'],
776   'riscv' : ['CONFIG_RISCV_DIS'],
777   'rx' : ['CONFIG_RX_DIS'],
778   's390' : ['CONFIG_S390_DIS'],
779   'sh4' : ['CONFIG_SH4_DIS'],
780   'sparc' : ['CONFIG_SPARC_DIS'],
781   'xtensa' : ['CONFIG_XTENSA_DIS'],
782 }
783 if link_language == 'cpp'
784   disassemblers += {
785     'aarch64' : [ 'CONFIG_ARM_A64_DIS'],
786     'arm' : [ 'CONFIG_ARM_DIS', 'CONFIG_ARM_A64_DIS'],
787     'mips' : [ 'CONFIG_MIPS_DIS', 'CONFIG_NANOMIPS_DIS'],
788   }
789 endif
790
791 kconfig_external_symbols = [
792   'CONFIG_KVM',
793   'CONFIG_XEN',
794   'CONFIG_TPM',
795   'CONFIG_SPICE',
796   'CONFIG_IVSHMEM',
797   'CONFIG_OPENGL',
798   'CONFIG_X11',
799   'CONFIG_VHOST_USER',
800   'CONFIG_VHOST_VDPA',
801   'CONFIG_VHOST_KERNEL',
802   'CONFIG_VIRTFS',
803   'CONFIG_LINUX',
804   'CONFIG_PVRDMA',
805 ]
806 ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ]
807
808 default_targets = 'CONFIG_DEFAULT_TARGETS' in config_host
809 actual_target_dirs = []
810 fdt_required = []
811 foreach target : target_dirs
812   config_target = { 'TARGET_NAME': target.split('-')[0] }
813   if target.endswith('linux-user')
814     if targetos != 'linux'
815       if default_targets
816         continue
817       endif
818       error('Target @0@ is only available on a Linux host'.format(target))
819     endif
820     config_target += { 'CONFIG_LINUX_USER': 'y' }
821   elif target.endswith('bsd-user')
822     if 'CONFIG_BSD' not in config_host
823       if default_targets
824         continue
825       endif
826       error('Target @0@ is only available on a BSD host'.format(target))
827     endif
828     config_target += { 'CONFIG_BSD_USER': 'y' }
829   elif target.endswith('softmmu')
830     config_target += { 'CONFIG_SOFTMMU': 'y' }
831   endif
832   if target.endswith('-user')
833     config_target += {
834       'CONFIG_USER_ONLY': 'y',
835       'CONFIG_QEMU_INTERP_PREFIX':
836         config_host['CONFIG_QEMU_INTERP_PREFIX'].format(config_target['TARGET_NAME'])
837     }
838   endif
839
840   have_accel = false
841   foreach sym: accelerators
842     if sym == 'CONFIG_TCG' or target in accelerator_targets.get(sym, [])
843       config_target += { sym: 'y' }
844       config_all += { sym: 'y' }
845       if sym == 'CONFIG_XEN' and have_xen_pci_passthrough
846         config_target += { 'CONFIG_XEN_PCI_PASSTHROUGH': 'y' }
847       endif
848       have_accel = true
849     endif
850   endforeach
851   if not have_accel
852     if default_targets
853       continue
854     endif
855     error('No accelerator available for target @0@'.format(target))
856   endif
857
858   actual_target_dirs += target
859   config_target += keyval.load('default-configs/targets' / target + '.mak')
860   config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
861
862   if 'TARGET_NEED_FDT' in config_target
863     fdt_required += target
864   endif
865
866   # Add default keys
867   if 'TARGET_BASE_ARCH' not in config_target
868     config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
869   endif
870   if 'TARGET_ABI_DIR' not in config_target
871     config_target += {'TARGET_ABI_DIR': config_target['TARGET_ARCH']}
872   endif
873
874   foreach k, v: disassemblers
875     if config_host['ARCH'].startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k)
876       foreach sym: v
877         config_target += { sym: 'y' }
878         config_all_disas += { sym: 'y' }
879       endforeach
880     endif
881   endforeach
882
883   config_target_data = configuration_data()
884   foreach k, v: config_target
885     if not k.startswith('TARGET_') and not k.startswith('CONFIG_')
886       # do nothing
887     elif ignored.contains(k)
888       # do nothing
889     elif k == 'TARGET_BASE_ARCH'
890       # Note that TARGET_BASE_ARCH ends up in config-target.h but it is
891       # not used to select files from sourcesets.
892       config_target_data.set('TARGET_' + v.to_upper(), 1)
893     elif k == 'TARGET_NAME' or k == 'CONFIG_QEMU_INTERP_PREFIX'
894       config_target_data.set_quoted(k, v)
895     elif v == 'y'
896       config_target_data.set(k, 1)
897     else
898       config_target_data.set(k, v)
899     endif
900   endforeach
901   config_target_h += {target: configure_file(output: target + '-config-target.h',
902                                                configuration: config_target_data)}
903
904   if target.endswith('-softmmu')
905     base_kconfig = []
906     foreach sym : kconfig_external_symbols
907       if sym in config_target or sym in config_host
908         base_kconfig += '@0@=y'.format(sym)
909       endif
910     endforeach
911
912     config_devices_mak = target + '-config-devices.mak'
913     config_devices_mak = configure_file(
914       input: ['default-configs/devices' / target + '.mak', 'Kconfig'],
915       output: config_devices_mak,
916       depfile: config_devices_mak + '.d',
917       capture: true,
918       command: [minikconf, config_host['CONFIG_MINIKCONF_MODE'],
919                 config_devices_mak, '@DEPFILE@', '@INPUT@',
920                 base_kconfig])
921
922     config_devices_data = configuration_data()
923     config_devices = keyval.load(config_devices_mak)
924     foreach k, v: config_devices
925       config_devices_data.set(k, 1)
926     endforeach
927     config_devices_mak_list += config_devices_mak
928     config_devices_h += {target: configure_file(output: target + '-config-devices.h',
929                                                 configuration: config_devices_data)}
930     config_target += config_devices
931     config_all_devices += config_devices
932   endif
933   config_target_mak += {target: config_target}
934 endforeach
935 target_dirs = actual_target_dirs
936
937 # This configuration is used to build files that are shared by
938 # multiple binaries, and then extracted out of the "common"
939 # static_library target.
940 #
941 # We do not use all_sources()/all_dependencies(), because it would
942 # build literally all source files, including devices only used by
943 # targets that are not built for this compilation.  The CONFIG_ALL
944 # pseudo symbol replaces it.
945
946 config_all += config_all_devices
947 config_all += config_host
948 config_all += config_all_disas
949 config_all += {
950   'CONFIG_XEN': config_host.has_key('CONFIG_XEN_BACKEND'),
951   'CONFIG_SOFTMMU': have_system,
952   'CONFIG_USER_ONLY': have_user,
953   'CONFIG_ALL': true,
954 }
955
956 ##############
957 # Submodules #
958 ##############
959
960 capstone = not_found
961 capstone_opt = get_option('capstone')
962 if capstone_opt in ['enabled', 'auto', 'system']
963   have_internal = fs.exists(meson.current_source_dir() / 'capstone/Makefile')
964   capstone = dependency('capstone', version: '>=4.0',
965                         static: enable_static, method: 'pkg-config',
966                         required: capstone_opt == 'system' or
967                                   capstone_opt == 'enabled' and not have_internal)
968   if capstone.found()
969     capstone_opt = 'system'
970   elif have_internal
971     capstone_opt = 'internal'
972   else
973     capstone_opt = 'disabled'
974   endif
975 endif
976 if capstone_opt == 'internal'
977   capstone_data = configuration_data()
978   capstone_data.set('CAPSTONE_USE_SYS_DYN_MEM', '1')
979
980   capstone_files = files(
981     'capstone/cs.c',
982     'capstone/MCInst.c',
983     'capstone/MCInstrDesc.c',
984     'capstone/MCRegisterInfo.c',
985     'capstone/SStream.c',
986     'capstone/utils.c'
987   )
988
989   if 'CONFIG_ARM_DIS' in config_all_disas
990     capstone_data.set('CAPSTONE_HAS_ARM', '1')
991     capstone_files += files(
992       'capstone/arch/ARM/ARMDisassembler.c',
993       'capstone/arch/ARM/ARMInstPrinter.c',
994       'capstone/arch/ARM/ARMMapping.c',
995       'capstone/arch/ARM/ARMModule.c'
996     )
997   endif
998
999   # FIXME: This config entry currently depends on a c++ compiler.
1000   # Which is needed for building libvixl, but not for capstone.
1001   if 'CONFIG_ARM_A64_DIS' in config_all_disas
1002     capstone_data.set('CAPSTONE_HAS_ARM64', '1')
1003     capstone_files += files(
1004       'capstone/arch/AArch64/AArch64BaseInfo.c',
1005       'capstone/arch/AArch64/AArch64Disassembler.c',
1006       'capstone/arch/AArch64/AArch64InstPrinter.c',
1007       'capstone/arch/AArch64/AArch64Mapping.c',
1008       'capstone/arch/AArch64/AArch64Module.c'
1009     )
1010   endif
1011
1012   if 'CONFIG_PPC_DIS' in config_all_disas
1013     capstone_data.set('CAPSTONE_HAS_POWERPC', '1')
1014     capstone_files += files(
1015       'capstone/arch/PowerPC/PPCDisassembler.c',
1016       'capstone/arch/PowerPC/PPCInstPrinter.c',
1017       'capstone/arch/PowerPC/PPCMapping.c',
1018       'capstone/arch/PowerPC/PPCModule.c'
1019     )
1020   endif
1021
1022   if 'CONFIG_S390_DIS' in config_all_disas
1023     capstone_data.set('CAPSTONE_HAS_SYSZ', '1')
1024     capstone_files += files(
1025       'capstone/arch/SystemZ/SystemZDisassembler.c',
1026       'capstone/arch/SystemZ/SystemZInstPrinter.c',
1027       'capstone/arch/SystemZ/SystemZMapping.c',
1028       'capstone/arch/SystemZ/SystemZModule.c',
1029       'capstone/arch/SystemZ/SystemZMCTargetDesc.c'
1030     )
1031   endif
1032
1033   if 'CONFIG_I386_DIS' in config_all_disas
1034     capstone_data.set('CAPSTONE_HAS_X86', 1)
1035     capstone_files += files(
1036       'capstone/arch/X86/X86Disassembler.c',
1037       'capstone/arch/X86/X86DisassemblerDecoder.c',
1038       'capstone/arch/X86/X86ATTInstPrinter.c',
1039       'capstone/arch/X86/X86IntelInstPrinter.c',
1040       'capstone/arch/X86/X86InstPrinterCommon.c',
1041       'capstone/arch/X86/X86Mapping.c',
1042       'capstone/arch/X86/X86Module.c'
1043     )
1044   endif
1045
1046   configure_file(output: 'capstone-defs.h', configuration: capstone_data)
1047
1048   capstone_cargs = [
1049     # FIXME: There does not seem to be a way to completely replace the c_args
1050     # that come from add_project_arguments() -- we can only add to them.
1051     # So: disable all warnings with a big hammer.
1052     '-Wno-error', '-w',
1053
1054     # Include all configuration defines via a header file, which will wind up
1055     # as a dependency on the object file, and thus changes here will result
1056     # in a rebuild.
1057     '-include', 'capstone-defs.h'
1058   ]
1059
1060   libcapstone = static_library('capstone',
1061                                sources: capstone_files,
1062                                c_args: capstone_cargs,
1063                                include_directories: 'capstone/include')
1064   capstone = declare_dependency(link_with: libcapstone,
1065                                 include_directories: 'capstone/include/capstone')
1066 endif
1067
1068 slirp = not_found
1069 slirp_opt = 'disabled'
1070 if have_system
1071   slirp_opt = get_option('slirp')
1072   if slirp_opt in ['enabled', 'auto', 'system']
1073     have_internal = fs.exists(meson.current_source_dir() / 'slirp/meson.build')
1074     slirp = dependency('slirp', static: enable_static,
1075                        method: 'pkg-config',
1076                        required: slirp_opt == 'system' or
1077                                  slirp_opt == 'enabled' and not have_internal)
1078     if slirp.found()
1079       slirp_opt = 'system'
1080     elif have_internal
1081       slirp_opt = 'internal'
1082     else
1083       slirp_opt = 'disabled'
1084     endif
1085   endif
1086   if slirp_opt == 'internal'
1087     slirp_deps = []
1088     if targetos == 'windows'
1089       slirp_deps = cc.find_library('iphlpapi')
1090     endif
1091     slirp_conf = configuration_data()
1092     slirp_conf.set('SLIRP_MAJOR_VERSION', meson.project_version().split('.')[0])
1093     slirp_conf.set('SLIRP_MINOR_VERSION', meson.project_version().split('.')[1])
1094     slirp_conf.set('SLIRP_MICRO_VERSION', meson.project_version().split('.')[2])
1095     slirp_conf.set_quoted('SLIRP_VERSION_STRING', meson.project_version())
1096     slirp_cargs = ['-DG_LOG_DOMAIN="Slirp"']
1097     slirp_files = [
1098       'slirp/src/arp_table.c',
1099       'slirp/src/bootp.c',
1100       'slirp/src/cksum.c',
1101       'slirp/src/dhcpv6.c',
1102       'slirp/src/dnssearch.c',
1103       'slirp/src/if.c',
1104       'slirp/src/ip6_icmp.c',
1105       'slirp/src/ip6_input.c',
1106       'slirp/src/ip6_output.c',
1107       'slirp/src/ip_icmp.c',
1108       'slirp/src/ip_input.c',
1109       'slirp/src/ip_output.c',
1110       'slirp/src/mbuf.c',
1111       'slirp/src/misc.c',
1112       'slirp/src/ncsi.c',
1113       'slirp/src/ndp_table.c',
1114       'slirp/src/sbuf.c',
1115       'slirp/src/slirp.c',
1116       'slirp/src/socket.c',
1117       'slirp/src/state.c',
1118       'slirp/src/stream.c',
1119       'slirp/src/tcp_input.c',
1120       'slirp/src/tcp_output.c',
1121       'slirp/src/tcp_subr.c',
1122       'slirp/src/tcp_timer.c',
1123       'slirp/src/tftp.c',
1124       'slirp/src/udp.c',
1125       'slirp/src/udp6.c',
1126       'slirp/src/util.c',
1127       'slirp/src/version.c',
1128       'slirp/src/vmstate.c',
1129     ]
1130
1131     configure_file(
1132       input : 'slirp/src/libslirp-version.h.in',
1133       output : 'libslirp-version.h',
1134       configuration: slirp_conf)
1135
1136     slirp_inc = include_directories('slirp', 'slirp/src')
1137     libslirp = static_library('slirp',
1138                               sources: slirp_files,
1139                               c_args: slirp_cargs,
1140                               include_directories: slirp_inc)
1141     slirp = declare_dependency(link_with: libslirp,
1142                                dependencies: slirp_deps,
1143                                include_directories: slirp_inc)
1144   endif
1145 endif
1146
1147 fdt = not_found
1148 fdt_opt = get_option('fdt')
1149 if have_system
1150   if fdt_opt in ['enabled', 'auto', 'system']
1151     have_internal = fs.exists(meson.current_source_dir() / 'dtc/libfdt/Makefile.libfdt')
1152     fdt = cc.find_library('fdt', static: enable_static,
1153                           required: fdt_opt == 'system' or
1154                                     fdt_opt == 'enabled' and not have_internal)
1155     if fdt.found() and cc.links('''
1156        #include <libfdt.h>
1157        #include <libfdt_env.h>
1158        int main(void) { fdt_check_full(NULL, 0); return 0; }''',
1159          dependencies: fdt)
1160       fdt_opt = 'system'
1161     elif have_internal
1162       fdt_opt = 'internal'
1163     else
1164       fdt_opt = 'disabled'
1165     endif
1166   endif
1167   if fdt_opt == 'internal'
1168     fdt_files = files(
1169       'dtc/libfdt/fdt.c',
1170       'dtc/libfdt/fdt_ro.c',
1171       'dtc/libfdt/fdt_wip.c',
1172       'dtc/libfdt/fdt_sw.c',
1173       'dtc/libfdt/fdt_rw.c',
1174       'dtc/libfdt/fdt_strerror.c',
1175       'dtc/libfdt/fdt_empty_tree.c',
1176       'dtc/libfdt/fdt_addresses.c',
1177       'dtc/libfdt/fdt_overlay.c',
1178       'dtc/libfdt/fdt_check.c',
1179     )
1180
1181     fdt_inc = include_directories('dtc/libfdt')
1182     libfdt = static_library('fdt',
1183                             sources: fdt_files,
1184                             include_directories: fdt_inc)
1185     fdt = declare_dependency(link_with: libfdt,
1186                              include_directories: fdt_inc)
1187   endif
1188 endif
1189 if not fdt.found() and fdt_required.length() > 0
1190   error('fdt not available but required by targets ' + ', '.join(fdt_required))
1191 endif
1192
1193 config_host_data.set('CONFIG_CAPSTONE', capstone.found())
1194 config_host_data.set('CONFIG_FDT', fdt.found())
1195 config_host_data.set('CONFIG_SLIRP', slirp.found())
1196
1197 #####################
1198 # Generated sources #
1199 #####################
1200
1201 genh += configure_file(output: 'config-host.h', configuration: config_host_data)
1202
1203 hxtool = find_program('scripts/hxtool')
1204 shaderinclude = find_program('scripts/shaderinclude.pl')
1205 qapi_gen = find_program('scripts/qapi-gen.py')
1206 qapi_gen_depends = [ meson.source_root() / 'scripts/qapi/__init__.py',
1207                      meson.source_root() / 'scripts/qapi/commands.py',
1208                      meson.source_root() / 'scripts/qapi/common.py',
1209                      meson.source_root() / 'scripts/qapi/error.py',
1210                      meson.source_root() / 'scripts/qapi/events.py',
1211                      meson.source_root() / 'scripts/qapi/expr.py',
1212                      meson.source_root() / 'scripts/qapi/gen.py',
1213                      meson.source_root() / 'scripts/qapi/introspect.py',
1214                      meson.source_root() / 'scripts/qapi/parser.py',
1215                      meson.source_root() / 'scripts/qapi/schema.py',
1216                      meson.source_root() / 'scripts/qapi/source.py',
1217                      meson.source_root() / 'scripts/qapi/types.py',
1218                      meson.source_root() / 'scripts/qapi/visit.py',
1219                      meson.source_root() / 'scripts/qapi/common.py',
1220                      meson.source_root() / 'scripts/qapi-gen.py'
1221 ]
1222
1223 tracetool = [
1224   python, files('scripts/tracetool.py'),
1225    '--backend=' + config_host['TRACE_BACKENDS']
1226 ]
1227
1228 qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
1229                     meson.current_source_dir(),
1230                     config_host['PKGVERSION'], meson.project_version()]
1231 qemu_version = custom_target('qemu-version.h',
1232                              output: 'qemu-version.h',
1233                              command: qemu_version_cmd,
1234                              capture: true,
1235                              build_by_default: true,
1236                              build_always_stale: true)
1237 genh += qemu_version
1238
1239 hxdep = []
1240 hx_headers = [
1241   ['qemu-options.hx', 'qemu-options.def'],
1242   ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
1243 ]
1244 if have_system
1245   hx_headers += [
1246     ['hmp-commands.hx', 'hmp-commands.h'],
1247     ['hmp-commands-info.hx', 'hmp-commands-info.h'],
1248   ]
1249 endif
1250 foreach d : hx_headers
1251   hxdep += custom_target(d[1],
1252                 input: files(d[0]),
1253                 output: d[1],
1254                 capture: true,
1255                 build_by_default: true, # to be removed when added to a target
1256                 command: [hxtool, '-h', '@INPUT0@'])
1257 endforeach
1258 genh += hxdep
1259
1260 SPHINX_ARGS = [config_host['SPHINX_BUILD'],
1261                '-Dversion=' + meson.project_version(),
1262                '-Drelease=' + config_host['PKGVERSION']]
1263
1264 if get_option('werror')
1265   SPHINX_ARGS += [ '-W' ]
1266 endif
1267
1268 sphinx_extn_depends = [ meson.source_root() / 'docs/sphinx/depfile.py',
1269                         meson.source_root() / 'docs/sphinx/hxtool.py',
1270                         meson.source_root() / 'docs/sphinx/kerneldoc.py',
1271                         meson.source_root() / 'docs/sphinx/kernellog.py',
1272                         meson.source_root() / 'docs/sphinx/qapidoc.py',
1273                         meson.source_root() / 'docs/sphinx/qmp_lexer.py',
1274                         qapi_gen_depends ]
1275
1276 ###################
1277 # Collect sources #
1278 ###################
1279
1280 authz_ss = ss.source_set()
1281 blockdev_ss = ss.source_set()
1282 block_ss = ss.source_set()
1283 bsd_user_ss = ss.source_set()
1284 chardev_ss = ss.source_set()
1285 common_ss = ss.source_set()
1286 crypto_ss = ss.source_set()
1287 io_ss = ss.source_set()
1288 linux_user_ss = ss.source_set()
1289 qmp_ss = ss.source_set()
1290 qom_ss = ss.source_set()
1291 softmmu_ss = ss.source_set()
1292 specific_fuzz_ss = ss.source_set()
1293 specific_ss = ss.source_set()
1294 stub_ss = ss.source_set()
1295 trace_ss = ss.source_set()
1296 user_ss = ss.source_set()
1297 util_ss = ss.source_set()
1298
1299 modules = {}
1300 hw_arch = {}
1301 target_arch = {}
1302 target_softmmu_arch = {}
1303
1304 ###############
1305 # Trace files #
1306 ###############
1307
1308 # TODO: add each directory to the subdirs from its own meson.build, once
1309 # we have those
1310 trace_events_subdirs = [
1311   'accel/kvm',
1312   'accel/tcg',
1313   'crypto',
1314   'monitor',
1315 ]
1316 if have_user
1317   trace_events_subdirs += [ 'linux-user' ]
1318 endif
1319 if have_block
1320   trace_events_subdirs += [
1321     'authz',
1322     'block',
1323     'io',
1324     'nbd',
1325     'scsi',
1326   ]
1327 endif
1328 if have_system
1329   trace_events_subdirs += [
1330     'audio',
1331     'backends',
1332     'backends/tpm',
1333     'chardev',
1334     'hw/9pfs',
1335     'hw/acpi',
1336     'hw/alpha',
1337     'hw/arm',
1338     'hw/audio',
1339     'hw/block',
1340     'hw/block/dataplane',
1341     'hw/char',
1342     'hw/display',
1343     'hw/dma',
1344     'hw/hppa',
1345     'hw/hyperv',
1346     'hw/i2c',
1347     'hw/i386',
1348     'hw/i386/xen',
1349     'hw/ide',
1350     'hw/input',
1351     'hw/intc',
1352     'hw/isa',
1353     'hw/mem',
1354     'hw/mips',
1355     'hw/misc',
1356     'hw/misc/macio',
1357     'hw/net',
1358     'hw/nvram',
1359     'hw/pci',
1360     'hw/pci-host',
1361     'hw/ppc',
1362     'hw/rdma',
1363     'hw/rdma/vmw',
1364     'hw/rtc',
1365     'hw/s390x',
1366     'hw/scsi',
1367     'hw/sd',
1368     'hw/sparc',
1369     'hw/sparc64',
1370     'hw/ssi',
1371     'hw/timer',
1372     'hw/tpm',
1373     'hw/usb',
1374     'hw/vfio',
1375     'hw/virtio',
1376     'hw/watchdog',
1377     'hw/xen',
1378     'hw/gpio',
1379     'migration',
1380     'net',
1381     'softmmu',
1382     'ui',
1383   ]
1384 endif
1385 trace_events_subdirs += [
1386   'hw/core',
1387   'qapi',
1388   'qom',
1389   'target/arm',
1390   'target/hppa',
1391   'target/i386',
1392   'target/mips',
1393   'target/ppc',
1394   'target/riscv',
1395   'target/s390x',
1396   'target/sparc',
1397   'util',
1398 ]
1399
1400 subdir('qapi')
1401 subdir('qobject')
1402 subdir('stubs')
1403 subdir('trace')
1404 subdir('util')
1405 subdir('qom')
1406 subdir('authz')
1407 subdir('crypto')
1408 subdir('ui')
1409
1410
1411 if enable_modules
1412   libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
1413   modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
1414 endif
1415
1416 stub_ss = stub_ss.apply(config_all, strict: false)
1417
1418 util_ss.add_all(trace_ss)
1419 util_ss = util_ss.apply(config_all, strict: false)
1420 libqemuutil = static_library('qemuutil',
1421                              sources: util_ss.sources() + stub_ss.sources() + genh,
1422                              dependencies: [util_ss.dependencies(), m, glib, socket, malloc])
1423 qemuutil = declare_dependency(link_with: libqemuutil,
1424                               sources: genh + version_res)
1425
1426 decodetree = generator(find_program('scripts/decodetree.py'),
1427                        output: 'decode-@BASENAME@.c.inc',
1428                        arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
1429
1430 subdir('audio')
1431 subdir('io')
1432 subdir('chardev')
1433 subdir('fsdev')
1434 subdir('libdecnumber')
1435 subdir('target')
1436 subdir('dump')
1437
1438 block_ss.add(files(
1439   'block.c',
1440   'blockdev-nbd.c',
1441   'blockjob.c',
1442   'job.c',
1443   'qemu-io-cmds.c',
1444 ))
1445 block_ss.add(when: 'CONFIG_REPLICATION', if_true: files('replication.c'))
1446
1447 subdir('nbd')
1448 subdir('scsi')
1449 subdir('block')
1450
1451 blockdev_ss.add(files(
1452   'blockdev.c',
1453   'iothread.c',
1454   'job-qmp.c',
1455 ))
1456
1457 # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
1458 # os-win32.c does not
1459 blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
1460 softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
1461 softmmu_ss.add_all(blockdev_ss)
1462
1463 common_ss.add(files('cpus-common.c'))
1464
1465 subdir('softmmu')
1466
1467 common_ss.add(capstone)
1468 specific_ss.add(files('cpu.c', 'disas.c', 'gdbstub.c'), capstone)
1469 specific_ss.add(files('exec-vary.c'))
1470 specific_ss.add(when: 'CONFIG_TCG', if_true: files(
1471   'fpu/softfloat.c',
1472   'tcg/optimize.c',
1473   'tcg/tcg-common.c',
1474   'tcg/tcg-op-gvec.c',
1475   'tcg/tcg-op-vec.c',
1476   'tcg/tcg-op.c',
1477   'tcg/tcg.c',
1478 ))
1479 specific_ss.add(when: 'CONFIG_TCG_INTERPRETER', if_true: files('disas/tci.c', 'tcg/tci.c'))
1480
1481 subdir('backends')
1482 subdir('disas')
1483 subdir('migration')
1484 subdir('monitor')
1485 subdir('net')
1486 subdir('replay')
1487 subdir('hw')
1488 subdir('accel')
1489 subdir('plugins')
1490 subdir('bsd-user')
1491 subdir('linux-user')
1492
1493 bsd_user_ss.add(files('gdbstub.c'))
1494 specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss)
1495
1496 linux_user_ss.add(files('gdbstub.c', 'thunk.c'))
1497 specific_ss.add_all(when: 'CONFIG_LINUX_USER', if_true: linux_user_ss)
1498
1499 # needed for fuzzing binaries
1500 subdir('tests/qtest/libqos')
1501 subdir('tests/qtest/fuzz')
1502
1503 ########################
1504 # Library dependencies #
1505 ########################
1506
1507 block_mods = []
1508 softmmu_mods = []
1509 foreach d, list : modules
1510   foreach m, module_ss : list
1511     if enable_modules and targetos != 'windows'
1512       module_ss = module_ss.apply(config_all, strict: false)
1513       sl = static_library(d + '-' + m, [genh, module_ss.sources()],
1514                           dependencies: [modulecommon, module_ss.dependencies()], pic: true)
1515       if d == 'block'
1516         block_mods += sl
1517       else
1518         softmmu_mods += sl
1519       endif
1520     else
1521       if d == 'block'
1522         block_ss.add_all(module_ss)
1523       else
1524         softmmu_ss.add_all(module_ss)
1525       endif
1526     endif
1527   endforeach
1528 endforeach
1529
1530 nm = find_program('nm')
1531 undefsym = find_program('scripts/undefsym.py')
1532 block_syms = custom_target('block.syms', output: 'block.syms',
1533                              input: [libqemuutil, block_mods],
1534                              capture: true,
1535                              command: [undefsym, nm, '@INPUT@'])
1536 qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
1537                              input: [libqemuutil, softmmu_mods],
1538                              capture: true,
1539                              command: [undefsym, nm, '@INPUT@'])
1540
1541 qom_ss = qom_ss.apply(config_host, strict: false)
1542 libqom = static_library('qom', qom_ss.sources() + genh,
1543                         dependencies: [qom_ss.dependencies()],
1544                         name_suffix: 'fa')
1545
1546 qom = declare_dependency(link_whole: libqom)
1547
1548 authz_ss = authz_ss.apply(config_host, strict: false)
1549 libauthz = static_library('authz', authz_ss.sources() + genh,
1550                           dependencies: [authz_ss.dependencies()],
1551                           name_suffix: 'fa',
1552                           build_by_default: false)
1553
1554 authz = declare_dependency(link_whole: libauthz,
1555                            dependencies: qom)
1556
1557 crypto_ss = crypto_ss.apply(config_host, strict: false)
1558 libcrypto = static_library('crypto', crypto_ss.sources() + genh,
1559                            dependencies: [crypto_ss.dependencies()],
1560                            name_suffix: 'fa',
1561                            build_by_default: false)
1562
1563 crypto = declare_dependency(link_whole: libcrypto,
1564                             dependencies: [authz, qom])
1565
1566 io_ss = io_ss.apply(config_host, strict: false)
1567 libio = static_library('io', io_ss.sources() + genh,
1568                        dependencies: [io_ss.dependencies()],
1569                        link_with: libqemuutil,
1570                        name_suffix: 'fa',
1571                        build_by_default: false)
1572
1573 io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
1574
1575 libmigration = static_library('migration', sources: migration_files + genh,
1576                               name_suffix: 'fa',
1577                               build_by_default: false)
1578 migration = declare_dependency(link_with: libmigration,
1579                                dependencies: [zlib, qom, io])
1580 softmmu_ss.add(migration)
1581
1582 block_ss = block_ss.apply(config_host, strict: false)
1583 libblock = static_library('block', block_ss.sources() + genh,
1584                           dependencies: block_ss.dependencies(),
1585                           link_depends: block_syms,
1586                           name_suffix: 'fa',
1587                           build_by_default: false)
1588
1589 block = declare_dependency(link_whole: [libblock],
1590                            link_args: '@block.syms',
1591                            dependencies: [crypto, io])
1592
1593 qmp_ss = qmp_ss.apply(config_host, strict: false)
1594 libqmp = static_library('qmp', qmp_ss.sources() + genh,
1595                         dependencies: qmp_ss.dependencies(),
1596                         name_suffix: 'fa',
1597                         build_by_default: false)
1598
1599 qmp = declare_dependency(link_whole: [libqmp])
1600
1601 libchardev = static_library('chardev', chardev_ss.sources() + genh,
1602                             name_suffix: 'fa',
1603                             build_by_default: false)
1604
1605 chardev = declare_dependency(link_whole: libchardev)
1606
1607 libhwcore = static_library('hwcore', sources: hwcore_files + genh,
1608                            name_suffix: 'fa',
1609                            build_by_default: false)
1610 hwcore = declare_dependency(link_whole: libhwcore)
1611 common_ss.add(hwcore)
1612
1613 ###########
1614 # Targets #
1615 ###########
1616
1617 foreach m : block_mods + softmmu_mods
1618   shared_module(m.name(),
1619                 name_prefix: '',
1620                 link_whole: m,
1621                 install: true,
1622                 install_dir: config_host['qemu_moddir'])
1623 endforeach
1624
1625 softmmu_ss.add(authz, block, chardev, crypto, io, qmp)
1626 common_ss.add(qom, qemuutil)
1627
1628 common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
1629 common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
1630
1631 common_all = common_ss.apply(config_all, strict: false)
1632 common_all = static_library('common',
1633                             build_by_default: false,
1634                             sources: common_all.sources() + genh,
1635                             dependencies: common_all.dependencies(),
1636                             name_suffix: 'fa')
1637
1638 feature_to_c = find_program('scripts/feature_to_c.sh')
1639
1640 emulators = {}
1641 foreach target : target_dirs
1642   config_target = config_target_mak[target]
1643   target_name = config_target['TARGET_NAME']
1644   arch = config_target['TARGET_BASE_ARCH']
1645   arch_srcs = [config_target_h[target]]
1646   arch_deps = []
1647   c_args = ['-DNEED_CPU_H',
1648             '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
1649             '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
1650   link_args = emulator_link_args
1651
1652   config_target += config_host
1653   target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
1654   if targetos == 'linux'
1655     target_inc += include_directories('linux-headers', is_system: true)
1656   endif
1657   if target.endswith('-softmmu')
1658     qemu_target_name = 'qemu-system-' + target_name
1659     target_type='system'
1660     t = target_softmmu_arch[arch].apply(config_target, strict: false)
1661     arch_srcs += t.sources()
1662     arch_deps += t.dependencies()
1663
1664     hw_dir = target_name == 'sparc64' ? 'sparc64' : arch
1665     hw = hw_arch[hw_dir].apply(config_target, strict: false)
1666     arch_srcs += hw.sources()
1667     arch_deps += hw.dependencies()
1668
1669     arch_srcs += config_devices_h[target]
1670     link_args += ['@block.syms', '@qemu.syms']
1671   else
1672     abi = config_target['TARGET_ABI_DIR']
1673     target_type='user'
1674     qemu_target_name = 'qemu-' + target_name
1675     if 'CONFIG_LINUX_USER' in config_target
1676       base_dir = 'linux-user'
1677       target_inc += include_directories('linux-user/host/' / config_host['ARCH'])
1678     else
1679       base_dir = 'bsd-user'
1680     endif
1681     target_inc += include_directories(
1682       base_dir,
1683       base_dir / abi,
1684     )
1685     if 'CONFIG_LINUX_USER' in config_target
1686       dir = base_dir / abi
1687       arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
1688       if config_target.has_key('TARGET_SYSTBL_ABI')
1689         arch_srcs += \
1690           syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
1691                                              extra_args : config_target['TARGET_SYSTBL_ABI'])
1692       endif
1693     endif
1694   endif
1695
1696   if 'TARGET_XML_FILES' in config_target
1697     gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
1698                                 output: target + '-gdbstub-xml.c',
1699                                 input: files(config_target['TARGET_XML_FILES'].split()),
1700                                 command: [feature_to_c, '@INPUT@'],
1701                                 capture: true)
1702     arch_srcs += gdbstub_xml
1703   endif
1704
1705   t = target_arch[arch].apply(config_target, strict: false)
1706   arch_srcs += t.sources()
1707   arch_deps += t.dependencies()
1708
1709   target_common = common_ss.apply(config_target, strict: false)
1710   objects = common_all.extract_objects(target_common.sources())
1711   deps = target_common.dependencies()
1712
1713   target_specific = specific_ss.apply(config_target, strict: false)
1714   arch_srcs += target_specific.sources()
1715   arch_deps += target_specific.dependencies()
1716
1717   lib = static_library('qemu-' + target,
1718                  sources: arch_srcs + genh,
1719                  dependencies: arch_deps,
1720                  objects: objects,
1721                  include_directories: target_inc,
1722                  c_args: c_args,
1723                  build_by_default: false,
1724                  name_suffix: 'fa')
1725
1726   if target.endswith('-softmmu')
1727     execs = [{
1728       'name': 'qemu-system-' + target_name,
1729       'gui': false,
1730       'sources': files('softmmu/main.c'),
1731       'dependencies': []
1732     }]
1733     if targetos == 'windows' and (sdl.found() or gtk.found())
1734       execs += [{
1735         'name': 'qemu-system-' + target_name + 'w',
1736         'gui': true,
1737         'sources': files('softmmu/main.c'),
1738         'dependencies': []
1739       }]
1740     endif
1741     if config_host.has_key('CONFIG_FUZZ')
1742       specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
1743       execs += [{
1744         'name': 'qemu-fuzz-' + target_name,
1745         'gui': false,
1746         'sources': specific_fuzz.sources(),
1747         'dependencies': specific_fuzz.dependencies(),
1748       }]
1749     endif
1750   else
1751     execs = [{
1752       'name': 'qemu-' + target_name,
1753       'gui': false,
1754       'sources': [],
1755       'dependencies': []
1756     }]
1757   endif
1758   foreach exe: execs
1759     emulators += {exe['name']:
1760          executable(exe['name'], exe['sources'],
1761                install: true,
1762                c_args: c_args,
1763                dependencies: arch_deps + deps + exe['dependencies'],
1764                objects: lib.extract_all_objects(recursive: true),
1765                link_language: link_language,
1766                link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
1767                link_args: link_args,
1768                gui_app: exe['gui'])
1769     }
1770
1771     if 'CONFIG_TRACE_SYSTEMTAP' in config_host
1772       foreach stp: [
1773         {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
1774         {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
1775         {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
1776         {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
1777       ]
1778         custom_target(exe['name'] + stp['ext'],
1779                       input: trace_events_all,
1780                       output: exe['name'] + stp['ext'],
1781                       capture: true,
1782                       install: stp['install'],
1783                       install_dir: qemu_datadir / '../systemtap/tapset',
1784                       command: [
1785                         tracetool, '--group=all', '--format=' + stp['fmt'],
1786                         '--binary=' + stp['bin'],
1787                         '--target-name=' + target_name,
1788                         '--target-type=' + target_type,
1789                         '--probe-prefix=qemu.' + target_type + '.' + target_name,
1790                         '@INPUT@',
1791                       ])
1792       endforeach
1793     endif
1794   endforeach
1795 endforeach
1796
1797 # Other build targets
1798
1799 if 'CONFIG_PLUGIN' in config_host
1800   install_headers('include/qemu/qemu-plugin.h')
1801 endif
1802
1803 if 'CONFIG_GUEST_AGENT' in config_host
1804   subdir('qga')
1805 endif
1806
1807 # Don't build qemu-keymap if xkbcommon is not explicitly enabled
1808 # when we don't build tools or system
1809 if xkbcommon.found()
1810   # used for the update-keymaps target, so include rules even if !have_tools
1811   qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
1812                            dependencies: [qemuutil, xkbcommon], install: have_tools)
1813 endif
1814
1815 if have_tools
1816   qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
1817              dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
1818   qemu_io = executable('qemu-io', files('qemu-io.c'),
1819              dependencies: [block, qemuutil], install: true)
1820   qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
1821                dependencies: [block, qemuutil], install: true)
1822
1823   subdir('storage-daemon')
1824   subdir('contrib/rdmacm-mux')
1825   subdir('contrib/elf2dmp')
1826
1827   executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
1828              dependencies: qemuutil,
1829              install: true)
1830
1831   if 'CONFIG_VHOST_USER' in config_host
1832     subdir('contrib/libvhost-user')
1833     subdir('contrib/vhost-user-blk')
1834     subdir('contrib/vhost-user-gpu')
1835     subdir('contrib/vhost-user-input')
1836     subdir('contrib/vhost-user-scsi')
1837   endif
1838
1839   if targetos == 'linux'
1840     executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
1841                dependencies: [qemuutil, libcap_ng],
1842                install: true,
1843                install_dir: get_option('libexecdir'))
1844
1845     executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
1846                dependencies: [authz, crypto, io, qom, qemuutil,
1847                               libcap_ng, mpathpersist],
1848                install: true)
1849   endif
1850
1851   if 'CONFIG_IVSHMEM' in config_host
1852     subdir('contrib/ivshmem-client')
1853     subdir('contrib/ivshmem-server')
1854   endif
1855 endif
1856
1857 subdir('scripts')
1858 subdir('tools')
1859 subdir('pc-bios')
1860 subdir('tests')
1861 subdir('docs')
1862 if 'CONFIG_GTK' in config_host
1863   subdir('po')
1864 endif
1865
1866 if host_machine.system() == 'windows'
1867   nsis_cmd = [
1868     find_program('scripts/nsis.py'),
1869     '@OUTPUT@',
1870     get_option('prefix'),
1871     meson.current_source_dir(),
1872     host_machine.cpu_family(),
1873     '--',
1874     '-DDISPLAYVERSION=' + meson.project_version(),
1875   ]
1876   if build_docs
1877     nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
1878   endif
1879   if 'CONFIG_GTK' in config_host
1880     nsis_cmd += '-DCONFIG_GTK=y'
1881   endif
1882
1883   nsis = custom_target('nsis',
1884                        output: 'qemu-setup-' + meson.project_version() + '.exe',
1885                        input: files('qemu.nsi'),
1886                        build_always_stale: true,
1887                        command: nsis_cmd + ['@INPUT@'])
1888   alias_target('installer', nsis)
1889 endif
1890
1891 #########################
1892 # Configuration summary #
1893 #########################
1894
1895 summary_info = {}
1896 summary_info += {'Install prefix':    config_host['prefix']}
1897 summary_info += {'BIOS directory':    config_host['qemu_datadir']}
1898 summary_info += {'firmware path':     config_host['qemu_firmwarepath']}
1899 summary_info += {'binary directory':  config_host['bindir']}
1900 summary_info += {'library directory': config_host['libdir']}
1901 summary_info += {'module directory':  config_host['qemu_moddir']}
1902 summary_info += {'libexec directory': config_host['libexecdir']}
1903 summary_info += {'include directory': config_host['includedir']}
1904 summary_info += {'config directory':  config_host['sysconfdir']}
1905 if targetos != 'windows'
1906   summary_info += {'local state directory': config_host['qemu_localstatedir']}
1907   summary_info += {'Manual directory':      get_option('mandir')}
1908 else
1909   summary_info += {'local state directory': 'queried at runtime'}
1910 endif
1911 summary_info += {'Doc directory':     get_option('docdir')}
1912 summary_info += {'Build directory':   meson.current_build_dir()}
1913 summary_info += {'Source path':       meson.current_source_dir()}
1914 summary_info += {'GIT binary':        config_host['GIT']}
1915 summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
1916 summary_info += {'C compiler':        meson.get_compiler('c').cmd_array()[0]}
1917 summary_info += {'Host C compiler':   meson.get_compiler('c', native: true).cmd_array()[0]}
1918 if link_language == 'cpp'
1919   summary_info += {'C++ compiler':      meson.get_compiler('cpp').cmd_array()[0]}
1920 else
1921   summary_info += {'C++ compiler':      false}
1922 endif
1923 if targetos == 'darwin'
1924   summary_info += {'Objective-C compiler': meson.get_compiler('objc').cmd_array()[0]}
1925 endif
1926 summary_info += {'ARFLAGS':           config_host['ARFLAGS']}
1927 summary_info += {'CFLAGS':            ' '.join(get_option('c_args')
1928                                                + ['-O' + get_option('optimization')]
1929                                                + (get_option('debug') ? ['-g'] : []))}
1930 if link_language == 'cpp'
1931   summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args')
1932                                                + ['-O' + get_option('optimization')]
1933                                                + (get_option('debug') ? ['-g'] : []))}
1934 endif
1935 link_args = get_option(link_language + '_link_args')
1936 if link_args.length() > 0
1937   summary_info += {'LDFLAGS':         ' '.join(link_args)}
1938 endif
1939 summary_info += {'QEMU_CFLAGS':       config_host['QEMU_CFLAGS']}
1940 summary_info += {'QEMU_LDFLAGS':      config_host['QEMU_LDFLAGS']}
1941 summary_info += {'make':              config_host['MAKE']}
1942 summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
1943 summary_info += {'sphinx-build':      config_host['SPHINX_BUILD']}
1944 summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
1945 # TODO: add back version
1946 summary_info += {'slirp support':     slirp_opt == 'disabled' ? false : slirp_opt}
1947 if slirp_opt != 'disabled'
1948   summary_info += {'smbd':            config_host['CONFIG_SMBD_COMMAND']}
1949 endif
1950 summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
1951 if config_host.has_key('CONFIG_MODULES')
1952   summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')}
1953 endif
1954 summary_info += {'host CPU':          cpu}
1955 summary_info += {'host endianness':   build_machine.endian()}
1956 summary_info += {'target list':       ' '.join(target_dirs)}
1957 summary_info += {'gprof enabled':     config_host.has_key('CONFIG_GPROF')}
1958 summary_info += {'sparse enabled':    sparse.found()}
1959 summary_info += {'strip binaries':    get_option('strip')}
1960 summary_info += {'profiler':          config_host.has_key('CONFIG_PROFILER')}
1961 summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
1962 if targetos == 'darwin'
1963   summary_info += {'Cocoa support': config_host.has_key('CONFIG_COCOA')}
1964 endif
1965 # TODO: add back version
1966 summary_info += {'SDL support':       sdl.found()}
1967 summary_info += {'SDL image support': sdl_image.found()}
1968 # TODO: add back version
1969 summary_info += {'GTK support':       config_host.has_key('CONFIG_GTK')}
1970 summary_info += {'GTK GL support':    config_host.has_key('CONFIG_GTK_GL')}
1971 summary_info += {'pixman':            pixman.found()}
1972 # TODO: add back version
1973 summary_info += {'VTE support':       config_host.has_key('CONFIG_VTE')}
1974 summary_info += {'TLS priority':      config_host['CONFIG_TLS_PRIORITY']}
1975 summary_info += {'GNUTLS support':    config_host.has_key('CONFIG_GNUTLS')}
1976 # TODO: add back version
1977 summary_info += {'libgcrypt':         config_host.has_key('CONFIG_GCRYPT')}
1978 if config_host.has_key('CONFIG_GCRYPT')
1979    summary_info += {'  hmac':            config_host.has_key('CONFIG_GCRYPT_HMAC')}
1980    summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
1981 endif
1982 # TODO: add back version
1983 summary_info += {'nettle':            config_host.has_key('CONFIG_NETTLE')}
1984 if config_host.has_key('CONFIG_NETTLE')
1985    summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
1986 endif
1987 summary_info += {'libtasn1':          config_host.has_key('CONFIG_TASN1')}
1988 summary_info += {'PAM':               config_host.has_key('CONFIG_AUTH_PAM')}
1989 summary_info += {'iconv support':     iconv.found()}
1990 summary_info += {'curses support':    curses.found()}
1991 # TODO: add back version
1992 summary_info += {'virgl support':     config_host.has_key('CONFIG_VIRGL')}
1993 summary_info += {'curl support':      config_host.has_key('CONFIG_CURL')}
1994 summary_info += {'mingw32 support':   targetos == 'windows'}
1995 summary_info += {'Audio drivers':     config_host['CONFIG_AUDIO_DRIVERS']}
1996 summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']}
1997 summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']}
1998 summary_info += {'VirtFS support':    config_host.has_key('CONFIG_VIRTFS')}
1999 summary_info += {'Multipath support': mpathpersist.found()}
2000 summary_info += {'VNC support':       vnc.found()}
2001 if vnc.found()
2002   summary_info += {'VNC SASL support':  sasl.found()}
2003   summary_info += {'VNC JPEG support':  jpeg.found()}
2004   summary_info += {'VNC PNG support':   png.found()}
2005 endif
2006 summary_info += {'xen support':       config_host.has_key('CONFIG_XEN_BACKEND')}
2007 if config_host.has_key('CONFIG_XEN_BACKEND')
2008   summary_info += {'xen ctrl version':  config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
2009 endif
2010 summary_info += {'brlapi support':    config_host.has_key('CONFIG_BRLAPI')}
2011 summary_info += {'Documentation':     config_host.has_key('BUILD_DOCS')}
2012 summary_info += {'PIE':               get_option('b_pie')}
2013 summary_info += {'vde support':       config_host.has_key('CONFIG_VDE')}
2014 summary_info += {'netmap support':    config_host.has_key('CONFIG_NETMAP')}
2015 summary_info += {'Linux AIO support': config_host.has_key('CONFIG_LINUX_AIO')}
2016 summary_info += {'Linux io_uring support': config_host.has_key('CONFIG_LINUX_IO_URING')}
2017 summary_info += {'ATTR/XATTR support': config_host.has_key('CONFIG_ATTR')}
2018 summary_info += {'Install blobs':     config_host.has_key('INSTALL_BLOBS')}
2019 summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
2020 summary_info += {'HAX support':       config_all.has_key('CONFIG_HAX')}
2021 summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
2022 summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
2023 summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
2024 if config_all.has_key('CONFIG_TCG')
2025   summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
2026   summary_info += {'TCG interpreter':   config_host.has_key('CONFIG_TCG_INTERPRETER')}
2027 endif
2028 summary_info += {'malloc trim support': has_malloc_trim}
2029 summary_info += {'RDMA support':      config_host.has_key('CONFIG_RDMA')}
2030 summary_info += {'PVRDMA support':    config_host.has_key('CONFIG_PVRDMA')}
2031 summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
2032 summary_info += {'membarrier':        config_host.has_key('CONFIG_MEMBARRIER')}
2033 summary_info += {'preadv support':    config_host.has_key('CONFIG_PREADV')}
2034 summary_info += {'fdatasync':         config_host.has_key('CONFIG_FDATASYNC')}
2035 summary_info += {'madvise':           config_host.has_key('CONFIG_MADVISE')}
2036 summary_info += {'posix_madvise':     config_host.has_key('CONFIG_POSIX_MADVISE')}
2037 summary_info += {'posix_memalign':    config_host.has_key('CONFIG_POSIX_MEMALIGN')}
2038 summary_info += {'libcap-ng support': config_host.has_key('CONFIG_LIBCAP_NG')}
2039 summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')}
2040 summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')}
2041 summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')}
2042 summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')}
2043 summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_KERNEL')}
2044 summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')}
2045 summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')}
2046 summary_info += {'Trace backends':    config_host['TRACE_BACKENDS']}
2047 if config_host['TRACE_BACKENDS'].split().contains('simple')
2048   summary_info += {'Trace output file': config_host['CONFIG_TRACE_FILE'] + '-<pid>'}
2049 endif
2050 # TODO: add back protocol and server version
2051 summary_info += {'spice support':     config_host.has_key('CONFIG_SPICE')}
2052 summary_info += {'rbd support':       config_host.has_key('CONFIG_RBD')}
2053 summary_info += {'xfsctl support':    config_host.has_key('CONFIG_XFS')}
2054 summary_info += {'smartcard support': config_host.has_key('CONFIG_SMARTCARD')}
2055 summary_info += {'U2F support':       u2f.found()}
2056 summary_info += {'libusb':            config_host.has_key('CONFIG_USB_LIBUSB')}
2057 summary_info += {'usb net redir':     config_host.has_key('CONFIG_USB_REDIR')}
2058 summary_info += {'OpenGL support':    config_host.has_key('CONFIG_OPENGL')}
2059 summary_info += {'OpenGL dmabufs':    config_host.has_key('CONFIG_OPENGL_DMABUF')}
2060 summary_info += {'libiscsi support':  config_host.has_key('CONFIG_LIBISCSI')}
2061 summary_info += {'libnfs support':    config_host.has_key('CONFIG_LIBNFS')}
2062 summary_info += {'build guest agent': config_host.has_key('CONFIG_GUEST_AGENT')}
2063 if targetos == 'windows'
2064   if 'WIN_SDK' in config_host
2065     summary_info += {'Windows SDK':       config_host['WIN_SDK']}
2066   endif
2067   summary_info += {'QGA VSS support':   config_host.has_key('CONFIG_QGA_VSS')}
2068   summary_info += {'QGA w32 disk info': config_host.has_key('CONFIG_QGA_NTDDSCSI')}
2069   summary_info += {'QGA MSI support':   config_host.has_key('CONFIG_QGA_MSI')}
2070 endif
2071 summary_info += {'seccomp support':   config_host.has_key('CONFIG_SECCOMP')}
2072 summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
2073 summary_info += {'coroutine pool':    config_host['CONFIG_COROUTINE_POOL'] == '1'}
2074 summary_info += {'debug stack usage': config_host.has_key('CONFIG_DEBUG_STACK_USAGE')}
2075 summary_info += {'mutex debugging':   config_host.has_key('CONFIG_DEBUG_MUTEX')}
2076 summary_info += {'crypto afalg':      config_host.has_key('CONFIG_AF_ALG')}
2077 summary_info += {'GlusterFS support': config_host.has_key('CONFIG_GLUSTERFS')}
2078 summary_info += {'gcov':              get_option('b_coverage')}
2079 summary_info += {'TPM support':       config_host.has_key('CONFIG_TPM')}
2080 summary_info += {'libssh support':    config_host.has_key('CONFIG_LIBSSH')}
2081 summary_info += {'QOM debugging':     config_host.has_key('CONFIG_QOM_CAST_DEBUG')}
2082 summary_info += {'Live block migration': config_host.has_key('CONFIG_LIVE_BLOCK_MIGRATION')}
2083 summary_info += {'lzo support':       config_host.has_key('CONFIG_LZO')}
2084 summary_info += {'snappy support':    config_host.has_key('CONFIG_SNAPPY')}
2085 summary_info += {'bzip2 support':     config_host.has_key('CONFIG_BZIP2')}
2086 summary_info += {'lzfse support':     config_host.has_key('CONFIG_LZFSE')}
2087 summary_info += {'zstd support':      config_host.has_key('CONFIG_ZSTD')}
2088 summary_info += {'NUMA host support': config_host.has_key('CONFIG_NUMA')}
2089 summary_info += {'libxml2':           config_host.has_key('CONFIG_LIBXML2')}
2090 summary_info += {'memory allocator':  get_option('malloc')}
2091 summary_info += {'avx2 optimization': config_host.has_key('CONFIG_AVX2_OPT')}
2092 summary_info += {'avx512f optimization': config_host.has_key('CONFIG_AVX512F_OPT')}
2093 summary_info += {'replication support': config_host.has_key('CONFIG_REPLICATION')}
2094 summary_info += {'bochs support':     config_host.has_key('CONFIG_BOCHS')}
2095 summary_info += {'cloop support':     config_host.has_key('CONFIG_CLOOP')}
2096 summary_info += {'dmg support':       config_host.has_key('CONFIG_DMG')}
2097 summary_info += {'qcow v1 support':   config_host.has_key('CONFIG_QCOW1')}
2098 summary_info += {'vdi support':       config_host.has_key('CONFIG_VDI')}
2099 summary_info += {'vvfat support':     config_host.has_key('CONFIG_VVFAT')}
2100 summary_info += {'qed support':       config_host.has_key('CONFIG_QED')}
2101 summary_info += {'parallels support': config_host.has_key('CONFIG_PARALLELS')}
2102 summary_info += {'sheepdog support':  config_host.has_key('CONFIG_SHEEPDOG')}
2103 summary_info += {'capstone':          capstone_opt == 'disabled' ? false : capstone_opt}
2104 summary_info += {'libpmem support':   config_host.has_key('CONFIG_LIBPMEM')}
2105 summary_info += {'libdaxctl support': config_host.has_key('CONFIG_LIBDAXCTL')}
2106 summary_info += {'libudev':           libudev.found()}
2107 summary_info += {'default devices':   config_host['CONFIG_MINIKCONF_MODE'] == '--defconfig'}
2108 summary_info += {'plugin support':    config_host.has_key('CONFIG_PLUGIN')}
2109 summary_info += {'fuzzing support':   config_host.has_key('CONFIG_FUZZ')}
2110 if config_host.has_key('HAVE_GDB_BIN')
2111   summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
2112 endif
2113 summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
2114 summary_info += {'rng-none':          config_host.has_key('CONFIG_RNG_NONE')}
2115 summary_info += {'Linux keyring':     config_host.has_key('CONFIG_SECRET_KEYRING')}
2116 summary(summary_info, bool_yn: true)
2117
2118 if not supported_cpus.contains(cpu)
2119   message()
2120   warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
2121   message()
2122   message('CPU host architecture ' + cpu + ' support is not currently maintained.')
2123   message('The QEMU project intends to remove support for this host CPU in')
2124   message('a future release if nobody volunteers to maintain it and to')
2125   message('provide a build host for our continuous integration setup.')
2126   message('configure has succeeded and you can continue to build, but')
2127   message('if you care about QEMU on this platform you should contact')
2128   message('us upstream at qemu-devel@nongnu.org.')
2129 endif
2130
2131 if not supported_oses.contains(targetos)
2132   message()
2133   warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
2134   message()
2135   message('Host OS ' + targetos + 'support is not currently maintained.')
2136   message('The QEMU project intends to remove support for this host OS in')
2137   message('a future release if nobody volunteers to maintain it and to')
2138   message('provide a build host for our continuous integration setup.')
2139   message('configure has succeeded and you can continue to build, but')
2140   message('if you care about QEMU on this platform you should contact')
2141   message('us upstream at qemu-devel@nongnu.org.')
2142 endif