OSDN Git Service

configure, meson: move remaining HAVE_* compiler tests to Meson
[qmiga/qemu.git] / meson.build
1 project('qemu', ['c'], meson_version: '>=0.58.2',
2         default_options: ['warning_level=1', 'c_std=gnu11', 'cpp_std=gnu++11', 'b_colorout=auto',
3                           'b_staticpic=false'],
4         version: files('VERSION'))
5
6 not_found = dependency('', required: false)
7 keyval = import('keyval')
8 ss = import('sourceset')
9 fs = import('fs')
10
11 sh = find_program('sh')
12 cc = meson.get_compiler('c')
13 config_host = keyval.load(meson.current_build_dir() / 'config-host.mak')
14 enable_modules = 'CONFIG_MODULES' in config_host
15 enable_static = 'CONFIG_STATIC' in config_host
16
17 # Allow both shared and static libraries unless --enable-static
18 static_kwargs = enable_static ? {'static': true} : {}
19
20 # Temporary directory used for files created while
21 # configure runs. Since it is in the build directory
22 # we can safely blow away any previous version of it
23 # (and we need not jump through hoops to try to delete
24 # it when configure exits.)
25 tmpdir = meson.current_build_dir() / 'meson-private/temp'
26
27 if get_option('qemu_suffix').startswith('/')
28   error('qemu_suffix cannot start with a /')
29 endif
30
31 qemu_confdir = get_option('sysconfdir') / get_option('qemu_suffix')
32 qemu_datadir = get_option('datadir') / get_option('qemu_suffix')
33 qemu_docdir = get_option('docdir') / get_option('qemu_suffix')
34 qemu_moddir = get_option('libdir') / get_option('qemu_suffix')
35
36 qemu_desktopdir = get_option('datadir') / 'applications'
37 qemu_icondir = get_option('datadir') / 'icons'
38
39 config_host_data = configuration_data()
40 genh = []
41
42 target_dirs = config_host['TARGET_DIRS'].split()
43 have_user = false
44 have_system = false
45 foreach target : target_dirs
46   have_user = have_user or target.endswith('-user')
47   have_system = have_system or target.endswith('-softmmu')
48 endforeach
49 have_tools = 'CONFIG_TOOLS' in config_host
50 have_block = have_system or have_tools
51
52 python = import('python').find_installation()
53
54 supported_oses = ['windows', 'freebsd', 'netbsd', 'openbsd', 'darwin', 'sunos', 'linux']
55 supported_cpus = ['ppc', 'ppc64', 's390x', 'riscv32', 'riscv64', 'x86', 'x86_64',
56   'arm', 'aarch64', 'mips', 'mips64', 'sparc', 'sparc64']
57
58 cpu = host_machine.cpu_family()
59 targetos = host_machine.system()
60
61 if cpu in ['x86', 'x86_64']
62   kvm_targets = ['i386-softmmu', 'x86_64-softmmu']
63 elif cpu == 'aarch64'
64   kvm_targets = ['aarch64-softmmu']
65 elif cpu == 's390x'
66   kvm_targets = ['s390x-softmmu']
67 elif cpu in ['ppc', 'ppc64']
68   kvm_targets = ['ppc-softmmu', 'ppc64-softmmu']
69 elif cpu in ['mips', 'mips64']
70   kvm_targets = ['mips-softmmu', 'mipsel-softmmu', 'mips64-softmmu', 'mips64el-softmmu']
71 else
72   kvm_targets = []
73 endif
74
75 accelerator_targets = { 'CONFIG_KVM': kvm_targets }
76
77 if cpu in ['aarch64']
78   accelerator_targets += {
79     'CONFIG_HVF': ['aarch64-softmmu']
80   }
81 endif
82
83 if cpu in ['x86', 'x86_64', 'arm', 'aarch64']
84   # i386 emulator provides xenpv machine type for multiple architectures
85   accelerator_targets += {
86     'CONFIG_XEN': ['i386-softmmu', 'x86_64-softmmu'],
87   }
88 endif
89 if cpu in ['x86', 'x86_64']
90   accelerator_targets += {
91     'CONFIG_HAX': ['i386-softmmu', 'x86_64-softmmu'],
92     'CONFIG_HVF': ['x86_64-softmmu'],
93     'CONFIG_NVMM': ['i386-softmmu', 'x86_64-softmmu'],
94     'CONFIG_WHPX': ['i386-softmmu', 'x86_64-softmmu'],
95   }
96 endif
97
98 modular_tcg = []
99 # Darwin does not support references to thread-local variables in modules
100 if targetos != 'darwin'
101   modular_tcg = ['i386-softmmu', 'x86_64-softmmu']
102 endif
103
104 edk2_targets = [ 'arm-softmmu', 'aarch64-softmmu', 'i386-softmmu', 'x86_64-softmmu' ]
105 unpack_edk2_blobs = false
106 foreach target : edk2_targets
107   if target in target_dirs
108     bzip2 = find_program('bzip2', required: get_option('install_blobs'))
109     unpack_edk2_blobs = bzip2.found()
110     break
111   endif
112 endforeach
113
114 dtrace = not_found
115 stap = not_found
116 if 'dtrace' in get_option('trace_backends')
117   dtrace = find_program('dtrace', required: true)
118   stap = find_program('stap', required: false)
119   if stap.found()
120     # Workaround to avoid dtrace(1) producing a file with 'hidden' symbol
121     # visibility. Define STAP_SDT_V2 to produce 'default' symbol visibility
122     # instead. QEMU --enable-modules depends on this because the SystemTap
123     # semaphores are linked into the main binary and not the module's shared
124     # object.
125     add_global_arguments('-DSTAP_SDT_V2',
126                          native: false, language: ['c', 'cpp', 'objc'])
127   endif
128 endif
129
130 ##################
131 # Compiler flags #
132 ##################
133
134 # Specify linker-script with add_project_link_arguments so that it is not placed
135 # within a linker --start-group/--end-group pair
136 if get_option('fuzzing')
137   add_project_link_arguments(['-Wl,-T,',
138                               (meson.current_source_dir() / 'tests/qtest/fuzz/fork_fuzz.ld')],
139                              native: false, language: ['c', 'cpp', 'objc'])
140
141   # Specify a filter to only instrument code that is directly related to
142   # virtual-devices.
143   configure_file(output: 'instrumentation-filter',
144                  input: 'scripts/oss-fuzz/instrumentation-filter-template',
145                  copy: true)
146   add_global_arguments(
147       cc.get_supported_arguments('-fsanitize-coverage-allowlist=instrumentation-filter'),
148       native: false, language: ['c', 'cpp', 'objc'])
149
150   if get_option('fuzzing_engine') == ''
151     # Add CFLAGS to tell clang to add fuzzer-related instrumentation to all the
152     # compiled code.  To build non-fuzzer binaries with --enable-fuzzing, link
153     # everything with fsanitize=fuzzer-no-link. Otherwise, the linker will be
154     # unable to bind the fuzzer-related callbacks added by instrumentation.
155     add_global_arguments('-fsanitize=fuzzer-no-link',
156                          native: false, language: ['c', 'cpp', 'objc'])
157     add_global_link_arguments('-fsanitize=fuzzer-no-link',
158                               native: false, language: ['c', 'cpp', 'objc'])
159     # For the actual fuzzer binaries, we need to link against the libfuzzer
160     # library. They need to be configurable, to support OSS-Fuzz
161     fuzz_exe_ldflags = ['-fsanitize=fuzzer']
162   else
163     # LIB_FUZZING_ENGINE was set; assume we are running on OSS-Fuzz, and
164     # the needed CFLAGS have already been provided
165     fuzz_exe_ldflags = get_option('fuzzing_engine').split()
166   endif
167 endif
168
169 add_global_arguments(config_host['QEMU_CFLAGS'].split(),
170                      native: false, language: ['c', 'objc'])
171 add_global_arguments(config_host['QEMU_CXXFLAGS'].split(),
172                      native: false, language: 'cpp')
173 add_global_link_arguments(config_host['QEMU_LDFLAGS'].split(),
174                           native: false, language: ['c', 'cpp', 'objc'])
175
176 if targetos == 'linux'
177   add_project_arguments('-isystem', meson.current_source_dir() / 'linux-headers',
178                         '-isystem', 'linux-headers',
179                         language: ['c', 'cpp'])
180 endif
181
182 add_project_arguments('-iquote', '.',
183                       '-iquote', meson.current_source_dir(),
184                       '-iquote', meson.current_source_dir() / 'include',
185                       '-iquote', meson.current_source_dir() / 'disas/libvixl',
186                       language: ['c', 'cpp', 'objc'])
187
188 link_language = meson.get_external_property('link_language', 'cpp')
189 if link_language == 'cpp'
190   add_languages('cpp', required: true, native: false)
191 endif
192 if host_machine.system() == 'darwin'
193   add_languages('objc', required: false, native: false)
194 endif
195
196 sparse = find_program('cgcc', required: get_option('sparse'))
197 if sparse.found()
198   run_target('sparse',
199              command: [find_program('scripts/check_sparse.py'),
200                        'compile_commands.json', sparse.full_path(), '-Wbitwise',
201                        '-Wno-transparent-union', '-Wno-old-initializer',
202                        '-Wno-non-pointer-null'])
203 endif
204
205 ###########################################
206 # Target-specific checks and dependencies #
207 ###########################################
208
209 if get_option('fuzzing') and get_option('fuzzing_engine') == '' and \
210     not cc.links('''
211           #include <stdint.h>
212           #include <sys/types.h>
213           int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
214           int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { return 0; }
215         ''',
216         args: ['-Werror', '-fsanitize=fuzzer'])
217   error('Your compiler does not support -fsanitize=fuzzer')
218 endif
219
220 if 'ftrace' in get_option('trace_backends') and targetos != 'linux'
221   error('ftrace is supported only on Linux')
222 endif
223 if 'syslog' in get_option('trace_backends') and not cc.compiles('''
224     #include <syslog.h>
225     int main(void) {
226         openlog("qemu", LOG_PID, LOG_DAEMON);
227         syslog(LOG_INFO, "configure");
228         return 0;
229     }''')
230   error('syslog is not supported on this system')
231 endif
232
233 if targetos != 'linux' and get_option('mpath').enabled()
234   error('Multipath is supported only on Linux')
235 endif
236
237 if targetos != 'linux' and get_option('multiprocess').enabled()
238   error('Multiprocess QEMU is supported only on Linux')
239 endif
240 multiprocess_allowed = targetos == 'linux' and not get_option('multiprocess').disabled()
241
242 libm = cc.find_library('m', required: false)
243 threads = dependency('threads')
244 util = cc.find_library('util', required: false)
245 winmm = []
246 socket = []
247 version_res = []
248 coref = []
249 iokit = []
250 emulator_link_args = []
251 nvmm =not_found
252 hvf = not_found
253 host_dsosuf = '.so'
254 if targetos == 'windows'
255   socket = cc.find_library('ws2_32')
256   winmm = cc.find_library('winmm')
257
258   win = import('windows')
259   version_res = win.compile_resources('version.rc',
260                                       depend_files: files('pc-bios/qemu-nsis.ico'),
261                                       include_directories: include_directories('.'))
262   host_dsosuf = '.dll'
263 elif targetos == 'darwin'
264   coref = dependency('appleframeworks', modules: 'CoreFoundation')
265   iokit = dependency('appleframeworks', modules: 'IOKit', required: false)
266   host_dsosuf = '.dylib'
267 elif targetos == 'sunos'
268   socket = [cc.find_library('socket'),
269             cc.find_library('nsl'),
270             cc.find_library('resolv')]
271 elif targetos == 'haiku'
272   socket = [cc.find_library('posix_error_mapper'),
273             cc.find_library('network'),
274             cc.find_library('bsd')]
275 elif targetos == 'openbsd'
276   if not get_option('tcg').disabled() and target_dirs.length() > 0
277     # Disable OpenBSD W^X if available
278     emulator_link_args = cc.get_supported_link_arguments('-Wl,-z,wxneeded')
279   endif
280 endif
281
282 accelerators = []
283 if not get_option('kvm').disabled() and targetos == 'linux'
284   accelerators += 'CONFIG_KVM'
285 endif
286 if not get_option('xen').disabled() and 'CONFIG_XEN_BACKEND' in config_host
287   accelerators += 'CONFIG_XEN'
288   have_xen_pci_passthrough = not get_option('xen_pci_passthrough').disabled() and targetos == 'linux'
289 else
290   have_xen_pci_passthrough = false
291 endif
292 if not get_option('whpx').disabled() and targetos == 'windows'
293   if get_option('whpx').enabled() and host_machine.cpu() != 'x86_64'
294     error('WHPX requires 64-bit host')
295   elif cc.has_header('WinHvPlatform.h', required: get_option('whpx')) and \
296        cc.has_header('WinHvEmulation.h', required: get_option('whpx'))
297     accelerators += 'CONFIG_WHPX'
298   endif
299 endif
300 if not get_option('hvf').disabled()
301   hvf = dependency('appleframeworks', modules: 'Hypervisor',
302                    required: get_option('hvf'))
303   if hvf.found()
304     accelerators += 'CONFIG_HVF'
305   endif
306 endif
307 if not get_option('hax').disabled()
308   if get_option('hax').enabled() or targetos in ['windows', 'darwin', 'netbsd']
309     accelerators += 'CONFIG_HAX'
310   endif
311 endif
312 if targetos == 'netbsd'
313   if cc.has_header_symbol('nvmm.h', 'nvmm_cpu_stop', required: get_option('nvmm'))
314     nvmm = cc.find_library('nvmm', required: get_option('nvmm'))
315   endif
316   if nvmm.found()
317     accelerators += 'CONFIG_NVMM'
318   endif
319 endif
320
321 tcg_arch = config_host['ARCH']
322 if not get_option('tcg').disabled()
323   if cpu not in supported_cpus
324     if get_option('tcg_interpreter')
325       warning('Unsupported CPU @0@, will use TCG with TCI (experimental and slow)'.format(cpu))
326     else
327       error('Unsupported CPU @0@, try --enable-tcg-interpreter'.format(cpu))
328     endif
329   elif get_option('tcg_interpreter')
330     warning('Use of the TCG interpretor is not recommended on this host')
331     warning('architecture. There is a native TCG execution backend available')
332     warning('which provides substantially better performance and reliability.')
333     warning('It is strongly recommended to remove the --enable-tcg-interpreter')
334     warning('configuration option on this architecture to use the native')
335     warning('backend.')
336   endif
337   if get_option('tcg_interpreter')
338     tcg_arch = 'tci'
339   elif config_host['ARCH'] == 'sparc64'
340     tcg_arch = 'sparc'
341   elif config_host['ARCH'] in ['x86_64', 'x32']
342     tcg_arch = 'i386'
343   elif config_host['ARCH'] == 'ppc64'
344     tcg_arch = 'ppc'
345   elif config_host['ARCH'] in ['riscv32', 'riscv64']
346     tcg_arch = 'riscv'
347   endif
348   add_project_arguments('-iquote', meson.current_source_dir() / 'tcg' / tcg_arch,
349                         language: ['c', 'cpp', 'objc'])
350
351   accelerators += 'CONFIG_TCG'
352   config_host += { 'CONFIG_TCG': 'y' }
353 endif
354
355 if 'CONFIG_KVM' not in accelerators and get_option('kvm').enabled()
356   error('KVM not available on this platform')
357 endif
358 if 'CONFIG_HVF' not in accelerators and get_option('hvf').enabled()
359   error('HVF not available on this platform')
360 endif
361 if 'CONFIG_NVMM' not in accelerators and get_option('nvmm').enabled()
362   error('NVMM not available on this platform')
363 endif
364 if 'CONFIG_WHPX' not in accelerators and get_option('whpx').enabled()
365   error('WHPX not available on this platform')
366 endif
367 if not have_xen_pci_passthrough and get_option('xen_pci_passthrough').enabled()
368   if 'CONFIG_XEN' in accelerators
369     error('Xen PCI passthrough not available on this platform')
370   else
371     error('Xen PCI passthrough requested but Xen not enabled')
372   endif
373 endif
374
375 ################
376 # Dependencies #
377 ################
378
379 # The path to glib.h is added to all compilation commands.  This was
380 # grandfathered in from the QEMU Makefiles.
381 add_project_arguments(config_host['GLIB_CFLAGS'].split(),
382                       native: false, language: ['c', 'cpp', 'objc'])
383 glib = declare_dependency(compile_args: config_host['GLIB_CFLAGS'].split(),
384                           link_args: config_host['GLIB_LIBS'].split())
385 # override glib dep with the configure results (for subprojects)
386 meson.override_dependency('glib-2.0', glib)
387
388 gio = not_found
389 if 'CONFIG_GIO' in config_host
390   gio = declare_dependency(compile_args: config_host['GIO_CFLAGS'].split(),
391                            link_args: config_host['GIO_LIBS'].split())
392 endif
393 lttng = not_found
394 if 'ust' in get_option('trace_backends')
395   lttng = dependency('lttng-ust', required: true, method: 'pkg-config',
396                      kwargs: static_kwargs)
397 endif
398 pixman = not_found
399 if have_system or have_tools
400   pixman = dependency('pixman-1', required: have_system, version:'>=0.21.8',
401                       method: 'pkg-config', kwargs: static_kwargs)
402 endif
403 libaio = cc.find_library('aio', required: false)
404 zlib = dependency('zlib', required: true, kwargs: static_kwargs)
405
406 linux_io_uring = not_found
407 if not get_option('linux_io_uring').auto() or have_block
408   linux_io_uring = dependency('liburing', required: get_option('linux_io_uring'),
409                               method: 'pkg-config', kwargs: static_kwargs)
410 endif
411 libxml2 = not_found
412 if not get_option('libxml2').auto() or have_block
413   libxml2 = dependency('libxml-2.0', required: get_option('libxml2'),
414                        method: 'pkg-config', kwargs: static_kwargs)
415 endif
416 libnfs = not_found
417 if not get_option('libnfs').auto() or have_block
418   libnfs = dependency('libnfs', version: '>=1.9.3',
419                       required: get_option('libnfs'),
420                       method: 'pkg-config', kwargs: static_kwargs)
421 endif
422
423 libattr_test = '''
424   #include <stddef.h>
425   #include <sys/types.h>
426   #ifdef CONFIG_LIBATTR
427   #include <attr/xattr.h>
428   #else
429   #include <sys/xattr.h>
430   #endif
431   int main(void) { getxattr(NULL, NULL, NULL, 0); setxattr(NULL, NULL, NULL, 0, 0); return 0; }'''
432
433 libattr = not_found
434 have_old_libattr = false
435 if not get_option('attr').disabled()
436   if cc.links(libattr_test)
437     libattr = declare_dependency()
438   else
439     libattr = cc.find_library('attr', has_headers: ['attr/xattr.h'],
440                               required: get_option('attr'),
441                               kwargs: static_kwargs)
442     if libattr.found() and not \
443       cc.links(libattr_test, dependencies: libattr, args: '-DCONFIG_LIBATTR')
444       libattr = not_found
445       if get_option('attr').enabled()
446         error('could not link libattr')
447       else
448         warning('could not link libattr, disabling')
449       endif
450     else
451       have_old_libattr = libattr.found()
452     endif
453   endif
454 endif
455
456 cocoa = dependency('appleframeworks', modules: 'Cocoa', required: get_option('cocoa'))
457 if cocoa.found() and get_option('sdl').enabled()
458   error('Cocoa and SDL cannot be enabled at the same time')
459 endif
460 if cocoa.found() and get_option('gtk').enabled()
461   error('Cocoa and GTK+ cannot be enabled at the same time')
462 endif
463
464 seccomp = not_found
465 if not get_option('seccomp').auto() or have_system or have_tools
466   seccomp = dependency('libseccomp', version: '>=2.3.0',
467                        required: get_option('seccomp'),
468                        method: 'pkg-config', kwargs: static_kwargs)
469 endif
470
471 libcap_ng = not_found
472 if not get_option('cap_ng').auto() or have_system or have_tools
473   libcap_ng = cc.find_library('cap-ng', has_headers: ['cap-ng.h'],
474                               required: get_option('cap_ng'),
475                               kwargs: static_kwargs)
476 endif
477 if libcap_ng.found() and not cc.links('''
478    #include <cap-ng.h>
479    int main(void)
480    {
481      capng_capability_to_name(CAPNG_EFFECTIVE);
482      return 0;
483    }''', dependencies: libcap_ng)
484   libcap_ng = not_found
485   if get_option('cap_ng').enabled()
486     error('could not link libcap-ng')
487   else
488     warning('could not link libcap-ng, disabling')
489   endif
490 endif
491
492 if get_option('xkbcommon').auto() and not have_system and not have_tools
493   xkbcommon = not_found
494 else
495   xkbcommon = dependency('xkbcommon', required: get_option('xkbcommon'),
496                          method: 'pkg-config', kwargs: static_kwargs)
497 endif
498 vde = not_found
499 if config_host.has_key('CONFIG_VDE')
500   vde = declare_dependency(link_args: config_host['VDE_LIBS'].split())
501 endif
502
503 pulse = not_found
504 if not get_option('pa').auto() or (targetos == 'linux' and have_system)
505   pulse = dependency('libpulse', required: get_option('pa'),
506                      method: 'pkg-config', kwargs: static_kwargs)
507 endif
508 alsa = not_found
509 if not get_option('alsa').auto() or (targetos == 'linux' and have_system)
510   alsa = dependency('alsa', required: get_option('alsa'),
511                     method: 'pkg-config', kwargs: static_kwargs)
512 endif
513 jack = not_found
514 if not get_option('jack').auto() or have_system
515   jack = dependency('jack', required: get_option('jack'),
516                     method: 'pkg-config', kwargs: static_kwargs)
517 endif
518
519 spice = not_found
520 spice_headers = not_found
521 spice_protocol = not_found
522 if 'CONFIG_SPICE' in config_host
523   spice = declare_dependency(compile_args: config_host['SPICE_CFLAGS'].split(),
524                              link_args: config_host['SPICE_LIBS'].split())
525   spice_headers = declare_dependency(compile_args: config_host['SPICE_CFLAGS'].split())
526 endif
527 if 'CONFIG_SPICE_PROTOCOL' in config_host
528   spice_protocol = declare_dependency(compile_args: config_host['SPICE_PROTOCOL_CFLAGS'].split())
529 endif
530 rt = cc.find_library('rt', required: false)
531 libdl = not_found
532 if 'CONFIG_PLUGIN' in config_host
533   libdl = cc.find_library('dl', required: false)
534   if not cc.has_function('dlopen', dependencies: libdl)
535     error('dlopen not found')
536   endif
537 endif
538 libiscsi = not_found
539 if not get_option('libiscsi').auto() or have_block
540   libiscsi = dependency('libiscsi', version: '>=1.9.0',
541                          required: get_option('libiscsi'),
542                          method: 'pkg-config', kwargs: static_kwargs)
543 endif
544 zstd = not_found
545 if not get_option('zstd').auto() or have_block
546   zstd = dependency('libzstd', version: '>=1.4.0',
547                     required: get_option('zstd'),
548                     method: 'pkg-config', kwargs: static_kwargs)
549 endif
550 virgl = not_found
551 if not get_option('virglrenderer').auto() or have_system
552   virgl = dependency('virglrenderer',
553                      method: 'pkg-config',
554                      required: get_option('virglrenderer'),
555                      kwargs: static_kwargs)
556 endif
557 curl = not_found
558 if not get_option('curl').auto() or have_block
559   curl = dependency('libcurl', version: '>=7.29.0',
560                     method: 'pkg-config',
561                     required: get_option('curl'),
562                     kwargs: static_kwargs)
563 endif
564 libudev = not_found
565 if targetos == 'linux' and (have_system or have_tools)
566   libudev = dependency('libudev',
567                        method: 'pkg-config',
568                        required: get_option('libudev'),
569                        kwargs: static_kwargs)
570 endif
571
572 mpathlibs = [libudev]
573 mpathpersist = not_found
574 mpathpersist_new_api = false
575 if targetos == 'linux' and have_tools and not get_option('mpath').disabled()
576   mpath_test_source_new = '''
577     #include <libudev.h>
578     #include <mpath_persist.h>
579     unsigned mpath_mx_alloc_len = 1024;
580     int logsink;
581     static struct config *multipath_conf;
582     extern struct udev *udev;
583     extern struct config *get_multipath_config(void);
584     extern void put_multipath_config(struct config *conf);
585     struct udev *udev;
586     struct config *get_multipath_config(void) { return multipath_conf; }
587     void put_multipath_config(struct config *conf) { }
588     int main(void) {
589         udev = udev_new();
590         multipath_conf = mpath_lib_init();
591         return 0;
592     }'''
593   mpath_test_source_old = '''
594       #include <libudev.h>
595       #include <mpath_persist.h>
596       unsigned mpath_mx_alloc_len = 1024;
597       int logsink;
598       int main(void) {
599           struct udev *udev = udev_new();
600           mpath_lib_init(udev);
601           return 0;
602       }'''
603   libmpathpersist = cc.find_library('mpathpersist',
604                                     required: get_option('mpath'),
605                                     kwargs: static_kwargs)
606   if libmpathpersist.found()
607     mpathlibs += libmpathpersist
608     if enable_static
609       mpathlibs += cc.find_library('devmapper',
610                                      required: get_option('mpath'),
611                                      kwargs: static_kwargs)
612     endif
613     mpathlibs += cc.find_library('multipath',
614                                  required: get_option('mpath'),
615                                  kwargs: static_kwargs)
616     foreach lib: mpathlibs
617       if not lib.found()
618         mpathlibs = []
619         break
620       endif
621     endforeach
622     if mpathlibs.length() == 0
623       msg = 'Dependencies missing for libmpathpersist'
624     elif cc.links(mpath_test_source_new, dependencies: mpathlibs)
625       mpathpersist = declare_dependency(dependencies: mpathlibs)
626       mpathpersist_new_api = true
627     elif cc.links(mpath_test_source_old, dependencies: mpathlibs)
628       mpathpersist = declare_dependency(dependencies: mpathlibs)
629     else
630       msg = 'Cannot detect libmpathpersist API'
631     endif
632     if not mpathpersist.found()
633       if get_option('mpath').enabled()
634         error(msg)
635       else
636         warning(msg + ', disabling')
637       endif
638     endif
639   endif
640 endif
641
642 iconv = not_found
643 curses = not_found
644 if have_system and not get_option('curses').disabled()
645   curses_test = '''
646     #include <locale.h>
647     #include <curses.h>
648     #include <wchar.h>
649     int main(void) {
650       wchar_t wch = L'w';
651       setlocale(LC_ALL, "");
652       resize_term(0, 0);
653       addwstr(L"wide chars\n");
654       addnwstr(&wch, 1);
655       add_wch(WACS_DEGREE);
656       return 0;
657     }'''
658
659   curses_dep_list = targetos == 'windows' ? ['ncurses', 'ncursesw'] : ['ncursesw']
660   foreach curses_dep : curses_dep_list
661     if not curses.found()
662       curses = dependency(curses_dep,
663                           required: false,
664                           method: 'pkg-config',
665                           kwargs: static_kwargs)
666     endif
667   endforeach
668   msg = get_option('curses').enabled() ? 'curses library not found' : ''
669   curses_compile_args = ['-DNCURSES_WIDECHAR']
670   if curses.found()
671     if cc.links(curses_test, args: curses_compile_args, dependencies: [curses])
672       curses = declare_dependency(compile_args: curses_compile_args, dependencies: [curses])
673     else
674       msg = 'curses package not usable'
675       curses = not_found
676     endif
677   endif
678   if not curses.found()
679     has_curses_h = cc.has_header('curses.h', args: curses_compile_args)
680     if targetos != 'windows' and not has_curses_h
681       message('Trying with /usr/include/ncursesw')
682       curses_compile_args += ['-I/usr/include/ncursesw']
683       has_curses_h = cc.has_header('curses.h', args: curses_compile_args)
684     endif
685     if has_curses_h
686       curses_libname_list = (targetos == 'windows' ? ['pdcurses'] : ['ncursesw', 'cursesw'])
687       foreach curses_libname : curses_libname_list
688         libcurses = cc.find_library(curses_libname,
689                                     required: false,
690                                     kwargs: static_kwargs)
691         if libcurses.found()
692           if cc.links(curses_test, args: curses_compile_args, dependencies: libcurses)
693             curses = declare_dependency(compile_args: curses_compile_args,
694                                         dependencies: [libcurses])
695             break
696           else
697             msg = 'curses library not usable'
698           endif
699         endif
700       endforeach
701     endif
702   endif
703   if not get_option('iconv').disabled()
704     foreach link_args : [ ['-liconv'], [] ]
705       # Programs will be linked with glib and this will bring in libiconv on FreeBSD.
706       # We need to use libiconv if available because mixing libiconv's headers with
707       # the system libc does not work.
708       # However, without adding glib to the dependencies -L/usr/local/lib will not be
709       # included in the command line and libiconv will not be found.
710       if cc.links('''
711         #include <iconv.h>
712         int main(void) {
713           iconv_t conv = iconv_open("WCHAR_T", "UCS-2");
714           return conv != (iconv_t) -1;
715         }''', args: config_host['GLIB_CFLAGS'].split() + config_host['GLIB_LIBS'].split() + link_args)
716         iconv = declare_dependency(link_args: link_args, dependencies: glib)
717         break
718       endif
719     endforeach
720   endif
721   if curses.found() and not iconv.found()
722     if get_option('iconv').enabled()
723       error('iconv not available')
724     endif
725     msg = 'iconv required for curses UI but not available'
726     curses = not_found
727   endif
728   if not curses.found() and msg != ''
729     if get_option('curses').enabled()
730       error(msg)
731     else
732       warning(msg + ', disabling')
733     endif
734   endif
735 endif
736
737 brlapi = not_found
738 if not get_option('brlapi').auto() or have_system
739   brlapi = cc.find_library('brlapi', has_headers: ['brlapi.h'],
740                          required: get_option('brlapi'),
741                          kwargs: static_kwargs)
742   if brlapi.found() and not cc.links('''
743      #include <brlapi.h>
744      #include <stddef.h>
745      int main(void) { return brlapi__openConnection (NULL, NULL, NULL); }''', dependencies: brlapi)
746     brlapi = not_found
747     if get_option('brlapi').enabled()
748       error('could not link brlapi')
749     else
750       warning('could not link brlapi, disabling')
751     endif
752   endif
753 endif
754
755 sdl = not_found
756 if not get_option('sdl').auto() or (have_system and not cocoa.found())
757   sdl = dependency('sdl2', required: get_option('sdl'), kwargs: static_kwargs)
758   sdl_image = not_found
759 endif
760 if sdl.found()
761   # work around 2.0.8 bug
762   sdl = declare_dependency(compile_args: '-Wno-undef',
763                            dependencies: sdl)
764   sdl_image = dependency('SDL2_image', required: get_option('sdl_image'),
765                          method: 'pkg-config', kwargs: static_kwargs)
766 else
767   if get_option('sdl_image').enabled()
768     error('sdl-image required, but SDL was @0@'.format(
769           get_option('sdl').disabled() ? 'disabled' : 'not found'))
770   endif
771   sdl_image = not_found
772 endif
773
774 rbd = not_found
775 if not get_option('rbd').auto() or have_block
776   librados = cc.find_library('rados', required: get_option('rbd'),
777                              kwargs: static_kwargs)
778   librbd = cc.find_library('rbd', has_headers: ['rbd/librbd.h'],
779                            required: get_option('rbd'),
780                            kwargs: static_kwargs)
781   if librados.found() and librbd.found()
782     if cc.links('''
783       #include <stdio.h>
784       #include <rbd/librbd.h>
785       int main(void) {
786         rados_t cluster;
787         rados_create(&cluster, NULL);
788         #if LIBRBD_VERSION_CODE < LIBRBD_VERSION(1, 12, 0)
789         #error
790         #endif
791         return 0;
792       }''', dependencies: [librbd, librados])
793       rbd = declare_dependency(dependencies: [librbd, librados])
794     elif get_option('rbd').enabled()
795       error('librbd >= 1.12.0 required')
796     else
797       warning('librbd >= 1.12.0 not found, disabling')
798     endif
799   endif
800 endif
801
802 glusterfs = not_found
803 glusterfs_ftruncate_has_stat = false
804 glusterfs_iocb_has_stat = false
805 if not get_option('glusterfs').auto() or have_block
806   glusterfs = dependency('glusterfs-api', version: '>=3',
807                          required: get_option('glusterfs'),
808                          method: 'pkg-config', kwargs: static_kwargs)
809   if glusterfs.found()
810     glusterfs_ftruncate_has_stat = cc.links('''
811       #include <glusterfs/api/glfs.h>
812
813       int
814       main(void)
815       {
816           /* new glfs_ftruncate() passes two additional args */
817           return glfs_ftruncate(NULL, 0, NULL, NULL);
818       }
819     ''', dependencies: glusterfs)
820     glusterfs_iocb_has_stat = cc.links('''
821       #include <glusterfs/api/glfs.h>
822
823       /* new glfs_io_cbk() passes two additional glfs_stat structs */
824       static void
825       glusterfs_iocb(glfs_fd_t *fd, ssize_t ret, struct glfs_stat *prestat, struct glfs_stat *poststat, void *data)
826       {}
827
828       int
829       main(void)
830       {
831           glfs_io_cbk iocb = &glusterfs_iocb;
832           iocb(NULL, 0 , NULL, NULL, NULL);
833           return 0;
834       }
835     ''', dependencies: glusterfs)
836   endif
837 endif
838 libssh = not_found
839 if 'CONFIG_LIBSSH' in config_host
840   libssh = declare_dependency(compile_args: config_host['LIBSSH_CFLAGS'].split(),
841                               link_args: config_host['LIBSSH_LIBS'].split())
842 endif
843 libbzip2 = not_found
844 if not get_option('bzip2').auto() or have_block
845   libbzip2 = cc.find_library('bz2', has_headers: ['bzlib.h'],
846                              required: get_option('bzip2'),
847                              kwargs: static_kwargs)
848   if libbzip2.found() and not cc.links('''
849      #include <bzlib.h>
850      int main(void) { BZ2_bzlibVersion(); return 0; }''', dependencies: libbzip2)
851     libbzip2 = not_found
852     if get_option('bzip2').enabled()
853       error('could not link libbzip2')
854     else
855       warning('could not link libbzip2, disabling')
856     endif
857   endif
858 endif
859
860 liblzfse = not_found
861 if not get_option('lzfse').auto() or have_block
862   liblzfse = cc.find_library('lzfse', has_headers: ['lzfse.h'],
863                              required: get_option('lzfse'),
864                              kwargs: static_kwargs)
865 endif
866 if liblzfse.found() and not cc.links('''
867    #include <lzfse.h>
868    int main(void) { lzfse_decode_scratch_size(); return 0; }''', dependencies: liblzfse)
869   liblzfse = not_found
870   if get_option('lzfse').enabled()
871     error('could not link liblzfse')
872   else
873     warning('could not link liblzfse, disabling')
874   endif
875 endif
876
877 oss = not_found
878 if not get_option('oss').auto() or have_system
879   if not cc.has_header('sys/soundcard.h')
880     # not found
881   elif targetos == 'netbsd'
882     oss = cc.find_library('ossaudio', required: get_option('oss'),
883                           kwargs: static_kwargs)
884   else
885     oss = declare_dependency()
886   endif
887
888   if not oss.found()
889     if get_option('oss').enabled()
890       error('OSS not found')
891     else
892       warning('OSS not found, disabling')
893     endif
894   endif
895 endif
896 dsound = not_found
897 if not get_option('dsound').auto() or (targetos == 'windows' and have_system)
898   if cc.has_header('dsound.h')
899     dsound = declare_dependency(link_args: ['-lole32', '-ldxguid'])
900   endif
901
902   if not dsound.found()
903     if get_option('dsound').enabled()
904       error('DirectSound not found')
905     else
906       warning('DirectSound not found, disabling')
907     endif
908   endif
909 endif
910
911 coreaudio = not_found
912 if not get_option('coreaudio').auto() or (targetos == 'darwin' and have_system)
913   coreaudio = dependency('appleframeworks', modules: 'CoreAudio',
914                          required: get_option('coreaudio'))
915   if coreaudio.found() and not cc.links('''
916     #include <CoreAudio/CoreAudio.h>
917     int main(void)
918     {
919       return (int)AudioGetCurrentHostTime();
920     }''')
921     coreaudio = not_found
922   endif
923
924   if not coreaudio.found()
925     if get_option('coreaudio').enabled()
926       error('CoreAudio not found')
927     else
928       warning('CoreAudio not found, disabling')
929     endif
930   endif
931 endif
932
933 opengl = not_found
934 if 'CONFIG_OPENGL' in config_host
935   opengl = declare_dependency(compile_args: config_host['OPENGL_CFLAGS'].split(),
936                               link_args: config_host['OPENGL_LIBS'].split())
937 endif
938 gbm = not_found
939 if (have_system or have_tools) and (virgl.found() or opengl.found())
940   gbm = dependency('gbm', method: 'pkg-config', required: false,
941                    kwargs: static_kwargs)
942 endif
943
944 gnutls = not_found
945 gnutls_crypto = not_found
946 if get_option('gnutls').enabled() or (get_option('gnutls').auto() and have_system)
947   # For general TLS support our min gnutls matches
948   # that implied by our platform support matrix
949   #
950   # For the crypto backends, we look for a newer
951   # gnutls:
952   #
953   #   Version 3.6.8  is needed to get XTS
954   #   Version 3.6.13 is needed to get PBKDF
955   #   Version 3.6.14 is needed to get HW accelerated XTS
956   #
957   # If newer enough gnutls isn't available, we can
958   # still use a different crypto backend to satisfy
959   # the platform support requirements
960   gnutls_crypto = dependency('gnutls', version: '>=3.6.14',
961                              method: 'pkg-config',
962                              required: false,
963                              kwargs: static_kwargs)
964   if gnutls_crypto.found()
965     gnutls = gnutls_crypto
966   else
967     # Our min version if all we need is TLS
968     gnutls = dependency('gnutls', version: '>=3.5.18',
969                         method: 'pkg-config',
970                         required: get_option('gnutls'),
971                         kwargs: static_kwargs)
972   endif
973 endif
974
975 # We prefer use of gnutls for crypto, unless the options
976 # explicitly asked for nettle or gcrypt.
977 #
978 # If gnutls isn't available for crypto, then we'll prefer
979 # gcrypt over nettle for performance reasons.
980 gcrypt = not_found
981 nettle = not_found
982 xts = 'none'
983
984 if get_option('nettle').enabled() and get_option('gcrypt').enabled()
985   error('Only one of gcrypt & nettle can be enabled')
986 endif
987
988 # Explicit nettle/gcrypt request, so ignore gnutls for crypto
989 if get_option('nettle').enabled() or get_option('gcrypt').enabled()
990   gnutls_crypto = not_found
991 endif
992
993 if not gnutls_crypto.found()
994   if (not get_option('gcrypt').auto() or have_system) and not get_option('nettle').enabled()
995     gcrypt = dependency('libgcrypt', version: '>=1.8',
996                         method: 'config-tool',
997                         required: get_option('gcrypt'),
998                         kwargs: static_kwargs)
999     # Debian has removed -lgpg-error from libgcrypt-config
1000     # as it "spreads unnecessary dependencies" which in
1001     # turn breaks static builds...
1002     if gcrypt.found() and enable_static
1003       gcrypt = declare_dependency(dependencies: [
1004         gcrypt,
1005         cc.find_library('gpg-error', required: true, kwargs: static_kwargs)])
1006     endif
1007   endif
1008   if (not get_option('nettle').auto() or have_system) and not gcrypt.found()
1009     nettle = dependency('nettle', version: '>=3.4',
1010                         method: 'pkg-config',
1011                         required: get_option('nettle'),
1012                         kwargs: static_kwargs)
1013     if nettle.found() and not cc.has_header('nettle/xts.h', dependencies: nettle)
1014       xts = 'private'
1015     endif
1016   endif
1017 endif
1018
1019 gtk = not_found
1020 gtkx11 = not_found
1021 vte = not_found
1022 if not get_option('gtk').auto() or (have_system and not cocoa.found())
1023   gtk = dependency('gtk+-3.0', version: '>=3.22.0',
1024                    method: 'pkg-config',
1025                    required: get_option('gtk'),
1026                    kwargs: static_kwargs)
1027   if gtk.found()
1028     gtkx11 = dependency('gtk+-x11-3.0', version: '>=3.22.0',
1029                         method: 'pkg-config',
1030                         required: false,
1031                         kwargs: static_kwargs)
1032     gtk = declare_dependency(dependencies: [gtk, gtkx11])
1033
1034     if not get_option('vte').auto() or have_system
1035       vte = dependency('vte-2.91',
1036                        method: 'pkg-config',
1037                        required: get_option('vte'),
1038                        kwargs: static_kwargs)
1039     endif
1040   endif
1041 endif
1042
1043 x11 = not_found
1044 if gtkx11.found()
1045   x11 = dependency('x11', method: 'pkg-config', required: gtkx11.found(),
1046                    kwargs: static_kwargs)
1047 endif
1048 vnc = not_found
1049 png = not_found
1050 jpeg = not_found
1051 sasl = not_found
1052 if have_system and not get_option('vnc').disabled()
1053   vnc = declare_dependency() # dummy dependency
1054   png = dependency('libpng', required: get_option('vnc_png'),
1055                    method: 'pkg-config', kwargs: static_kwargs)
1056   jpeg = dependency('libjpeg', required: get_option('vnc_jpeg'),
1057                     method: 'pkg-config', kwargs: static_kwargs)
1058   sasl = cc.find_library('sasl2', has_headers: ['sasl/sasl.h'],
1059                          required: get_option('vnc_sasl'),
1060                          kwargs: static_kwargs)
1061   if sasl.found()
1062     sasl = declare_dependency(dependencies: sasl,
1063                               compile_args: '-DSTRUCT_IOVEC_DEFINED')
1064   endif
1065 endif
1066
1067 pam = not_found
1068 if not get_option('auth_pam').auto() or have_system
1069   pam = cc.find_library('pam', has_headers: ['security/pam_appl.h'],
1070                         required: get_option('auth_pam'),
1071                         kwargs: static_kwargs)
1072 endif
1073 if pam.found() and not cc.links('''
1074    #include <stddef.h>
1075    #include <security/pam_appl.h>
1076    int main(void) {
1077      const char *service_name = "qemu";
1078      const char *user = "frank";
1079      const struct pam_conv pam_conv = { 0 };
1080      pam_handle_t *pamh = NULL;
1081      pam_start(service_name, user, &pam_conv, &pamh);
1082      return 0;
1083    }''', dependencies: pam)
1084   pam = not_found
1085   if get_option('auth_pam').enabled()
1086     error('could not link libpam')
1087   else
1088     warning('could not link libpam, disabling')
1089   endif
1090 endif
1091
1092 snappy = not_found
1093 if not get_option('snappy').auto() or have_system
1094   snappy = cc.find_library('snappy', has_headers: ['snappy-c.h'],
1095                            required: get_option('snappy'),
1096                            kwargs: static_kwargs)
1097 endif
1098 if snappy.found() and not cc.links('''
1099    #include <snappy-c.h>
1100    int main(void) { snappy_max_compressed_length(4096); return 0; }''', dependencies: snappy)
1101   snappy = not_found
1102   if get_option('snappy').enabled()
1103     error('could not link libsnappy')
1104   else
1105     warning('could not link libsnappy, disabling')
1106   endif
1107 endif
1108
1109 lzo = not_found
1110 if not get_option('lzo').auto() or have_system
1111   lzo = cc.find_library('lzo2', has_headers: ['lzo/lzo1x.h'],
1112                         required: get_option('lzo'),
1113                         kwargs: static_kwargs)
1114 endif
1115 if lzo.found() and not cc.links('''
1116    #include <lzo/lzo1x.h>
1117    int main(void) { lzo_version(); return 0; }''', dependencies: lzo)
1118   lzo = not_found
1119   if get_option('lzo').enabled()
1120     error('could not link liblzo2')
1121   else
1122     warning('could not link liblzo2, disabling')
1123   endif
1124 endif
1125
1126 rdma = not_found
1127 if 'CONFIG_RDMA' in config_host
1128   rdma = declare_dependency(link_args: config_host['RDMA_LIBS'].split())
1129 endif
1130 numa = not_found
1131 if 'CONFIG_NUMA' in config_host
1132   numa = declare_dependency(link_args: config_host['NUMA_LIBS'].split())
1133 endif
1134 xen = not_found
1135 if 'CONFIG_XEN_BACKEND' in config_host
1136   xen = declare_dependency(compile_args: config_host['XEN_CFLAGS'].split(),
1137                            link_args: config_host['XEN_LIBS'].split())
1138 endif
1139 cacard = not_found
1140 if not get_option('smartcard').auto() or have_system
1141   cacard = dependency('libcacard', required: get_option('smartcard'),
1142                       version: '>=2.5.1', method: 'pkg-config',
1143                       kwargs: static_kwargs)
1144 endif
1145 u2f = not_found
1146 if have_system
1147   u2f = dependency('u2f-emu', required: get_option('u2f'),
1148                    method: 'pkg-config',
1149                    kwargs: static_kwargs)
1150 endif
1151 usbredir = not_found
1152 if not get_option('usb_redir').auto() or have_system
1153   usbredir = dependency('libusbredirparser-0.5', required: get_option('usb_redir'),
1154                         version: '>=0.6', method: 'pkg-config',
1155                         kwargs: static_kwargs)
1156 endif
1157 libusb = not_found
1158 if not get_option('libusb').auto() or have_system
1159   libusb = dependency('libusb-1.0', required: get_option('libusb'),
1160                       version: '>=1.0.13', method: 'pkg-config',
1161                       kwargs: static_kwargs)
1162 endif
1163
1164 libpmem = not_found
1165 if not get_option('libpmem').auto() or have_system
1166   libpmem = dependency('libpmem', required: get_option('libpmem'),
1167                        method: 'pkg-config', kwargs: static_kwargs)
1168 endif
1169 libdaxctl = not_found
1170 if not get_option('libdaxctl').auto() or have_system
1171   libdaxctl = dependency('libdaxctl', required: get_option('libdaxctl'),
1172                          version: '>=57', method: 'pkg-config',
1173                          kwargs: static_kwargs)
1174 endif
1175 tasn1 = not_found
1176 if gnutls.found()
1177   tasn1 = dependency('libtasn1',
1178                      method: 'pkg-config',
1179                      kwargs: static_kwargs)
1180 endif
1181 keyutils = dependency('libkeyutils', required: false,
1182                       method: 'pkg-config', kwargs: static_kwargs)
1183
1184 has_gettid = cc.has_function('gettid')
1185
1186 # Malloc tests
1187
1188 malloc = []
1189 if get_option('malloc') == 'system'
1190   has_malloc_trim = \
1191     not get_option('malloc_trim').disabled() and \
1192     cc.links('''#include <malloc.h>
1193                 int main(void) { malloc_trim(0); return 0; }''')
1194 else
1195   has_malloc_trim = false
1196   malloc = cc.find_library(get_option('malloc'), required: true)
1197 endif
1198 if not has_malloc_trim and get_option('malloc_trim').enabled()
1199   if get_option('malloc') == 'system'
1200     error('malloc_trim not available on this platform.')
1201   else
1202     error('malloc_trim not available with non-libc memory allocator')
1203   endif
1204 endif
1205
1206 # Check whether the glibc provides statx()
1207
1208 gnu_source_prefix = '''
1209   #ifndef _GNU_SOURCE
1210   #define _GNU_SOURCE
1211   #endif
1212 '''
1213 statx_test = gnu_source_prefix + '''
1214   #include <sys/stat.h>
1215   int main(void) {
1216     struct statx statxbuf;
1217     statx(0, "", 0, STATX_BASIC_STATS, &statxbuf);
1218     return 0;
1219   }'''
1220
1221 has_statx = cc.links(statx_test)
1222
1223 have_vhost_user_blk_server = (targetos == 'linux' and
1224     'CONFIG_VHOST_USER' in config_host)
1225
1226 if get_option('vhost_user_blk_server').enabled()
1227     if targetos != 'linux'
1228         error('vhost_user_blk_server requires linux')
1229     elif 'CONFIG_VHOST_USER' not in config_host
1230         error('vhost_user_blk_server requires vhost-user support')
1231     endif
1232 elif get_option('vhost_user_blk_server').disabled() or not have_system
1233     have_vhost_user_blk_server = false
1234 endif
1235
1236
1237 if get_option('fuse').disabled() and get_option('fuse_lseek').enabled()
1238   error('Cannot enable fuse-lseek while fuse is disabled')
1239 endif
1240
1241 fuse = dependency('fuse3', required: get_option('fuse'),
1242                   version: '>=3.1', method: 'pkg-config',
1243                   kwargs: static_kwargs)
1244
1245 fuse_lseek = not_found
1246 if not get_option('fuse_lseek').disabled()
1247   if fuse.version().version_compare('>=3.8')
1248     # Dummy dependency
1249     fuse_lseek = declare_dependency()
1250   elif get_option('fuse_lseek').enabled()
1251     if fuse.found()
1252       error('fuse-lseek requires libfuse >=3.8, found ' + fuse.version())
1253     else
1254       error('fuse-lseek requires libfuse, which was not found')
1255     endif
1256   endif
1257 endif
1258
1259 # libbpf
1260 libbpf = dependency('libbpf', required: get_option('bpf'), method: 'pkg-config')
1261 if libbpf.found() and not cc.links('''
1262    #include <bpf/libbpf.h>
1263    int main(void)
1264    {
1265      bpf_object__destroy_skeleton(NULL);
1266      return 0;
1267    }''', dependencies: libbpf)
1268   libbpf = not_found
1269   if get_option('bpf').enabled()
1270     error('libbpf skeleton test failed')
1271   else
1272     warning('libbpf skeleton test failed, disabling')
1273   endif
1274 endif
1275
1276 #################
1277 # config-host.h #
1278 #################
1279
1280 audio_drivers_selected = []
1281 if have_system
1282   audio_drivers_available = {
1283     'alsa': alsa.found(),
1284     'coreaudio': coreaudio.found(),
1285     'dsound': dsound.found(),
1286     'jack': jack.found(),
1287     'oss': oss.found(),
1288     'pa': pulse.found(),
1289     'sdl': sdl.found(),
1290   }
1291   foreach k, v: audio_drivers_available
1292     config_host_data.set('CONFIG_AUDIO_' + k.to_upper(), v)
1293   endforeach
1294
1295   # Default to native drivers first, OSS second, SDL third
1296   audio_drivers_priority = \
1297     [ 'pa', 'coreaudio', 'dsound', 'oss' ] + \
1298     (targetos == 'linux' ? [] : [ 'sdl' ])
1299   audio_drivers_default = []
1300   foreach k: audio_drivers_priority
1301     if audio_drivers_available[k]
1302       audio_drivers_default += k
1303     endif
1304   endforeach
1305
1306   foreach k: get_option('audio_drv_list')
1307     if k == 'default'
1308       audio_drivers_selected += audio_drivers_default
1309     elif not audio_drivers_available[k]
1310       error('Audio driver "@0@" not available.'.format(k))
1311     else
1312       audio_drivers_selected += k
1313     endif
1314   endforeach
1315 endif
1316 config_host_data.set('CONFIG_AUDIO_DRIVERS',
1317                      '"' + '", "'.join(audio_drivers_selected) + '", ')
1318
1319 if get_option('cfi')
1320   cfi_flags=[]
1321   # Check for dependency on LTO
1322   if not get_option('b_lto')
1323     error('Selected Control-Flow Integrity but LTO is disabled')
1324   endif
1325   if config_host.has_key('CONFIG_MODULES')
1326     error('Selected Control-Flow Integrity is not compatible with modules')
1327   endif
1328   # Check for cfi flags. CFI requires LTO so we can't use
1329   # get_supported_arguments, but need a more complex "compiles" which allows
1330   # custom arguments
1331   if cc.compiles('int main () { return 0; }', name: '-fsanitize=cfi-icall',
1332                  args: ['-flto', '-fsanitize=cfi-icall'] )
1333     cfi_flags += '-fsanitize=cfi-icall'
1334   else
1335     error('-fsanitize=cfi-icall is not supported by the compiler')
1336   endif
1337   if cc.compiles('int main () { return 0; }',
1338                  name: '-fsanitize-cfi-icall-generalize-pointers',
1339                  args: ['-flto', '-fsanitize=cfi-icall',
1340                         '-fsanitize-cfi-icall-generalize-pointers'] )
1341     cfi_flags += '-fsanitize-cfi-icall-generalize-pointers'
1342   else
1343     error('-fsanitize-cfi-icall-generalize-pointers is not supported by the compiler')
1344   endif
1345   if get_option('cfi_debug')
1346     if cc.compiles('int main () { return 0; }',
1347                    name: '-fno-sanitize-trap=cfi-icall',
1348                    args: ['-flto', '-fsanitize=cfi-icall',
1349                           '-fno-sanitize-trap=cfi-icall'] )
1350       cfi_flags += '-fno-sanitize-trap=cfi-icall'
1351     else
1352       error('-fno-sanitize-trap=cfi-icall is not supported by the compiler')
1353     endif
1354   endif
1355   add_global_arguments(cfi_flags, native: false, language: ['c', 'cpp', 'objc'])
1356   add_global_link_arguments(cfi_flags, native: false, language: ['c', 'cpp', 'objc'])
1357 endif
1358
1359 have_host_block_device = (targetos != 'darwin' or
1360     cc.has_header('IOKit/storage/IOMedia.h'))
1361
1362 have_virtfs = (targetos == 'linux' and
1363     have_system and
1364     libattr.found() and
1365     libcap_ng.found())
1366
1367 have_virtfs_proxy_helper = have_virtfs and have_tools
1368
1369 if get_option('virtfs').enabled()
1370   if not have_virtfs
1371     if targetos != 'linux'
1372       error('virtio-9p (virtfs) requires Linux')
1373     elif not libcap_ng.found() or not libattr.found()
1374       error('virtio-9p (virtfs) requires libcap-ng-devel and libattr-devel')
1375     elif not have_system
1376       error('virtio-9p (virtfs) needs system emulation support')
1377     endif
1378   endif
1379 elif get_option('virtfs').disabled()
1380   have_virtfs = false
1381 endif
1382
1383 foreach k : get_option('trace_backends')
1384   config_host_data.set('CONFIG_TRACE_' + k.to_upper(), true)
1385 endforeach
1386 config_host_data.set_quoted('CONFIG_TRACE_FILE', get_option('trace_file'))
1387
1388 config_host_data.set_quoted('CONFIG_BINDIR', get_option('prefix') / get_option('bindir'))
1389 config_host_data.set_quoted('CONFIG_PREFIX', get_option('prefix'))
1390 config_host_data.set_quoted('CONFIG_QEMU_CONFDIR', get_option('prefix') / qemu_confdir)
1391 config_host_data.set_quoted('CONFIG_QEMU_DATADIR', get_option('prefix') / qemu_datadir)
1392 config_host_data.set_quoted('CONFIG_QEMU_DESKTOPDIR', get_option('prefix') / qemu_desktopdir)
1393 config_host_data.set_quoted('CONFIG_QEMU_FIRMWAREPATH', get_option('qemu_firmwarepath'))
1394 config_host_data.set_quoted('CONFIG_QEMU_HELPERDIR', get_option('prefix') / get_option('libexecdir'))
1395 config_host_data.set_quoted('CONFIG_QEMU_ICONDIR', get_option('prefix') / qemu_icondir)
1396 config_host_data.set_quoted('CONFIG_QEMU_LOCALEDIR', get_option('prefix') / get_option('localedir'))
1397 config_host_data.set_quoted('CONFIG_QEMU_LOCALSTATEDIR', get_option('prefix') / get_option('localstatedir'))
1398 config_host_data.set_quoted('CONFIG_QEMU_MODDIR', get_option('prefix') / qemu_moddir)
1399 config_host_data.set_quoted('CONFIG_SYSCONFDIR', get_option('prefix') / get_option('sysconfdir'))
1400
1401 config_host_data.set('CONFIG_ATTR', libattr.found())
1402 config_host_data.set('CONFIG_BRLAPI', brlapi.found())
1403 config_host_data.set('CONFIG_COCOA', cocoa.found())
1404 config_host_data.set('CONFIG_FUZZ', get_option('fuzzing'))
1405 config_host_data.set('CONFIG_GCOV', get_option('b_coverage'))
1406 config_host_data.set('CONFIG_LIBUDEV', libudev.found())
1407 config_host_data.set('CONFIG_LZO', lzo.found())
1408 config_host_data.set('CONFIG_MPATH', mpathpersist.found())
1409 config_host_data.set('CONFIG_MPATH_NEW_API', mpathpersist_new_api)
1410 config_host_data.set('CONFIG_CURL', curl.found())
1411 config_host_data.set('CONFIG_CURSES', curses.found())
1412 config_host_data.set('CONFIG_GBM', gbm.found())
1413 config_host_data.set('CONFIG_GLUSTERFS', glusterfs.found())
1414 if glusterfs.found()
1415   config_host_data.set('CONFIG_GLUSTERFS_XLATOR_OPT', glusterfs.version().version_compare('>=4'))
1416   config_host_data.set('CONFIG_GLUSTERFS_DISCARD', glusterfs.version().version_compare('>=5'))
1417   config_host_data.set('CONFIG_GLUSTERFS_FALLOCATE', glusterfs.version().version_compare('>=6'))
1418   config_host_data.set('CONFIG_GLUSTERFS_ZEROFILL', glusterfs.version().version_compare('>=6'))
1419   config_host_data.set('CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT', glusterfs_ftruncate_has_stat)
1420   config_host_data.set('CONFIG_GLUSTERFS_IOCB_HAS_STAT', glusterfs_iocb_has_stat)
1421 endif
1422 config_host_data.set('CONFIG_GTK', gtk.found())
1423 config_host_data.set('CONFIG_VTE', vte.found())
1424 config_host_data.set('CONFIG_LIBATTR', have_old_libattr)
1425 config_host_data.set('CONFIG_LIBCAP_NG', libcap_ng.found())
1426 config_host_data.set('CONFIG_EBPF', libbpf.found())
1427 config_host_data.set('CONFIG_LIBDAXCTL', libdaxctl.found())
1428 config_host_data.set('CONFIG_LIBISCSI', libiscsi.found())
1429 config_host_data.set('CONFIG_LIBNFS', libnfs.found())
1430 config_host_data.set('CONFIG_LINUX_IO_URING', linux_io_uring.found())
1431 config_host_data.set('CONFIG_LIBPMEM', libpmem.found())
1432 config_host_data.set('CONFIG_RBD', rbd.found())
1433 config_host_data.set('CONFIG_SDL', sdl.found())
1434 config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found())
1435 config_host_data.set('CONFIG_SECCOMP', seccomp.found())
1436 config_host_data.set('CONFIG_SNAPPY', snappy.found())
1437 config_host_data.set('CONFIG_USB_LIBUSB', libusb.found())
1438 config_host_data.set('CONFIG_VHOST_USER_BLK_SERVER', have_vhost_user_blk_server)
1439 config_host_data.set('CONFIG_VNC', vnc.found())
1440 config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
1441 config_host_data.set('CONFIG_VNC_PNG', png.found())
1442 config_host_data.set('CONFIG_VNC_SASL', sasl.found())
1443 config_host_data.set('CONFIG_VIRTFS', have_virtfs)
1444 config_host_data.set('CONFIG_VTE', vte.found())
1445 config_host_data.set('CONFIG_XKBCOMMON', xkbcommon.found())
1446 config_host_data.set('CONFIG_KEYUTILS', keyutils.found())
1447 config_host_data.set('CONFIG_GETTID', has_gettid)
1448 config_host_data.set('CONFIG_GNUTLS', gnutls.found())
1449 config_host_data.set('CONFIG_GNUTLS_CRYPTO', gnutls_crypto.found())
1450 config_host_data.set('CONFIG_GCRYPT', gcrypt.found())
1451 config_host_data.set('CONFIG_NETTLE', nettle.found())
1452 config_host_data.set('CONFIG_QEMU_PRIVATE_XTS', xts == 'private')
1453 config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim)
1454 config_host_data.set('CONFIG_STATX', has_statx)
1455 config_host_data.set('CONFIG_ZSTD', zstd.found())
1456 config_host_data.set('CONFIG_FUSE', fuse.found())
1457 config_host_data.set('CONFIG_FUSE_LSEEK', fuse_lseek.found())
1458 config_host_data.set('CONFIG_X11', x11.found())
1459 config_host_data.set('CONFIG_CFI', get_option('cfi'))
1460 config_host_data.set('QEMU_VERSION', '"@0@"'.format(meson.project_version()))
1461 config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0])
1462 config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1])
1463 config_host_data.set('QEMU_VERSION_MICRO', meson.project_version().split('.')[2])
1464
1465 config_host_data.set_quoted('CONFIG_HOST_DSOSUF', host_dsosuf)
1466 config_host_data.set('HAVE_HOST_BLOCK_DEVICE', have_host_block_device)
1467 config_host_data.set('HOST_WORDS_BIGENDIAN', host_machine.endian() == 'big')
1468
1469 # has_header
1470 config_host_data.set('CONFIG_EPOLL', cc.has_header('sys/epoll.h'))
1471 config_host_data.set('CONFIG_LINUX_MAGIC_H', cc.has_header('linux/magic.h'))
1472 config_host_data.set('CONFIG_VALGRIND_H', cc.has_header('valgrind/valgrind.h'))
1473 config_host_data.set('HAVE_BTRFS_H', cc.has_header('linux/btrfs.h'))
1474 config_host_data.set('HAVE_DRM_H', cc.has_header('libdrm/drm.h'))
1475 config_host_data.set('HAVE_PTY_H', cc.has_header('pty.h'))
1476 config_host_data.set('HAVE_SYS_DISK_H', cc.has_header('sys/disk.h'))
1477 config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h'))
1478 config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h'))
1479
1480 # has_function
1481 config_host_data.set('CONFIG_ACCEPT4', cc.has_function('accept4'))
1482 config_host_data.set('CONFIG_CLOCK_ADJTIME', cc.has_function('clock_adjtime'))
1483 config_host_data.set('CONFIG_DUP3', cc.has_function('dup3'))
1484 config_host_data.set('CONFIG_FALLOCATE', cc.has_function('fallocate'))
1485 config_host_data.set('CONFIG_POSIX_FALLOCATE', cc.has_function('posix_fallocate'))
1486 config_host_data.set('CONFIG_POSIX_MEMALIGN', cc.has_function('posix_memalign'))
1487 config_host_data.set('CONFIG_PPOLL', cc.has_function('ppoll'))
1488 config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include <sys/uio.h>'))
1489 config_host_data.set('CONFIG_SEM_TIMEDWAIT', cc.has_function('sem_timedwait', dependencies: threads))
1490 config_host_data.set('CONFIG_SENDFILE', cc.has_function('sendfile'))
1491 config_host_data.set('CONFIG_SETNS', cc.has_function('setns') and cc.has_function('unshare'))
1492 config_host_data.set('CONFIG_SYNCFS', cc.has_function('syncfs'))
1493 config_host_data.set('CONFIG_SYNC_FILE_RANGE', cc.has_function('sync_file_range'))
1494 config_host_data.set('CONFIG_TIMERFD', cc.has_function('timerfd_create'))
1495 config_host_data.set('HAVE_COPY_FILE_RANGE', cc.has_function('copy_file_range'))
1496 config_host_data.set('HAVE_OPENPTY', cc.has_function('openpty', dependencies: util))
1497 config_host_data.set('HAVE_STRCHRNUL', cc.has_function('strchrnul'))
1498 config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: '#include <stdlib.h>'))
1499
1500 # has_header_symbol
1501 config_host_data.set('CONFIG_BYTESWAP_H',
1502                      cc.has_header_symbol('byteswap.h', 'bswap_32'))
1503 config_host_data.set('CONFIG_EPOLL_CREATE1',
1504                      cc.has_header_symbol('sys/epoll.h', 'epoll_create1'))
1505 config_host_data.set('CONFIG_HAS_ENVIRON',
1506                      cc.has_header_symbol('unistd.h', 'environ', prefix: gnu_source_prefix))
1507 config_host_data.set('CONFIG_FALLOCATE_PUNCH_HOLE',
1508                      cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_PUNCH_HOLE') and
1509                      cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_KEEP_SIZE'))
1510 config_host_data.set('CONFIG_FALLOCATE_ZERO_RANGE',
1511                      cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_ZERO_RANGE'))
1512 config_host_data.set('CONFIG_FIEMAP',
1513                      cc.has_header('linux/fiemap.h') and
1514                      cc.has_header_symbol('linux/fs.h', 'FS_IOC_FIEMAP'))
1515 config_host_data.set('CONFIG_GETRANDOM',
1516                      cc.has_function('getrandom') and
1517                      cc.has_header_symbol('sys/random.h', 'GRND_NONBLOCK'))
1518 config_host_data.set('CONFIG_INOTIFY',
1519                      cc.has_header_symbol('sys/inotify.h', 'inotify_init'))
1520 config_host_data.set('CONFIG_INOTIFY1',
1521                      cc.has_header_symbol('sys/inotify.h', 'inotify_init1'))
1522 config_host_data.set('CONFIG_MACHINE_BSWAP_H',
1523                      cc.has_header_symbol('machine/bswap.h', 'bswap32',
1524                                           prefix: '''#include <sys/endian.h>
1525                                                      #include <sys/types.h>'''))
1526 config_host_data.set('CONFIG_PRCTL_PR_SET_TIMERSLACK',
1527                      cc.has_header_symbol('sys/prctl.h', 'PR_SET_TIMERSLACK'))
1528 config_host_data.set('CONFIG_RTNETLINK',
1529                      cc.has_header_symbol('linux/rtnetlink.h', 'IFLA_PROTO_DOWN'))
1530 config_host_data.set('CONFIG_SYSMACROS',
1531                      cc.has_header_symbol('sys/sysmacros.h', 'makedev'))
1532 config_host_data.set('HAVE_OPTRESET',
1533                      cc.has_header_symbol('getopt.h', 'optreset'))
1534 config_host_data.set('HAVE_UTMPX',
1535                      cc.has_header_symbol('utmpx.h', 'struct utmpx'))
1536 config_host_data.set('HAVE_IPPROTO_MPTCP',
1537                      cc.has_header_symbol('netinet/in.h', 'IPPROTO_MPTCP'))
1538
1539 # has_member
1540 config_host_data.set('HAVE_SIGEV_NOTIFY_THREAD_ID',
1541                      cc.has_member('struct sigevent', 'sigev_notify_thread_id',
1542                                    prefix: '#include <signal.h>'))
1543 config_host_data.set('HAVE_STRUCT_STAT_ST_ATIM',
1544                      cc.has_member('struct stat', 'st_atim',
1545                                    prefix: '#include <sys/stat.h>'))
1546
1547 config_host_data.set('CONFIG_EVENTFD', cc.links('''
1548   #include <sys/eventfd.h>
1549   int main(void) { return eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); }'''))
1550 config_host_data.set('CONFIG_FDATASYNC', cc.links(gnu_source_prefix + '''
1551   #include <unistd.h>
1552   int main(void) {
1553   #if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
1554   return fdatasync(0);
1555   #else
1556   #error Not supported
1557   #endif
1558   }'''))
1559 config_host_data.set('CONFIG_MADVISE', cc.links(gnu_source_prefix + '''
1560   #include <sys/types.h>
1561   #include <sys/mman.h>
1562   #include <stddef.h>
1563   int main(void) { return madvise(NULL, 0, MADV_DONTNEED); }'''))
1564 config_host_data.set('CONFIG_MEMFD', cc.links(gnu_source_prefix + '''
1565   #include <sys/mman.h>
1566   int main(void) { return memfd_create("foo", MFD_ALLOW_SEALING); }'''))
1567 config_host_data.set('CONFIG_OPEN_BY_HANDLE', cc.links(gnu_source_prefix + '''
1568   #include <fcntl.h>
1569   #if !defined(AT_EMPTY_PATH)
1570   # error missing definition
1571   #else
1572   int main(void) { struct file_handle fh; return open_by_handle_at(0, &fh, 0); }
1573   #endif'''))
1574 config_host_data.set('CONFIG_PIPE2', cc.links(gnu_source_prefix + '''
1575   #include <unistd.h>
1576   #include <fcntl.h>
1577
1578   int main(void)
1579   {
1580       int pipefd[2];
1581       return pipe2(pipefd, O_CLOEXEC);
1582   }'''))
1583 config_host_data.set('CONFIG_POSIX_MADVISE', cc.links(gnu_source_prefix + '''
1584   #include <sys/mman.h>
1585   #include <stddef.h>
1586   int main(void) { return posix_madvise(NULL, 0, POSIX_MADV_DONTNEED); }'''))
1587 config_host_data.set('CONFIG_SIGNALFD', cc.links(gnu_source_prefix + '''
1588   #include <sys/signalfd.h>
1589   #include <stddef.h>
1590   int main(void) { return signalfd(-1, NULL, SFD_CLOEXEC); }'''))
1591 config_host_data.set('CONFIG_SPLICE', cc.links(gnu_source_prefix + '''
1592   #include <unistd.h>
1593   #include <fcntl.h>
1594   #include <limits.h>
1595
1596   int main(void)
1597   {
1598     int len, fd = 0;
1599     len = tee(STDIN_FILENO, STDOUT_FILENO, INT_MAX, SPLICE_F_NONBLOCK);
1600     splice(STDIN_FILENO, NULL, fd, NULL, len, SPLICE_F_MOVE);
1601     return 0;
1602   }'''))
1603
1604 config_host_data.set('HAVE_MLOCKALL', cc.links(gnu_source_prefix + '''
1605   #include <sys/mman.h>
1606   int main(int argc, char *argv[]) {
1607     return mlockall(MCL_FUTURE);
1608   }'''))
1609
1610 # Work around a system header bug with some kernel/XFS header
1611 # versions where they both try to define 'struct fsxattr':
1612 # xfs headers will not try to redefine structs from linux headers
1613 # if this macro is set.
1614 config_host_data.set('HAVE_FSXATTR', cc.links('''
1615   #include <linux/fs.h>'
1616   struct fsxattr foo;
1617   int main(void) {
1618     return 0;
1619   }'''))
1620
1621 # Some versions of Mac OS X incorrectly define SIZE_MAX
1622 config_host_data.set('HAVE_BROKEN_SIZE_MAX', not cc.compiles('''
1623     #include <stdint.h>
1624     #include <stdio.h>
1625     int main(int argc, char *argv[]) {
1626         return printf("%zu", SIZE_MAX);
1627     }''', args: ['-Werror']))
1628
1629 ignored = ['CONFIG_QEMU_INTERP_PREFIX', # actually per-target
1630     'HAVE_GDB_BIN']
1631 arrays = ['CONFIG_BDRV_RW_WHITELIST', 'CONFIG_BDRV_RO_WHITELIST']
1632 strings = ['CONFIG_IASL']
1633 foreach k, v: config_host
1634   if ignored.contains(k)
1635     # do nothing
1636   elif arrays.contains(k)
1637     if v != ''
1638       v = '"' + '", "'.join(v.split()) + '", '
1639     endif
1640     config_host_data.set(k, v)
1641   elif k == 'ARCH'
1642     config_host_data.set('HOST_' + v.to_upper(), 1)
1643   elif strings.contains(k)
1644     config_host_data.set_quoted(k, v)
1645   elif k.startswith('CONFIG_')
1646     config_host_data.set(k, v == 'y' ? 1 : v)
1647   endif
1648 endforeach
1649
1650 ########################
1651 # Target configuration #
1652 ########################
1653
1654 minikconf = find_program('scripts/minikconf.py')
1655 config_all = {}
1656 config_all_devices = {}
1657 config_all_disas = {}
1658 config_devices_mak_list = []
1659 config_devices_h = {}
1660 config_target_h = {}
1661 config_target_mak = {}
1662
1663 disassemblers = {
1664   'alpha' : ['CONFIG_ALPHA_DIS'],
1665   'arm' : ['CONFIG_ARM_DIS'],
1666   'avr' : ['CONFIG_AVR_DIS'],
1667   'cris' : ['CONFIG_CRIS_DIS'],
1668   'hexagon' : ['CONFIG_HEXAGON_DIS'],
1669   'hppa' : ['CONFIG_HPPA_DIS'],
1670   'i386' : ['CONFIG_I386_DIS'],
1671   'x86_64' : ['CONFIG_I386_DIS'],
1672   'x32' : ['CONFIG_I386_DIS'],
1673   'm68k' : ['CONFIG_M68K_DIS'],
1674   'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
1675   'mips' : ['CONFIG_MIPS_DIS'],
1676   'nios2' : ['CONFIG_NIOS2_DIS'],
1677   'or1k' : ['CONFIG_OPENRISC_DIS'],
1678   'ppc' : ['CONFIG_PPC_DIS'],
1679   'riscv' : ['CONFIG_RISCV_DIS'],
1680   'rx' : ['CONFIG_RX_DIS'],
1681   's390' : ['CONFIG_S390_DIS'],
1682   'sh4' : ['CONFIG_SH4_DIS'],
1683   'sparc' : ['CONFIG_SPARC_DIS'],
1684   'xtensa' : ['CONFIG_XTENSA_DIS'],
1685 }
1686 if link_language == 'cpp'
1687   disassemblers += {
1688     'aarch64' : [ 'CONFIG_ARM_A64_DIS'],
1689     'arm' : [ 'CONFIG_ARM_DIS', 'CONFIG_ARM_A64_DIS'],
1690     'mips' : [ 'CONFIG_MIPS_DIS', 'CONFIG_NANOMIPS_DIS'],
1691   }
1692 endif
1693
1694 have_ivshmem = config_host_data.get('CONFIG_EVENTFD')
1695 host_kconfig = \
1696   (get_option('fuzzing') ? ['CONFIG_FUZZ=y'] : []) + \
1697   ('CONFIG_TPM' in config_host ? ['CONFIG_TPM=y'] : []) + \
1698   ('CONFIG_SPICE' in config_host ? ['CONFIG_SPICE=y'] : []) + \
1699   (have_ivshmem ? ['CONFIG_IVSHMEM=y'] : []) + \
1700   ('CONFIG_OPENGL' in config_host ? ['CONFIG_OPENGL=y'] : []) + \
1701   (x11.found() ? ['CONFIG_X11=y'] : []) + \
1702   ('CONFIG_VHOST_USER' in config_host ? ['CONFIG_VHOST_USER=y'] : []) + \
1703   ('CONFIG_VHOST_VDPA' in config_host ? ['CONFIG_VHOST_VDPA=y'] : []) + \
1704   ('CONFIG_VHOST_KERNEL' in config_host ? ['CONFIG_VHOST_KERNEL=y'] : []) + \
1705   (have_virtfs ? ['CONFIG_VIRTFS=y'] : []) + \
1706   ('CONFIG_LINUX' in config_host ? ['CONFIG_LINUX=y'] : []) + \
1707   ('CONFIG_PVRDMA' in config_host ? ['CONFIG_PVRDMA=y'] : []) + \
1708   (multiprocess_allowed ? ['CONFIG_MULTIPROCESS_ALLOWED=y'] : [])
1709
1710 ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ]
1711
1712 default_targets = 'CONFIG_DEFAULT_TARGETS' in config_host
1713 actual_target_dirs = []
1714 fdt_required = []
1715 foreach target : target_dirs
1716   config_target = { 'TARGET_NAME': target.split('-')[0] }
1717   if target.endswith('linux-user')
1718     if targetos != 'linux'
1719       if default_targets
1720         continue
1721       endif
1722       error('Target @0@ is only available on a Linux host'.format(target))
1723     endif
1724     config_target += { 'CONFIG_LINUX_USER': 'y' }
1725   elif target.endswith('bsd-user')
1726     if 'CONFIG_BSD' not in config_host
1727       if default_targets
1728         continue
1729       endif
1730       error('Target @0@ is only available on a BSD host'.format(target))
1731     endif
1732     config_target += { 'CONFIG_BSD_USER': 'y' }
1733   elif target.endswith('softmmu')
1734     config_target += { 'CONFIG_SOFTMMU': 'y' }
1735   endif
1736   if target.endswith('-user')
1737     config_target += {
1738       'CONFIG_USER_ONLY': 'y',
1739       'CONFIG_QEMU_INTERP_PREFIX':
1740         config_host['CONFIG_QEMU_INTERP_PREFIX'].format(config_target['TARGET_NAME'])
1741     }
1742   endif
1743
1744   accel_kconfig = []
1745   foreach sym: accelerators
1746     if sym == 'CONFIG_TCG' or target in accelerator_targets.get(sym, [])
1747       config_target += { sym: 'y' }
1748       config_all += { sym: 'y' }
1749       if sym == 'CONFIG_TCG' and tcg_arch == 'tci'
1750         config_target += { 'CONFIG_TCG_INTERPRETER': 'y' }
1751       elif sym == 'CONFIG_XEN' and have_xen_pci_passthrough
1752         config_target += { 'CONFIG_XEN_PCI_PASSTHROUGH': 'y' }
1753       endif
1754       if target in modular_tcg
1755         config_target += { 'CONFIG_TCG_MODULAR': 'y' }
1756       else
1757         config_target += { 'CONFIG_TCG_BUILTIN': 'y' }
1758       endif
1759       accel_kconfig += [ sym + '=y' ]
1760     endif
1761   endforeach
1762   if accel_kconfig.length() == 0
1763     if default_targets
1764       continue
1765     endif
1766     error('No accelerator available for target @0@'.format(target))
1767   endif
1768
1769   actual_target_dirs += target
1770   config_target += keyval.load('configs/targets' / target + '.mak')
1771   config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
1772
1773   if 'TARGET_NEED_FDT' in config_target
1774     fdt_required += target
1775   endif
1776
1777   # Add default keys
1778   if 'TARGET_BASE_ARCH' not in config_target
1779     config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
1780   endif
1781   if 'TARGET_ABI_DIR' not in config_target
1782     config_target += {'TARGET_ABI_DIR': config_target['TARGET_ARCH']}
1783   endif
1784
1785   foreach k, v: disassemblers
1786     if config_host['ARCH'].startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k)
1787       foreach sym: v
1788         config_target += { sym: 'y' }
1789         config_all_disas += { sym: 'y' }
1790       endforeach
1791     endif
1792   endforeach
1793
1794   config_target_data = configuration_data()
1795   foreach k, v: config_target
1796     if not k.startswith('TARGET_') and not k.startswith('CONFIG_')
1797       # do nothing
1798     elif ignored.contains(k)
1799       # do nothing
1800     elif k == 'TARGET_BASE_ARCH'
1801       # Note that TARGET_BASE_ARCH ends up in config-target.h but it is
1802       # not used to select files from sourcesets.
1803       config_target_data.set('TARGET_' + v.to_upper(), 1)
1804     elif k == 'TARGET_NAME' or k == 'CONFIG_QEMU_INTERP_PREFIX'
1805       config_target_data.set_quoted(k, v)
1806     elif v == 'y'
1807       config_target_data.set(k, 1)
1808     else
1809       config_target_data.set(k, v)
1810     endif
1811   endforeach
1812   config_target_data.set('QEMU_ARCH',
1813                          'QEMU_ARCH_' + config_target['TARGET_BASE_ARCH'].to_upper())
1814   config_target_h += {target: configure_file(output: target + '-config-target.h',
1815                                                configuration: config_target_data)}
1816
1817   if target.endswith('-softmmu')
1818     config_input = meson.get_external_property(target, 'default')
1819     config_devices_mak = target + '-config-devices.mak'
1820     config_devices_mak = configure_file(
1821       input: ['configs/devices' / target / config_input + '.mak', 'Kconfig'],
1822       output: config_devices_mak,
1823       depfile: config_devices_mak + '.d',
1824       capture: true,
1825       command: [minikconf,
1826                 get_option('default_devices') ? '--defconfig' : '--allnoconfig',
1827                 config_devices_mak, '@DEPFILE@', '@INPUT@',
1828                 host_kconfig, accel_kconfig,
1829                 'CONFIG_' + config_target['TARGET_ARCH'].to_upper() + '=y'])
1830
1831     config_devices_data = configuration_data()
1832     config_devices = keyval.load(config_devices_mak)
1833     foreach k, v: config_devices
1834       config_devices_data.set(k, 1)
1835     endforeach
1836     config_devices_mak_list += config_devices_mak
1837     config_devices_h += {target: configure_file(output: target + '-config-devices.h',
1838                                                 configuration: config_devices_data)}
1839     config_target += config_devices
1840     config_all_devices += config_devices
1841   endif
1842   config_target_mak += {target: config_target}
1843 endforeach
1844 target_dirs = actual_target_dirs
1845
1846 # This configuration is used to build files that are shared by
1847 # multiple binaries, and then extracted out of the "common"
1848 # static_library target.
1849 #
1850 # We do not use all_sources()/all_dependencies(), because it would
1851 # build literally all source files, including devices only used by
1852 # targets that are not built for this compilation.  The CONFIG_ALL
1853 # pseudo symbol replaces it.
1854
1855 config_all += config_all_devices
1856 config_all += config_host
1857 config_all += config_all_disas
1858 config_all += {
1859   'CONFIG_XEN': config_host.has_key('CONFIG_XEN_BACKEND'),
1860   'CONFIG_SOFTMMU': have_system,
1861   'CONFIG_USER_ONLY': have_user,
1862   'CONFIG_ALL': true,
1863 }
1864
1865 ##############
1866 # Submodules #
1867 ##############
1868
1869 capstone = not_found
1870 capstone_opt = get_option('capstone')
1871 if capstone_opt in ['enabled', 'auto', 'system']
1872   have_internal = fs.exists(meson.current_source_dir() / 'capstone/Makefile')
1873   capstone = dependency('capstone', version: '>=4.0',
1874                         kwargs: static_kwargs, method: 'pkg-config',
1875                         required: capstone_opt == 'system' or
1876                                   capstone_opt == 'enabled' and not have_internal)
1877
1878   # Some versions of capstone have broken pkg-config file
1879   # that reports a wrong -I path, causing the #include to
1880   # fail later. If the system has such a broken version
1881   # do not use it.
1882   if capstone.found() and not cc.compiles('#include <capstone.h>',
1883                                           dependencies: [capstone])
1884     capstone = not_found
1885     if capstone_opt == 'system'
1886       error('system capstone requested, it does not appear to work')
1887     endif
1888   endif
1889
1890   if capstone.found()
1891     capstone_opt = 'system'
1892   elif have_internal
1893     capstone_opt = 'internal'
1894   else
1895     capstone_opt = 'disabled'
1896   endif
1897 endif
1898 if capstone_opt == 'internal'
1899   capstone_data = configuration_data()
1900   capstone_data.set('CAPSTONE_USE_SYS_DYN_MEM', '1')
1901
1902   capstone_files = files(
1903     'capstone/cs.c',
1904     'capstone/MCInst.c',
1905     'capstone/MCInstrDesc.c',
1906     'capstone/MCRegisterInfo.c',
1907     'capstone/SStream.c',
1908     'capstone/utils.c'
1909   )
1910
1911   if 'CONFIG_ARM_DIS' in config_all_disas
1912     capstone_data.set('CAPSTONE_HAS_ARM', '1')
1913     capstone_files += files(
1914       'capstone/arch/ARM/ARMDisassembler.c',
1915       'capstone/arch/ARM/ARMInstPrinter.c',
1916       'capstone/arch/ARM/ARMMapping.c',
1917       'capstone/arch/ARM/ARMModule.c'
1918     )
1919   endif
1920
1921   # FIXME: This config entry currently depends on a c++ compiler.
1922   # Which is needed for building libvixl, but not for capstone.
1923   if 'CONFIG_ARM_A64_DIS' in config_all_disas
1924     capstone_data.set('CAPSTONE_HAS_ARM64', '1')
1925     capstone_files += files(
1926       'capstone/arch/AArch64/AArch64BaseInfo.c',
1927       'capstone/arch/AArch64/AArch64Disassembler.c',
1928       'capstone/arch/AArch64/AArch64InstPrinter.c',
1929       'capstone/arch/AArch64/AArch64Mapping.c',
1930       'capstone/arch/AArch64/AArch64Module.c'
1931     )
1932   endif
1933
1934   if 'CONFIG_PPC_DIS' in config_all_disas
1935     capstone_data.set('CAPSTONE_HAS_POWERPC', '1')
1936     capstone_files += files(
1937       'capstone/arch/PowerPC/PPCDisassembler.c',
1938       'capstone/arch/PowerPC/PPCInstPrinter.c',
1939       'capstone/arch/PowerPC/PPCMapping.c',
1940       'capstone/arch/PowerPC/PPCModule.c'
1941     )
1942   endif
1943
1944   if 'CONFIG_S390_DIS' in config_all_disas
1945     capstone_data.set('CAPSTONE_HAS_SYSZ', '1')
1946     capstone_files += files(
1947       'capstone/arch/SystemZ/SystemZDisassembler.c',
1948       'capstone/arch/SystemZ/SystemZInstPrinter.c',
1949       'capstone/arch/SystemZ/SystemZMapping.c',
1950       'capstone/arch/SystemZ/SystemZModule.c',
1951       'capstone/arch/SystemZ/SystemZMCTargetDesc.c'
1952     )
1953   endif
1954
1955   if 'CONFIG_I386_DIS' in config_all_disas
1956     capstone_data.set('CAPSTONE_HAS_X86', 1)
1957     capstone_files += files(
1958       'capstone/arch/X86/X86Disassembler.c',
1959       'capstone/arch/X86/X86DisassemblerDecoder.c',
1960       'capstone/arch/X86/X86ATTInstPrinter.c',
1961       'capstone/arch/X86/X86IntelInstPrinter.c',
1962       'capstone/arch/X86/X86InstPrinterCommon.c',
1963       'capstone/arch/X86/X86Mapping.c',
1964       'capstone/arch/X86/X86Module.c'
1965     )
1966   endif
1967
1968   configure_file(output: 'capstone-defs.h', configuration: capstone_data)
1969
1970   capstone_cargs = [
1971     # FIXME: There does not seem to be a way to completely replace the c_args
1972     # that come from add_project_arguments() -- we can only add to them.
1973     # So: disable all warnings with a big hammer.
1974     '-Wno-error', '-w',
1975
1976     # Include all configuration defines via a header file, which will wind up
1977     # as a dependency on the object file, and thus changes here will result
1978     # in a rebuild.
1979     '-include', 'capstone-defs.h'
1980   ]
1981
1982   libcapstone = static_library('capstone',
1983                                build_by_default: false,
1984                                sources: capstone_files,
1985                                c_args: capstone_cargs,
1986                                include_directories: 'capstone/include')
1987   capstone = declare_dependency(link_with: libcapstone,
1988                                 include_directories: 'capstone/include/capstone')
1989 endif
1990
1991 slirp = not_found
1992 slirp_opt = 'disabled'
1993 if have_system
1994   slirp_opt = get_option('slirp')
1995   if slirp_opt in ['enabled', 'auto', 'system']
1996     have_internal = fs.exists(meson.current_source_dir() / 'slirp/meson.build')
1997     slirp = dependency('slirp', kwargs: static_kwargs,
1998                        method: 'pkg-config',
1999                        required: slirp_opt == 'system' or
2000                                  slirp_opt == 'enabled' and not have_internal)
2001     if slirp.found()
2002       slirp_opt = 'system'
2003     elif have_internal
2004       slirp_opt = 'internal'
2005     else
2006       slirp_opt = 'disabled'
2007     endif
2008   endif
2009   if slirp_opt == 'internal'
2010     slirp_deps = []
2011     if targetos == 'windows'
2012       slirp_deps = cc.find_library('iphlpapi')
2013     elif targetos == 'darwin'
2014       slirp_deps = cc.find_library('resolv')
2015     endif
2016     slirp_conf = configuration_data()
2017     slirp_conf.set('SLIRP_MAJOR_VERSION', meson.project_version().split('.')[0])
2018     slirp_conf.set('SLIRP_MINOR_VERSION', meson.project_version().split('.')[1])
2019     slirp_conf.set('SLIRP_MICRO_VERSION', meson.project_version().split('.')[2])
2020     slirp_conf.set_quoted('SLIRP_VERSION_STRING', meson.project_version())
2021     slirp_cargs = ['-DG_LOG_DOMAIN="Slirp"']
2022     slirp_files = [
2023       'slirp/src/arp_table.c',
2024       'slirp/src/bootp.c',
2025       'slirp/src/cksum.c',
2026       'slirp/src/dhcpv6.c',
2027       'slirp/src/dnssearch.c',
2028       'slirp/src/if.c',
2029       'slirp/src/ip6_icmp.c',
2030       'slirp/src/ip6_input.c',
2031       'slirp/src/ip6_output.c',
2032       'slirp/src/ip_icmp.c',
2033       'slirp/src/ip_input.c',
2034       'slirp/src/ip_output.c',
2035       'slirp/src/mbuf.c',
2036       'slirp/src/misc.c',
2037       'slirp/src/ncsi.c',
2038       'slirp/src/ndp_table.c',
2039       'slirp/src/sbuf.c',
2040       'slirp/src/slirp.c',
2041       'slirp/src/socket.c',
2042       'slirp/src/state.c',
2043       'slirp/src/stream.c',
2044       'slirp/src/tcp_input.c',
2045       'slirp/src/tcp_output.c',
2046       'slirp/src/tcp_subr.c',
2047       'slirp/src/tcp_timer.c',
2048       'slirp/src/tftp.c',
2049       'slirp/src/udp.c',
2050       'slirp/src/udp6.c',
2051       'slirp/src/util.c',
2052       'slirp/src/version.c',
2053       'slirp/src/vmstate.c',
2054     ]
2055
2056     configure_file(
2057       input : 'slirp/src/libslirp-version.h.in',
2058       output : 'libslirp-version.h',
2059       configuration: slirp_conf)
2060
2061     slirp_inc = include_directories('slirp', 'slirp/src')
2062     libslirp = static_library('slirp',
2063                               build_by_default: false,
2064                               sources: slirp_files,
2065                               c_args: slirp_cargs,
2066                               include_directories: slirp_inc)
2067     slirp = declare_dependency(link_with: libslirp,
2068                                dependencies: slirp_deps,
2069                                include_directories: slirp_inc)
2070   endif
2071 endif
2072
2073 # For CFI, we need to compile slirp as a static library together with qemu.
2074 # This is because we register slirp functions as callbacks for QEMU Timers.
2075 # When using a system-wide shared libslirp, the type information for the
2076 # callback is missing and the timer call produces a false positive with CFI.
2077 #
2078 # Now that slirp_opt has been defined, check if the selected slirp is compatible
2079 # with control-flow integrity.
2080 if get_option('cfi') and slirp_opt == 'system'
2081   error('Control-Flow Integrity is not compatible with system-wide slirp.' \
2082          + ' Please configure with --enable-slirp=git')
2083 endif
2084
2085 fdt = not_found
2086 fdt_opt = get_option('fdt')
2087 if have_system
2088   if fdt_opt in ['enabled', 'auto', 'system']
2089     have_internal = fs.exists(meson.current_source_dir() / 'dtc/libfdt/Makefile.libfdt')
2090     fdt = cc.find_library('fdt', kwargs: static_kwargs,
2091                           required: fdt_opt == 'system' or
2092                                     fdt_opt == 'enabled' and not have_internal)
2093     if fdt.found() and cc.links('''
2094        #include <libfdt.h>
2095        #include <libfdt_env.h>
2096        int main(void) { fdt_check_full(NULL, 0); return 0; }''',
2097          dependencies: fdt)
2098       fdt_opt = 'system'
2099     elif fdt_opt == 'system'
2100        error('system libfdt requested, but it is too old (1.5.1 or newer required)')
2101     elif have_internal
2102       fdt_opt = 'internal'
2103     else
2104       fdt_opt = 'disabled'
2105       fdt = not_found
2106     endif
2107   endif
2108   if fdt_opt == 'internal'
2109     fdt_files = files(
2110       'dtc/libfdt/fdt.c',
2111       'dtc/libfdt/fdt_ro.c',
2112       'dtc/libfdt/fdt_wip.c',
2113       'dtc/libfdt/fdt_sw.c',
2114       'dtc/libfdt/fdt_rw.c',
2115       'dtc/libfdt/fdt_strerror.c',
2116       'dtc/libfdt/fdt_empty_tree.c',
2117       'dtc/libfdt/fdt_addresses.c',
2118       'dtc/libfdt/fdt_overlay.c',
2119       'dtc/libfdt/fdt_check.c',
2120     )
2121
2122     fdt_inc = include_directories('dtc/libfdt')
2123     libfdt = static_library('fdt',
2124                             build_by_default: false,
2125                             sources: fdt_files,
2126                             include_directories: fdt_inc)
2127     fdt = declare_dependency(link_with: libfdt,
2128                              include_directories: fdt_inc)
2129   endif
2130 endif
2131 if not fdt.found() and fdt_required.length() > 0
2132   error('fdt not available but required by targets ' + ', '.join(fdt_required))
2133 endif
2134
2135 config_host_data.set('CONFIG_CAPSTONE', capstone.found())
2136 config_host_data.set('CONFIG_FDT', fdt.found())
2137 config_host_data.set('CONFIG_SLIRP', slirp.found())
2138
2139 #####################
2140 # Generated sources #
2141 #####################
2142
2143 genh += configure_file(output: 'config-host.h', configuration: config_host_data)
2144
2145 hxtool = find_program('scripts/hxtool')
2146 shaderinclude = find_program('scripts/shaderinclude.pl')
2147 qapi_gen = find_program('scripts/qapi-gen.py')
2148 qapi_gen_depends = [ meson.current_source_dir() / 'scripts/qapi/__init__.py',
2149                      meson.current_source_dir() / 'scripts/qapi/commands.py',
2150                      meson.current_source_dir() / 'scripts/qapi/common.py',
2151                      meson.current_source_dir() / 'scripts/qapi/error.py',
2152                      meson.current_source_dir() / 'scripts/qapi/events.py',
2153                      meson.current_source_dir() / 'scripts/qapi/expr.py',
2154                      meson.current_source_dir() / 'scripts/qapi/gen.py',
2155                      meson.current_source_dir() / 'scripts/qapi/introspect.py',
2156                      meson.current_source_dir() / 'scripts/qapi/parser.py',
2157                      meson.current_source_dir() / 'scripts/qapi/schema.py',
2158                      meson.current_source_dir() / 'scripts/qapi/source.py',
2159                      meson.current_source_dir() / 'scripts/qapi/types.py',
2160                      meson.current_source_dir() / 'scripts/qapi/visit.py',
2161                      meson.current_source_dir() / 'scripts/qapi/common.py',
2162                      meson.current_source_dir() / 'scripts/qapi-gen.py'
2163 ]
2164
2165 tracetool = [
2166   python, files('scripts/tracetool.py'),
2167    '--backend=' + ','.join(get_option('trace_backends'))
2168 ]
2169 tracetool_depends = files(
2170   'scripts/tracetool/backend/log.py',
2171   'scripts/tracetool/backend/__init__.py',
2172   'scripts/tracetool/backend/dtrace.py',
2173   'scripts/tracetool/backend/ftrace.py',
2174   'scripts/tracetool/backend/simple.py',
2175   'scripts/tracetool/backend/syslog.py',
2176   'scripts/tracetool/backend/ust.py',
2177   'scripts/tracetool/format/tcg_h.py',
2178   'scripts/tracetool/format/ust_events_c.py',
2179   'scripts/tracetool/format/ust_events_h.py',
2180   'scripts/tracetool/format/__init__.py',
2181   'scripts/tracetool/format/d.py',
2182   'scripts/tracetool/format/tcg_helper_c.py',
2183   'scripts/tracetool/format/simpletrace_stap.py',
2184   'scripts/tracetool/format/c.py',
2185   'scripts/tracetool/format/h.py',
2186   'scripts/tracetool/format/tcg_helper_h.py',
2187   'scripts/tracetool/format/log_stap.py',
2188   'scripts/tracetool/format/stap.py',
2189   'scripts/tracetool/format/tcg_helper_wrapper_h.py',
2190   'scripts/tracetool/__init__.py',
2191   'scripts/tracetool/transform.py',
2192   'scripts/tracetool/vcpu.py'
2193 )
2194
2195 qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
2196                     meson.current_source_dir(),
2197                     config_host['PKGVERSION'], meson.project_version()]
2198 qemu_version = custom_target('qemu-version.h',
2199                              output: 'qemu-version.h',
2200                              command: qemu_version_cmd,
2201                              capture: true,
2202                              build_by_default: true,
2203                              build_always_stale: true)
2204 genh += qemu_version
2205
2206 hxdep = []
2207 hx_headers = [
2208   ['qemu-options.hx', 'qemu-options.def'],
2209   ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
2210 ]
2211 if have_system
2212   hx_headers += [
2213     ['hmp-commands.hx', 'hmp-commands.h'],
2214     ['hmp-commands-info.hx', 'hmp-commands-info.h'],
2215   ]
2216 endif
2217 foreach d : hx_headers
2218   hxdep += custom_target(d[1],
2219                 input: files(d[0]),
2220                 output: d[1],
2221                 capture: true,
2222                 build_by_default: true, # to be removed when added to a target
2223                 command: [hxtool, '-h', '@INPUT0@'])
2224 endforeach
2225 genh += hxdep
2226
2227 ###################
2228 # Collect sources #
2229 ###################
2230
2231 authz_ss = ss.source_set()
2232 blockdev_ss = ss.source_set()
2233 block_ss = ss.source_set()
2234 bsd_user_ss = ss.source_set()
2235 chardev_ss = ss.source_set()
2236 common_ss = ss.source_set()
2237 crypto_ss = ss.source_set()
2238 io_ss = ss.source_set()
2239 linux_user_ss = ss.source_set()
2240 qmp_ss = ss.source_set()
2241 qom_ss = ss.source_set()
2242 softmmu_ss = ss.source_set()
2243 specific_fuzz_ss = ss.source_set()
2244 specific_ss = ss.source_set()
2245 stub_ss = ss.source_set()
2246 trace_ss = ss.source_set()
2247 user_ss = ss.source_set()
2248 util_ss = ss.source_set()
2249
2250 # accel modules
2251 qtest_module_ss = ss.source_set()
2252 tcg_module_ss = ss.source_set()
2253
2254 modules = {}
2255 target_modules = {}
2256 hw_arch = {}
2257 target_arch = {}
2258 target_softmmu_arch = {}
2259 target_user_arch = {}
2260
2261 ###############
2262 # Trace files #
2263 ###############
2264
2265 # TODO: add each directory to the subdirs from its own meson.build, once
2266 # we have those
2267 trace_events_subdirs = [
2268   'crypto',
2269   'qapi',
2270   'qom',
2271   'monitor',
2272   'util',
2273 ]
2274 if have_user
2275   trace_events_subdirs += [ 'linux-user' ]
2276 endif
2277 if have_block
2278   trace_events_subdirs += [
2279     'authz',
2280     'block',
2281     'io',
2282     'nbd',
2283     'scsi',
2284   ]
2285 endif
2286 if have_system
2287   trace_events_subdirs += [
2288     'accel/kvm',
2289     'audio',
2290     'backends',
2291     'backends/tpm',
2292     'chardev',
2293     'ebpf',
2294     'hw/9pfs',
2295     'hw/acpi',
2296     'hw/adc',
2297     'hw/alpha',
2298     'hw/arm',
2299     'hw/audio',
2300     'hw/block',
2301     'hw/block/dataplane',
2302     'hw/char',
2303     'hw/display',
2304     'hw/dma',
2305     'hw/hppa',
2306     'hw/hyperv',
2307     'hw/i2c',
2308     'hw/i386',
2309     'hw/i386/xen',
2310     'hw/ide',
2311     'hw/input',
2312     'hw/intc',
2313     'hw/isa',
2314     'hw/mem',
2315     'hw/mips',
2316     'hw/misc',
2317     'hw/misc/macio',
2318     'hw/net',
2319     'hw/net/can',
2320     'hw/nubus',
2321     'hw/nvme',
2322     'hw/nvram',
2323     'hw/pci',
2324     'hw/pci-host',
2325     'hw/ppc',
2326     'hw/rdma',
2327     'hw/rdma/vmw',
2328     'hw/rtc',
2329     'hw/s390x',
2330     'hw/scsi',
2331     'hw/sd',
2332     'hw/sparc',
2333     'hw/sparc64',
2334     'hw/ssi',
2335     'hw/timer',
2336     'hw/tpm',
2337     'hw/usb',
2338     'hw/vfio',
2339     'hw/virtio',
2340     'hw/watchdog',
2341     'hw/xen',
2342     'hw/gpio',
2343     'migration',
2344     'net',
2345     'softmmu',
2346     'ui',
2347     'hw/remote',
2348   ]
2349 endif
2350 if have_system or have_user
2351   trace_events_subdirs += [
2352     'accel/tcg',
2353     'hw/core',
2354     'target/arm',
2355     'target/arm/hvf',
2356     'target/hppa',
2357     'target/i386',
2358     'target/i386/kvm',
2359     'target/mips/tcg',
2360     'target/ppc',
2361     'target/riscv',
2362     'target/s390x',
2363     'target/s390x/kvm',
2364     'target/sparc',
2365   ]
2366 endif
2367
2368 vhost_user = not_found
2369 if 'CONFIG_VHOST_USER' in config_host
2370   libvhost_user = subproject('libvhost-user')
2371   vhost_user = libvhost_user.get_variable('vhost_user_dep')
2372 endif
2373
2374 subdir('qapi')
2375 subdir('qobject')
2376 subdir('stubs')
2377 subdir('trace')
2378 subdir('util')
2379 subdir('qom')
2380 subdir('authz')
2381 subdir('crypto')
2382 subdir('ui')
2383
2384
2385 if enable_modules
2386   libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
2387   modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
2388 endif
2389
2390 stub_ss = stub_ss.apply(config_all, strict: false)
2391
2392 util_ss.add_all(trace_ss)
2393 util_ss = util_ss.apply(config_all, strict: false)
2394 libqemuutil = static_library('qemuutil',
2395                              sources: util_ss.sources() + stub_ss.sources() + genh,
2396                              dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc, pixman])
2397 qemuutil = declare_dependency(link_with: libqemuutil,
2398                               sources: genh + version_res)
2399
2400 if have_system or have_user
2401   decodetree = generator(find_program('scripts/decodetree.py'),
2402                          output: 'decode-@BASENAME@.c.inc',
2403                          arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
2404   subdir('libdecnumber')
2405   subdir('target')
2406 endif
2407
2408 subdir('audio')
2409 subdir('io')
2410 subdir('chardev')
2411 subdir('fsdev')
2412 subdir('dump')
2413
2414 if have_block
2415   block_ss.add(files(
2416     'block.c',
2417     'blockjob.c',
2418     'job.c',
2419     'qemu-io-cmds.c',
2420   ))
2421   block_ss.add(when: 'CONFIG_REPLICATION', if_true: files('replication.c'))
2422
2423   subdir('nbd')
2424   subdir('scsi')
2425   subdir('block')
2426
2427   blockdev_ss.add(files(
2428     'blockdev.c',
2429     'blockdev-nbd.c',
2430     'iothread.c',
2431     'job-qmp.c',
2432   ), gnutls)
2433
2434   # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
2435   # os-win32.c does not
2436   blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
2437   softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
2438 endif
2439
2440 common_ss.add(files('cpus-common.c'))
2441
2442 subdir('softmmu')
2443
2444 common_ss.add(capstone)
2445 specific_ss.add(files('cpu.c', 'disas.c', 'gdbstub.c'), capstone)
2446
2447 # Work around a gcc bug/misfeature wherein constant propagation looks
2448 # through an alias:
2449 #   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99696
2450 # to guess that a const variable is always zero.  Without lto, this is
2451 # impossible, as the alias is restricted to page-vary-common.c.  Indeed,
2452 # without lto, not even the alias is required -- we simply use different
2453 # declarations in different compilation units.
2454 pagevary = files('page-vary-common.c')
2455 if get_option('b_lto')
2456   pagevary_flags = ['-fno-lto']
2457   if get_option('cfi')
2458     pagevary_flags += '-fno-sanitize=cfi-icall'
2459   endif
2460   pagevary = static_library('page-vary-common', sources: pagevary,
2461                             c_args: pagevary_flags)
2462   pagevary = declare_dependency(link_with: pagevary)
2463 endif
2464 common_ss.add(pagevary)
2465 specific_ss.add(files('page-vary.c'))
2466
2467 subdir('backends')
2468 subdir('disas')
2469 subdir('migration')
2470 subdir('monitor')
2471 subdir('net')
2472 subdir('replay')
2473 subdir('semihosting')
2474 subdir('hw')
2475 subdir('tcg')
2476 subdir('fpu')
2477 subdir('accel')
2478 subdir('plugins')
2479 subdir('bsd-user')
2480 subdir('linux-user')
2481 subdir('ebpf')
2482
2483 bsd_user_ss.add(files('gdbstub.c'))
2484 specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss)
2485
2486 linux_user_ss.add(files('gdbstub.c', 'thunk.c'))
2487 specific_ss.add_all(when: 'CONFIG_LINUX_USER', if_true: linux_user_ss)
2488
2489 # needed for fuzzing binaries
2490 subdir('tests/qtest/libqos')
2491 subdir('tests/qtest/fuzz')
2492
2493 # accel modules
2494 tcg_real_module_ss = ss.source_set()
2495 tcg_real_module_ss.add_all(when: 'CONFIG_TCG_MODULAR', if_true: tcg_module_ss)
2496 specific_ss.add_all(when: 'CONFIG_TCG_BUILTIN', if_true: tcg_module_ss)
2497 target_modules += { 'accel' : { 'qtest': qtest_module_ss,
2498                                 'tcg': tcg_real_module_ss }}
2499
2500 ########################
2501 # Library dependencies #
2502 ########################
2503
2504 modinfo_collect = find_program('scripts/modinfo-collect.py')
2505 modinfo_generate = find_program('scripts/modinfo-generate.py')
2506 modinfo_files = []
2507
2508 block_mods = []
2509 softmmu_mods = []
2510 foreach d, list : modules
2511   foreach m, module_ss : list
2512     if enable_modules and targetos != 'windows'
2513       module_ss = module_ss.apply(config_all, strict: false)
2514       sl = static_library(d + '-' + m, [genh, module_ss.sources()],
2515                           dependencies: [modulecommon, module_ss.dependencies()], pic: true)
2516       if d == 'block'
2517         block_mods += sl
2518       else
2519         softmmu_mods += sl
2520       endif
2521       if module_ss.sources() != []
2522         # FIXME: Should use sl.extract_all_objects(recursive: true) as
2523         # input. Sources can be used multiple times but objects are
2524         # unique when it comes to lookup in compile_commands.json.
2525         # Depnds on a mesion version with
2526         # https://github.com/mesonbuild/meson/pull/8900
2527         modinfo_files += custom_target(d + '-' + m + '.modinfo',
2528                                        output: d + '-' + m + '.modinfo',
2529                                        input: module_ss.sources() + genh,
2530                                        capture: true,
2531                                        command: [modinfo_collect, module_ss.sources()])
2532       endif
2533     else
2534       if d == 'block'
2535         block_ss.add_all(module_ss)
2536       else
2537         softmmu_ss.add_all(module_ss)
2538       endif
2539     endif
2540   endforeach
2541 endforeach
2542
2543 foreach d, list : target_modules
2544   foreach m, module_ss : list
2545     if enable_modules and targetos != 'windows'
2546       foreach target : target_dirs
2547         if target.endswith('-softmmu')
2548           config_target = config_target_mak[target]
2549           config_target += config_host
2550           target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
2551           c_args = ['-DNEED_CPU_H',
2552                     '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
2553                     '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
2554           target_module_ss = module_ss.apply(config_target, strict: false)
2555           if target_module_ss.sources() != []
2556             module_name = d + '-' + m + '-' + config_target['TARGET_NAME']
2557             sl = static_library(module_name,
2558                                 [genh, target_module_ss.sources()],
2559                                 dependencies: [modulecommon, target_module_ss.dependencies()],
2560                                 include_directories: target_inc,
2561                                 c_args: c_args,
2562                                 pic: true)
2563             softmmu_mods += sl
2564             # FIXME: Should use sl.extract_all_objects(recursive: true) too.
2565             modinfo_files += custom_target(module_name + '.modinfo',
2566                                            output: module_name + '.modinfo',
2567                                            input: target_module_ss.sources() + genh,
2568                                            capture: true,
2569                                            command: [modinfo_collect, '--target', target, target_module_ss.sources()])
2570           endif
2571         endif
2572       endforeach
2573     else
2574       specific_ss.add_all(module_ss)
2575     endif
2576   endforeach
2577 endforeach
2578
2579 if enable_modules
2580   modinfo_src = custom_target('modinfo.c',
2581                               output: 'modinfo.c',
2582                               input: modinfo_files,
2583                               command: [modinfo_generate, '@INPUT@'],
2584                               capture: true)
2585   modinfo_lib = static_library('modinfo', modinfo_src)
2586   modinfo_dep = declare_dependency(link_whole: modinfo_lib)
2587   softmmu_ss.add(modinfo_dep)
2588 endif
2589
2590 nm = find_program('nm')
2591 undefsym = find_program('scripts/undefsym.py')
2592 block_syms = custom_target('block.syms', output: 'block.syms',
2593                              input: [libqemuutil, block_mods],
2594                              capture: true,
2595                              command: [undefsym, nm, '@INPUT@'])
2596 qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
2597                              input: [libqemuutil, softmmu_mods],
2598                              capture: true,
2599                              command: [undefsym, nm, '@INPUT@'])
2600
2601 qom_ss = qom_ss.apply(config_host, strict: false)
2602 libqom = static_library('qom', qom_ss.sources() + genh,
2603                         dependencies: [qom_ss.dependencies()],
2604                         name_suffix: 'fa')
2605
2606 qom = declare_dependency(link_whole: libqom)
2607
2608 authz_ss = authz_ss.apply(config_host, strict: false)
2609 libauthz = static_library('authz', authz_ss.sources() + genh,
2610                           dependencies: [authz_ss.dependencies()],
2611                           name_suffix: 'fa',
2612                           build_by_default: false)
2613
2614 authz = declare_dependency(link_whole: libauthz,
2615                            dependencies: qom)
2616
2617 crypto_ss = crypto_ss.apply(config_host, strict: false)
2618 libcrypto = static_library('crypto', crypto_ss.sources() + genh,
2619                            dependencies: [crypto_ss.dependencies()],
2620                            name_suffix: 'fa',
2621                            build_by_default: false)
2622
2623 crypto = declare_dependency(link_whole: libcrypto,
2624                             dependencies: [authz, qom])
2625
2626 io_ss = io_ss.apply(config_host, strict: false)
2627 libio = static_library('io', io_ss.sources() + genh,
2628                        dependencies: [io_ss.dependencies()],
2629                        link_with: libqemuutil,
2630                        name_suffix: 'fa',
2631                        build_by_default: false)
2632
2633 io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
2634
2635 libmigration = static_library('migration', sources: migration_files + genh,
2636                               name_suffix: 'fa',
2637                               build_by_default: false)
2638 migration = declare_dependency(link_with: libmigration,
2639                                dependencies: [zlib, qom, io])
2640 softmmu_ss.add(migration)
2641
2642 block_ss = block_ss.apply(config_host, strict: false)
2643 libblock = static_library('block', block_ss.sources() + genh,
2644                           dependencies: block_ss.dependencies(),
2645                           link_depends: block_syms,
2646                           name_suffix: 'fa',
2647                           build_by_default: false)
2648
2649 block = declare_dependency(link_whole: [libblock],
2650                            link_args: '@block.syms',
2651                            dependencies: [crypto, io])
2652
2653 blockdev_ss = blockdev_ss.apply(config_host, strict: false)
2654 libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
2655                              dependencies: blockdev_ss.dependencies(),
2656                              name_suffix: 'fa',
2657                              build_by_default: false)
2658
2659 blockdev = declare_dependency(link_whole: [libblockdev],
2660                               dependencies: [block])
2661
2662 qmp_ss = qmp_ss.apply(config_host, strict: false)
2663 libqmp = static_library('qmp', qmp_ss.sources() + genh,
2664                         dependencies: qmp_ss.dependencies(),
2665                         name_suffix: 'fa',
2666                         build_by_default: false)
2667
2668 qmp = declare_dependency(link_whole: [libqmp])
2669
2670 libchardev = static_library('chardev', chardev_ss.sources() + genh,
2671                             name_suffix: 'fa',
2672                             dependencies: [gnutls],
2673                             build_by_default: false)
2674
2675 chardev = declare_dependency(link_whole: libchardev)
2676
2677 libhwcore = static_library('hwcore', sources: hwcore_files + genh,
2678                            name_suffix: 'fa',
2679                            build_by_default: false)
2680 hwcore = declare_dependency(link_whole: libhwcore)
2681 common_ss.add(hwcore)
2682
2683 ###########
2684 # Targets #
2685 ###########
2686
2687 foreach m : block_mods + softmmu_mods
2688   shared_module(m.name(),
2689                 name_prefix: '',
2690                 link_whole: m,
2691                 install: true,
2692                 install_dir: qemu_moddir)
2693 endforeach
2694
2695 softmmu_ss.add(authz, blockdev, chardev, crypto, io, qmp)
2696 common_ss.add(qom, qemuutil)
2697
2698 common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
2699 common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
2700
2701 common_all = common_ss.apply(config_all, strict: false)
2702 common_all = static_library('common',
2703                             build_by_default: false,
2704                             sources: common_all.sources() + genh,
2705                             implicit_include_directories: false,
2706                             dependencies: common_all.dependencies(),
2707                             name_suffix: 'fa')
2708
2709 feature_to_c = find_program('scripts/feature_to_c.sh')
2710
2711 emulators = {}
2712 foreach target : target_dirs
2713   config_target = config_target_mak[target]
2714   target_name = config_target['TARGET_NAME']
2715   arch = config_target['TARGET_BASE_ARCH']
2716   arch_srcs = [config_target_h[target]]
2717   arch_deps = []
2718   c_args = ['-DNEED_CPU_H',
2719             '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
2720             '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
2721   link_args = emulator_link_args
2722
2723   config_target += config_host
2724   target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
2725   if targetos == 'linux'
2726     target_inc += include_directories('linux-headers', is_system: true)
2727   endif
2728   if target.endswith('-softmmu')
2729     qemu_target_name = 'qemu-system-' + target_name
2730     target_type='system'
2731     t = target_softmmu_arch[arch].apply(config_target, strict: false)
2732     arch_srcs += t.sources()
2733     arch_deps += t.dependencies()
2734
2735     hw_dir = target_name == 'sparc64' ? 'sparc64' : arch
2736     hw = hw_arch[hw_dir].apply(config_target, strict: false)
2737     arch_srcs += hw.sources()
2738     arch_deps += hw.dependencies()
2739
2740     arch_srcs += config_devices_h[target]
2741     link_args += ['@block.syms', '@qemu.syms']
2742   else
2743     abi = config_target['TARGET_ABI_DIR']
2744     target_type='user'
2745     qemu_target_name = 'qemu-' + target_name
2746     if arch in target_user_arch
2747       t = target_user_arch[arch].apply(config_target, strict: false)
2748       arch_srcs += t.sources()
2749       arch_deps += t.dependencies()
2750     endif
2751     if 'CONFIG_LINUX_USER' in config_target
2752       base_dir = 'linux-user'
2753       target_inc += include_directories('linux-user/host/' / config_host['ARCH'])
2754     endif
2755     if 'CONFIG_BSD_USER' in config_target
2756       base_dir = 'bsd-user'
2757       target_inc += include_directories('bsd-user/' / targetos)
2758       dir = base_dir / abi
2759       arch_srcs += files(dir / 'target_arch_cpu.c')
2760     endif
2761     target_inc += include_directories(
2762       base_dir,
2763       base_dir / abi,
2764     )
2765     if 'CONFIG_LINUX_USER' in config_target
2766       dir = base_dir / abi
2767       arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
2768       if config_target.has_key('TARGET_SYSTBL_ABI')
2769         arch_srcs += \
2770           syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
2771                                              extra_args : config_target['TARGET_SYSTBL_ABI'])
2772       endif
2773     endif
2774   endif
2775
2776   if 'TARGET_XML_FILES' in config_target
2777     gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
2778                                 output: target + '-gdbstub-xml.c',
2779                                 input: files(config_target['TARGET_XML_FILES'].split()),
2780                                 command: [feature_to_c, '@INPUT@'],
2781                                 capture: true)
2782     arch_srcs += gdbstub_xml
2783   endif
2784
2785   t = target_arch[arch].apply(config_target, strict: false)
2786   arch_srcs += t.sources()
2787   arch_deps += t.dependencies()
2788
2789   target_common = common_ss.apply(config_target, strict: false)
2790   objects = common_all.extract_objects(target_common.sources())
2791   deps = target_common.dependencies()
2792
2793   target_specific = specific_ss.apply(config_target, strict: false)
2794   arch_srcs += target_specific.sources()
2795   arch_deps += target_specific.dependencies()
2796
2797   lib = static_library('qemu-' + target,
2798                  sources: arch_srcs + genh,
2799                  dependencies: arch_deps,
2800                  objects: objects,
2801                  include_directories: target_inc,
2802                  c_args: c_args,
2803                  build_by_default: false,
2804                  name_suffix: 'fa')
2805
2806   if target.endswith('-softmmu')
2807     execs = [{
2808       'name': 'qemu-system-' + target_name,
2809       'win_subsystem': 'console',
2810       'sources': files('softmmu/main.c'),
2811       'dependencies': []
2812     }]
2813     if targetos == 'windows' and (sdl.found() or gtk.found())
2814       execs += [{
2815         'name': 'qemu-system-' + target_name + 'w',
2816         'win_subsystem': 'windows',
2817         'sources': files('softmmu/main.c'),
2818         'dependencies': []
2819       }]
2820     endif
2821     if get_option('fuzzing')
2822       specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
2823       execs += [{
2824         'name': 'qemu-fuzz-' + target_name,
2825         'win_subsystem': 'console',
2826         'sources': specific_fuzz.sources(),
2827         'dependencies': specific_fuzz.dependencies(),
2828       }]
2829     endif
2830   else
2831     execs = [{
2832       'name': 'qemu-' + target_name,
2833       'win_subsystem': 'console',
2834       'sources': [],
2835       'dependencies': []
2836     }]
2837   endif
2838   foreach exe: execs
2839     exe_name = exe['name']
2840     if targetos == 'darwin'
2841       exe_name += '-unsigned'
2842     endif
2843
2844     emulator = executable(exe_name, exe['sources'],
2845                install: true,
2846                c_args: c_args,
2847                dependencies: arch_deps + deps + exe['dependencies'],
2848                objects: lib.extract_all_objects(recursive: true),
2849                link_language: link_language,
2850                link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
2851                link_args: link_args,
2852                win_subsystem: exe['win_subsystem'])
2853
2854     if targetos == 'darwin'
2855       icon = 'pc-bios/qemu.rsrc'
2856       build_input = [emulator, files(icon)]
2857       install_input = [
2858         get_option('bindir') / exe_name,
2859         meson.current_source_dir() / icon
2860       ]
2861       if 'CONFIG_HVF' in config_target
2862         entitlements = 'accel/hvf/entitlements.plist'
2863         build_input += files(entitlements)
2864         install_input += meson.current_source_dir() / entitlements
2865       endif
2866
2867       emulators += {exe['name'] : custom_target(exe['name'],
2868                    input: build_input,
2869                    output: exe['name'],
2870                    command: [
2871                      files('scripts/entitlement.sh'),
2872                      '@OUTPUT@',
2873                      '@INPUT@'
2874                    ])
2875       }
2876
2877       meson.add_install_script('scripts/entitlement.sh', '--install',
2878                                get_option('bindir') / exe['name'],
2879                                install_input)
2880     else
2881       emulators += {exe['name']: emulator}
2882     endif
2883
2884     if stap.found()
2885       foreach stp: [
2886         {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
2887         {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
2888         {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
2889         {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
2890       ]
2891         custom_target(exe['name'] + stp['ext'],
2892                       input: trace_events_all,
2893                       output: exe['name'] + stp['ext'],
2894                       install: stp['install'],
2895                       install_dir: get_option('datadir') / 'systemtap/tapset',
2896                       command: [
2897                         tracetool, '--group=all', '--format=' + stp['fmt'],
2898                         '--binary=' + stp['bin'],
2899                         '--target-name=' + target_name,
2900                         '--target-type=' + target_type,
2901                         '--probe-prefix=qemu.' + target_type + '.' + target_name,
2902                         '@INPUT@', '@OUTPUT@'
2903                       ],
2904                       depend_files: tracetool_depends)
2905       endforeach
2906     endif
2907   endforeach
2908 endforeach
2909
2910 # Other build targets
2911
2912 if 'CONFIG_PLUGIN' in config_host
2913   install_headers('include/qemu/qemu-plugin.h')
2914 endif
2915
2916 if 'CONFIG_GUEST_AGENT' in config_host
2917   subdir('qga')
2918 elif get_option('guest_agent_msi').enabled()
2919   error('Guest agent MSI requested, but the guest agent is not being built')
2920 endif
2921
2922 # Don't build qemu-keymap if xkbcommon is not explicitly enabled
2923 # when we don't build tools or system
2924 if xkbcommon.found()
2925   # used for the update-keymaps target, so include rules even if !have_tools
2926   qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
2927                            dependencies: [qemuutil, xkbcommon], install: have_tools)
2928 endif
2929
2930 if have_tools
2931   qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
2932              dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
2933   qemu_io = executable('qemu-io', files('qemu-io.c'),
2934              dependencies: [block, qemuutil], install: true)
2935   qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
2936                dependencies: [blockdev, qemuutil, gnutls], install: true)
2937
2938   subdir('storage-daemon')
2939   subdir('contrib/rdmacm-mux')
2940   subdir('contrib/elf2dmp')
2941
2942   executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
2943              dependencies: qemuutil,
2944              install: true)
2945
2946   if 'CONFIG_VHOST_USER' in config_host
2947     subdir('contrib/vhost-user-blk')
2948     subdir('contrib/vhost-user-gpu')
2949     subdir('contrib/vhost-user-input')
2950     subdir('contrib/vhost-user-scsi')
2951   endif
2952
2953   if targetos == 'linux'
2954     executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
2955                dependencies: [qemuutil, libcap_ng],
2956                install: true,
2957                install_dir: get_option('libexecdir'))
2958
2959     executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
2960                dependencies: [authz, crypto, io, qom, qemuutil,
2961                               libcap_ng, mpathpersist],
2962                install: true)
2963   endif
2964
2965   if have_ivshmem
2966     subdir('contrib/ivshmem-client')
2967     subdir('contrib/ivshmem-server')
2968   endif
2969 endif
2970
2971 subdir('scripts')
2972 subdir('tools')
2973 subdir('pc-bios')
2974 subdir('docs')
2975 subdir('tests')
2976 if gtk.found()
2977   subdir('po')
2978 endif
2979
2980 if host_machine.system() == 'windows'
2981   nsis_cmd = [
2982     find_program('scripts/nsis.py'),
2983     '@OUTPUT@',
2984     get_option('prefix'),
2985     meson.current_source_dir(),
2986     host_machine.cpu(),
2987     '--',
2988     '-DDISPLAYVERSION=' + meson.project_version(),
2989   ]
2990   if build_docs
2991     nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
2992   endif
2993   if gtk.found()
2994     nsis_cmd += '-DCONFIG_GTK=y'
2995   endif
2996
2997   nsis = custom_target('nsis',
2998                        output: 'qemu-setup-' + meson.project_version() + '.exe',
2999                        input: files('qemu.nsi'),
3000                        build_always_stale: true,
3001                        command: nsis_cmd + ['@INPUT@'])
3002   alias_target('installer', nsis)
3003 endif
3004
3005 #########################
3006 # Configuration summary #
3007 #########################
3008
3009 # Directories
3010 summary_info = {}
3011 summary_info += {'Install prefix':    get_option('prefix')}
3012 summary_info += {'BIOS directory':    qemu_datadir}
3013 summary_info += {'firmware path':     get_option('qemu_firmwarepath')}
3014 summary_info += {'binary directory':  get_option('bindir')}
3015 summary_info += {'library directory': get_option('libdir')}
3016 summary_info += {'module directory':  qemu_moddir}
3017 summary_info += {'libexec directory': get_option('libexecdir')}
3018 summary_info += {'include directory': get_option('includedir')}
3019 summary_info += {'config directory':  get_option('sysconfdir')}
3020 if targetos != 'windows'
3021   summary_info += {'local state directory': get_option('localstatedir')}
3022   summary_info += {'Manual directory':      get_option('mandir')}
3023 else
3024   summary_info += {'local state directory': 'queried at runtime'}
3025 endif
3026 summary_info += {'Doc directory':     get_option('docdir')}
3027 summary_info += {'Build directory':   meson.current_build_dir()}
3028 summary_info += {'Source path':       meson.current_source_dir()}
3029 summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
3030 summary(summary_info, bool_yn: true, section: 'Directories')
3031
3032 # Host binaries
3033 summary_info = {}
3034 summary_info += {'git':               config_host['GIT']}
3035 summary_info += {'make':              config_host['MAKE']}
3036 summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
3037 summary_info += {'sphinx-build':      sphinx_build}
3038 if config_host.has_key('HAVE_GDB_BIN')
3039   summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
3040 endif
3041 summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
3042 if targetos == 'windows' and config_host.has_key('CONFIG_GUEST_AGENT')
3043   summary_info += {'wixl':            wixl}
3044 endif
3045 if slirp_opt != 'disabled' and 'CONFIG_SLIRP_SMBD' in config_host
3046   summary_info += {'smbd':            config_host['CONFIG_SMBD_COMMAND']}
3047 endif
3048 summary(summary_info, bool_yn: true, section: 'Host binaries')
3049
3050 # Configurable features
3051 summary_info = {}
3052 summary_info += {'Documentation':     build_docs}
3053 summary_info += {'system-mode emulation': have_system}
3054 summary_info += {'user-mode emulation': have_user}
3055 summary_info += {'block layer':       have_block}
3056 summary_info += {'Install blobs':     get_option('install_blobs')}
3057 summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
3058 if config_host.has_key('CONFIG_MODULES')
3059   summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')}
3060 endif
3061 summary_info += {'fuzzing support':   get_option('fuzzing')}
3062 if have_system
3063   summary_info += {'Audio drivers':     ' '.join(audio_drivers_selected)}
3064 endif
3065 summary_info += {'Trace backends':    ','.join(get_option('trace_backends'))}
3066 if 'simple' in get_option('trace_backends')
3067   summary_info += {'Trace output file': get_option('trace_file') + '-<pid>'}
3068 endif
3069 summary_info += {'QOM debugging':     config_host.has_key('CONFIG_QOM_CAST_DEBUG')}
3070 summary_info += {'vhost-kernel support': config_host.has_key('CONFIG_VHOST_KERNEL')}
3071 summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')}
3072 summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')}
3073 summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')}
3074 summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')}
3075 summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_USER')}
3076 summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
3077 summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')}
3078 summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')}
3079 summary_info += {'build guest agent': config_host.has_key('CONFIG_GUEST_AGENT')}
3080 summary(summary_info, bool_yn: true, section: 'Configurable features')
3081
3082 # Compilation information
3083 summary_info = {}
3084 summary_info += {'host CPU':          cpu}
3085 summary_info += {'host endianness':   build_machine.endian()}
3086 summary_info += {'C compiler':        ' '.join(meson.get_compiler('c').cmd_array())}
3087 summary_info += {'Host C compiler':   ' '.join(meson.get_compiler('c', native: true).cmd_array())}
3088 if link_language == 'cpp'
3089   summary_info += {'C++ compiler':    ' '.join(meson.get_compiler('cpp').cmd_array())}
3090 else
3091   summary_info += {'C++ compiler':      false}
3092 endif
3093 if targetos == 'darwin'
3094   summary_info += {'Objective-C compiler': ' '.join(meson.get_compiler('objc').cmd_array())}
3095 endif
3096 if targetos == 'windows'
3097   if 'WIN_SDK' in config_host
3098     summary_info += {'Windows SDK':   config_host['WIN_SDK']}
3099   endif
3100 endif
3101 summary_info += {'CFLAGS':            ' '.join(get_option('c_args')
3102                                                + ['-O' + get_option('optimization')]
3103                                                + (get_option('debug') ? ['-g'] : []))}
3104 if link_language == 'cpp'
3105   summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args')
3106                                                + ['-O' + get_option('optimization')]
3107                                                + (get_option('debug') ? ['-g'] : []))}
3108 endif
3109 link_args = get_option(link_language + '_link_args')
3110 if link_args.length() > 0
3111   summary_info += {'LDFLAGS':         ' '.join(link_args)}
3112 endif
3113 summary_info += {'QEMU_CFLAGS':       config_host['QEMU_CFLAGS']}
3114 summary_info += {'QEMU_LDFLAGS':      config_host['QEMU_LDFLAGS']}
3115 summary_info += {'profiler':          config_host.has_key('CONFIG_PROFILER')}
3116 summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
3117 summary_info += {'PIE':               get_option('b_pie')}
3118 summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
3119 summary_info += {'malloc trim support': has_malloc_trim}
3120 summary_info += {'membarrier':        config_host.has_key('CONFIG_MEMBARRIER')}
3121 summary_info += {'debug stack usage': config_host.has_key('CONFIG_DEBUG_STACK_USAGE')}
3122 summary_info += {'mutex debugging':   config_host.has_key('CONFIG_DEBUG_MUTEX')}
3123 summary_info += {'memory allocator':  get_option('malloc')}
3124 summary_info += {'avx2 optimization': config_host.has_key('CONFIG_AVX2_OPT')}
3125 summary_info += {'avx512f optimization': config_host.has_key('CONFIG_AVX512F_OPT')}
3126 summary_info += {'gprof enabled':     config_host.has_key('CONFIG_GPROF')}
3127 summary_info += {'gcov':              get_option('b_coverage')}
3128 summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
3129 summary_info += {'CFI support':       get_option('cfi')}
3130 if get_option('cfi')
3131   summary_info += {'CFI debug support': get_option('cfi_debug')}
3132 endif
3133 summary_info += {'strip binaries':    get_option('strip')}
3134 summary_info += {'sparse':            sparse}
3135 summary_info += {'mingw32 support':   targetos == 'windows'}
3136
3137 # snarf the cross-compilation information for tests
3138 foreach target: target_dirs
3139   tcg_mak = meson.current_build_dir() / 'tests/tcg' / 'config-' + target + '.mak'
3140   if fs.exists(tcg_mak)
3141     config_cross_tcg = keyval.load(tcg_mak)
3142     target = config_cross_tcg['TARGET_NAME']
3143     compiler = ''
3144     if 'DOCKER_CROSS_CC_GUEST' in config_cross_tcg
3145       summary_info += {target + ' tests': config_cross_tcg['DOCKER_CROSS_CC_GUEST'] +
3146                                           ' via ' + config_cross_tcg['DOCKER_IMAGE']}
3147     elif 'CROSS_CC_GUEST' in config_cross_tcg
3148       summary_info += {target + ' tests'
3149                                 : config_cross_tcg['CROSS_CC_GUEST'] }
3150     endif
3151    endif
3152 endforeach
3153
3154 summary(summary_info, bool_yn: true, section: 'Compilation')
3155
3156 # Targets and accelerators
3157 summary_info = {}
3158 if have_system
3159   summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
3160   summary_info += {'HAX support':       config_all.has_key('CONFIG_HAX')}
3161   summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
3162   summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
3163   summary_info += {'NVMM support':      config_all.has_key('CONFIG_NVMM')}
3164   summary_info += {'Xen support':       config_host.has_key('CONFIG_XEN_BACKEND')}
3165   if config_host.has_key('CONFIG_XEN_BACKEND')
3166     summary_info += {'xen ctrl version':  config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
3167   endif
3168 endif
3169 summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
3170 if config_all.has_key('CONFIG_TCG')
3171   if get_option('tcg_interpreter')
3172     summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, experimental and slow)'}
3173   else
3174     summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
3175   endif
3176   summary_info += {'TCG plugins': config_host.has_key('CONFIG_PLUGIN')}
3177   summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
3178 endif
3179 summary_info += {'target list':       ' '.join(target_dirs)}
3180 if have_system
3181   summary_info += {'default devices':   get_option('default_devices')}
3182   summary_info += {'out of process emulation': multiprocess_allowed}
3183 endif
3184 summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
3185
3186 # Block layer
3187 summary_info = {}
3188 summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
3189 summary_info += {'coroutine pool':    config_host['CONFIG_COROUTINE_POOL'] == '1'}
3190 if have_block
3191   summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']}
3192   summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']}
3193   summary_info += {'Use block whitelist in tools': config_host.has_key('CONFIG_BDRV_WHITELIST_TOOLS')}
3194   summary_info += {'VirtFS support':    have_virtfs}
3195   summary_info += {'build virtiofs daemon': have_virtiofsd}
3196   summary_info += {'Live block migration': config_host.has_key('CONFIG_LIVE_BLOCK_MIGRATION')}
3197   summary_info += {'replication support': config_host.has_key('CONFIG_REPLICATION')}
3198   summary_info += {'bochs support':     config_host.has_key('CONFIG_BOCHS')}
3199   summary_info += {'cloop support':     config_host.has_key('CONFIG_CLOOP')}
3200   summary_info += {'dmg support':       config_host.has_key('CONFIG_DMG')}
3201   summary_info += {'qcow v1 support':   config_host.has_key('CONFIG_QCOW1')}
3202   summary_info += {'vdi support':       config_host.has_key('CONFIG_VDI')}
3203   summary_info += {'vvfat support':     config_host.has_key('CONFIG_VVFAT')}
3204   summary_info += {'qed support':       config_host.has_key('CONFIG_QED')}
3205   summary_info += {'parallels support': config_host.has_key('CONFIG_PARALLELS')}
3206   summary_info += {'FUSE exports':      fuse}
3207 endif
3208 summary(summary_info, bool_yn: true, section: 'Block layer support')
3209
3210 # Crypto
3211 summary_info = {}
3212 summary_info += {'TLS priority':      config_host['CONFIG_TLS_PRIORITY']}
3213 summary_info += {'GNUTLS support':    gnutls}
3214 if gnutls.found()
3215   summary_info += {'  GNUTLS crypto':   gnutls_crypto.found()}
3216 endif
3217 summary_info += {'libgcrypt':         gcrypt}
3218 summary_info += {'nettle':            nettle}
3219 if nettle.found()
3220    summary_info += {'  XTS':             xts != 'private'}
3221 endif
3222 summary_info += {'crypto afalg':      config_host.has_key('CONFIG_AF_ALG')}
3223 summary_info += {'rng-none':          config_host.has_key('CONFIG_RNG_NONE')}
3224 summary_info += {'Linux keyring':     config_host.has_key('CONFIG_SECRET_KEYRING')}
3225 summary(summary_info, bool_yn: true, section: 'Crypto')
3226
3227 # Libraries
3228 summary_info = {}
3229 if targetos == 'darwin'
3230   summary_info += {'Cocoa support':   cocoa}
3231 endif
3232 summary_info += {'SDL support':       sdl}
3233 summary_info += {'SDL image support': sdl_image}
3234 summary_info += {'GTK support':       gtk}
3235 summary_info += {'pixman':            pixman}
3236 summary_info += {'VTE support':       vte}
3237 summary_info += {'slirp support':     slirp_opt == 'internal' ? slirp_opt : slirp}
3238 summary_info += {'libtasn1':          tasn1}
3239 summary_info += {'PAM':               pam}
3240 summary_info += {'iconv support':     iconv}
3241 summary_info += {'curses support':    curses}
3242 summary_info += {'virgl support':     virgl}
3243 summary_info += {'curl support':      curl}
3244 summary_info += {'Multipath support': mpathpersist}
3245 summary_info += {'VNC support':       vnc}
3246 if vnc.found()
3247   summary_info += {'VNC SASL support':  sasl}
3248   summary_info += {'VNC JPEG support':  jpeg}
3249   summary_info += {'VNC PNG support':   png}
3250 endif
3251 if targetos not in ['darwin', 'haiku', 'windows']
3252   summary_info += {'OSS support':     oss}
3253 elif targetos == 'darwin'
3254   summary_info += {'CoreAudio support': coreaudio}
3255 elif targetos == 'windows'
3256   summary_info += {'DirectSound support': dsound}
3257 endif
3258 if targetos == 'linux'
3259   summary_info += {'ALSA support':    alsa}
3260   summary_info += {'PulseAudio support': pulse}
3261 endif
3262 summary_info += {'JACK support':      jack}
3263 summary_info += {'brlapi support':    brlapi}
3264 summary_info += {'vde support':       config_host.has_key('CONFIG_VDE')}
3265 summary_info += {'netmap support':    config_host.has_key('CONFIG_NETMAP')}
3266 summary_info += {'Linux AIO support': config_host.has_key('CONFIG_LINUX_AIO')}
3267 summary_info += {'Linux io_uring support': linux_io_uring}
3268 summary_info += {'ATTR/XATTR support': libattr}
3269 summary_info += {'RDMA support':      config_host.has_key('CONFIG_RDMA')}
3270 summary_info += {'PVRDMA support':    config_host.has_key('CONFIG_PVRDMA')}
3271 summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
3272 summary_info += {'libcap-ng support': libcap_ng}
3273 summary_info += {'bpf support':       libbpf}
3274 # TODO: add back protocol and server version
3275 summary_info += {'spice support':     config_host.has_key('CONFIG_SPICE')}
3276 summary_info += {'rbd support':       rbd}
3277 summary_info += {'xfsctl support':    config_host.has_key('CONFIG_XFS')}
3278 summary_info += {'smartcard support': cacard}
3279 summary_info += {'U2F support':       u2f}
3280 summary_info += {'libusb':            libusb}
3281 summary_info += {'usb net redir':     usbredir}
3282 summary_info += {'OpenGL support':    config_host.has_key('CONFIG_OPENGL')}
3283 summary_info += {'GBM':               gbm}
3284 summary_info += {'libiscsi support':  libiscsi}
3285 summary_info += {'libnfs support':    libnfs}
3286 if targetos == 'windows'
3287   if config_host.has_key('CONFIG_GUEST_AGENT')
3288     summary_info += {'QGA VSS support':   config_host.has_key('CONFIG_QGA_VSS')}
3289     summary_info += {'QGA w32 disk info': config_host.has_key('CONFIG_QGA_NTDDSCSI')}
3290   endif
3291 endif
3292 summary_info += {'seccomp support':   seccomp}
3293 summary_info += {'GlusterFS support': glusterfs}
3294 summary_info += {'TPM support':       config_host.has_key('CONFIG_TPM')}
3295 summary_info += {'libssh support':    config_host.has_key('CONFIG_LIBSSH')}
3296 summary_info += {'lzo support':       lzo}
3297 summary_info += {'snappy support':    snappy}
3298 summary_info += {'bzip2 support':     libbzip2}
3299 summary_info += {'lzfse support':     liblzfse}
3300 summary_info += {'zstd support':      zstd}
3301 summary_info += {'NUMA host support': config_host.has_key('CONFIG_NUMA')}
3302 summary_info += {'libxml2':           libxml2}
3303 summary_info += {'capstone':          capstone_opt == 'internal' ? capstone_opt : capstone}
3304 summary_info += {'libpmem support':   libpmem}
3305 summary_info += {'libdaxctl support': libdaxctl}
3306 summary_info += {'libudev':           libudev}
3307 # Dummy dependency, keep .found()
3308 summary_info += {'FUSE lseek':        fuse_lseek.found()}
3309 summary(summary_info, bool_yn: true, section: 'Dependencies')
3310
3311 if not supported_cpus.contains(cpu)
3312   message()
3313   warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
3314   message()
3315   message('CPU host architecture ' + cpu + ' support is not currently maintained.')
3316   message('The QEMU project intends to remove support for this host CPU in')
3317   message('a future release if nobody volunteers to maintain it and to')
3318   message('provide a build host for our continuous integration setup.')
3319   message('configure has succeeded and you can continue to build, but')
3320   message('if you care about QEMU on this platform you should contact')
3321   message('us upstream at qemu-devel@nongnu.org.')
3322 endif
3323
3324 if not supported_oses.contains(targetos)
3325   message()
3326   warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
3327   message()
3328   message('Host OS ' + targetos + 'support is not currently maintained.')
3329   message('The QEMU project intends to remove support for this host OS in')
3330   message('a future release if nobody volunteers to maintain it and to')
3331   message('provide a build host for our continuous integration setup.')
3332   message('configure has succeeded and you can continue to build, but')
3333   message('if you care about QEMU on this platform you should contact')
3334   message('us upstream at qemu-devel@nongnu.org.')
3335 endif