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