OSDN Git Service

configure, meson: get HOST_WORDS_BIGENDIAN via the machine object
[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_LIBUDEV', libudev.found())
1406 config_host_data.set('CONFIG_LZO', lzo.found())
1407 config_host_data.set('CONFIG_MPATH', mpathpersist.found())
1408 config_host_data.set('CONFIG_MPATH_NEW_API', mpathpersist_new_api)
1409 config_host_data.set('CONFIG_CURL', curl.found())
1410 config_host_data.set('CONFIG_CURSES', curses.found())
1411 config_host_data.set('CONFIG_GBM', gbm.found())
1412 config_host_data.set('CONFIG_GLUSTERFS', glusterfs.found())
1413 if glusterfs.found()
1414   config_host_data.set('CONFIG_GLUSTERFS_XLATOR_OPT', glusterfs.version().version_compare('>=4'))
1415   config_host_data.set('CONFIG_GLUSTERFS_DISCARD', glusterfs.version().version_compare('>=5'))
1416   config_host_data.set('CONFIG_GLUSTERFS_FALLOCATE', glusterfs.version().version_compare('>=6'))
1417   config_host_data.set('CONFIG_GLUSTERFS_ZEROFILL', glusterfs.version().version_compare('>=6'))
1418   config_host_data.set('CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT', glusterfs_ftruncate_has_stat)
1419   config_host_data.set('CONFIG_GLUSTERFS_IOCB_HAS_STAT', glusterfs_iocb_has_stat)
1420 endif
1421 config_host_data.set('CONFIG_GTK', gtk.found())
1422 config_host_data.set('CONFIG_VTE', vte.found())
1423 config_host_data.set('CONFIG_LIBATTR', have_old_libattr)
1424 config_host_data.set('CONFIG_LIBCAP_NG', libcap_ng.found())
1425 config_host_data.set('CONFIG_EBPF', libbpf.found())
1426 config_host_data.set('CONFIG_LIBDAXCTL', libdaxctl.found())
1427 config_host_data.set('CONFIG_LIBISCSI', libiscsi.found())
1428 config_host_data.set('CONFIG_LIBNFS', libnfs.found())
1429 config_host_data.set('CONFIG_LINUX_IO_URING', linux_io_uring.found())
1430 config_host_data.set('CONFIG_LIBPMEM', libpmem.found())
1431 config_host_data.set('CONFIG_RBD', rbd.found())
1432 config_host_data.set('CONFIG_SDL', sdl.found())
1433 config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found())
1434 config_host_data.set('CONFIG_SECCOMP', seccomp.found())
1435 config_host_data.set('CONFIG_SNAPPY', snappy.found())
1436 config_host_data.set('CONFIG_USB_LIBUSB', libusb.found())
1437 config_host_data.set('CONFIG_VHOST_USER_BLK_SERVER', have_vhost_user_blk_server)
1438 config_host_data.set('CONFIG_VNC', vnc.found())
1439 config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
1440 config_host_data.set('CONFIG_VNC_PNG', png.found())
1441 config_host_data.set('CONFIG_VNC_SASL', sasl.found())
1442 config_host_data.set('CONFIG_VIRTFS', have_virtfs)
1443 config_host_data.set('CONFIG_VTE', vte.found())
1444 config_host_data.set('CONFIG_XKBCOMMON', xkbcommon.found())
1445 config_host_data.set('CONFIG_KEYUTILS', keyutils.found())
1446 config_host_data.set('CONFIG_GETTID', has_gettid)
1447 config_host_data.set('CONFIG_GNUTLS', gnutls.found())
1448 config_host_data.set('CONFIG_GNUTLS_CRYPTO', gnutls_crypto.found())
1449 config_host_data.set('CONFIG_GCRYPT', gcrypt.found())
1450 config_host_data.set('CONFIG_NETTLE', nettle.found())
1451 config_host_data.set('CONFIG_QEMU_PRIVATE_XTS', xts == 'private')
1452 config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim)
1453 config_host_data.set('CONFIG_STATX', has_statx)
1454 config_host_data.set('CONFIG_ZSTD', zstd.found())
1455 config_host_data.set('CONFIG_FUSE', fuse.found())
1456 config_host_data.set('CONFIG_FUSE_LSEEK', fuse_lseek.found())
1457 config_host_data.set('CONFIG_X11', x11.found())
1458 config_host_data.set('CONFIG_CFI', get_option('cfi'))
1459 config_host_data.set('QEMU_VERSION', '"@0@"'.format(meson.project_version()))
1460 config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0])
1461 config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1])
1462 config_host_data.set('QEMU_VERSION_MICRO', meson.project_version().split('.')[2])
1463
1464 config_host_data.set_quoted('CONFIG_HOST_DSOSUF', host_dsosuf)
1465 config_host_data.set('HAVE_HOST_BLOCK_DEVICE', have_host_block_device)
1466 config_host_data.set('HOST_WORDS_BIGENDIAN', host_machine.endian() == 'big')
1467
1468 # has_header
1469 config_host_data.set('CONFIG_EPOLL', cc.has_header('sys/epoll.h'))
1470 config_host_data.set('CONFIG_LINUX_MAGIC_H', cc.has_header('linux/magic.h'))
1471 config_host_data.set('CONFIG_VALGRIND_H', cc.has_header('valgrind/valgrind.h'))
1472 config_host_data.set('HAVE_BTRFS_H', cc.has_header('linux/btrfs.h'))
1473 config_host_data.set('HAVE_DRM_H', cc.has_header('libdrm/drm.h'))
1474 config_host_data.set('HAVE_PTY_H', cc.has_header('pty.h'))
1475 config_host_data.set('HAVE_SYS_DISK_H', cc.has_header('sys/disk.h'))
1476 config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h'))
1477 config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h'))
1478
1479 # has_function
1480 config_host_data.set('CONFIG_ACCEPT4', cc.has_function('accept4'))
1481 config_host_data.set('CONFIG_CLOCK_ADJTIME', cc.has_function('clock_adjtime'))
1482 config_host_data.set('CONFIG_DUP3', cc.has_function('dup3'))
1483 config_host_data.set('CONFIG_FALLOCATE', cc.has_function('fallocate'))
1484 config_host_data.set('CONFIG_POSIX_FALLOCATE', cc.has_function('posix_fallocate'))
1485 config_host_data.set('CONFIG_POSIX_MEMALIGN', cc.has_function('posix_memalign'))
1486 config_host_data.set('CONFIG_PPOLL', cc.has_function('ppoll'))
1487 config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include <sys/uio.h>'))
1488 config_host_data.set('CONFIG_SEM_TIMEDWAIT', cc.has_function('sem_timedwait', dependencies: threads))
1489 config_host_data.set('CONFIG_SENDFILE', cc.has_function('sendfile'))
1490 config_host_data.set('CONFIG_SETNS', cc.has_function('setns') and cc.has_function('unshare'))
1491 config_host_data.set('CONFIG_SYNCFS', cc.has_function('syncfs'))
1492 config_host_data.set('CONFIG_SYNC_FILE_RANGE', cc.has_function('sync_file_range'))
1493 config_host_data.set('CONFIG_TIMERFD', cc.has_function('timerfd_create'))
1494 config_host_data.set('HAVE_COPY_FILE_RANGE', cc.has_function('copy_file_range'))
1495 config_host_data.set('HAVE_OPENPTY', cc.has_function('openpty', dependencies: util))
1496 config_host_data.set('HAVE_STRCHRNUL', cc.has_function('strchrnul'))
1497 config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: '#include <stdlib.h>'))
1498
1499 # has_header_symbol
1500 config_host_data.set('CONFIG_BYTESWAP_H',
1501                      cc.has_header_symbol('byteswap.h', 'bswap_32'))
1502 config_host_data.set('CONFIG_EPOLL_CREATE1',
1503                      cc.has_header_symbol('sys/epoll.h', 'epoll_create1'))
1504 config_host_data.set('CONFIG_HAS_ENVIRON',
1505                      cc.has_header_symbol('unistd.h', 'environ', prefix: gnu_source_prefix))
1506 config_host_data.set('CONFIG_FALLOCATE_PUNCH_HOLE',
1507                      cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_PUNCH_HOLE') and
1508                      cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_KEEP_SIZE'))
1509 config_host_data.set('CONFIG_FALLOCATE_ZERO_RANGE',
1510                      cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_ZERO_RANGE'))
1511 config_host_data.set('CONFIG_FIEMAP',
1512                      cc.has_header('linux/fiemap.h') and
1513                      cc.has_header_symbol('linux/fs.h', 'FS_IOC_FIEMAP'))
1514 config_host_data.set('CONFIG_GETRANDOM',
1515                      cc.has_function('getrandom') and
1516                      cc.has_header_symbol('sys/random.h', 'GRND_NONBLOCK'))
1517 config_host_data.set('CONFIG_INOTIFY',
1518                      cc.has_header_symbol('sys/inotify.h', 'inotify_init'))
1519 config_host_data.set('CONFIG_INOTIFY1',
1520                      cc.has_header_symbol('sys/inotify.h', 'inotify_init1'))
1521 config_host_data.set('CONFIG_MACHINE_BSWAP_H',
1522                      cc.has_header_symbol('machine/bswap.h', 'bswap32',
1523                                           prefix: '''#include <sys/endian.h>
1524                                                      #include <sys/types.h>'''))
1525 config_host_data.set('CONFIG_PRCTL_PR_SET_TIMERSLACK',
1526                      cc.has_header_symbol('sys/prctl.h', 'PR_SET_TIMERSLACK'))
1527 config_host_data.set('CONFIG_RTNETLINK',
1528                      cc.has_header_symbol('linux/rtnetlink.h', 'IFLA_PROTO_DOWN'))
1529 config_host_data.set('CONFIG_SYSMACROS',
1530                      cc.has_header_symbol('sys/sysmacros.h', 'makedev'))
1531 config_host_data.set('HAVE_OPTRESET',
1532                      cc.has_header_symbol('getopt.h', 'optreset'))
1533 config_host_data.set('HAVE_UTMPX',
1534                      cc.has_header_symbol('utmpx.h', 'struct utmpx'))
1535 config_host_data.set('HAVE_IPPROTO_MPTCP',
1536                      cc.has_header_symbol('netinet/in.h', 'IPPROTO_MPTCP'))
1537
1538 # has_member
1539 config_host_data.set('HAVE_SIGEV_NOTIFY_THREAD_ID',
1540                      cc.has_member('struct sigevent', 'sigev_notify_thread_id',
1541                                    prefix: '#include <signal.h>'))
1542 config_host_data.set('HAVE_STRUCT_STAT_ST_ATIM',
1543                      cc.has_member('struct stat', 'st_atim',
1544                                    prefix: '#include <sys/stat.h>'))
1545
1546 config_host_data.set('CONFIG_EVENTFD', cc.links('''
1547   #include <sys/eventfd.h>
1548   int main(void) { return eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); }'''))
1549 config_host_data.set('CONFIG_FDATASYNC', cc.links(gnu_source_prefix + '''
1550   #include <unistd.h>
1551   int main(void) {
1552   #if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
1553   return fdatasync(0);
1554   #else
1555   #error Not supported
1556   #endif
1557   }'''))
1558 config_host_data.set('CONFIG_MADVISE', cc.links(gnu_source_prefix + '''
1559   #include <sys/types.h>
1560   #include <sys/mman.h>
1561   #include <stddef.h>
1562   int main(void) { return madvise(NULL, 0, MADV_DONTNEED); }'''))
1563 config_host_data.set('CONFIG_MEMFD', cc.links(gnu_source_prefix + '''
1564   #include <sys/mman.h>
1565   int main(void) { return memfd_create("foo", MFD_ALLOW_SEALING); }'''))
1566 config_host_data.set('CONFIG_OPEN_BY_HANDLE', cc.links(gnu_source_prefix + '''
1567   #include <fcntl.h>
1568   #if !defined(AT_EMPTY_PATH)
1569   # error missing definition
1570   #else
1571   int main(void) { struct file_handle fh; return open_by_handle_at(0, &fh, 0); }
1572   #endif'''))
1573 config_host_data.set('CONFIG_PIPE2', cc.links(gnu_source_prefix + '''
1574   #include <unistd.h>
1575   #include <fcntl.h>
1576
1577   int main(void)
1578   {
1579       int pipefd[2];
1580       return pipe2(pipefd, O_CLOEXEC);
1581   }'''))
1582 config_host_data.set('CONFIG_POSIX_MADVISE', cc.links(gnu_source_prefix + '''
1583   #include <sys/mman.h>
1584   #include <stddef.h>
1585   int main(void) { return posix_madvise(NULL, 0, POSIX_MADV_DONTNEED); }'''))
1586 config_host_data.set('CONFIG_SIGNALFD', cc.links(gnu_source_prefix + '''
1587   #include <sys/signalfd.h>
1588   #include <stddef.h>
1589   int main(void) { return signalfd(-1, NULL, SFD_CLOEXEC); }'''))
1590 config_host_data.set('CONFIG_SPLICE', cc.links(gnu_source_prefix + '''
1591   #include <unistd.h>
1592   #include <fcntl.h>
1593   #include <limits.h>
1594
1595   int main(void)
1596   {
1597     int len, fd = 0;
1598     len = tee(STDIN_FILENO, STDOUT_FILENO, INT_MAX, SPLICE_F_NONBLOCK);
1599     splice(STDIN_FILENO, NULL, fd, NULL, len, SPLICE_F_MOVE);
1600     return 0;
1601   }'''))
1602
1603 # Some versions of Mac OS X incorrectly define SIZE_MAX
1604 config_host_data.set('HAVE_BROKEN_SIZE_MAX', not cc.compiles('''
1605     #include <stdint.h>
1606     #include <stdio.h>
1607     int main(int argc, char *argv[]) {
1608         return printf("%zu", SIZE_MAX);
1609     }''', args: ['-Werror']))
1610
1611 ignored = ['CONFIG_QEMU_INTERP_PREFIX'] # actually per-target
1612 arrays = ['CONFIG_BDRV_RW_WHITELIST', 'CONFIG_BDRV_RO_WHITELIST']
1613 strings = ['CONFIG_IASL']
1614 foreach k, v: config_host
1615   if ignored.contains(k)
1616     # do nothing
1617   elif arrays.contains(k)
1618     if v != ''
1619       v = '"' + '", "'.join(v.split()) + '", '
1620     endif
1621     config_host_data.set(k, v)
1622   elif k == 'ARCH'
1623     config_host_data.set('HOST_' + v.to_upper(), 1)
1624   elif strings.contains(k)
1625     config_host_data.set_quoted(k, v)
1626   elif k.startswith('CONFIG_') or k.startswith('HAVE_')
1627     config_host_data.set(k, v == 'y' ? 1 : v)
1628   endif
1629 endforeach
1630
1631 ########################
1632 # Target configuration #
1633 ########################
1634
1635 minikconf = find_program('scripts/minikconf.py')
1636 config_all = {}
1637 config_all_devices = {}
1638 config_all_disas = {}
1639 config_devices_mak_list = []
1640 config_devices_h = {}
1641 config_target_h = {}
1642 config_target_mak = {}
1643
1644 disassemblers = {
1645   'alpha' : ['CONFIG_ALPHA_DIS'],
1646   'arm' : ['CONFIG_ARM_DIS'],
1647   'avr' : ['CONFIG_AVR_DIS'],
1648   'cris' : ['CONFIG_CRIS_DIS'],
1649   'hexagon' : ['CONFIG_HEXAGON_DIS'],
1650   'hppa' : ['CONFIG_HPPA_DIS'],
1651   'i386' : ['CONFIG_I386_DIS'],
1652   'x86_64' : ['CONFIG_I386_DIS'],
1653   'x32' : ['CONFIG_I386_DIS'],
1654   'm68k' : ['CONFIG_M68K_DIS'],
1655   'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
1656   'mips' : ['CONFIG_MIPS_DIS'],
1657   'nios2' : ['CONFIG_NIOS2_DIS'],
1658   'or1k' : ['CONFIG_OPENRISC_DIS'],
1659   'ppc' : ['CONFIG_PPC_DIS'],
1660   'riscv' : ['CONFIG_RISCV_DIS'],
1661   'rx' : ['CONFIG_RX_DIS'],
1662   's390' : ['CONFIG_S390_DIS'],
1663   'sh4' : ['CONFIG_SH4_DIS'],
1664   'sparc' : ['CONFIG_SPARC_DIS'],
1665   'xtensa' : ['CONFIG_XTENSA_DIS'],
1666 }
1667 if link_language == 'cpp'
1668   disassemblers += {
1669     'aarch64' : [ 'CONFIG_ARM_A64_DIS'],
1670     'arm' : [ 'CONFIG_ARM_DIS', 'CONFIG_ARM_A64_DIS'],
1671     'mips' : [ 'CONFIG_MIPS_DIS', 'CONFIG_NANOMIPS_DIS'],
1672   }
1673 endif
1674
1675 have_ivshmem = config_host_data.get('CONFIG_EVENTFD')
1676 host_kconfig = \
1677   (get_option('fuzzing') ? ['CONFIG_FUZZ=y'] : []) + \
1678   ('CONFIG_TPM' in config_host ? ['CONFIG_TPM=y'] : []) + \
1679   ('CONFIG_SPICE' in config_host ? ['CONFIG_SPICE=y'] : []) + \
1680   (have_ivshmem ? ['CONFIG_IVSHMEM=y'] : []) + \
1681   ('CONFIG_OPENGL' in config_host ? ['CONFIG_OPENGL=y'] : []) + \
1682   (x11.found() ? ['CONFIG_X11=y'] : []) + \
1683   ('CONFIG_VHOST_USER' in config_host ? ['CONFIG_VHOST_USER=y'] : []) + \
1684   ('CONFIG_VHOST_VDPA' in config_host ? ['CONFIG_VHOST_VDPA=y'] : []) + \
1685   ('CONFIG_VHOST_KERNEL' in config_host ? ['CONFIG_VHOST_KERNEL=y'] : []) + \
1686   (have_virtfs ? ['CONFIG_VIRTFS=y'] : []) + \
1687   ('CONFIG_LINUX' in config_host ? ['CONFIG_LINUX=y'] : []) + \
1688   ('CONFIG_PVRDMA' in config_host ? ['CONFIG_PVRDMA=y'] : []) + \
1689   (multiprocess_allowed ? ['CONFIG_MULTIPROCESS_ALLOWED=y'] : [])
1690
1691 ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ]
1692
1693 default_targets = 'CONFIG_DEFAULT_TARGETS' in config_host
1694 actual_target_dirs = []
1695 fdt_required = []
1696 foreach target : target_dirs
1697   config_target = { 'TARGET_NAME': target.split('-')[0] }
1698   if target.endswith('linux-user')
1699     if targetos != 'linux'
1700       if default_targets
1701         continue
1702       endif
1703       error('Target @0@ is only available on a Linux host'.format(target))
1704     endif
1705     config_target += { 'CONFIG_LINUX_USER': 'y' }
1706   elif target.endswith('bsd-user')
1707     if 'CONFIG_BSD' not in config_host
1708       if default_targets
1709         continue
1710       endif
1711       error('Target @0@ is only available on a BSD host'.format(target))
1712     endif
1713     config_target += { 'CONFIG_BSD_USER': 'y' }
1714   elif target.endswith('softmmu')
1715     config_target += { 'CONFIG_SOFTMMU': 'y' }
1716   endif
1717   if target.endswith('-user')
1718     config_target += {
1719       'CONFIG_USER_ONLY': 'y',
1720       'CONFIG_QEMU_INTERP_PREFIX':
1721         config_host['CONFIG_QEMU_INTERP_PREFIX'].format(config_target['TARGET_NAME'])
1722     }
1723   endif
1724
1725   accel_kconfig = []
1726   foreach sym: accelerators
1727     if sym == 'CONFIG_TCG' or target in accelerator_targets.get(sym, [])
1728       config_target += { sym: 'y' }
1729       config_all += { sym: 'y' }
1730       if sym == 'CONFIG_TCG' and tcg_arch == 'tci'
1731         config_target += { 'CONFIG_TCG_INTERPRETER': 'y' }
1732       elif sym == 'CONFIG_XEN' and have_xen_pci_passthrough
1733         config_target += { 'CONFIG_XEN_PCI_PASSTHROUGH': 'y' }
1734       endif
1735       if target in modular_tcg
1736         config_target += { 'CONFIG_TCG_MODULAR': 'y' }
1737       else
1738         config_target += { 'CONFIG_TCG_BUILTIN': 'y' }
1739       endif
1740       accel_kconfig += [ sym + '=y' ]
1741     endif
1742   endforeach
1743   if accel_kconfig.length() == 0
1744     if default_targets
1745       continue
1746     endif
1747     error('No accelerator available for target @0@'.format(target))
1748   endif
1749
1750   actual_target_dirs += target
1751   config_target += keyval.load('configs/targets' / target + '.mak')
1752   config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
1753
1754   if 'TARGET_NEED_FDT' in config_target
1755     fdt_required += target
1756   endif
1757
1758   # Add default keys
1759   if 'TARGET_BASE_ARCH' not in config_target
1760     config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
1761   endif
1762   if 'TARGET_ABI_DIR' not in config_target
1763     config_target += {'TARGET_ABI_DIR': config_target['TARGET_ARCH']}
1764   endif
1765
1766   foreach k, v: disassemblers
1767     if config_host['ARCH'].startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k)
1768       foreach sym: v
1769         config_target += { sym: 'y' }
1770         config_all_disas += { sym: 'y' }
1771       endforeach
1772     endif
1773   endforeach
1774
1775   config_target_data = configuration_data()
1776   foreach k, v: config_target
1777     if not k.startswith('TARGET_') and not k.startswith('CONFIG_')
1778       # do nothing
1779     elif ignored.contains(k)
1780       # do nothing
1781     elif k == 'TARGET_BASE_ARCH'
1782       # Note that TARGET_BASE_ARCH ends up in config-target.h but it is
1783       # not used to select files from sourcesets.
1784       config_target_data.set('TARGET_' + v.to_upper(), 1)
1785     elif k == 'TARGET_NAME' or k == 'CONFIG_QEMU_INTERP_PREFIX'
1786       config_target_data.set_quoted(k, v)
1787     elif v == 'y'
1788       config_target_data.set(k, 1)
1789     else
1790       config_target_data.set(k, v)
1791     endif
1792   endforeach
1793   config_target_data.set('QEMU_ARCH',
1794                          'QEMU_ARCH_' + config_target['TARGET_BASE_ARCH'].to_upper())
1795   config_target_h += {target: configure_file(output: target + '-config-target.h',
1796                                                configuration: config_target_data)}
1797
1798   if target.endswith('-softmmu')
1799     config_input = meson.get_external_property(target, 'default')
1800     config_devices_mak = target + '-config-devices.mak'
1801     config_devices_mak = configure_file(
1802       input: ['configs/devices' / target / config_input + '.mak', 'Kconfig'],
1803       output: config_devices_mak,
1804       depfile: config_devices_mak + '.d',
1805       capture: true,
1806       command: [minikconf,
1807                 get_option('default_devices') ? '--defconfig' : '--allnoconfig',
1808                 config_devices_mak, '@DEPFILE@', '@INPUT@',
1809                 host_kconfig, accel_kconfig,
1810                 'CONFIG_' + config_target['TARGET_ARCH'].to_upper() + '=y'])
1811
1812     config_devices_data = configuration_data()
1813     config_devices = keyval.load(config_devices_mak)
1814     foreach k, v: config_devices
1815       config_devices_data.set(k, 1)
1816     endforeach
1817     config_devices_mak_list += config_devices_mak
1818     config_devices_h += {target: configure_file(output: target + '-config-devices.h',
1819                                                 configuration: config_devices_data)}
1820     config_target += config_devices
1821     config_all_devices += config_devices
1822   endif
1823   config_target_mak += {target: config_target}
1824 endforeach
1825 target_dirs = actual_target_dirs
1826
1827 # This configuration is used to build files that are shared by
1828 # multiple binaries, and then extracted out of the "common"
1829 # static_library target.
1830 #
1831 # We do not use all_sources()/all_dependencies(), because it would
1832 # build literally all source files, including devices only used by
1833 # targets that are not built for this compilation.  The CONFIG_ALL
1834 # pseudo symbol replaces it.
1835
1836 config_all += config_all_devices
1837 config_all += config_host
1838 config_all += config_all_disas
1839 config_all += {
1840   'CONFIG_XEN': config_host.has_key('CONFIG_XEN_BACKEND'),
1841   'CONFIG_SOFTMMU': have_system,
1842   'CONFIG_USER_ONLY': have_user,
1843   'CONFIG_ALL': true,
1844 }
1845
1846 ##############
1847 # Submodules #
1848 ##############
1849
1850 capstone = not_found
1851 capstone_opt = get_option('capstone')
1852 if capstone_opt in ['enabled', 'auto', 'system']
1853   have_internal = fs.exists(meson.current_source_dir() / 'capstone/Makefile')
1854   capstone = dependency('capstone', version: '>=4.0',
1855                         kwargs: static_kwargs, method: 'pkg-config',
1856                         required: capstone_opt == 'system' or
1857                                   capstone_opt == 'enabled' and not have_internal)
1858
1859   # Some versions of capstone have broken pkg-config file
1860   # that reports a wrong -I path, causing the #include to
1861   # fail later. If the system has such a broken version
1862   # do not use it.
1863   if capstone.found() and not cc.compiles('#include <capstone.h>',
1864                                           dependencies: [capstone])
1865     capstone = not_found
1866     if capstone_opt == 'system'
1867       error('system capstone requested, it does not appear to work')
1868     endif
1869   endif
1870
1871   if capstone.found()
1872     capstone_opt = 'system'
1873   elif have_internal
1874     capstone_opt = 'internal'
1875   else
1876     capstone_opt = 'disabled'
1877   endif
1878 endif
1879 if capstone_opt == 'internal'
1880   capstone_data = configuration_data()
1881   capstone_data.set('CAPSTONE_USE_SYS_DYN_MEM', '1')
1882
1883   capstone_files = files(
1884     'capstone/cs.c',
1885     'capstone/MCInst.c',
1886     'capstone/MCInstrDesc.c',
1887     'capstone/MCRegisterInfo.c',
1888     'capstone/SStream.c',
1889     'capstone/utils.c'
1890   )
1891
1892   if 'CONFIG_ARM_DIS' in config_all_disas
1893     capstone_data.set('CAPSTONE_HAS_ARM', '1')
1894     capstone_files += files(
1895       'capstone/arch/ARM/ARMDisassembler.c',
1896       'capstone/arch/ARM/ARMInstPrinter.c',
1897       'capstone/arch/ARM/ARMMapping.c',
1898       'capstone/arch/ARM/ARMModule.c'
1899     )
1900   endif
1901
1902   # FIXME: This config entry currently depends on a c++ compiler.
1903   # Which is needed for building libvixl, but not for capstone.
1904   if 'CONFIG_ARM_A64_DIS' in config_all_disas
1905     capstone_data.set('CAPSTONE_HAS_ARM64', '1')
1906     capstone_files += files(
1907       'capstone/arch/AArch64/AArch64BaseInfo.c',
1908       'capstone/arch/AArch64/AArch64Disassembler.c',
1909       'capstone/arch/AArch64/AArch64InstPrinter.c',
1910       'capstone/arch/AArch64/AArch64Mapping.c',
1911       'capstone/arch/AArch64/AArch64Module.c'
1912     )
1913   endif
1914
1915   if 'CONFIG_PPC_DIS' in config_all_disas
1916     capstone_data.set('CAPSTONE_HAS_POWERPC', '1')
1917     capstone_files += files(
1918       'capstone/arch/PowerPC/PPCDisassembler.c',
1919       'capstone/arch/PowerPC/PPCInstPrinter.c',
1920       'capstone/arch/PowerPC/PPCMapping.c',
1921       'capstone/arch/PowerPC/PPCModule.c'
1922     )
1923   endif
1924
1925   if 'CONFIG_S390_DIS' in config_all_disas
1926     capstone_data.set('CAPSTONE_HAS_SYSZ', '1')
1927     capstone_files += files(
1928       'capstone/arch/SystemZ/SystemZDisassembler.c',
1929       'capstone/arch/SystemZ/SystemZInstPrinter.c',
1930       'capstone/arch/SystemZ/SystemZMapping.c',
1931       'capstone/arch/SystemZ/SystemZModule.c',
1932       'capstone/arch/SystemZ/SystemZMCTargetDesc.c'
1933     )
1934   endif
1935
1936   if 'CONFIG_I386_DIS' in config_all_disas
1937     capstone_data.set('CAPSTONE_HAS_X86', 1)
1938     capstone_files += files(
1939       'capstone/arch/X86/X86Disassembler.c',
1940       'capstone/arch/X86/X86DisassemblerDecoder.c',
1941       'capstone/arch/X86/X86ATTInstPrinter.c',
1942       'capstone/arch/X86/X86IntelInstPrinter.c',
1943       'capstone/arch/X86/X86InstPrinterCommon.c',
1944       'capstone/arch/X86/X86Mapping.c',
1945       'capstone/arch/X86/X86Module.c'
1946     )
1947   endif
1948
1949   configure_file(output: 'capstone-defs.h', configuration: capstone_data)
1950
1951   capstone_cargs = [
1952     # FIXME: There does not seem to be a way to completely replace the c_args
1953     # that come from add_project_arguments() -- we can only add to them.
1954     # So: disable all warnings with a big hammer.
1955     '-Wno-error', '-w',
1956
1957     # Include all configuration defines via a header file, which will wind up
1958     # as a dependency on the object file, and thus changes here will result
1959     # in a rebuild.
1960     '-include', 'capstone-defs.h'
1961   ]
1962
1963   libcapstone = static_library('capstone',
1964                                build_by_default: false,
1965                                sources: capstone_files,
1966                                c_args: capstone_cargs,
1967                                include_directories: 'capstone/include')
1968   capstone = declare_dependency(link_with: libcapstone,
1969                                 include_directories: 'capstone/include/capstone')
1970 endif
1971
1972 slirp = not_found
1973 slirp_opt = 'disabled'
1974 if have_system
1975   slirp_opt = get_option('slirp')
1976   if slirp_opt in ['enabled', 'auto', 'system']
1977     have_internal = fs.exists(meson.current_source_dir() / 'slirp/meson.build')
1978     slirp = dependency('slirp', kwargs: static_kwargs,
1979                        method: 'pkg-config',
1980                        required: slirp_opt == 'system' or
1981                                  slirp_opt == 'enabled' and not have_internal)
1982     if slirp.found()
1983       slirp_opt = 'system'
1984     elif have_internal
1985       slirp_opt = 'internal'
1986     else
1987       slirp_opt = 'disabled'
1988     endif
1989   endif
1990   if slirp_opt == 'internal'
1991     slirp_deps = []
1992     if targetos == 'windows'
1993       slirp_deps = cc.find_library('iphlpapi')
1994     elif targetos == 'darwin'
1995       slirp_deps = cc.find_library('resolv')
1996     endif
1997     slirp_conf = configuration_data()
1998     slirp_conf.set('SLIRP_MAJOR_VERSION', meson.project_version().split('.')[0])
1999     slirp_conf.set('SLIRP_MINOR_VERSION', meson.project_version().split('.')[1])
2000     slirp_conf.set('SLIRP_MICRO_VERSION', meson.project_version().split('.')[2])
2001     slirp_conf.set_quoted('SLIRP_VERSION_STRING', meson.project_version())
2002     slirp_cargs = ['-DG_LOG_DOMAIN="Slirp"']
2003     slirp_files = [
2004       'slirp/src/arp_table.c',
2005       'slirp/src/bootp.c',
2006       'slirp/src/cksum.c',
2007       'slirp/src/dhcpv6.c',
2008       'slirp/src/dnssearch.c',
2009       'slirp/src/if.c',
2010       'slirp/src/ip6_icmp.c',
2011       'slirp/src/ip6_input.c',
2012       'slirp/src/ip6_output.c',
2013       'slirp/src/ip_icmp.c',
2014       'slirp/src/ip_input.c',
2015       'slirp/src/ip_output.c',
2016       'slirp/src/mbuf.c',
2017       'slirp/src/misc.c',
2018       'slirp/src/ncsi.c',
2019       'slirp/src/ndp_table.c',
2020       'slirp/src/sbuf.c',
2021       'slirp/src/slirp.c',
2022       'slirp/src/socket.c',
2023       'slirp/src/state.c',
2024       'slirp/src/stream.c',
2025       'slirp/src/tcp_input.c',
2026       'slirp/src/tcp_output.c',
2027       'slirp/src/tcp_subr.c',
2028       'slirp/src/tcp_timer.c',
2029       'slirp/src/tftp.c',
2030       'slirp/src/udp.c',
2031       'slirp/src/udp6.c',
2032       'slirp/src/util.c',
2033       'slirp/src/version.c',
2034       'slirp/src/vmstate.c',
2035     ]
2036
2037     configure_file(
2038       input : 'slirp/src/libslirp-version.h.in',
2039       output : 'libslirp-version.h',
2040       configuration: slirp_conf)
2041
2042     slirp_inc = include_directories('slirp', 'slirp/src')
2043     libslirp = static_library('slirp',
2044                               build_by_default: false,
2045                               sources: slirp_files,
2046                               c_args: slirp_cargs,
2047                               include_directories: slirp_inc)
2048     slirp = declare_dependency(link_with: libslirp,
2049                                dependencies: slirp_deps,
2050                                include_directories: slirp_inc)
2051   endif
2052 endif
2053
2054 # For CFI, we need to compile slirp as a static library together with qemu.
2055 # This is because we register slirp functions as callbacks for QEMU Timers.
2056 # When using a system-wide shared libslirp, the type information for the
2057 # callback is missing and the timer call produces a false positive with CFI.
2058 #
2059 # Now that slirp_opt has been defined, check if the selected slirp is compatible
2060 # with control-flow integrity.
2061 if get_option('cfi') and slirp_opt == 'system'
2062   error('Control-Flow Integrity is not compatible with system-wide slirp.' \
2063          + ' Please configure with --enable-slirp=git')
2064 endif
2065
2066 fdt = not_found
2067 fdt_opt = get_option('fdt')
2068 if have_system
2069   if fdt_opt in ['enabled', 'auto', 'system']
2070     have_internal = fs.exists(meson.current_source_dir() / 'dtc/libfdt/Makefile.libfdt')
2071     fdt = cc.find_library('fdt', kwargs: static_kwargs,
2072                           required: fdt_opt == 'system' or
2073                                     fdt_opt == 'enabled' and not have_internal)
2074     if fdt.found() and cc.links('''
2075        #include <libfdt.h>
2076        #include <libfdt_env.h>
2077        int main(void) { fdt_check_full(NULL, 0); return 0; }''',
2078          dependencies: fdt)
2079       fdt_opt = 'system'
2080     elif fdt_opt == 'system'
2081        error('system libfdt requested, but it is too old (1.5.1 or newer required)')
2082     elif have_internal
2083       fdt_opt = 'internal'
2084     else
2085       fdt_opt = 'disabled'
2086       fdt = not_found
2087     endif
2088   endif
2089   if fdt_opt == 'internal'
2090     fdt_files = files(
2091       'dtc/libfdt/fdt.c',
2092       'dtc/libfdt/fdt_ro.c',
2093       'dtc/libfdt/fdt_wip.c',
2094       'dtc/libfdt/fdt_sw.c',
2095       'dtc/libfdt/fdt_rw.c',
2096       'dtc/libfdt/fdt_strerror.c',
2097       'dtc/libfdt/fdt_empty_tree.c',
2098       'dtc/libfdt/fdt_addresses.c',
2099       'dtc/libfdt/fdt_overlay.c',
2100       'dtc/libfdt/fdt_check.c',
2101     )
2102
2103     fdt_inc = include_directories('dtc/libfdt')
2104     libfdt = static_library('fdt',
2105                             build_by_default: false,
2106                             sources: fdt_files,
2107                             include_directories: fdt_inc)
2108     fdt = declare_dependency(link_with: libfdt,
2109                              include_directories: fdt_inc)
2110   endif
2111 endif
2112 if not fdt.found() and fdt_required.length() > 0
2113   error('fdt not available but required by targets ' + ', '.join(fdt_required))
2114 endif
2115
2116 config_host_data.set('CONFIG_CAPSTONE', capstone.found())
2117 config_host_data.set('CONFIG_FDT', fdt.found())
2118 config_host_data.set('CONFIG_SLIRP', slirp.found())
2119
2120 #####################
2121 # Generated sources #
2122 #####################
2123
2124 genh += configure_file(output: 'config-host.h', configuration: config_host_data)
2125
2126 hxtool = find_program('scripts/hxtool')
2127 shaderinclude = find_program('scripts/shaderinclude.pl')
2128 qapi_gen = find_program('scripts/qapi-gen.py')
2129 qapi_gen_depends = [ meson.current_source_dir() / 'scripts/qapi/__init__.py',
2130                      meson.current_source_dir() / 'scripts/qapi/commands.py',
2131                      meson.current_source_dir() / 'scripts/qapi/common.py',
2132                      meson.current_source_dir() / 'scripts/qapi/error.py',
2133                      meson.current_source_dir() / 'scripts/qapi/events.py',
2134                      meson.current_source_dir() / 'scripts/qapi/expr.py',
2135                      meson.current_source_dir() / 'scripts/qapi/gen.py',
2136                      meson.current_source_dir() / 'scripts/qapi/introspect.py',
2137                      meson.current_source_dir() / 'scripts/qapi/parser.py',
2138                      meson.current_source_dir() / 'scripts/qapi/schema.py',
2139                      meson.current_source_dir() / 'scripts/qapi/source.py',
2140                      meson.current_source_dir() / 'scripts/qapi/types.py',
2141                      meson.current_source_dir() / 'scripts/qapi/visit.py',
2142                      meson.current_source_dir() / 'scripts/qapi/common.py',
2143                      meson.current_source_dir() / 'scripts/qapi-gen.py'
2144 ]
2145
2146 tracetool = [
2147   python, files('scripts/tracetool.py'),
2148    '--backend=' + ','.join(get_option('trace_backends'))
2149 ]
2150 tracetool_depends = files(
2151   'scripts/tracetool/backend/log.py',
2152   'scripts/tracetool/backend/__init__.py',
2153   'scripts/tracetool/backend/dtrace.py',
2154   'scripts/tracetool/backend/ftrace.py',
2155   'scripts/tracetool/backend/simple.py',
2156   'scripts/tracetool/backend/syslog.py',
2157   'scripts/tracetool/backend/ust.py',
2158   'scripts/tracetool/format/tcg_h.py',
2159   'scripts/tracetool/format/ust_events_c.py',
2160   'scripts/tracetool/format/ust_events_h.py',
2161   'scripts/tracetool/format/__init__.py',
2162   'scripts/tracetool/format/d.py',
2163   'scripts/tracetool/format/tcg_helper_c.py',
2164   'scripts/tracetool/format/simpletrace_stap.py',
2165   'scripts/tracetool/format/c.py',
2166   'scripts/tracetool/format/h.py',
2167   'scripts/tracetool/format/tcg_helper_h.py',
2168   'scripts/tracetool/format/log_stap.py',
2169   'scripts/tracetool/format/stap.py',
2170   'scripts/tracetool/format/tcg_helper_wrapper_h.py',
2171   'scripts/tracetool/__init__.py',
2172   'scripts/tracetool/transform.py',
2173   'scripts/tracetool/vcpu.py'
2174 )
2175
2176 qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
2177                     meson.current_source_dir(),
2178                     config_host['PKGVERSION'], meson.project_version()]
2179 qemu_version = custom_target('qemu-version.h',
2180                              output: 'qemu-version.h',
2181                              command: qemu_version_cmd,
2182                              capture: true,
2183                              build_by_default: true,
2184                              build_always_stale: true)
2185 genh += qemu_version
2186
2187 hxdep = []
2188 hx_headers = [
2189   ['qemu-options.hx', 'qemu-options.def'],
2190   ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
2191 ]
2192 if have_system
2193   hx_headers += [
2194     ['hmp-commands.hx', 'hmp-commands.h'],
2195     ['hmp-commands-info.hx', 'hmp-commands-info.h'],
2196   ]
2197 endif
2198 foreach d : hx_headers
2199   hxdep += custom_target(d[1],
2200                 input: files(d[0]),
2201                 output: d[1],
2202                 capture: true,
2203                 build_by_default: true, # to be removed when added to a target
2204                 command: [hxtool, '-h', '@INPUT0@'])
2205 endforeach
2206 genh += hxdep
2207
2208 ###################
2209 # Collect sources #
2210 ###################
2211
2212 authz_ss = ss.source_set()
2213 blockdev_ss = ss.source_set()
2214 block_ss = ss.source_set()
2215 bsd_user_ss = ss.source_set()
2216 chardev_ss = ss.source_set()
2217 common_ss = ss.source_set()
2218 crypto_ss = ss.source_set()
2219 io_ss = ss.source_set()
2220 linux_user_ss = ss.source_set()
2221 qmp_ss = ss.source_set()
2222 qom_ss = ss.source_set()
2223 softmmu_ss = ss.source_set()
2224 specific_fuzz_ss = ss.source_set()
2225 specific_ss = ss.source_set()
2226 stub_ss = ss.source_set()
2227 trace_ss = ss.source_set()
2228 user_ss = ss.source_set()
2229 util_ss = ss.source_set()
2230
2231 # accel modules
2232 qtest_module_ss = ss.source_set()
2233 tcg_module_ss = ss.source_set()
2234
2235 modules = {}
2236 target_modules = {}
2237 hw_arch = {}
2238 target_arch = {}
2239 target_softmmu_arch = {}
2240 target_user_arch = {}
2241
2242 ###############
2243 # Trace files #
2244 ###############
2245
2246 # TODO: add each directory to the subdirs from its own meson.build, once
2247 # we have those
2248 trace_events_subdirs = [
2249   'crypto',
2250   'qapi',
2251   'qom',
2252   'monitor',
2253   'util',
2254 ]
2255 if have_user
2256   trace_events_subdirs += [ 'linux-user' ]
2257 endif
2258 if have_block
2259   trace_events_subdirs += [
2260     'authz',
2261     'block',
2262     'io',
2263     'nbd',
2264     'scsi',
2265   ]
2266 endif
2267 if have_system
2268   trace_events_subdirs += [
2269     'accel/kvm',
2270     'audio',
2271     'backends',
2272     'backends/tpm',
2273     'chardev',
2274     'ebpf',
2275     'hw/9pfs',
2276     'hw/acpi',
2277     'hw/adc',
2278     'hw/alpha',
2279     'hw/arm',
2280     'hw/audio',
2281     'hw/block',
2282     'hw/block/dataplane',
2283     'hw/char',
2284     'hw/display',
2285     'hw/dma',
2286     'hw/hppa',
2287     'hw/hyperv',
2288     'hw/i2c',
2289     'hw/i386',
2290     'hw/i386/xen',
2291     'hw/ide',
2292     'hw/input',
2293     'hw/intc',
2294     'hw/isa',
2295     'hw/mem',
2296     'hw/mips',
2297     'hw/misc',
2298     'hw/misc/macio',
2299     'hw/net',
2300     'hw/net/can',
2301     'hw/nubus',
2302     'hw/nvme',
2303     'hw/nvram',
2304     'hw/pci',
2305     'hw/pci-host',
2306     'hw/ppc',
2307     'hw/rdma',
2308     'hw/rdma/vmw',
2309     'hw/rtc',
2310     'hw/s390x',
2311     'hw/scsi',
2312     'hw/sd',
2313     'hw/sparc',
2314     'hw/sparc64',
2315     'hw/ssi',
2316     'hw/timer',
2317     'hw/tpm',
2318     'hw/usb',
2319     'hw/vfio',
2320     'hw/virtio',
2321     'hw/watchdog',
2322     'hw/xen',
2323     'hw/gpio',
2324     'migration',
2325     'net',
2326     'softmmu',
2327     'ui',
2328     'hw/remote',
2329   ]
2330 endif
2331 if have_system or have_user
2332   trace_events_subdirs += [
2333     'accel/tcg',
2334     'hw/core',
2335     'target/arm',
2336     'target/arm/hvf',
2337     'target/hppa',
2338     'target/i386',
2339     'target/i386/kvm',
2340     'target/mips/tcg',
2341     'target/ppc',
2342     'target/riscv',
2343     'target/s390x',
2344     'target/s390x/kvm',
2345     'target/sparc',
2346   ]
2347 endif
2348
2349 vhost_user = not_found
2350 if 'CONFIG_VHOST_USER' in config_host
2351   libvhost_user = subproject('libvhost-user')
2352   vhost_user = libvhost_user.get_variable('vhost_user_dep')
2353 endif
2354
2355 subdir('qapi')
2356 subdir('qobject')
2357 subdir('stubs')
2358 subdir('trace')
2359 subdir('util')
2360 subdir('qom')
2361 subdir('authz')
2362 subdir('crypto')
2363 subdir('ui')
2364
2365
2366 if enable_modules
2367   libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
2368   modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
2369 endif
2370
2371 stub_ss = stub_ss.apply(config_all, strict: false)
2372
2373 util_ss.add_all(trace_ss)
2374 util_ss = util_ss.apply(config_all, strict: false)
2375 libqemuutil = static_library('qemuutil',
2376                              sources: util_ss.sources() + stub_ss.sources() + genh,
2377                              dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc, pixman])
2378 qemuutil = declare_dependency(link_with: libqemuutil,
2379                               sources: genh + version_res)
2380
2381 if have_system or have_user
2382   decodetree = generator(find_program('scripts/decodetree.py'),
2383                          output: 'decode-@BASENAME@.c.inc',
2384                          arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
2385   subdir('libdecnumber')
2386   subdir('target')
2387 endif
2388
2389 subdir('audio')
2390 subdir('io')
2391 subdir('chardev')
2392 subdir('fsdev')
2393 subdir('dump')
2394
2395 if have_block
2396   block_ss.add(files(
2397     'block.c',
2398     'blockjob.c',
2399     'job.c',
2400     'qemu-io-cmds.c',
2401   ))
2402   block_ss.add(when: 'CONFIG_REPLICATION', if_true: files('replication.c'))
2403
2404   subdir('nbd')
2405   subdir('scsi')
2406   subdir('block')
2407
2408   blockdev_ss.add(files(
2409     'blockdev.c',
2410     'blockdev-nbd.c',
2411     'iothread.c',
2412     'job-qmp.c',
2413   ), gnutls)
2414
2415   # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
2416   # os-win32.c does not
2417   blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
2418   softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
2419 endif
2420
2421 common_ss.add(files('cpus-common.c'))
2422
2423 subdir('softmmu')
2424
2425 common_ss.add(capstone)
2426 specific_ss.add(files('cpu.c', 'disas.c', 'gdbstub.c'), capstone)
2427
2428 # Work around a gcc bug/misfeature wherein constant propagation looks
2429 # through an alias:
2430 #   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99696
2431 # to guess that a const variable is always zero.  Without lto, this is
2432 # impossible, as the alias is restricted to page-vary-common.c.  Indeed,
2433 # without lto, not even the alias is required -- we simply use different
2434 # declarations in different compilation units.
2435 pagevary = files('page-vary-common.c')
2436 if get_option('b_lto')
2437   pagevary_flags = ['-fno-lto']
2438   if get_option('cfi')
2439     pagevary_flags += '-fno-sanitize=cfi-icall'
2440   endif
2441   pagevary = static_library('page-vary-common', sources: pagevary,
2442                             c_args: pagevary_flags)
2443   pagevary = declare_dependency(link_with: pagevary)
2444 endif
2445 common_ss.add(pagevary)
2446 specific_ss.add(files('page-vary.c'))
2447
2448 subdir('backends')
2449 subdir('disas')
2450 subdir('migration')
2451 subdir('monitor')
2452 subdir('net')
2453 subdir('replay')
2454 subdir('semihosting')
2455 subdir('hw')
2456 subdir('tcg')
2457 subdir('fpu')
2458 subdir('accel')
2459 subdir('plugins')
2460 subdir('bsd-user')
2461 subdir('linux-user')
2462 subdir('ebpf')
2463
2464 bsd_user_ss.add(files('gdbstub.c'))
2465 specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss)
2466
2467 linux_user_ss.add(files('gdbstub.c', 'thunk.c'))
2468 specific_ss.add_all(when: 'CONFIG_LINUX_USER', if_true: linux_user_ss)
2469
2470 # needed for fuzzing binaries
2471 subdir('tests/qtest/libqos')
2472 subdir('tests/qtest/fuzz')
2473
2474 # accel modules
2475 tcg_real_module_ss = ss.source_set()
2476 tcg_real_module_ss.add_all(when: 'CONFIG_TCG_MODULAR', if_true: tcg_module_ss)
2477 specific_ss.add_all(when: 'CONFIG_TCG_BUILTIN', if_true: tcg_module_ss)
2478 target_modules += { 'accel' : { 'qtest': qtest_module_ss,
2479                                 'tcg': tcg_real_module_ss }}
2480
2481 ########################
2482 # Library dependencies #
2483 ########################
2484
2485 modinfo_collect = find_program('scripts/modinfo-collect.py')
2486 modinfo_generate = find_program('scripts/modinfo-generate.py')
2487 modinfo_files = []
2488
2489 block_mods = []
2490 softmmu_mods = []
2491 foreach d, list : modules
2492   foreach m, module_ss : list
2493     if enable_modules and targetos != 'windows'
2494       module_ss = module_ss.apply(config_all, strict: false)
2495       sl = static_library(d + '-' + m, [genh, module_ss.sources()],
2496                           dependencies: [modulecommon, module_ss.dependencies()], pic: true)
2497       if d == 'block'
2498         block_mods += sl
2499       else
2500         softmmu_mods += sl
2501       endif
2502       if module_ss.sources() != []
2503         # FIXME: Should use sl.extract_all_objects(recursive: true) as
2504         # input. Sources can be used multiple times but objects are
2505         # unique when it comes to lookup in compile_commands.json.
2506         # Depnds on a mesion version with
2507         # https://github.com/mesonbuild/meson/pull/8900
2508         modinfo_files += custom_target(d + '-' + m + '.modinfo',
2509                                        output: d + '-' + m + '.modinfo',
2510                                        input: module_ss.sources() + genh,
2511                                        capture: true,
2512                                        command: [modinfo_collect, module_ss.sources()])
2513       endif
2514     else
2515       if d == 'block'
2516         block_ss.add_all(module_ss)
2517       else
2518         softmmu_ss.add_all(module_ss)
2519       endif
2520     endif
2521   endforeach
2522 endforeach
2523
2524 foreach d, list : target_modules
2525   foreach m, module_ss : list
2526     if enable_modules and targetos != 'windows'
2527       foreach target : target_dirs
2528         if target.endswith('-softmmu')
2529           config_target = config_target_mak[target]
2530           config_target += config_host
2531           target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
2532           c_args = ['-DNEED_CPU_H',
2533                     '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
2534                     '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
2535           target_module_ss = module_ss.apply(config_target, strict: false)
2536           if target_module_ss.sources() != []
2537             module_name = d + '-' + m + '-' + config_target['TARGET_NAME']
2538             sl = static_library(module_name,
2539                                 [genh, target_module_ss.sources()],
2540                                 dependencies: [modulecommon, target_module_ss.dependencies()],
2541                                 include_directories: target_inc,
2542                                 c_args: c_args,
2543                                 pic: true)
2544             softmmu_mods += sl
2545             # FIXME: Should use sl.extract_all_objects(recursive: true) too.
2546             modinfo_files += custom_target(module_name + '.modinfo',
2547                                            output: module_name + '.modinfo',
2548                                            input: target_module_ss.sources() + genh,
2549                                            capture: true,
2550                                            command: [modinfo_collect, '--target', target, target_module_ss.sources()])
2551           endif
2552         endif
2553       endforeach
2554     else
2555       specific_ss.add_all(module_ss)
2556     endif
2557   endforeach
2558 endforeach
2559
2560 if enable_modules
2561   modinfo_src = custom_target('modinfo.c',
2562                               output: 'modinfo.c',
2563                               input: modinfo_files,
2564                               command: [modinfo_generate, '@INPUT@'],
2565                               capture: true)
2566   modinfo_lib = static_library('modinfo', modinfo_src)
2567   modinfo_dep = declare_dependency(link_whole: modinfo_lib)
2568   softmmu_ss.add(modinfo_dep)
2569 endif
2570
2571 nm = find_program('nm')
2572 undefsym = find_program('scripts/undefsym.py')
2573 block_syms = custom_target('block.syms', output: 'block.syms',
2574                              input: [libqemuutil, block_mods],
2575                              capture: true,
2576                              command: [undefsym, nm, '@INPUT@'])
2577 qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
2578                              input: [libqemuutil, softmmu_mods],
2579                              capture: true,
2580                              command: [undefsym, nm, '@INPUT@'])
2581
2582 qom_ss = qom_ss.apply(config_host, strict: false)
2583 libqom = static_library('qom', qom_ss.sources() + genh,
2584                         dependencies: [qom_ss.dependencies()],
2585                         name_suffix: 'fa')
2586
2587 qom = declare_dependency(link_whole: libqom)
2588
2589 authz_ss = authz_ss.apply(config_host, strict: false)
2590 libauthz = static_library('authz', authz_ss.sources() + genh,
2591                           dependencies: [authz_ss.dependencies()],
2592                           name_suffix: 'fa',
2593                           build_by_default: false)
2594
2595 authz = declare_dependency(link_whole: libauthz,
2596                            dependencies: qom)
2597
2598 crypto_ss = crypto_ss.apply(config_host, strict: false)
2599 libcrypto = static_library('crypto', crypto_ss.sources() + genh,
2600                            dependencies: [crypto_ss.dependencies()],
2601                            name_suffix: 'fa',
2602                            build_by_default: false)
2603
2604 crypto = declare_dependency(link_whole: libcrypto,
2605                             dependencies: [authz, qom])
2606
2607 io_ss = io_ss.apply(config_host, strict: false)
2608 libio = static_library('io', io_ss.sources() + genh,
2609                        dependencies: [io_ss.dependencies()],
2610                        link_with: libqemuutil,
2611                        name_suffix: 'fa',
2612                        build_by_default: false)
2613
2614 io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
2615
2616 libmigration = static_library('migration', sources: migration_files + genh,
2617                               name_suffix: 'fa',
2618                               build_by_default: false)
2619 migration = declare_dependency(link_with: libmigration,
2620                                dependencies: [zlib, qom, io])
2621 softmmu_ss.add(migration)
2622
2623 block_ss = block_ss.apply(config_host, strict: false)
2624 libblock = static_library('block', block_ss.sources() + genh,
2625                           dependencies: block_ss.dependencies(),
2626                           link_depends: block_syms,
2627                           name_suffix: 'fa',
2628                           build_by_default: false)
2629
2630 block = declare_dependency(link_whole: [libblock],
2631                            link_args: '@block.syms',
2632                            dependencies: [crypto, io])
2633
2634 blockdev_ss = blockdev_ss.apply(config_host, strict: false)
2635 libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
2636                              dependencies: blockdev_ss.dependencies(),
2637                              name_suffix: 'fa',
2638                              build_by_default: false)
2639
2640 blockdev = declare_dependency(link_whole: [libblockdev],
2641                               dependencies: [block])
2642
2643 qmp_ss = qmp_ss.apply(config_host, strict: false)
2644 libqmp = static_library('qmp', qmp_ss.sources() + genh,
2645                         dependencies: qmp_ss.dependencies(),
2646                         name_suffix: 'fa',
2647                         build_by_default: false)
2648
2649 qmp = declare_dependency(link_whole: [libqmp])
2650
2651 libchardev = static_library('chardev', chardev_ss.sources() + genh,
2652                             name_suffix: 'fa',
2653                             dependencies: [gnutls],
2654                             build_by_default: false)
2655
2656 chardev = declare_dependency(link_whole: libchardev)
2657
2658 libhwcore = static_library('hwcore', sources: hwcore_files + genh,
2659                            name_suffix: 'fa',
2660                            build_by_default: false)
2661 hwcore = declare_dependency(link_whole: libhwcore)
2662 common_ss.add(hwcore)
2663
2664 ###########
2665 # Targets #
2666 ###########
2667
2668 foreach m : block_mods + softmmu_mods
2669   shared_module(m.name(),
2670                 name_prefix: '',
2671                 link_whole: m,
2672                 install: true,
2673                 install_dir: qemu_moddir)
2674 endforeach
2675
2676 softmmu_ss.add(authz, blockdev, chardev, crypto, io, qmp)
2677 common_ss.add(qom, qemuutil)
2678
2679 common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
2680 common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
2681
2682 common_all = common_ss.apply(config_all, strict: false)
2683 common_all = static_library('common',
2684                             build_by_default: false,
2685                             sources: common_all.sources() + genh,
2686                             implicit_include_directories: false,
2687                             dependencies: common_all.dependencies(),
2688                             name_suffix: 'fa')
2689
2690 feature_to_c = find_program('scripts/feature_to_c.sh')
2691
2692 emulators = {}
2693 foreach target : target_dirs
2694   config_target = config_target_mak[target]
2695   target_name = config_target['TARGET_NAME']
2696   arch = config_target['TARGET_BASE_ARCH']
2697   arch_srcs = [config_target_h[target]]
2698   arch_deps = []
2699   c_args = ['-DNEED_CPU_H',
2700             '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
2701             '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
2702   link_args = emulator_link_args
2703
2704   config_target += config_host
2705   target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
2706   if targetos == 'linux'
2707     target_inc += include_directories('linux-headers', is_system: true)
2708   endif
2709   if target.endswith('-softmmu')
2710     qemu_target_name = 'qemu-system-' + target_name
2711     target_type='system'
2712     t = target_softmmu_arch[arch].apply(config_target, strict: false)
2713     arch_srcs += t.sources()
2714     arch_deps += t.dependencies()
2715
2716     hw_dir = target_name == 'sparc64' ? 'sparc64' : arch
2717     hw = hw_arch[hw_dir].apply(config_target, strict: false)
2718     arch_srcs += hw.sources()
2719     arch_deps += hw.dependencies()
2720
2721     arch_srcs += config_devices_h[target]
2722     link_args += ['@block.syms', '@qemu.syms']
2723   else
2724     abi = config_target['TARGET_ABI_DIR']
2725     target_type='user'
2726     qemu_target_name = 'qemu-' + target_name
2727     if arch in target_user_arch
2728       t = target_user_arch[arch].apply(config_target, strict: false)
2729       arch_srcs += t.sources()
2730       arch_deps += t.dependencies()
2731     endif
2732     if 'CONFIG_LINUX_USER' in config_target
2733       base_dir = 'linux-user'
2734       target_inc += include_directories('linux-user/host/' / config_host['ARCH'])
2735     endif
2736     if 'CONFIG_BSD_USER' in config_target
2737       base_dir = 'bsd-user'
2738       target_inc += include_directories('bsd-user/' / targetos)
2739       dir = base_dir / abi
2740       arch_srcs += files(dir / 'target_arch_cpu.c')
2741     endif
2742     target_inc += include_directories(
2743       base_dir,
2744       base_dir / abi,
2745     )
2746     if 'CONFIG_LINUX_USER' in config_target
2747       dir = base_dir / abi
2748       arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
2749       if config_target.has_key('TARGET_SYSTBL_ABI')
2750         arch_srcs += \
2751           syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
2752                                              extra_args : config_target['TARGET_SYSTBL_ABI'])
2753       endif
2754     endif
2755   endif
2756
2757   if 'TARGET_XML_FILES' in config_target
2758     gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
2759                                 output: target + '-gdbstub-xml.c',
2760                                 input: files(config_target['TARGET_XML_FILES'].split()),
2761                                 command: [feature_to_c, '@INPUT@'],
2762                                 capture: true)
2763     arch_srcs += gdbstub_xml
2764   endif
2765
2766   t = target_arch[arch].apply(config_target, strict: false)
2767   arch_srcs += t.sources()
2768   arch_deps += t.dependencies()
2769
2770   target_common = common_ss.apply(config_target, strict: false)
2771   objects = common_all.extract_objects(target_common.sources())
2772   deps = target_common.dependencies()
2773
2774   target_specific = specific_ss.apply(config_target, strict: false)
2775   arch_srcs += target_specific.sources()
2776   arch_deps += target_specific.dependencies()
2777
2778   lib = static_library('qemu-' + target,
2779                  sources: arch_srcs + genh,
2780                  dependencies: arch_deps,
2781                  objects: objects,
2782                  include_directories: target_inc,
2783                  c_args: c_args,
2784                  build_by_default: false,
2785                  name_suffix: 'fa')
2786
2787   if target.endswith('-softmmu')
2788     execs = [{
2789       'name': 'qemu-system-' + target_name,
2790       'win_subsystem': 'console',
2791       'sources': files('softmmu/main.c'),
2792       'dependencies': []
2793     }]
2794     if targetos == 'windows' and (sdl.found() or gtk.found())
2795       execs += [{
2796         'name': 'qemu-system-' + target_name + 'w',
2797         'win_subsystem': 'windows',
2798         'sources': files('softmmu/main.c'),
2799         'dependencies': []
2800       }]
2801     endif
2802     if get_option('fuzzing')
2803       specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
2804       execs += [{
2805         'name': 'qemu-fuzz-' + target_name,
2806         'win_subsystem': 'console',
2807         'sources': specific_fuzz.sources(),
2808         'dependencies': specific_fuzz.dependencies(),
2809       }]
2810     endif
2811   else
2812     execs = [{
2813       'name': 'qemu-' + target_name,
2814       'win_subsystem': 'console',
2815       'sources': [],
2816       'dependencies': []
2817     }]
2818   endif
2819   foreach exe: execs
2820     exe_name = exe['name']
2821     if targetos == 'darwin'
2822       exe_name += '-unsigned'
2823     endif
2824
2825     emulator = executable(exe_name, exe['sources'],
2826                install: true,
2827                c_args: c_args,
2828                dependencies: arch_deps + deps + exe['dependencies'],
2829                objects: lib.extract_all_objects(recursive: true),
2830                link_language: link_language,
2831                link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
2832                link_args: link_args,
2833                win_subsystem: exe['win_subsystem'])
2834
2835     if targetos == 'darwin'
2836       icon = 'pc-bios/qemu.rsrc'
2837       build_input = [emulator, files(icon)]
2838       install_input = [
2839         get_option('bindir') / exe_name,
2840         meson.current_source_dir() / icon
2841       ]
2842       if 'CONFIG_HVF' in config_target
2843         entitlements = 'accel/hvf/entitlements.plist'
2844         build_input += files(entitlements)
2845         install_input += meson.current_source_dir() / entitlements
2846       endif
2847
2848       emulators += {exe['name'] : custom_target(exe['name'],
2849                    input: build_input,
2850                    output: exe['name'],
2851                    command: [
2852                      files('scripts/entitlement.sh'),
2853                      '@OUTPUT@',
2854                      '@INPUT@'
2855                    ])
2856       }
2857
2858       meson.add_install_script('scripts/entitlement.sh', '--install',
2859                                get_option('bindir') / exe['name'],
2860                                install_input)
2861     else
2862       emulators += {exe['name']: emulator}
2863     endif
2864
2865     if stap.found()
2866       foreach stp: [
2867         {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
2868         {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
2869         {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
2870         {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
2871       ]
2872         custom_target(exe['name'] + stp['ext'],
2873                       input: trace_events_all,
2874                       output: exe['name'] + stp['ext'],
2875                       install: stp['install'],
2876                       install_dir: get_option('datadir') / 'systemtap/tapset',
2877                       command: [
2878                         tracetool, '--group=all', '--format=' + stp['fmt'],
2879                         '--binary=' + stp['bin'],
2880                         '--target-name=' + target_name,
2881                         '--target-type=' + target_type,
2882                         '--probe-prefix=qemu.' + target_type + '.' + target_name,
2883                         '@INPUT@', '@OUTPUT@'
2884                       ],
2885                       depend_files: tracetool_depends)
2886       endforeach
2887     endif
2888   endforeach
2889 endforeach
2890
2891 # Other build targets
2892
2893 if 'CONFIG_PLUGIN' in config_host
2894   install_headers('include/qemu/qemu-plugin.h')
2895 endif
2896
2897 if 'CONFIG_GUEST_AGENT' in config_host
2898   subdir('qga')
2899 elif get_option('guest_agent_msi').enabled()
2900   error('Guest agent MSI requested, but the guest agent is not being built')
2901 endif
2902
2903 # Don't build qemu-keymap if xkbcommon is not explicitly enabled
2904 # when we don't build tools or system
2905 if xkbcommon.found()
2906   # used for the update-keymaps target, so include rules even if !have_tools
2907   qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
2908                            dependencies: [qemuutil, xkbcommon], install: have_tools)
2909 endif
2910
2911 if have_tools
2912   qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
2913              dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
2914   qemu_io = executable('qemu-io', files('qemu-io.c'),
2915              dependencies: [block, qemuutil], install: true)
2916   qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
2917                dependencies: [blockdev, qemuutil, gnutls], install: true)
2918
2919   subdir('storage-daemon')
2920   subdir('contrib/rdmacm-mux')
2921   subdir('contrib/elf2dmp')
2922
2923   executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
2924              dependencies: qemuutil,
2925              install: true)
2926
2927   if 'CONFIG_VHOST_USER' in config_host
2928     subdir('contrib/vhost-user-blk')
2929     subdir('contrib/vhost-user-gpu')
2930     subdir('contrib/vhost-user-input')
2931     subdir('contrib/vhost-user-scsi')
2932   endif
2933
2934   if targetos == 'linux'
2935     executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
2936                dependencies: [qemuutil, libcap_ng],
2937                install: true,
2938                install_dir: get_option('libexecdir'))
2939
2940     executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
2941                dependencies: [authz, crypto, io, qom, qemuutil,
2942                               libcap_ng, mpathpersist],
2943                install: true)
2944   endif
2945
2946   if have_ivshmem
2947     subdir('contrib/ivshmem-client')
2948     subdir('contrib/ivshmem-server')
2949   endif
2950 endif
2951
2952 subdir('scripts')
2953 subdir('tools')
2954 subdir('pc-bios')
2955 subdir('docs')
2956 subdir('tests')
2957 if gtk.found()
2958   subdir('po')
2959 endif
2960
2961 if host_machine.system() == 'windows'
2962   nsis_cmd = [
2963     find_program('scripts/nsis.py'),
2964     '@OUTPUT@',
2965     get_option('prefix'),
2966     meson.current_source_dir(),
2967     host_machine.cpu(),
2968     '--',
2969     '-DDISPLAYVERSION=' + meson.project_version(),
2970   ]
2971   if build_docs
2972     nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
2973   endif
2974   if gtk.found()
2975     nsis_cmd += '-DCONFIG_GTK=y'
2976   endif
2977
2978   nsis = custom_target('nsis',
2979                        output: 'qemu-setup-' + meson.project_version() + '.exe',
2980                        input: files('qemu.nsi'),
2981                        build_always_stale: true,
2982                        command: nsis_cmd + ['@INPUT@'])
2983   alias_target('installer', nsis)
2984 endif
2985
2986 #########################
2987 # Configuration summary #
2988 #########################
2989
2990 # Directories
2991 summary_info = {}
2992 summary_info += {'Install prefix':    get_option('prefix')}
2993 summary_info += {'BIOS directory':    qemu_datadir}
2994 summary_info += {'firmware path':     get_option('qemu_firmwarepath')}
2995 summary_info += {'binary directory':  get_option('bindir')}
2996 summary_info += {'library directory': get_option('libdir')}
2997 summary_info += {'module directory':  qemu_moddir}
2998 summary_info += {'libexec directory': get_option('libexecdir')}
2999 summary_info += {'include directory': get_option('includedir')}
3000 summary_info += {'config directory':  get_option('sysconfdir')}
3001 if targetos != 'windows'
3002   summary_info += {'local state directory': get_option('localstatedir')}
3003   summary_info += {'Manual directory':      get_option('mandir')}
3004 else
3005   summary_info += {'local state directory': 'queried at runtime'}
3006 endif
3007 summary_info += {'Doc directory':     get_option('docdir')}
3008 summary_info += {'Build directory':   meson.current_build_dir()}
3009 summary_info += {'Source path':       meson.current_source_dir()}
3010 summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
3011 summary(summary_info, bool_yn: true, section: 'Directories')
3012
3013 # Host binaries
3014 summary_info = {}
3015 summary_info += {'git':               config_host['GIT']}
3016 summary_info += {'make':              config_host['MAKE']}
3017 summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
3018 summary_info += {'sphinx-build':      sphinx_build}
3019 if config_host.has_key('HAVE_GDB_BIN')
3020   summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
3021 endif
3022 summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
3023 if targetos == 'windows' and config_host.has_key('CONFIG_GUEST_AGENT')
3024   summary_info += {'wixl':            wixl}
3025 endif
3026 if slirp_opt != 'disabled' and 'CONFIG_SLIRP_SMBD' in config_host
3027   summary_info += {'smbd':            config_host['CONFIG_SMBD_COMMAND']}
3028 endif
3029 summary(summary_info, bool_yn: true, section: 'Host binaries')
3030
3031 # Configurable features
3032 summary_info = {}
3033 summary_info += {'Documentation':     build_docs}
3034 summary_info += {'system-mode emulation': have_system}
3035 summary_info += {'user-mode emulation': have_user}
3036 summary_info += {'block layer':       have_block}
3037 summary_info += {'Install blobs':     get_option('install_blobs')}
3038 summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
3039 if config_host.has_key('CONFIG_MODULES')
3040   summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')}
3041 endif
3042 summary_info += {'fuzzing support':   get_option('fuzzing')}
3043 if have_system
3044   summary_info += {'Audio drivers':     ' '.join(audio_drivers_selected)}
3045 endif
3046 summary_info += {'Trace backends':    ','.join(get_option('trace_backends'))}
3047 if 'simple' in get_option('trace_backends')
3048   summary_info += {'Trace output file': get_option('trace_file') + '-<pid>'}
3049 endif
3050 summary_info += {'QOM debugging':     config_host.has_key('CONFIG_QOM_CAST_DEBUG')}
3051 summary_info += {'vhost-kernel support': config_host.has_key('CONFIG_VHOST_KERNEL')}
3052 summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')}
3053 summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')}
3054 summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')}
3055 summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')}
3056 summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_USER')}
3057 summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
3058 summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')}
3059 summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')}
3060 summary_info += {'build guest agent': config_host.has_key('CONFIG_GUEST_AGENT')}
3061 summary(summary_info, bool_yn: true, section: 'Configurable features')
3062
3063 # Compilation information
3064 summary_info = {}
3065 summary_info += {'host CPU':          cpu}
3066 summary_info += {'host endianness':   build_machine.endian()}
3067 summary_info += {'C compiler':        ' '.join(meson.get_compiler('c').cmd_array())}
3068 summary_info += {'Host C compiler':   ' '.join(meson.get_compiler('c', native: true).cmd_array())}
3069 if link_language == 'cpp'
3070   summary_info += {'C++ compiler':    ' '.join(meson.get_compiler('cpp').cmd_array())}
3071 else
3072   summary_info += {'C++ compiler':      false}
3073 endif
3074 if targetos == 'darwin'
3075   summary_info += {'Objective-C compiler': ' '.join(meson.get_compiler('objc').cmd_array())}
3076 endif
3077 if targetos == 'windows'
3078   if 'WIN_SDK' in config_host
3079     summary_info += {'Windows SDK':   config_host['WIN_SDK']}
3080   endif
3081 endif
3082 summary_info += {'CFLAGS':            ' '.join(get_option('c_args')
3083                                                + ['-O' + get_option('optimization')]
3084                                                + (get_option('debug') ? ['-g'] : []))}
3085 if link_language == 'cpp'
3086   summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args')
3087                                                + ['-O' + get_option('optimization')]
3088                                                + (get_option('debug') ? ['-g'] : []))}
3089 endif
3090 link_args = get_option(link_language + '_link_args')
3091 if link_args.length() > 0
3092   summary_info += {'LDFLAGS':         ' '.join(link_args)}
3093 endif
3094 summary_info += {'QEMU_CFLAGS':       config_host['QEMU_CFLAGS']}
3095 summary_info += {'QEMU_LDFLAGS':      config_host['QEMU_LDFLAGS']}
3096 summary_info += {'profiler':          config_host.has_key('CONFIG_PROFILER')}
3097 summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
3098 summary_info += {'PIE':               get_option('b_pie')}
3099 summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
3100 summary_info += {'malloc trim support': has_malloc_trim}
3101 summary_info += {'membarrier':        config_host.has_key('CONFIG_MEMBARRIER')}
3102 summary_info += {'debug stack usage': config_host.has_key('CONFIG_DEBUG_STACK_USAGE')}
3103 summary_info += {'mutex debugging':   config_host.has_key('CONFIG_DEBUG_MUTEX')}
3104 summary_info += {'memory allocator':  get_option('malloc')}
3105 summary_info += {'avx2 optimization': config_host.has_key('CONFIG_AVX2_OPT')}
3106 summary_info += {'avx512f optimization': config_host.has_key('CONFIG_AVX512F_OPT')}
3107 summary_info += {'gprof enabled':     config_host.has_key('CONFIG_GPROF')}
3108 summary_info += {'gcov':              get_option('b_coverage')}
3109 summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
3110 summary_info += {'CFI support':       get_option('cfi')}
3111 if get_option('cfi')
3112   summary_info += {'CFI debug support': get_option('cfi_debug')}
3113 endif
3114 summary_info += {'strip binaries':    get_option('strip')}
3115 summary_info += {'sparse':            sparse}
3116 summary_info += {'mingw32 support':   targetos == 'windows'}
3117
3118 # snarf the cross-compilation information for tests
3119 foreach target: target_dirs
3120   tcg_mak = meson.current_build_dir() / 'tests/tcg' / 'config-' + target + '.mak'
3121   if fs.exists(tcg_mak)
3122     config_cross_tcg = keyval.load(tcg_mak)
3123     target = config_cross_tcg['TARGET_NAME']
3124     compiler = ''
3125     if 'DOCKER_CROSS_CC_GUEST' in config_cross_tcg
3126       summary_info += {target + ' tests': config_cross_tcg['DOCKER_CROSS_CC_GUEST'] +
3127                                           ' via ' + config_cross_tcg['DOCKER_IMAGE']}
3128     elif 'CROSS_CC_GUEST' in config_cross_tcg
3129       summary_info += {target + ' tests'
3130                                 : config_cross_tcg['CROSS_CC_GUEST'] }
3131     endif
3132    endif
3133 endforeach
3134
3135 summary(summary_info, bool_yn: true, section: 'Compilation')
3136
3137 # Targets and accelerators
3138 summary_info = {}
3139 if have_system
3140   summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
3141   summary_info += {'HAX support':       config_all.has_key('CONFIG_HAX')}
3142   summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
3143   summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
3144   summary_info += {'NVMM support':      config_all.has_key('CONFIG_NVMM')}
3145   summary_info += {'Xen support':       config_host.has_key('CONFIG_XEN_BACKEND')}
3146   if config_host.has_key('CONFIG_XEN_BACKEND')
3147     summary_info += {'xen ctrl version':  config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
3148   endif
3149 endif
3150 summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
3151 if config_all.has_key('CONFIG_TCG')
3152   if get_option('tcg_interpreter')
3153     summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, experimental and slow)'}
3154   else
3155     summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
3156   endif
3157   summary_info += {'TCG plugins': config_host.has_key('CONFIG_PLUGIN')}
3158   summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
3159 endif
3160 summary_info += {'target list':       ' '.join(target_dirs)}
3161 if have_system
3162   summary_info += {'default devices':   get_option('default_devices')}
3163   summary_info += {'out of process emulation': multiprocess_allowed}
3164 endif
3165 summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
3166
3167 # Block layer
3168 summary_info = {}
3169 summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
3170 summary_info += {'coroutine pool':    config_host['CONFIG_COROUTINE_POOL'] == '1'}
3171 if have_block
3172   summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']}
3173   summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']}
3174   summary_info += {'Use block whitelist in tools': config_host.has_key('CONFIG_BDRV_WHITELIST_TOOLS')}
3175   summary_info += {'VirtFS support':    have_virtfs}
3176   summary_info += {'build virtiofs daemon': have_virtiofsd}
3177   summary_info += {'Live block migration': config_host.has_key('CONFIG_LIVE_BLOCK_MIGRATION')}
3178   summary_info += {'replication support': config_host.has_key('CONFIG_REPLICATION')}
3179   summary_info += {'bochs support':     config_host.has_key('CONFIG_BOCHS')}
3180   summary_info += {'cloop support':     config_host.has_key('CONFIG_CLOOP')}
3181   summary_info += {'dmg support':       config_host.has_key('CONFIG_DMG')}
3182   summary_info += {'qcow v1 support':   config_host.has_key('CONFIG_QCOW1')}
3183   summary_info += {'vdi support':       config_host.has_key('CONFIG_VDI')}
3184   summary_info += {'vvfat support':     config_host.has_key('CONFIG_VVFAT')}
3185   summary_info += {'qed support':       config_host.has_key('CONFIG_QED')}
3186   summary_info += {'parallels support': config_host.has_key('CONFIG_PARALLELS')}
3187   summary_info += {'FUSE exports':      fuse}
3188 endif
3189 summary(summary_info, bool_yn: true, section: 'Block layer support')
3190
3191 # Crypto
3192 summary_info = {}
3193 summary_info += {'TLS priority':      config_host['CONFIG_TLS_PRIORITY']}
3194 summary_info += {'GNUTLS support':    gnutls}
3195 if gnutls.found()
3196   summary_info += {'  GNUTLS crypto':   gnutls_crypto.found()}
3197 endif
3198 summary_info += {'libgcrypt':         gcrypt}
3199 summary_info += {'nettle':            nettle}
3200 if nettle.found()
3201    summary_info += {'  XTS':             xts != 'private'}
3202 endif
3203 summary_info += {'crypto afalg':      config_host.has_key('CONFIG_AF_ALG')}
3204 summary_info += {'rng-none':          config_host.has_key('CONFIG_RNG_NONE')}
3205 summary_info += {'Linux keyring':     config_host.has_key('CONFIG_SECRET_KEYRING')}
3206 summary(summary_info, bool_yn: true, section: 'Crypto')
3207
3208 # Libraries
3209 summary_info = {}
3210 if targetos == 'darwin'
3211   summary_info += {'Cocoa support':   cocoa}
3212 endif
3213 summary_info += {'SDL support':       sdl}
3214 summary_info += {'SDL image support': sdl_image}
3215 summary_info += {'GTK support':       gtk}
3216 summary_info += {'pixman':            pixman}
3217 summary_info += {'VTE support':       vte}
3218 summary_info += {'slirp support':     slirp_opt == 'internal' ? slirp_opt : slirp}
3219 summary_info += {'libtasn1':          tasn1}
3220 summary_info += {'PAM':               pam}
3221 summary_info += {'iconv support':     iconv}
3222 summary_info += {'curses support':    curses}
3223 summary_info += {'virgl support':     virgl}
3224 summary_info += {'curl support':      curl}
3225 summary_info += {'Multipath support': mpathpersist}
3226 summary_info += {'VNC support':       vnc}
3227 if vnc.found()
3228   summary_info += {'VNC SASL support':  sasl}
3229   summary_info += {'VNC JPEG support':  jpeg}
3230   summary_info += {'VNC PNG support':   png}
3231 endif
3232 if targetos not in ['darwin', 'haiku', 'windows']
3233   summary_info += {'OSS support':     oss}
3234 elif targetos == 'darwin'
3235   summary_info += {'CoreAudio support': coreaudio}
3236 elif targetos == 'windows'
3237   summary_info += {'DirectSound support': dsound}
3238 endif
3239 if targetos == 'linux'
3240   summary_info += {'ALSA support':    alsa}
3241   summary_info += {'PulseAudio support': pulse}
3242 endif
3243 summary_info += {'JACK support':      jack}
3244 summary_info += {'brlapi support':    brlapi}
3245 summary_info += {'vde support':       config_host.has_key('CONFIG_VDE')}
3246 summary_info += {'netmap support':    config_host.has_key('CONFIG_NETMAP')}
3247 summary_info += {'Linux AIO support': config_host.has_key('CONFIG_LINUX_AIO')}
3248 summary_info += {'Linux io_uring support': linux_io_uring}
3249 summary_info += {'ATTR/XATTR support': libattr}
3250 summary_info += {'RDMA support':      config_host.has_key('CONFIG_RDMA')}
3251 summary_info += {'PVRDMA support':    config_host.has_key('CONFIG_PVRDMA')}
3252 summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
3253 summary_info += {'libcap-ng support': libcap_ng}
3254 summary_info += {'bpf support':       libbpf}
3255 # TODO: add back protocol and server version
3256 summary_info += {'spice support':     config_host.has_key('CONFIG_SPICE')}
3257 summary_info += {'rbd support':       rbd}
3258 summary_info += {'xfsctl support':    config_host.has_key('CONFIG_XFS')}
3259 summary_info += {'smartcard support': cacard}
3260 summary_info += {'U2F support':       u2f}
3261 summary_info += {'libusb':            libusb}
3262 summary_info += {'usb net redir':     usbredir}
3263 summary_info += {'OpenGL support':    config_host.has_key('CONFIG_OPENGL')}
3264 summary_info += {'GBM':               gbm}
3265 summary_info += {'libiscsi support':  libiscsi}
3266 summary_info += {'libnfs support':    libnfs}
3267 if targetos == 'windows'
3268   if config_host.has_key('CONFIG_GUEST_AGENT')
3269     summary_info += {'QGA VSS support':   config_host.has_key('CONFIG_QGA_VSS')}
3270     summary_info += {'QGA w32 disk info': config_host.has_key('CONFIG_QGA_NTDDSCSI')}
3271   endif
3272 endif
3273 summary_info += {'seccomp support':   seccomp}
3274 summary_info += {'GlusterFS support': glusterfs}
3275 summary_info += {'TPM support':       config_host.has_key('CONFIG_TPM')}
3276 summary_info += {'libssh support':    config_host.has_key('CONFIG_LIBSSH')}
3277 summary_info += {'lzo support':       lzo}
3278 summary_info += {'snappy support':    snappy}
3279 summary_info += {'bzip2 support':     libbzip2}
3280 summary_info += {'lzfse support':     liblzfse}
3281 summary_info += {'zstd support':      zstd}
3282 summary_info += {'NUMA host support': config_host.has_key('CONFIG_NUMA')}
3283 summary_info += {'libxml2':           libxml2}
3284 summary_info += {'capstone':          capstone_opt == 'internal' ? capstone_opt : capstone}
3285 summary_info += {'libpmem support':   libpmem}
3286 summary_info += {'libdaxctl support': libdaxctl}
3287 summary_info += {'libudev':           libudev}
3288 # Dummy dependency, keep .found()
3289 summary_info += {'FUSE lseek':        fuse_lseek.found()}
3290 summary(summary_info, bool_yn: true, section: 'Dependencies')
3291
3292 if not supported_cpus.contains(cpu)
3293   message()
3294   warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
3295   message()
3296   message('CPU host architecture ' + cpu + ' support is not currently maintained.')
3297   message('The QEMU project intends to remove support for this host CPU in')
3298   message('a future release if nobody volunteers to maintain it and to')
3299   message('provide a build host for our continuous integration setup.')
3300   message('configure has succeeded and you can continue to build, but')
3301   message('if you care about QEMU on this platform you should contact')
3302   message('us upstream at qemu-devel@nongnu.org.')
3303 endif
3304
3305 if not supported_oses.contains(targetos)
3306   message()
3307   warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
3308   message()
3309   message('Host OS ' + targetos + 'support is not currently maintained.')
3310   message('The QEMU project intends to remove support for this host OS in')
3311   message('a future release if nobody volunteers to maintain it and to')
3312   message('provide a build host for our continuous integration setup.')
3313   message('configure has succeeded and you can continue to build, but')
3314   message('if you care about QEMU on this platform you should contact')
3315   message('us upstream at qemu-devel@nongnu.org.')
3316 endif