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