gitlab: Extract default build/test jobs templates
[qemu/ar7.git] / meson.build
blob20d7035e447b46eb12a2b6bf3f469f97eec8ff84
1 project('qemu', ['c'], meson_version: '>=0.55.0',
2         default_options: ['warning_level=1', 'c_std=gnu99', 'cpp_std=gnu++11', 'b_colorout=auto'] +
3                          (meson.version().version_compare('>=0.56.0') ? [ 'b_staticpic=false' ] : []),
4         version: run_command('head', meson.source_root() / 'VERSION').stdout().strip())
6 not_found = dependency('', required: false)
7 if meson.version().version_compare('>=0.56.0')
8   keyval = import('keyval')
9 else
10   keyval = import('unstable-keyval')
11 endif
12 ss = import('sourceset')
13 fs = import('fs')
15 sh = find_program('sh')
16 cc = meson.get_compiler('c')
17 config_host = keyval.load(meson.current_build_dir() / 'config-host.mak')
18 enable_modules = 'CONFIG_MODULES' in config_host
19 enable_static = 'CONFIG_STATIC' in config_host
21 # Allow both shared and static libraries unless --enable-static
22 static_kwargs = enable_static ? {'static': true} : {}
24 # Temporary directory used for files created while
25 # configure runs. Since it is in the build directory
26 # we can safely blow away any previous version of it
27 # (and we need not jump through hoops to try to delete
28 # it when configure exits.)
29 tmpdir = meson.current_build_dir() / 'meson-private/temp'
31 if get_option('qemu_suffix').startswith('/')
32   error('qemu_suffix cannot start with a /')
33 endif
35 qemu_confdir = get_option('sysconfdir') / get_option('qemu_suffix')
36 qemu_datadir = get_option('datadir') / get_option('qemu_suffix')
37 qemu_docdir = get_option('docdir') / get_option('qemu_suffix')
38 qemu_moddir = get_option('libdir') / get_option('qemu_suffix')
40 qemu_desktopdir = get_option('datadir') / 'applications'
41 qemu_icondir = get_option('datadir') / 'icons'
43 config_host_data = configuration_data()
44 genh = []
46 target_dirs = config_host['TARGET_DIRS'].split()
47 have_user = false
48 have_system = false
49 foreach target : target_dirs
50   have_user = have_user or target.endswith('-user')
51   have_system = have_system or target.endswith('-softmmu')
52 endforeach
53 have_tools = 'CONFIG_TOOLS' in config_host
54 have_block = have_system or have_tools
56 python = import('python').find_installation()
58 supported_oses = ['windows', 'freebsd', 'netbsd', 'openbsd', 'darwin', 'sunos', 'linux']
59 supported_cpus = ['ppc', 'ppc64', 's390x', 'riscv32', 'riscv64', 'x86', 'x86_64',
60   'arm', 'aarch64', 'mips', 'mips64', 'sparc', 'sparc64']
62 cpu = host_machine.cpu_family()
63 targetos = host_machine.system()
65 if cpu in ['x86', 'x86_64']
66   kvm_targets = ['i386-softmmu', 'x86_64-softmmu']
67 elif cpu == 'aarch64'
68   kvm_targets = ['aarch64-softmmu']
69 elif cpu == 's390x'
70   kvm_targets = ['s390x-softmmu']
71 elif cpu in ['ppc', 'ppc64']
72   kvm_targets = ['ppc-softmmu', 'ppc64-softmmu']
73 elif cpu in ['mips', 'mips64']
74   kvm_targets = ['mips-softmmu', 'mipsel-softmmu', 'mips64-softmmu', 'mips64el-softmmu']
75 else
76   kvm_targets = []
77 endif
79 accelerator_targets = { 'CONFIG_KVM': kvm_targets }
80 if cpu in ['x86', 'x86_64', 'arm', 'aarch64']
81   # i368 emulator provides xenpv machine type for multiple architectures
82   accelerator_targets += {
83     'CONFIG_XEN': ['i386-softmmu', 'x86_64-softmmu'],
84   }
85 endif
86 if cpu in ['x86', 'x86_64']
87   accelerator_targets += {
88     'CONFIG_HAX': ['i386-softmmu', 'x86_64-softmmu'],
89     'CONFIG_HVF': ['x86_64-softmmu'],
90     'CONFIG_NVMM': ['i386-softmmu', 'x86_64-softmmu'],
91     'CONFIG_WHPX': ['i386-softmmu', 'x86_64-softmmu'],
92   }
93 endif
95 edk2_targets = [ 'arm-softmmu', 'aarch64-softmmu', 'i386-softmmu', 'x86_64-softmmu' ]
96 install_edk2_blobs = false
97 if get_option('install_blobs')
98   foreach target : target_dirs
99     install_edk2_blobs = install_edk2_blobs or target in edk2_targets
100   endforeach
101 endif
103 bzip2 = find_program('bzip2', required: install_edk2_blobs)
105 ##################
106 # Compiler flags #
107 ##################
109 # Specify linker-script with add_project_link_arguments so that it is not placed
110 # within a linker --start-group/--end-group pair
111 if 'CONFIG_FUZZ' in config_host
112    add_project_link_arguments(['-Wl,-T,',
113                                (meson.current_source_dir() / 'tests/qtest/fuzz/fork_fuzz.ld')],
114                               native: false, language: ['c', 'cpp', 'objc'])
115 endif
117 add_global_arguments(config_host['QEMU_CFLAGS'].split(),
118                      native: false, language: ['c', 'objc'])
119 add_global_arguments(config_host['QEMU_CXXFLAGS'].split(),
120                      native: false, language: 'cpp')
121 add_global_link_arguments(config_host['QEMU_LDFLAGS'].split(),
122                           native: false, language: ['c', 'cpp', 'objc'])
124 if targetos == 'linux'
125   add_project_arguments('-isystem', meson.current_source_dir() / 'linux-headers',
126                         '-isystem', 'linux-headers',
127                         language: ['c', 'cpp'])
128 endif
130 add_project_arguments('-iquote', '.',
131                       '-iquote', meson.current_source_dir(),
132                       '-iquote', meson.current_source_dir() / 'include',
133                       '-iquote', meson.current_source_dir() / 'disas/libvixl',
134                       language: ['c', 'cpp', 'objc'])
136 link_language = meson.get_external_property('link_language', 'cpp')
137 if link_language == 'cpp'
138   add_languages('cpp', required: true, native: false)
139 endif
140 if host_machine.system() == 'darwin'
141   add_languages('objc', required: false, native: false)
142 endif
144 sparse = find_program('cgcc', required: get_option('sparse'))
145 if sparse.found()
146   run_target('sparse',
147              command: [find_program('scripts/check_sparse.py'),
148                        'compile_commands.json', sparse.full_path(), '-Wbitwise',
149                        '-Wno-transparent-union', '-Wno-old-initializer',
150                        '-Wno-non-pointer-null'])
151 endif
153 ###########################################
154 # Target-specific checks and dependencies #
155 ###########################################
157 if targetos != 'linux' and get_option('mpath').enabled()
158   error('Multipath is supported only on Linux')
159 endif
161 if targetos != 'linux' and get_option('multiprocess').enabled()
162   error('Multiprocess QEMU is supported only on Linux')
163 endif
164 multiprocess_allowed = targetos == 'linux' and not get_option('multiprocess').disabled()
166 m = cc.find_library('m', required: false)
167 util = cc.find_library('util', required: false)
168 winmm = []
169 socket = []
170 version_res = []
171 coref = []
172 iokit = []
173 emulator_link_args = []
174 nvmm =not_found
175 hvf = not_found
176 if targetos == 'windows'
177   socket = cc.find_library('ws2_32')
178   winmm = cc.find_library('winmm')
180   win = import('windows')
181   version_res = win.compile_resources('version.rc',
182                                       depend_files: files('pc-bios/qemu-nsis.ico'),
183                                       include_directories: include_directories('.'))
184 elif targetos == 'darwin'
185   coref = dependency('appleframeworks', modules: 'CoreFoundation')
186   iokit = dependency('appleframeworks', modules: 'IOKit')
187 elif targetos == 'sunos'
188   socket = [cc.find_library('socket'),
189             cc.find_library('nsl'),
190             cc.find_library('resolv')]
191 elif targetos == 'haiku'
192   socket = [cc.find_library('posix_error_mapper'),
193             cc.find_library('network'),
194             cc.find_library('bsd')]
195 elif targetos == 'openbsd'
196   if not get_option('tcg').disabled() and target_dirs.length() > 0
197     # Disable OpenBSD W^X if available
198     emulator_link_args = cc.get_supported_link_arguments('-Wl,-z,wxneeded')
199   endif
200 endif
202 accelerators = []
203 if not get_option('kvm').disabled() and targetos == 'linux'
204   accelerators += 'CONFIG_KVM'
205 endif
206 if not get_option('xen').disabled() and 'CONFIG_XEN_BACKEND' in config_host
207   accelerators += 'CONFIG_XEN'
208   have_xen_pci_passthrough = not get_option('xen_pci_passthrough').disabled() and targetos == 'linux'
209 else
210   have_xen_pci_passthrough = false
211 endif
212 if not get_option('whpx').disabled() and targetos == 'windows'
213   if get_option('whpx').enabled() and host_machine.cpu() != 'x86_64'
214     error('WHPX requires 64-bit host')
215   elif cc.has_header('WinHvPlatform.h', required: get_option('whpx')) and \
216        cc.has_header('WinHvEmulation.h', required: get_option('whpx'))
217     accelerators += 'CONFIG_WHPX'
218   endif
219 endif
220 if not get_option('hvf').disabled()
221   hvf = dependency('appleframeworks', modules: 'Hypervisor',
222                    required: get_option('hvf'))
223   if hvf.found()
224     accelerators += 'CONFIG_HVF'
225   endif
226 endif
227 if not get_option('hax').disabled()
228   if get_option('hax').enabled() or targetos in ['windows', 'darwin', 'netbsd']
229     accelerators += 'CONFIG_HAX'
230   endif
231 endif
232 if targetos == 'netbsd'
233   if cc.has_header_symbol('nvmm.h', 'nvmm_cpu_stop', required: get_option('nvmm'))
234     nvmm = cc.find_library('nvmm', required: get_option('nvmm'))
235   endif
236   if nvmm.found()
237     accelerators += 'CONFIG_NVMM'
238   endif
239 endif
241 tcg_arch = config_host['ARCH']
242 if not get_option('tcg').disabled()
243   if cpu not in supported_cpus
244     if get_option('tcg_interpreter')
245       warning('Unsupported CPU @0@, will use TCG with TCI (experimental and slow)'.format(cpu))
246     else
247       error('Unsupported CPU @0@, try --enable-tcg-interpreter'.format(cpu))
248     endif
249   elif get_option('tcg_interpreter')
250     warning('Use of the TCG interpretor is not recommended on this host')
251     warning('architecture. There is a native TCG execution backend available')
252     warning('which provides substantially better performance and reliability.')
253     warning('It is strongly recommended to remove the --enable-tcg-interpreter')
254     warning('configuration option on this architecture to use the native')
255     warning('backend.')
256   endif
257   if get_option('tcg_interpreter')
258     tcg_arch = 'tci'
259   elif config_host['ARCH'] == 'sparc64'
260     tcg_arch = 'sparc'
261   elif config_host['ARCH'] == 's390x'
262     tcg_arch = 's390'
263   elif config_host['ARCH'] in ['x86_64', 'x32']
264     tcg_arch = 'i386'
265   elif config_host['ARCH'] == 'ppc64'
266     tcg_arch = 'ppc'
267   elif config_host['ARCH'] in ['riscv32', 'riscv64']
268     tcg_arch = 'riscv'
269   endif
270   add_project_arguments('-iquote', meson.current_source_dir() / 'tcg' / tcg_arch,
271                         language: ['c', 'cpp', 'objc'])
273   accelerators += 'CONFIG_TCG'
274   config_host += { 'CONFIG_TCG': 'y' }
275 endif
277 if 'CONFIG_KVM' not in accelerators and get_option('kvm').enabled()
278   error('KVM not available on this platform')
279 endif
280 if 'CONFIG_HVF' not in accelerators and get_option('hvf').enabled()
281   error('HVF not available on this platform')
282 endif
283 if 'CONFIG_NVMM' not in accelerators and get_option('nvmm').enabled()
284   error('NVMM not available on this platform')
285 endif
286 if 'CONFIG_WHPX' not in accelerators and get_option('whpx').enabled()
287   error('WHPX not available on this platform')
288 endif
289 if not have_xen_pci_passthrough and get_option('xen_pci_passthrough').enabled()
290   if 'CONFIG_XEN' in accelerators
291     error('Xen PCI passthrough not available on this platform')
292   else
293     error('Xen PCI passthrough requested but Xen not enabled')
294   endif
295 endif
297 ################
298 # Dependencies #
299 ################
301 # The path to glib.h is added to all compilation commands.  This was
302 # grandfathered in from the QEMU Makefiles.
303 add_project_arguments(config_host['GLIB_CFLAGS'].split(),
304                       native: false, language: ['c', 'cpp', 'objc'])
305 glib = declare_dependency(compile_args: config_host['GLIB_CFLAGS'].split(),
306                           link_args: config_host['GLIB_LIBS'].split())
307 # override glib dep with the configure results (for subprojects)
308 meson.override_dependency('glib-2.0', glib)
310 gio = not_found
311 if 'CONFIG_GIO' in config_host
312   gio = declare_dependency(compile_args: config_host['GIO_CFLAGS'].split(),
313                            link_args: config_host['GIO_LIBS'].split())
314 endif
315 lttng = not_found
316 if 'CONFIG_TRACE_UST' in config_host
317   lttng = declare_dependency(link_args: config_host['LTTNG_UST_LIBS'].split())
318 endif
319 urcubp = not_found
320 if 'CONFIG_TRACE_UST' in config_host
321   urcubp = declare_dependency(link_args: config_host['URCU_BP_LIBS'].split())
322 endif
323 gcrypt = not_found
324 if 'CONFIG_GCRYPT' in config_host
325   gcrypt = declare_dependency(compile_args: config_host['GCRYPT_CFLAGS'].split(),
326                               link_args: config_host['GCRYPT_LIBS'].split())
327 endif
328 nettle = not_found
329 if 'CONFIG_NETTLE' in config_host
330   nettle = declare_dependency(compile_args: config_host['NETTLE_CFLAGS'].split(),
331                               link_args: config_host['NETTLE_LIBS'].split())
332 endif
333 gnutls = not_found
334 if 'CONFIG_GNUTLS' in config_host
335   gnutls = declare_dependency(compile_args: config_host['GNUTLS_CFLAGS'].split(),
336                               link_args: config_host['GNUTLS_LIBS'].split())
337 endif
338 pixman = not_found
339 if have_system or have_tools
340   pixman = dependency('pixman-1', required: have_system, version:'>=0.21.8',
341                       method: 'pkg-config', kwargs: static_kwargs)
342 endif
343 pam = not_found
344 if 'CONFIG_AUTH_PAM' in config_host
345   pam = cc.find_library('pam')
346 endif
347 libaio = cc.find_library('aio', required: false)
348 zlib = dependency('zlib', required: true, kwargs: static_kwargs)
349 linux_io_uring = not_found
350 if 'CONFIG_LINUX_IO_URING' in config_host
351   linux_io_uring = declare_dependency(compile_args: config_host['LINUX_IO_URING_CFLAGS'].split(),
352                                       link_args: config_host['LINUX_IO_URING_LIBS'].split())
353 endif
354 libxml2 = not_found
355 if 'CONFIG_LIBXML2' in config_host
356   libxml2 = declare_dependency(compile_args: config_host['LIBXML2_CFLAGS'].split(),
357                                link_args: config_host['LIBXML2_LIBS'].split())
358 endif
359 libnfs = not_found
360 if not get_option('libnfs').auto() or have_block
361   libnfs = dependency('libnfs', version: '>=1.9.3',
362                       required: get_option('libnfs'),
363                       method: 'pkg-config', kwargs: static_kwargs)
364 endif
366 libattr_test = '''
367   #include <stddef.h>
368   #include <sys/types.h>
369   #ifdef CONFIG_LIBATTR
370   #include <attr/xattr.h>
371   #else
372   #include <sys/xattr.h>
373   #endif
374   int main(void) { getxattr(NULL, NULL, NULL, 0); setxattr(NULL, NULL, NULL, 0, 0); return 0; }'''
376 libattr = not_found
377 have_old_libattr = false
378 if not get_option('attr').disabled()
379   if cc.links(libattr_test)
380     libattr = declare_dependency()
381   else
382     libattr = cc.find_library('attr', has_headers: ['attr/xattr.h'],
383                               required: get_option('attr'),
384                               kwargs: static_kwargs)
385     if libattr.found() and not \
386       cc.links(libattr_test, dependencies: libattr, args: '-DCONFIG_LIBATTR')
387       libattr = not_found
388       if get_option('attr').enabled()
389         error('could not link libattr')
390       else
391         warning('could not link libattr, disabling')
392       endif
393     else
394       have_old_libattr = libattr.found()
395     endif
396   endif
397 endif
399 cocoa = dependency('appleframeworks', modules: 'Cocoa', required: get_option('cocoa'))
400 if cocoa.found() and get_option('sdl').enabled()
401   error('Cocoa and SDL cannot be enabled at the same time')
402 endif
403 if cocoa.found() and get_option('gtk').enabled()
404   error('Cocoa and GTK+ cannot be enabled at the same time')
405 endif
407 seccomp = not_found
408 if not get_option('seccomp').auto() or have_system or have_tools
409   seccomp = dependency('libseccomp', version: '>=2.3.0',
410                        required: get_option('seccomp'),
411                        method: 'pkg-config', kwargs: static_kwargs)
412 endif
414 libcap_ng = not_found
415 if not get_option('cap_ng').auto() or have_system or have_tools
416   libcap_ng = cc.find_library('cap-ng', has_headers: ['cap-ng.h'],
417                               required: get_option('cap_ng'),
418                               kwargs: static_kwargs)
419 endif
420 if libcap_ng.found() and not cc.links('''
421    #include <cap-ng.h>
422    int main(void)
423    {
424      capng_capability_to_name(CAPNG_EFFECTIVE);
425      return 0;
426    }''', dependencies: libcap_ng)
427   libcap_ng = not_found
428   if get_option('cap_ng').enabled()
429     error('could not link libcap-ng')
430   else
431     warning('could not link libcap-ng, disabling')
432   endif
433 endif
435 if get_option('xkbcommon').auto() and not have_system and not have_tools
436   xkbcommon = not_found
437 else
438   xkbcommon = dependency('xkbcommon', required: get_option('xkbcommon'),
439                          method: 'pkg-config', kwargs: static_kwargs)
440 endif
441 vde = not_found
442 if config_host.has_key('CONFIG_VDE')
443   vde = declare_dependency(link_args: config_host['VDE_LIBS'].split())
444 endif
445 pulse = not_found
446 if 'CONFIG_LIBPULSE' in config_host
447   pulse = declare_dependency(compile_args: config_host['PULSE_CFLAGS'].split(),
448                              link_args: config_host['PULSE_LIBS'].split())
449 endif
450 alsa = not_found
451 if 'CONFIG_ALSA' in config_host
452   alsa = declare_dependency(compile_args: config_host['ALSA_CFLAGS'].split(),
453                             link_args: config_host['ALSA_LIBS'].split())
454 endif
455 jack = not_found
456 if 'CONFIG_LIBJACK' in config_host
457   jack = declare_dependency(link_args: config_host['JACK_LIBS'].split())
458 endif
459 spice = not_found
460 spice_headers = not_found
461 spice_protocol = not_found
462 if 'CONFIG_SPICE' in config_host
463   spice = declare_dependency(compile_args: config_host['SPICE_CFLAGS'].split(),
464                              link_args: config_host['SPICE_LIBS'].split())
465   spice_headers = declare_dependency(compile_args: config_host['SPICE_CFLAGS'].split())
466 endif
467 if 'CONFIG_SPICE_PROTOCOL' in config_host
468   spice_protocol = declare_dependency(compile_args: config_host['SPICE_PROTOCOL_CFLAGS'].split())
469 endif
470 rt = cc.find_library('rt', required: false)
471 libdl = not_found
472 if 'CONFIG_PLUGIN' in config_host
473   libdl = cc.find_library('dl', required: true)
474 endif
475 libiscsi = not_found
476 if not get_option('libiscsi').auto() or have_block
477   libiscsi = dependency('libiscsi', version: '>=1.9.0',
478                          required: get_option('libiscsi'),
479                          method: 'pkg-config', kwargs: static_kwargs)
480 endif
481 zstd = not_found
482 if not get_option('zstd').auto() or have_block
483   zstd = dependency('libzstd', version: '>=1.4.0',
484                     required: get_option('zstd'),
485                     method: 'pkg-config', kwargs: static_kwargs)
486 endif
487 gbm = not_found
488 if 'CONFIG_GBM' in config_host
489   gbm = declare_dependency(compile_args: config_host['GBM_CFLAGS'].split(),
490                            link_args: config_host['GBM_LIBS'].split())
491 endif
492 virgl = not_found
493 if 'CONFIG_VIRGL' in config_host
494   virgl = declare_dependency(compile_args: config_host['VIRGL_CFLAGS'].split(),
495                              link_args: config_host['VIRGL_LIBS'].split())
496 endif
497 curl = not_found
498 if not get_option('curl').auto() or have_block
499   curl = dependency('libcurl', version: '>=7.29.0',
500                     method: 'pkg-config',
501                     required: get_option('curl'),
502                     kwargs: static_kwargs)
503 endif
504 libudev = not_found
505 if targetos == 'linux' and (have_system or have_tools)
506   libudev = dependency('libudev',
507                        method: 'pkg-config',
508                        required: get_option('libudev'),
509                        kwargs: static_kwargs)
510 endif
512 mpathlibs = [libudev]
513 mpathpersist = not_found
514 mpathpersist_new_api = false
515 if targetos == 'linux' and have_tools and not get_option('mpath').disabled()
516   mpath_test_source_new = '''
517     #include <libudev.h>
518     #include <mpath_persist.h>
519     unsigned mpath_mx_alloc_len = 1024;
520     int logsink;
521     static struct config *multipath_conf;
522     extern struct udev *udev;
523     extern struct config *get_multipath_config(void);
524     extern void put_multipath_config(struct config *conf);
525     struct udev *udev;
526     struct config *get_multipath_config(void) { return multipath_conf; }
527     void put_multipath_config(struct config *conf) { }
528     int main(void) {
529         udev = udev_new();
530         multipath_conf = mpath_lib_init();
531         return 0;
532     }'''
533   mpath_test_source_old = '''
534       #include <libudev.h>
535       #include <mpath_persist.h>
536       unsigned mpath_mx_alloc_len = 1024;
537       int logsink;
538       int main(void) {
539           struct udev *udev = udev_new();
540           mpath_lib_init(udev);
541           return 0;
542       }'''
543   libmpathpersist = cc.find_library('mpathpersist',
544                                     required: get_option('mpath'),
545                                     kwargs: static_kwargs)
546   if libmpathpersist.found()
547     mpathlibs += libmpathpersist
548     if enable_static
549       mpathlibs += cc.find_library('devmapper',
550                                      required: get_option('mpath'),
551                                      kwargs: static_kwargs)
552     endif
553     mpathlibs += cc.find_library('multipath',
554                                  required: get_option('mpath'),
555                                  kwargs: static_kwargs)
556     foreach lib: mpathlibs
557       if not lib.found()
558         mpathlibs = []
559         break
560       endif
561     endforeach
562     if mpathlibs.length() == 0
563       msg = 'Dependencies missing for libmpathpersist'
564     elif cc.links(mpath_test_source_new, dependencies: mpathlibs)
565       mpathpersist = declare_dependency(dependencies: mpathlibs)
566       mpathpersist_new_api = true
567     elif cc.links(mpath_test_source_old, dependencies: mpathlibs)
568       mpathpersist = declare_dependency(dependencies: mpathlibs)
569     else
570       msg = 'Cannot detect libmpathpersist API'
571     endif
572     if not mpathpersist.found()
573       if get_option('mpath').enabled()
574         error(msg)
575       else
576         warning(msg + ', disabling')
577       endif
578     endif
579   endif
580 endif
582 iconv = not_found
583 curses = not_found
584 if have_system and not get_option('curses').disabled()
585   curses_test = '''
586     #include <locale.h>
587     #include <curses.h>
588     #include <wchar.h>
589     int main(void) {
590       wchar_t wch = L'w';
591       setlocale(LC_ALL, "");
592       resize_term(0, 0);
593       addwstr(L"wide chars\n");
594       addnwstr(&wch, 1);
595       add_wch(WACS_DEGREE);
596       return 0;
597     }'''
599   curses_dep_list = targetos == 'windows' ? ['ncurses', 'ncursesw'] : ['ncursesw']
600   foreach curses_dep : curses_dep_list
601     if not curses.found()
602       curses = dependency(curses_dep,
603                           required: false,
604                           method: 'pkg-config',
605                           kwargs: static_kwargs)
606     endif
607   endforeach
608   msg = get_option('curses').enabled() ? 'curses library not found' : ''
609   curses_compile_args = ['-DNCURSES_WIDECHAR']
610   if curses.found()
611     if cc.links(curses_test, args: curses_compile_args, dependencies: [curses])
612       curses = declare_dependency(compile_args: curses_compile_args, dependencies: [curses])
613     else
614       msg = 'curses package not usable'
615       curses = not_found
616     endif
617   endif
618   if not curses.found()
619     has_curses_h = cc.has_header('curses.h', args: curses_compile_args)
620     if targetos != 'windows' and not has_curses_h
621       message('Trying with /usr/include/ncursesw')
622       curses_compile_args += ['-I/usr/include/ncursesw']
623       has_curses_h = cc.has_header('curses.h', args: curses_compile_args)
624     endif
625     if has_curses_h
626       curses_libname_list = (targetos == 'windows' ? ['pdcurses'] : ['ncursesw', 'cursesw'])
627       foreach curses_libname : curses_libname_list
628         libcurses = cc.find_library(curses_libname,
629                                     required: false,
630                                     kwargs: static_kwargs)
631         if libcurses.found()
632           if cc.links(curses_test, args: curses_compile_args, dependencies: libcurses)
633             curses = declare_dependency(compile_args: curses_compile_args,
634                                         dependencies: [libcurses])
635             break
636           else
637             msg = 'curses library not usable'
638           endif
639         endif
640       endforeach
641     endif
642   endif
643   if not get_option('iconv').disabled()
644     foreach link_args : [ ['-liconv'], [] ]
645       # Programs will be linked with glib and this will bring in libiconv on FreeBSD.
646       # We need to use libiconv if available because mixing libiconv's headers with
647       # the system libc does not work.
648       # However, without adding glib to the dependencies -L/usr/local/lib will not be
649       # included in the command line and libiconv will not be found.
650       if cc.links('''
651         #include <iconv.h>
652         int main(void) {
653           iconv_t conv = iconv_open("WCHAR_T", "UCS-2");
654           return conv != (iconv_t) -1;
655         }''', args: config_host['GLIB_CFLAGS'].split() + config_host['GLIB_LIBS'].split() + link_args)
656         iconv = declare_dependency(link_args: link_args, dependencies: glib)
657         break
658       endif
659     endforeach
660   endif
661   if curses.found() and not iconv.found()
662     if get_option('iconv').enabled()
663       error('iconv not available')
664     endif
665     msg = 'iconv required for curses UI but not available'
666     curses = not_found
667   endif
668   if not curses.found() and msg != ''
669     if get_option('curses').enabled()
670       error(msg)
671     else
672       warning(msg + ', disabling')
673     endif
674   endif
675 endif
677 brlapi = not_found
678 if not get_option('brlapi').auto() or have_system
679   brlapi = cc.find_library('brlapi', has_headers: ['brlapi.h'],
680                          required: get_option('brlapi'),
681                          kwargs: static_kwargs)
682   if brlapi.found() and not cc.links('''
683      #include <brlapi.h>
684      #include <stddef.h>
685      int main(void) { return brlapi__openConnection (NULL, NULL, NULL); }''', dependencies: brlapi)
686     brlapi = not_found
687     if get_option('brlapi').enabled()
688       error('could not link brlapi')
689     else
690       warning('could not link brlapi, disabling')
691     endif
692   endif
693 endif
695 sdl = not_found
696 if not get_option('sdl').auto() or (have_system and not cocoa.found())
697   sdl = dependency('sdl2', required: get_option('sdl'), kwargs: static_kwargs)
698   sdl_image = not_found
699 endif
700 if sdl.found()
701   # work around 2.0.8 bug
702   sdl = declare_dependency(compile_args: '-Wno-undef',
703                            dependencies: sdl)
704   sdl_image = dependency('SDL2_image', required: get_option('sdl_image'),
705                          method: 'pkg-config', kwargs: static_kwargs)
706 else
707   if get_option('sdl_image').enabled()
708     error('sdl-image required, but SDL was @0@'.format(
709           get_option('sdl').disabled() ? 'disabled' : 'not found'))
710   endif
711   sdl_image = not_found
712 endif
714 rbd = not_found
715 if not get_option('rbd').auto() or have_block
716   librados = cc.find_library('rados', required: get_option('rbd'),
717                              kwargs: static_kwargs)
718   librbd = cc.find_library('rbd', has_headers: ['rbd/librbd.h'],
719                            required: get_option('rbd'),
720                            kwargs: static_kwargs)
721   if librados.found() and librbd.found()
722     if cc.links('''
723       #include <stdio.h>
724       #include <rbd/librbd.h>
725       int main(void) {
726         rados_t cluster;
727         rados_create(&cluster, NULL);
728         return 0;
729       }''', dependencies: [librbd, librados])
730       rbd = declare_dependency(dependencies: [librbd, librados])
731     elif get_option('rbd').enabled()
732       error('could not link librados')
733     else
734       warning('could not link librados, disabling')
735     endif
736   endif
737 endif
739 glusterfs = not_found
740 glusterfs_ftruncate_has_stat = false
741 glusterfs_iocb_has_stat = false
742 if not get_option('glusterfs').auto() or have_block
743   glusterfs = dependency('glusterfs-api', version: '>=3',
744                          required: get_option('glusterfs'),
745                          method: 'pkg-config', kwargs: static_kwargs)
746   if glusterfs.found()
747     glusterfs_ftruncate_has_stat = cc.links('''
748       #include <glusterfs/api/glfs.h>
750       int
751       main(void)
752       {
753           /* new glfs_ftruncate() passes two additional args */
754           return glfs_ftruncate(NULL, 0, NULL, NULL);
755       }
756     ''', dependencies: glusterfs)
757     glusterfs_iocb_has_stat = cc.links('''
758       #include <glusterfs/api/glfs.h>
760       /* new glfs_io_cbk() passes two additional glfs_stat structs */
761       static void
762       glusterfs_iocb(glfs_fd_t *fd, ssize_t ret, struct glfs_stat *prestat, struct glfs_stat *poststat, void *data)
763       {}
765       int
766       main(void)
767       {
768           glfs_io_cbk iocb = &glusterfs_iocb;
769           iocb(NULL, 0 , NULL, NULL, NULL);
770           return 0;
771       }
772     ''', dependencies: glusterfs)
773   endif
774 endif
775 libssh = not_found
776 if 'CONFIG_LIBSSH' in config_host
777   libssh = declare_dependency(compile_args: config_host['LIBSSH_CFLAGS'].split(),
778                               link_args: config_host['LIBSSH_LIBS'].split())
779 endif
780 libbzip2 = not_found
781 if not get_option('bzip2').auto() or have_block
782   libbzip2 = cc.find_library('bz2', has_headers: ['bzlib.h'],
783                              required: get_option('bzip2'),
784                              kwargs: static_kwargs)
785   if libbzip2.found() and not cc.links('''
786      #include <bzlib.h>
787      int main(void) { BZ2_bzlibVersion(); return 0; }''', dependencies: libbzip2)
788     libbzip2 = not_found
789     if get_option('bzip2').enabled()
790       error('could not link libbzip2')
791     else
792       warning('could not link libbzip2, disabling')
793     endif
794   endif
795 endif
797 liblzfse = not_found
798 if not get_option('lzfse').auto() or have_block
799   liblzfse = cc.find_library('lzfse', has_headers: ['lzfse.h'],
800                              required: get_option('lzfse'),
801                              kwargs: static_kwargs)
802 endif
803 if liblzfse.found() and not cc.links('''
804    #include <lzfse.h>
805    int main(void) { lzfse_decode_scratch_size(); return 0; }''', dependencies: liblzfse)
806   liblzfse = not_found
807   if get_option('lzfse').enabled()
808     error('could not link liblzfse')
809   else
810     warning('could not link liblzfse, disabling')
811   endif
812 endif
814 oss = not_found
815 if 'CONFIG_AUDIO_OSS' in config_host
816   oss = declare_dependency(link_args: config_host['OSS_LIBS'].split())
817 endif
818 dsound = not_found
819 if 'CONFIG_AUDIO_DSOUND' in config_host
820   dsound = declare_dependency(link_args: config_host['DSOUND_LIBS'].split())
821 endif
822 coreaudio = not_found
823 if 'CONFIG_AUDIO_COREAUDIO' in config_host
824   coreaudio = declare_dependency(link_args: config_host['COREAUDIO_LIBS'].split())
825 endif
826 opengl = not_found
827 if 'CONFIG_OPENGL' in config_host
828   opengl = declare_dependency(compile_args: config_host['OPENGL_CFLAGS'].split(),
829                               link_args: config_host['OPENGL_LIBS'].split())
830 endif
832 gtk = not_found
833 gtkx11 = not_found
834 if not get_option('gtk').auto() or (have_system and not cocoa.found())
835   gtk = dependency('gtk+-3.0', version: '>=3.22.0',
836                    method: 'pkg-config',
837                    required: get_option('gtk'),
838                    kwargs: static_kwargs)
839   if gtk.found()
840     gtkx11 = dependency('gtk+-x11-3.0', version: '>=3.22.0',
841                         method: 'pkg-config',
842                         required: false,
843                         kwargs: static_kwargs)
844     gtk = declare_dependency(dependencies: [gtk, gtkx11])
845   endif
846 endif
848 vte = not_found
849 if 'CONFIG_VTE' in config_host
850   vte = declare_dependency(compile_args: config_host['VTE_CFLAGS'].split(),
851                            link_args: config_host['VTE_LIBS'].split())
852 endif
853 x11 = not_found
854 if gtkx11.found()
855   x11 = dependency('x11', method: 'pkg-config', required: gtkx11.found(),
856                    kwargs: static_kwargs)
857 endif
858 vnc = not_found
859 png = not_found
860 jpeg = not_found
861 sasl = not_found
862 if get_option('vnc').enabled()
863   vnc = declare_dependency() # dummy dependency
864   png = dependency('libpng', required: get_option('vnc_png'),
865                    method: 'pkg-config', kwargs: static_kwargs)
866   jpeg = dependency('libjpeg', required: get_option('vnc_jpeg'),
867                     method: 'pkg-config', kwargs: static_kwargs)
868   sasl = cc.find_library('sasl2', has_headers: ['sasl/sasl.h'],
869                          required: get_option('vnc_sasl'),
870                          kwargs: static_kwargs)
871   if sasl.found()
872     sasl = declare_dependency(dependencies: sasl,
873                               compile_args: '-DSTRUCT_IOVEC_DEFINED')
874   endif
875 endif
877 snappy = not_found
878 if not get_option('snappy').auto() or have_system
879   snappy = cc.find_library('snappy', has_headers: ['snappy-c.h'],
880                            required: get_option('snappy'),
881                            kwargs: static_kwargs)
882 endif
883 if snappy.found() and not cc.links('''
884    #include <snappy-c.h>
885    int main(void) { snappy_max_compressed_length(4096); return 0; }''', dependencies: snappy)
886   snappy = not_found
887   if get_option('snappy').enabled()
888     error('could not link libsnappy')
889   else
890     warning('could not link libsnappy, disabling')
891   endif
892 endif
894 lzo = not_found
895 if not get_option('lzo').auto() or have_system
896   lzo = cc.find_library('lzo2', has_headers: ['lzo/lzo1x.h'],
897                         required: get_option('lzo'),
898                         kwargs: static_kwargs)
899 endif
900 if lzo.found() and not cc.links('''
901    #include <lzo/lzo1x.h>
902    int main(void) { lzo_version(); return 0; }''', dependencies: lzo)
903   lzo = not_found
904   if get_option('lzo').enabled()
905     error('could not link liblzo2')
906   else
907     warning('could not link liblzo2, disabling')
908   endif
909 endif
911 rdma = not_found
912 if 'CONFIG_RDMA' in config_host
913   rdma = declare_dependency(link_args: config_host['RDMA_LIBS'].split())
914 endif
915 numa = not_found
916 if 'CONFIG_NUMA' in config_host
917   numa = declare_dependency(link_args: config_host['NUMA_LIBS'].split())
918 endif
919 xen = not_found
920 if 'CONFIG_XEN_BACKEND' in config_host
921   xen = declare_dependency(compile_args: config_host['XEN_CFLAGS'].split(),
922                            link_args: config_host['XEN_LIBS'].split())
923 endif
924 cacard = not_found
925 if 'CONFIG_SMARTCARD' in config_host
926   cacard = declare_dependency(compile_args: config_host['SMARTCARD_CFLAGS'].split(),
927                               link_args: config_host['SMARTCARD_LIBS'].split())
928 endif
929 u2f = not_found
930 if have_system
931   u2f = dependency('u2f-emu', required: get_option('u2f'),
932                    method: 'pkg-config',
933                    kwargs: static_kwargs)
934 endif
935 usbredir = not_found
936 if 'CONFIG_USB_REDIR' in config_host
937   usbredir = declare_dependency(compile_args: config_host['USB_REDIR_CFLAGS'].split(),
938                                 link_args: config_host['USB_REDIR_LIBS'].split())
939 endif
940 libusb = not_found
941 if 'CONFIG_USB_LIBUSB' in config_host
942   libusb = declare_dependency(compile_args: config_host['LIBUSB_CFLAGS'].split(),
943                               link_args: config_host['LIBUSB_LIBS'].split())
944 endif
945 libpmem = not_found
946 if 'CONFIG_LIBPMEM' in config_host
947   libpmem = declare_dependency(compile_args: config_host['LIBPMEM_CFLAGS'].split(),
948                                link_args: config_host['LIBPMEM_LIBS'].split())
949 endif
950 libdaxctl = not_found
951 if 'CONFIG_LIBDAXCTL' in config_host
952   libdaxctl = declare_dependency(link_args: config_host['LIBDAXCTL_LIBS'].split())
953 endif
954 tasn1 = not_found
955 if 'CONFIG_TASN1' in config_host
956   tasn1 = declare_dependency(compile_args: config_host['TASN1_CFLAGS'].split(),
957                              link_args: config_host['TASN1_LIBS'].split())
958 endif
959 keyutils = dependency('libkeyutils', required: false,
960                       method: 'pkg-config', kwargs: static_kwargs)
962 has_gettid = cc.has_function('gettid')
964 # Malloc tests
966 malloc = []
967 if get_option('malloc') == 'system'
968   has_malloc_trim = \
969     not get_option('malloc_trim').disabled() and \
970     cc.links('''#include <malloc.h>
971                 int main(void) { malloc_trim(0); return 0; }''')
972 else
973   has_malloc_trim = false
974   malloc = cc.find_library(get_option('malloc'), required: true)
975 endif
976 if not has_malloc_trim and get_option('malloc_trim').enabled()
977   if get_option('malloc') == 'system'
978     error('malloc_trim not available on this platform.')
979   else
980     error('malloc_trim not available with non-libc memory allocator')
981   endif
982 endif
984 # Check whether the glibc provides statx()
986 statx_test = '''
987   #ifndef _GNU_SOURCE
988   #define _GNU_SOURCE
989   #endif
990   #include <sys/stat.h>
991   int main(void) {
992     struct statx statxbuf;
993     statx(0, "", 0, STATX_BASIC_STATS, &statxbuf);
994     return 0;
995   }'''
997 has_statx = cc.links(statx_test)
999 have_vhost_user_blk_server = (targetos == 'linux' and
1000     'CONFIG_VHOST_USER' in config_host)
1002 if get_option('vhost_user_blk_server').enabled()
1003     if targetos != 'linux'
1004         error('vhost_user_blk_server requires linux')
1005     elif 'CONFIG_VHOST_USER' not in config_host
1006         error('vhost_user_blk_server requires vhost-user support')
1007     endif
1008 elif get_option('vhost_user_blk_server').disabled() or not have_system
1009     have_vhost_user_blk_server = false
1010 endif
1013 if get_option('fuse').disabled() and get_option('fuse_lseek').enabled()
1014   error('Cannot enable fuse-lseek while fuse is disabled')
1015 endif
1017 fuse = dependency('fuse3', required: get_option('fuse'),
1018                   version: '>=3.1', method: 'pkg-config',
1019                   kwargs: static_kwargs)
1021 fuse_lseek = not_found
1022 if not get_option('fuse_lseek').disabled()
1023   if fuse.version().version_compare('>=3.8')
1024     # Dummy dependency
1025     fuse_lseek = declare_dependency()
1026   elif get_option('fuse_lseek').enabled()
1027     if fuse.found()
1028       error('fuse-lseek requires libfuse >=3.8, found ' + fuse.version())
1029     else
1030       error('fuse-lseek requires libfuse, which was not found')
1031     endif
1032   endif
1033 endif
1035 if get_option('cfi')
1036   cfi_flags=[]
1037   # Check for dependency on LTO
1038   if not get_option('b_lto')
1039     error('Selected Control-Flow Integrity but LTO is disabled')
1040   endif
1041   if config_host.has_key('CONFIG_MODULES')
1042     error('Selected Control-Flow Integrity is not compatible with modules')
1043   endif
1044   # Check for cfi flags. CFI requires LTO so we can't use
1045   # get_supported_arguments, but need a more complex "compiles" which allows
1046   # custom arguments
1047   if cc.compiles('int main () { return 0; }', name: '-fsanitize=cfi-icall',
1048                  args: ['-flto', '-fsanitize=cfi-icall'] )
1049     cfi_flags += '-fsanitize=cfi-icall'
1050   else
1051     error('-fsanitize=cfi-icall is not supported by the compiler')
1052   endif
1053   if cc.compiles('int main () { return 0; }',
1054                  name: '-fsanitize-cfi-icall-generalize-pointers',
1055                  args: ['-flto', '-fsanitize=cfi-icall',
1056                         '-fsanitize-cfi-icall-generalize-pointers'] )
1057     cfi_flags += '-fsanitize-cfi-icall-generalize-pointers'
1058   else
1059     error('-fsanitize-cfi-icall-generalize-pointers is not supported by the compiler')
1060   endif
1061   if get_option('cfi_debug')
1062     if cc.compiles('int main () { return 0; }',
1063                    name: '-fno-sanitize-trap=cfi-icall',
1064                    args: ['-flto', '-fsanitize=cfi-icall',
1065                           '-fno-sanitize-trap=cfi-icall'] )
1066       cfi_flags += '-fno-sanitize-trap=cfi-icall'
1067     else
1068       error('-fno-sanitize-trap=cfi-icall is not supported by the compiler')
1069     endif
1070   endif
1071   add_global_arguments(cfi_flags, native: false, language: ['c', 'cpp', 'objc'])
1072   add_global_link_arguments(cfi_flags, native: false, language: ['c', 'cpp', 'objc'])
1073 endif
1075 #################
1076 # config-host.h #
1077 #################
1079 have_virtfs = (targetos == 'linux' and
1080     have_system and
1081     libattr.found() and
1082     libcap_ng.found())
1084 have_virtfs_proxy_helper = have_virtfs and have_tools
1086 if get_option('virtfs').enabled()
1087   if not have_virtfs
1088     if targetos != 'linux'
1089       error('virtio-9p (virtfs) requires Linux')
1090     elif not libcap_ng.found() or not libattr.found()
1091       error('virtio-9p (virtfs) requires libcap-ng-devel and libattr-devel')
1092     elif not have_system
1093       error('virtio-9p (virtfs) needs system emulation support')
1094     endif
1095   endif
1096 elif get_option('virtfs').disabled()
1097   have_virtfs = false
1098 endif
1100 config_host_data.set_quoted('CONFIG_BINDIR', get_option('prefix') / get_option('bindir'))
1101 config_host_data.set_quoted('CONFIG_PREFIX', get_option('prefix'))
1102 config_host_data.set_quoted('CONFIG_QEMU_CONFDIR', get_option('prefix') / qemu_confdir)
1103 config_host_data.set_quoted('CONFIG_QEMU_DATADIR', get_option('prefix') / qemu_datadir)
1104 config_host_data.set_quoted('CONFIG_QEMU_DESKTOPDIR', get_option('prefix') / qemu_desktopdir)
1105 config_host_data.set_quoted('CONFIG_QEMU_FIRMWAREPATH', get_option('qemu_firmwarepath'))
1106 config_host_data.set_quoted('CONFIG_QEMU_HELPERDIR', get_option('prefix') / get_option('libexecdir'))
1107 config_host_data.set_quoted('CONFIG_QEMU_ICONDIR', get_option('prefix') / qemu_icondir)
1108 config_host_data.set_quoted('CONFIG_QEMU_LOCALEDIR', get_option('prefix') / get_option('localedir'))
1109 config_host_data.set_quoted('CONFIG_QEMU_LOCALSTATEDIR', get_option('prefix') / get_option('localstatedir'))
1110 config_host_data.set_quoted('CONFIG_QEMU_MODDIR', get_option('prefix') / qemu_moddir)
1111 config_host_data.set_quoted('CONFIG_SYSCONFDIR', get_option('prefix') / get_option('sysconfdir'))
1113 config_host_data.set('CONFIG_ATTR', libattr.found())
1114 config_host_data.set('CONFIG_BRLAPI', brlapi.found())
1115 config_host_data.set('CONFIG_COCOA', cocoa.found())
1116 config_host_data.set('CONFIG_LIBUDEV', libudev.found())
1117 config_host_data.set('CONFIG_LZO', lzo.found())
1118 config_host_data.set('CONFIG_MPATH', mpathpersist.found())
1119 config_host_data.set('CONFIG_MPATH_NEW_API', mpathpersist_new_api)
1120 config_host_data.set('CONFIG_CURL', curl.found())
1121 config_host_data.set('CONFIG_CURSES', curses.found())
1122 config_host_data.set('CONFIG_GLUSTERFS', glusterfs.found())
1123 if glusterfs.found()
1124   config_host_data.set('CONFIG_GLUSTERFS_XLATOR_OPT', glusterfs.version().version_compare('>=4'))
1125   config_host_data.set('CONFIG_GLUSTERFS_DISCARD', glusterfs.version().version_compare('>=5'))
1126   config_host_data.set('CONFIG_GLUSTERFS_FALLOCATE', glusterfs.version().version_compare('>=6'))
1127   config_host_data.set('CONFIG_GLUSTERFS_ZEROFILL', glusterfs.version().version_compare('>=6'))
1128   config_host_data.set('CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT', glusterfs_ftruncate_has_stat)
1129   config_host_data.set('CONFIG_GLUSTERFS_IOCB_HAS_STAT', glusterfs_iocb_has_stat)
1130 endif
1131 config_host_data.set('CONFIG_GTK', gtk.found())
1132 config_host_data.set('CONFIG_LIBATTR', have_old_libattr)
1133 config_host_data.set('CONFIG_LIBCAP_NG', libcap_ng.found())
1134 config_host_data.set('CONFIG_LIBISCSI', libiscsi.found())
1135 config_host_data.set('CONFIG_LIBNFS', libnfs.found())
1136 config_host_data.set('CONFIG_RBD', rbd.found())
1137 config_host_data.set('CONFIG_SDL', sdl.found())
1138 config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found())
1139 config_host_data.set('CONFIG_SECCOMP', seccomp.found())
1140 config_host_data.set('CONFIG_SNAPPY', snappy.found())
1141 config_host_data.set('CONFIG_VHOST_USER_BLK_SERVER', have_vhost_user_blk_server)
1142 config_host_data.set('CONFIG_VNC', vnc.found())
1143 config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
1144 config_host_data.set('CONFIG_VNC_PNG', png.found())
1145 config_host_data.set('CONFIG_VNC_SASL', sasl.found())
1146 config_host_data.set('CONFIG_VIRTFS', have_virtfs)
1147 config_host_data.set('CONFIG_XKBCOMMON', xkbcommon.found())
1148 config_host_data.set('CONFIG_KEYUTILS', keyutils.found())
1149 config_host_data.set('CONFIG_GETTID', has_gettid)
1150 config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim)
1151 config_host_data.set('CONFIG_STATX', has_statx)
1152 config_host_data.set('CONFIG_ZSTD', zstd.found())
1153 config_host_data.set('CONFIG_FUSE', fuse.found())
1154 config_host_data.set('CONFIG_FUSE_LSEEK', fuse_lseek.found())
1155 config_host_data.set('CONFIG_X11', x11.found())
1156 config_host_data.set('CONFIG_CFI', get_option('cfi'))
1157 config_host_data.set('QEMU_VERSION', '"@0@"'.format(meson.project_version()))
1158 config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0])
1159 config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1])
1160 config_host_data.set('QEMU_VERSION_MICRO', meson.project_version().split('.')[2])
1162 config_host_data.set('HAVE_BTRFS_H', cc.has_header('linux/btrfs.h'))
1163 config_host_data.set('HAVE_DRM_H', cc.has_header('libdrm/drm.h'))
1164 config_host_data.set('HAVE_PTY_H', cc.has_header('pty.h'))
1165 config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h'))
1166 config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h'))
1167 config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: '#include <stdlib.h>'))
1169 config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include <sys/uio.h>'))
1171 ignored = ['CONFIG_QEMU_INTERP_PREFIX'] # actually per-target
1172 arrays = ['CONFIG_AUDIO_DRIVERS', 'CONFIG_BDRV_RW_WHITELIST', 'CONFIG_BDRV_RO_WHITELIST']
1173 strings = ['HOST_DSOSUF', 'CONFIG_IASL']
1174 foreach k, v: config_host
1175   if ignored.contains(k)
1176     # do nothing
1177   elif arrays.contains(k)
1178     if v != ''
1179       v = '"' + '", "'.join(v.split()) + '", '
1180     endif
1181     config_host_data.set(k, v)
1182   elif k == 'ARCH'
1183     config_host_data.set('HOST_' + v.to_upper(), 1)
1184   elif strings.contains(k)
1185     if not k.startswith('CONFIG_')
1186       k = 'CONFIG_' + k.to_upper()
1187     endif
1188     config_host_data.set_quoted(k, v)
1189   elif k.startswith('CONFIG_') or k.startswith('HAVE_') or k.startswith('HOST_')
1190     config_host_data.set(k, v == 'y' ? 1 : v)
1191   endif
1192 endforeach
1194 ########################
1195 # Target configuration #
1196 ########################
1198 minikconf = find_program('scripts/minikconf.py')
1199 config_all = {}
1200 config_all_devices = {}
1201 config_all_disas = {}
1202 config_devices_mak_list = []
1203 config_devices_h = {}
1204 config_target_h = {}
1205 config_target_mak = {}
1207 disassemblers = {
1208   'alpha' : ['CONFIG_ALPHA_DIS'],
1209   'arm' : ['CONFIG_ARM_DIS'],
1210   'avr' : ['CONFIG_AVR_DIS'],
1211   'cris' : ['CONFIG_CRIS_DIS'],
1212   'hexagon' : ['CONFIG_HEXAGON_DIS'],
1213   'hppa' : ['CONFIG_HPPA_DIS'],
1214   'i386' : ['CONFIG_I386_DIS'],
1215   'x86_64' : ['CONFIG_I386_DIS'],
1216   'x32' : ['CONFIG_I386_DIS'],
1217   'm68k' : ['CONFIG_M68K_DIS'],
1218   'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
1219   'mips' : ['CONFIG_MIPS_DIS'],
1220   'nios2' : ['CONFIG_NIOS2_DIS'],
1221   'or1k' : ['CONFIG_OPENRISC_DIS'],
1222   'ppc' : ['CONFIG_PPC_DIS'],
1223   'riscv' : ['CONFIG_RISCV_DIS'],
1224   'rx' : ['CONFIG_RX_DIS'],
1225   's390' : ['CONFIG_S390_DIS'],
1226   'sh4' : ['CONFIG_SH4_DIS'],
1227   'sparc' : ['CONFIG_SPARC_DIS'],
1228   'xtensa' : ['CONFIG_XTENSA_DIS'],
1230 if link_language == 'cpp'
1231   disassemblers += {
1232     'aarch64' : [ 'CONFIG_ARM_A64_DIS'],
1233     'arm' : [ 'CONFIG_ARM_DIS', 'CONFIG_ARM_A64_DIS'],
1234     'mips' : [ 'CONFIG_MIPS_DIS', 'CONFIG_NANOMIPS_DIS'],
1235   }
1236 endif
1238 host_kconfig = \
1239   ('CONFIG_TPM' in config_host ? ['CONFIG_TPM=y'] : []) + \
1240   ('CONFIG_SPICE' in config_host ? ['CONFIG_SPICE=y'] : []) + \
1241   ('CONFIG_IVSHMEM' in config_host ? ['CONFIG_IVSHMEM=y'] : []) + \
1242   ('CONFIG_OPENGL' in config_host ? ['CONFIG_OPENGL=y'] : []) + \
1243   (x11.found() ? ['CONFIG_X11=y'] : []) + \
1244   ('CONFIG_VHOST_USER' in config_host ? ['CONFIG_VHOST_USER=y'] : []) + \
1245   ('CONFIG_VHOST_VDPA' in config_host ? ['CONFIG_VHOST_VDPA=y'] : []) + \
1246   ('CONFIG_VHOST_KERNEL' in config_host ? ['CONFIG_VHOST_KERNEL=y'] : []) + \
1247   (have_virtfs ? ['CONFIG_VIRTFS=y'] : []) + \
1248   ('CONFIG_LINUX' in config_host ? ['CONFIG_LINUX=y'] : []) + \
1249   ('CONFIG_PVRDMA' in config_host ? ['CONFIG_PVRDMA=y'] : []) + \
1250   (multiprocess_allowed ? ['CONFIG_MULTIPROCESS_ALLOWED=y'] : [])
1252 ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ]
1254 default_targets = 'CONFIG_DEFAULT_TARGETS' in config_host
1255 actual_target_dirs = []
1256 fdt_required = []
1257 foreach target : target_dirs
1258   config_target = { 'TARGET_NAME': target.split('-')[0] }
1259   if target.endswith('linux-user')
1260     if targetos != 'linux'
1261       if default_targets
1262         continue
1263       endif
1264       error('Target @0@ is only available on a Linux host'.format(target))
1265     endif
1266     config_target += { 'CONFIG_LINUX_USER': 'y' }
1267   elif target.endswith('bsd-user')
1268     if 'CONFIG_BSD' not in config_host
1269       if default_targets
1270         continue
1271       endif
1272       error('Target @0@ is only available on a BSD host'.format(target))
1273     endif
1274     config_target += { 'CONFIG_BSD_USER': 'y' }
1275   elif target.endswith('softmmu')
1276     config_target += { 'CONFIG_SOFTMMU': 'y' }
1277   endif
1278   if target.endswith('-user')
1279     config_target += {
1280       'CONFIG_USER_ONLY': 'y',
1281       'CONFIG_QEMU_INTERP_PREFIX':
1282         config_host['CONFIG_QEMU_INTERP_PREFIX'].format(config_target['TARGET_NAME'])
1283     }
1284   endif
1286   accel_kconfig = []
1287   foreach sym: accelerators
1288     if sym == 'CONFIG_TCG' or target in accelerator_targets.get(sym, [])
1289       config_target += { sym: 'y' }
1290       config_all += { sym: 'y' }
1291       if sym == 'CONFIG_TCG' and tcg_arch == 'tci'
1292         config_target += { 'CONFIG_TCG_INTERPRETER': 'y' }
1293       elif sym == 'CONFIG_XEN' and have_xen_pci_passthrough
1294         config_target += { 'CONFIG_XEN_PCI_PASSTHROUGH': 'y' }
1295       endif
1296       accel_kconfig += [ sym + '=y' ]
1297     endif
1298   endforeach
1299   if accel_kconfig.length() == 0
1300     if default_targets
1301       continue
1302     endif
1303     error('No accelerator available for target @0@'.format(target))
1304   endif
1306   actual_target_dirs += target
1307   config_target += keyval.load('default-configs/targets' / target + '.mak')
1308   config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
1310   if 'TARGET_NEED_FDT' in config_target
1311     fdt_required += target
1312   endif
1314   # Add default keys
1315   if 'TARGET_BASE_ARCH' not in config_target
1316     config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
1317   endif
1318   if 'TARGET_ABI_DIR' not in config_target
1319     config_target += {'TARGET_ABI_DIR': config_target['TARGET_ARCH']}
1320   endif
1322   foreach k, v: disassemblers
1323     if config_host['ARCH'].startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k)
1324       foreach sym: v
1325         config_target += { sym: 'y' }
1326         config_all_disas += { sym: 'y' }
1327       endforeach
1328     endif
1329   endforeach
1331   config_target_data = configuration_data()
1332   foreach k, v: config_target
1333     if not k.startswith('TARGET_') and not k.startswith('CONFIG_')
1334       # do nothing
1335     elif ignored.contains(k)
1336       # do nothing
1337     elif k == 'TARGET_BASE_ARCH'
1338       # Note that TARGET_BASE_ARCH ends up in config-target.h but it is
1339       # not used to select files from sourcesets.
1340       config_target_data.set('TARGET_' + v.to_upper(), 1)
1341     elif k == 'TARGET_NAME' or k == 'CONFIG_QEMU_INTERP_PREFIX'
1342       config_target_data.set_quoted(k, v)
1343     elif v == 'y'
1344       config_target_data.set(k, 1)
1345     else
1346       config_target_data.set(k, v)
1347     endif
1348   endforeach
1349   config_target_h += {target: configure_file(output: target + '-config-target.h',
1350                                                configuration: config_target_data)}
1352   if target.endswith('-softmmu')
1353     config_devices_mak = target + '-config-devices.mak'
1354     config_devices_mak = configure_file(
1355       input: ['default-configs/devices' / target + '.mak', 'Kconfig'],
1356       output: config_devices_mak,
1357       depfile: config_devices_mak + '.d',
1358       capture: true,
1359       command: [minikconf,
1360                 get_option('default_devices') ? '--defconfig' : '--allnoconfig',
1361                 config_devices_mak, '@DEPFILE@', '@INPUT@',
1362                 host_kconfig, accel_kconfig])
1364     config_devices_data = configuration_data()
1365     config_devices = keyval.load(config_devices_mak)
1366     foreach k, v: config_devices
1367       config_devices_data.set(k, 1)
1368     endforeach
1369     config_devices_mak_list += config_devices_mak
1370     config_devices_h += {target: configure_file(output: target + '-config-devices.h',
1371                                                 configuration: config_devices_data)}
1372     config_target += config_devices
1373     config_all_devices += config_devices
1374   endif
1375   config_target_mak += {target: config_target}
1376 endforeach
1377 target_dirs = actual_target_dirs
1379 # This configuration is used to build files that are shared by
1380 # multiple binaries, and then extracted out of the "common"
1381 # static_library target.
1383 # We do not use all_sources()/all_dependencies(), because it would
1384 # build literally all source files, including devices only used by
1385 # targets that are not built for this compilation.  The CONFIG_ALL
1386 # pseudo symbol replaces it.
1388 config_all += config_all_devices
1389 config_all += config_host
1390 config_all += config_all_disas
1391 config_all += {
1392   'CONFIG_XEN': config_host.has_key('CONFIG_XEN_BACKEND'),
1393   'CONFIG_SOFTMMU': have_system,
1394   'CONFIG_USER_ONLY': have_user,
1395   'CONFIG_ALL': true,
1398 ##############
1399 # Submodules #
1400 ##############
1402 capstone = not_found
1403 capstone_opt = get_option('capstone')
1404 if capstone_opt in ['enabled', 'auto', 'system']
1405   have_internal = fs.exists(meson.current_source_dir() / 'capstone/Makefile')
1406   capstone = dependency('capstone', version: '>=4.0',
1407                         kwargs: static_kwargs, method: 'pkg-config',
1408                         required: capstone_opt == 'system' or
1409                                   capstone_opt == 'enabled' and not have_internal)
1410   if capstone.found()
1411     capstone_opt = 'system'
1412   elif have_internal
1413     capstone_opt = 'internal'
1414   else
1415     capstone_opt = 'disabled'
1416   endif
1417 endif
1418 if capstone_opt == 'internal'
1419   capstone_data = configuration_data()
1420   capstone_data.set('CAPSTONE_USE_SYS_DYN_MEM', '1')
1422   capstone_files = files(
1423     'capstone/cs.c',
1424     'capstone/MCInst.c',
1425     'capstone/MCInstrDesc.c',
1426     'capstone/MCRegisterInfo.c',
1427     'capstone/SStream.c',
1428     'capstone/utils.c'
1429   )
1431   if 'CONFIG_ARM_DIS' in config_all_disas
1432     capstone_data.set('CAPSTONE_HAS_ARM', '1')
1433     capstone_files += files(
1434       'capstone/arch/ARM/ARMDisassembler.c',
1435       'capstone/arch/ARM/ARMInstPrinter.c',
1436       'capstone/arch/ARM/ARMMapping.c',
1437       'capstone/arch/ARM/ARMModule.c'
1438     )
1439   endif
1441   # FIXME: This config entry currently depends on a c++ compiler.
1442   # Which is needed for building libvixl, but not for capstone.
1443   if 'CONFIG_ARM_A64_DIS' in config_all_disas
1444     capstone_data.set('CAPSTONE_HAS_ARM64', '1')
1445     capstone_files += files(
1446       'capstone/arch/AArch64/AArch64BaseInfo.c',
1447       'capstone/arch/AArch64/AArch64Disassembler.c',
1448       'capstone/arch/AArch64/AArch64InstPrinter.c',
1449       'capstone/arch/AArch64/AArch64Mapping.c',
1450       'capstone/arch/AArch64/AArch64Module.c'
1451     )
1452   endif
1454   if 'CONFIG_PPC_DIS' in config_all_disas
1455     capstone_data.set('CAPSTONE_HAS_POWERPC', '1')
1456     capstone_files += files(
1457       'capstone/arch/PowerPC/PPCDisassembler.c',
1458       'capstone/arch/PowerPC/PPCInstPrinter.c',
1459       'capstone/arch/PowerPC/PPCMapping.c',
1460       'capstone/arch/PowerPC/PPCModule.c'
1461     )
1462   endif
1464   if 'CONFIG_S390_DIS' in config_all_disas
1465     capstone_data.set('CAPSTONE_HAS_SYSZ', '1')
1466     capstone_files += files(
1467       'capstone/arch/SystemZ/SystemZDisassembler.c',
1468       'capstone/arch/SystemZ/SystemZInstPrinter.c',
1469       'capstone/arch/SystemZ/SystemZMapping.c',
1470       'capstone/arch/SystemZ/SystemZModule.c',
1471       'capstone/arch/SystemZ/SystemZMCTargetDesc.c'
1472     )
1473   endif
1475   if 'CONFIG_I386_DIS' in config_all_disas
1476     capstone_data.set('CAPSTONE_HAS_X86', 1)
1477     capstone_files += files(
1478       'capstone/arch/X86/X86Disassembler.c',
1479       'capstone/arch/X86/X86DisassemblerDecoder.c',
1480       'capstone/arch/X86/X86ATTInstPrinter.c',
1481       'capstone/arch/X86/X86IntelInstPrinter.c',
1482       'capstone/arch/X86/X86InstPrinterCommon.c',
1483       'capstone/arch/X86/X86Mapping.c',
1484       'capstone/arch/X86/X86Module.c'
1485     )
1486   endif
1488   configure_file(output: 'capstone-defs.h', configuration: capstone_data)
1490   capstone_cargs = [
1491     # FIXME: There does not seem to be a way to completely replace the c_args
1492     # that come from add_project_arguments() -- we can only add to them.
1493     # So: disable all warnings with a big hammer.
1494     '-Wno-error', '-w',
1496     # Include all configuration defines via a header file, which will wind up
1497     # as a dependency on the object file, and thus changes here will result
1498     # in a rebuild.
1499     '-include', 'capstone-defs.h'
1500   ]
1502   libcapstone = static_library('capstone',
1503                                build_by_default: false,
1504                                sources: capstone_files,
1505                                c_args: capstone_cargs,
1506                                include_directories: 'capstone/include')
1507   capstone = declare_dependency(link_with: libcapstone,
1508                                 include_directories: 'capstone/include/capstone')
1509 endif
1511 slirp = not_found
1512 slirp_opt = 'disabled'
1513 if have_system
1514   slirp_opt = get_option('slirp')
1515   if slirp_opt in ['enabled', 'auto', 'system']
1516     have_internal = fs.exists(meson.current_source_dir() / 'slirp/meson.build')
1517     slirp = dependency('slirp', kwargs: static_kwargs,
1518                        method: 'pkg-config',
1519                        required: slirp_opt == 'system' or
1520                                  slirp_opt == 'enabled' and not have_internal)
1521     if slirp.found()
1522       slirp_opt = 'system'
1523     elif have_internal
1524       slirp_opt = 'internal'
1525     else
1526       slirp_opt = 'disabled'
1527     endif
1528   endif
1529   if slirp_opt == 'internal'
1530     slirp_deps = []
1531     if targetos == 'windows'
1532       slirp_deps = cc.find_library('iphlpapi')
1533     endif
1534     slirp_conf = configuration_data()
1535     slirp_conf.set('SLIRP_MAJOR_VERSION', meson.project_version().split('.')[0])
1536     slirp_conf.set('SLIRP_MINOR_VERSION', meson.project_version().split('.')[1])
1537     slirp_conf.set('SLIRP_MICRO_VERSION', meson.project_version().split('.')[2])
1538     slirp_conf.set_quoted('SLIRP_VERSION_STRING', meson.project_version())
1539     slirp_cargs = ['-DG_LOG_DOMAIN="Slirp"']
1540     slirp_files = [
1541       'slirp/src/arp_table.c',
1542       'slirp/src/bootp.c',
1543       'slirp/src/cksum.c',
1544       'slirp/src/dhcpv6.c',
1545       'slirp/src/dnssearch.c',
1546       'slirp/src/if.c',
1547       'slirp/src/ip6_icmp.c',
1548       'slirp/src/ip6_input.c',
1549       'slirp/src/ip6_output.c',
1550       'slirp/src/ip_icmp.c',
1551       'slirp/src/ip_input.c',
1552       'slirp/src/ip_output.c',
1553       'slirp/src/mbuf.c',
1554       'slirp/src/misc.c',
1555       'slirp/src/ncsi.c',
1556       'slirp/src/ndp_table.c',
1557       'slirp/src/sbuf.c',
1558       'slirp/src/slirp.c',
1559       'slirp/src/socket.c',
1560       'slirp/src/state.c',
1561       'slirp/src/stream.c',
1562       'slirp/src/tcp_input.c',
1563       'slirp/src/tcp_output.c',
1564       'slirp/src/tcp_subr.c',
1565       'slirp/src/tcp_timer.c',
1566       'slirp/src/tftp.c',
1567       'slirp/src/udp.c',
1568       'slirp/src/udp6.c',
1569       'slirp/src/util.c',
1570       'slirp/src/version.c',
1571       'slirp/src/vmstate.c',
1572     ]
1574     configure_file(
1575       input : 'slirp/src/libslirp-version.h.in',
1576       output : 'libslirp-version.h',
1577       configuration: slirp_conf)
1579     slirp_inc = include_directories('slirp', 'slirp/src')
1580     libslirp = static_library('slirp',
1581                               build_by_default: false,
1582                               sources: slirp_files,
1583                               c_args: slirp_cargs,
1584                               include_directories: slirp_inc)
1585     slirp = declare_dependency(link_with: libslirp,
1586                                dependencies: slirp_deps,
1587                                include_directories: slirp_inc)
1588   endif
1589 endif
1591 # For CFI, we need to compile slirp as a static library together with qemu.
1592 # This is because we register slirp functions as callbacks for QEMU Timers.
1593 # When using a system-wide shared libslirp, the type information for the
1594 # callback is missing and the timer call produces a false positive with CFI.
1596 # Now that slirp_opt has been defined, check if the selected slirp is compatible
1597 # with control-flow integrity.
1598 if get_option('cfi') and slirp_opt == 'system'
1599   error('Control-Flow Integrity is not compatible with system-wide slirp.' \
1600          + ' Please configure with --enable-slirp=git')
1601 endif
1603 fdt = not_found
1604 fdt_opt = get_option('fdt')
1605 if have_system
1606   if fdt_opt in ['enabled', 'auto', 'system']
1607     have_internal = fs.exists(meson.current_source_dir() / 'dtc/libfdt/Makefile.libfdt')
1608     fdt = cc.find_library('fdt', kwargs: static_kwargs,
1609                           required: fdt_opt == 'system' or
1610                                     fdt_opt == 'enabled' and not have_internal)
1611     if fdt.found() and cc.links('''
1612        #include <libfdt.h>
1613        #include <libfdt_env.h>
1614        int main(void) { fdt_check_full(NULL, 0); return 0; }''',
1615          dependencies: fdt)
1616       fdt_opt = 'system'
1617     elif have_internal
1618       fdt_opt = 'internal'
1619     else
1620       fdt_opt = 'disabled'
1621     endif
1622   endif
1623   if fdt_opt == 'internal'
1624     fdt_files = files(
1625       'dtc/libfdt/fdt.c',
1626       'dtc/libfdt/fdt_ro.c',
1627       'dtc/libfdt/fdt_wip.c',
1628       'dtc/libfdt/fdt_sw.c',
1629       'dtc/libfdt/fdt_rw.c',
1630       'dtc/libfdt/fdt_strerror.c',
1631       'dtc/libfdt/fdt_empty_tree.c',
1632       'dtc/libfdt/fdt_addresses.c',
1633       'dtc/libfdt/fdt_overlay.c',
1634       'dtc/libfdt/fdt_check.c',
1635     )
1637     fdt_inc = include_directories('dtc/libfdt')
1638     libfdt = static_library('fdt',
1639                             build_by_default: false,
1640                             sources: fdt_files,
1641                             include_directories: fdt_inc)
1642     fdt = declare_dependency(link_with: libfdt,
1643                              include_directories: fdt_inc)
1644   endif
1645 endif
1646 if not fdt.found() and fdt_required.length() > 0
1647   error('fdt not available but required by targets ' + ', '.join(fdt_required))
1648 endif
1650 config_host_data.set('CONFIG_CAPSTONE', capstone.found())
1651 config_host_data.set('CONFIG_FDT', fdt.found())
1652 config_host_data.set('CONFIG_SLIRP', slirp.found())
1654 #####################
1655 # Generated sources #
1656 #####################
1658 genh += configure_file(output: 'config-host.h', configuration: config_host_data)
1660 hxtool = find_program('scripts/hxtool')
1661 shaderinclude = find_program('scripts/shaderinclude.pl')
1662 qapi_gen = find_program('scripts/qapi-gen.py')
1663 qapi_gen_depends = [ meson.source_root() / 'scripts/qapi/__init__.py',
1664                      meson.source_root() / 'scripts/qapi/commands.py',
1665                      meson.source_root() / 'scripts/qapi/common.py',
1666                      meson.source_root() / 'scripts/qapi/error.py',
1667                      meson.source_root() / 'scripts/qapi/events.py',
1668                      meson.source_root() / 'scripts/qapi/expr.py',
1669                      meson.source_root() / 'scripts/qapi/gen.py',
1670                      meson.source_root() / 'scripts/qapi/introspect.py',
1671                      meson.source_root() / 'scripts/qapi/parser.py',
1672                      meson.source_root() / 'scripts/qapi/schema.py',
1673                      meson.source_root() / 'scripts/qapi/source.py',
1674                      meson.source_root() / 'scripts/qapi/types.py',
1675                      meson.source_root() / 'scripts/qapi/visit.py',
1676                      meson.source_root() / 'scripts/qapi/common.py',
1677                      meson.source_root() / 'scripts/qapi-gen.py'
1680 tracetool = [
1681   python, files('scripts/tracetool.py'),
1682    '--backend=' + config_host['TRACE_BACKENDS']
1684 tracetool_depends = files(
1685   'scripts/tracetool/backend/log.py',
1686   'scripts/tracetool/backend/__init__.py',
1687   'scripts/tracetool/backend/dtrace.py',
1688   'scripts/tracetool/backend/ftrace.py',
1689   'scripts/tracetool/backend/simple.py',
1690   'scripts/tracetool/backend/syslog.py',
1691   'scripts/tracetool/backend/ust.py',
1692   'scripts/tracetool/format/tcg_h.py',
1693   'scripts/tracetool/format/ust_events_c.py',
1694   'scripts/tracetool/format/ust_events_h.py',
1695   'scripts/tracetool/format/__init__.py',
1696   'scripts/tracetool/format/d.py',
1697   'scripts/tracetool/format/tcg_helper_c.py',
1698   'scripts/tracetool/format/simpletrace_stap.py',
1699   'scripts/tracetool/format/c.py',
1700   'scripts/tracetool/format/h.py',
1701   'scripts/tracetool/format/tcg_helper_h.py',
1702   'scripts/tracetool/format/log_stap.py',
1703   'scripts/tracetool/format/stap.py',
1704   'scripts/tracetool/format/tcg_helper_wrapper_h.py',
1705   'scripts/tracetool/__init__.py',
1706   'scripts/tracetool/transform.py',
1707   'scripts/tracetool/vcpu.py'
1710 qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
1711                     meson.current_source_dir(),
1712                     config_host['PKGVERSION'], meson.project_version()]
1713 qemu_version = custom_target('qemu-version.h',
1714                              output: 'qemu-version.h',
1715                              command: qemu_version_cmd,
1716                              capture: true,
1717                              build_by_default: true,
1718                              build_always_stale: true)
1719 genh += qemu_version
1721 hxdep = []
1722 hx_headers = [
1723   ['qemu-options.hx', 'qemu-options.def'],
1724   ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
1726 if have_system
1727   hx_headers += [
1728     ['hmp-commands.hx', 'hmp-commands.h'],
1729     ['hmp-commands-info.hx', 'hmp-commands-info.h'],
1730   ]
1731 endif
1732 foreach d : hx_headers
1733   hxdep += custom_target(d[1],
1734                 input: files(d[0]),
1735                 output: d[1],
1736                 capture: true,
1737                 build_by_default: true, # to be removed when added to a target
1738                 command: [hxtool, '-h', '@INPUT0@'])
1739 endforeach
1740 genh += hxdep
1742 ###################
1743 # Collect sources #
1744 ###################
1746 authz_ss = ss.source_set()
1747 blockdev_ss = ss.source_set()
1748 block_ss = ss.source_set()
1749 bsd_user_ss = ss.source_set()
1750 chardev_ss = ss.source_set()
1751 common_ss = ss.source_set()
1752 crypto_ss = ss.source_set()
1753 io_ss = ss.source_set()
1754 linux_user_ss = ss.source_set()
1755 qmp_ss = ss.source_set()
1756 qom_ss = ss.source_set()
1757 softmmu_ss = ss.source_set()
1758 specific_fuzz_ss = ss.source_set()
1759 specific_ss = ss.source_set()
1760 stub_ss = ss.source_set()
1761 trace_ss = ss.source_set()
1762 user_ss = ss.source_set()
1763 util_ss = ss.source_set()
1765 modules = {}
1766 hw_arch = {}
1767 target_arch = {}
1768 target_softmmu_arch = {}
1769 target_user_arch = {}
1771 ###############
1772 # Trace files #
1773 ###############
1775 # TODO: add each directory to the subdirs from its own meson.build, once
1776 # we have those
1777 trace_events_subdirs = [
1778   'crypto',
1779   'qapi',
1780   'qom',
1781   'monitor',
1782   'util',
1784 if have_user
1785   trace_events_subdirs += [ 'linux-user' ]
1786 endif
1787 if have_block
1788   trace_events_subdirs += [
1789     'authz',
1790     'block',
1791     'io',
1792     'nbd',
1793     'scsi',
1794   ]
1795 endif
1796 if have_system
1797   trace_events_subdirs += [
1798     'accel/kvm',
1799     'audio',
1800     'backends',
1801     'backends/tpm',
1802     'chardev',
1803     'hw/9pfs',
1804     'hw/acpi',
1805     'hw/adc',
1806     'hw/alpha',
1807     'hw/arm',
1808     'hw/audio',
1809     'hw/block',
1810     'hw/block/dataplane',
1811     'hw/char',
1812     'hw/display',
1813     'hw/dma',
1814     'hw/hppa',
1815     'hw/hyperv',
1816     'hw/i2c',
1817     'hw/i386',
1818     'hw/i386/xen',
1819     'hw/ide',
1820     'hw/input',
1821     'hw/intc',
1822     'hw/isa',
1823     'hw/mem',
1824     'hw/mips',
1825     'hw/misc',
1826     'hw/misc/macio',
1827     'hw/net',
1828     'hw/net/can',
1829     'hw/nvme',
1830     'hw/nvram',
1831     'hw/pci',
1832     'hw/pci-host',
1833     'hw/ppc',
1834     'hw/rdma',
1835     'hw/rdma/vmw',
1836     'hw/rtc',
1837     'hw/s390x',
1838     'hw/scsi',
1839     'hw/sd',
1840     'hw/sparc',
1841     'hw/sparc64',
1842     'hw/ssi',
1843     'hw/timer',
1844     'hw/tpm',
1845     'hw/usb',
1846     'hw/vfio',
1847     'hw/virtio',
1848     'hw/watchdog',
1849     'hw/xen',
1850     'hw/gpio',
1851     'migration',
1852     'net',
1853     'softmmu',
1854     'ui',
1855     'hw/remote',
1856   ]
1857 endif
1858 if have_system or have_user
1859   trace_events_subdirs += [
1860     'accel/tcg',
1861     'hw/core',
1862     'target/arm',
1863     'target/hppa',
1864     'target/i386',
1865     'target/i386/kvm',
1866     'target/mips',
1867     'target/ppc',
1868     'target/riscv',
1869     'target/s390x',
1870     'target/sparc',
1871   ]
1872 endif
1874 vhost_user = not_found
1875 if 'CONFIG_VHOST_USER' in config_host
1876   libvhost_user = subproject('libvhost-user')
1877   vhost_user = libvhost_user.get_variable('vhost_user_dep')
1878 endif
1880 subdir('qapi')
1881 subdir('qobject')
1882 subdir('stubs')
1883 subdir('trace')
1884 subdir('util')
1885 subdir('qom')
1886 subdir('authz')
1887 subdir('crypto')
1888 subdir('ui')
1891 if enable_modules
1892   libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
1893   modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
1894 endif
1896 stub_ss = stub_ss.apply(config_all, strict: false)
1898 util_ss.add_all(trace_ss)
1899 util_ss = util_ss.apply(config_all, strict: false)
1900 libqemuutil = static_library('qemuutil',
1901                              sources: util_ss.sources() + stub_ss.sources() + genh,
1902                              dependencies: [util_ss.dependencies(), m, glib, socket, malloc])
1903 qemuutil = declare_dependency(link_with: libqemuutil,
1904                               sources: genh + version_res)
1906 if have_system or have_user
1907   decodetree = generator(find_program('scripts/decodetree.py'),
1908                          output: 'decode-@BASENAME@.c.inc',
1909                          arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
1910   subdir('libdecnumber')
1911   subdir('target')
1912 endif
1914 subdir('audio')
1915 subdir('io')
1916 subdir('chardev')
1917 subdir('fsdev')
1918 subdir('dump')
1920 if have_block
1921   block_ss.add(files(
1922     'block.c',
1923     'blockjob.c',
1924     'job.c',
1925     'qemu-io-cmds.c',
1926   ))
1927   block_ss.add(when: 'CONFIG_REPLICATION', if_true: files('replication.c'))
1929   subdir('nbd')
1930   subdir('scsi')
1931   subdir('block')
1933   blockdev_ss.add(files(
1934     'blockdev.c',
1935     'blockdev-nbd.c',
1936     'iothread.c',
1937     'job-qmp.c',
1938   ), gnutls)
1940   # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
1941   # os-win32.c does not
1942   blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
1943   softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
1944 endif
1946 common_ss.add(files('cpus-common.c'))
1948 subdir('softmmu')
1950 common_ss.add(capstone)
1951 specific_ss.add(files('cpu.c', 'disas.c', 'gdbstub.c'), capstone)
1952 specific_ss.add(when: 'CONFIG_TCG', if_true: files(
1953   'fpu/softfloat.c',
1954   'tcg/optimize.c',
1955   'tcg/tcg-common.c',
1956   'tcg/tcg-op-gvec.c',
1957   'tcg/tcg-op-vec.c',
1958   'tcg/tcg-op.c',
1959   'tcg/tcg.c',
1961 specific_ss.add(when: 'CONFIG_TCG_INTERPRETER', if_true: files('tcg/tci.c'))
1963 # Work around a gcc bug/misfeature wherein constant propagation looks
1964 # through an alias:
1965 #   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99696
1966 # to guess that a const variable is always zero.  Without lto, this is
1967 # impossible, as the alias is restricted to page-vary-common.c.  Indeed,
1968 # without lto, not even the alias is required -- we simply use different
1969 # declarations in different compilation units.
1970 pagevary = files('page-vary-common.c')
1971 if get_option('b_lto')
1972   pagevary_flags = ['-fno-lto']
1973   if get_option('cfi')
1974     pagevary_flags += '-fno-sanitize=cfi-icall'
1975   endif
1976   pagevary = static_library('page-vary-common', sources: pagevary,
1977                             c_args: pagevary_flags)
1978   pagevary = declare_dependency(link_with: pagevary)
1979 endif
1980 common_ss.add(pagevary)
1981 specific_ss.add(files('page-vary.c'))
1983 subdir('backends')
1984 subdir('disas')
1985 subdir('migration')
1986 subdir('monitor')
1987 subdir('net')
1988 subdir('replay')
1989 subdir('semihosting')
1990 subdir('hw')
1991 subdir('accel')
1992 subdir('plugins')
1993 subdir('bsd-user')
1994 subdir('linux-user')
1996 bsd_user_ss.add(files('gdbstub.c'))
1997 specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss)
1999 linux_user_ss.add(files('gdbstub.c', 'thunk.c'))
2000 specific_ss.add_all(when: 'CONFIG_LINUX_USER', if_true: linux_user_ss)
2002 # needed for fuzzing binaries
2003 subdir('tests/qtest/libqos')
2004 subdir('tests/qtest/fuzz')
2006 ########################
2007 # Library dependencies #
2008 ########################
2010 block_mods = []
2011 softmmu_mods = []
2012 foreach d, list : modules
2013   foreach m, module_ss : list
2014     if enable_modules and targetos != 'windows'
2015       module_ss = module_ss.apply(config_all, strict: false)
2016       sl = static_library(d + '-' + m, [genh, module_ss.sources()],
2017                           dependencies: [modulecommon, module_ss.dependencies()], pic: true)
2018       if d == 'block'
2019         block_mods += sl
2020       else
2021         softmmu_mods += sl
2022       endif
2023     else
2024       if d == 'block'
2025         block_ss.add_all(module_ss)
2026       else
2027         softmmu_ss.add_all(module_ss)
2028       endif
2029     endif
2030   endforeach
2031 endforeach
2033 nm = find_program('nm')
2034 undefsym = find_program('scripts/undefsym.py')
2035 block_syms = custom_target('block.syms', output: 'block.syms',
2036                              input: [libqemuutil, block_mods],
2037                              capture: true,
2038                              command: [undefsym, nm, '@INPUT@'])
2039 qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
2040                              input: [libqemuutil, softmmu_mods],
2041                              capture: true,
2042                              command: [undefsym, nm, '@INPUT@'])
2044 qom_ss = qom_ss.apply(config_host, strict: false)
2045 libqom = static_library('qom', qom_ss.sources() + genh,
2046                         dependencies: [qom_ss.dependencies()],
2047                         name_suffix: 'fa')
2049 qom = declare_dependency(link_whole: libqom)
2051 authz_ss = authz_ss.apply(config_host, strict: false)
2052 libauthz = static_library('authz', authz_ss.sources() + genh,
2053                           dependencies: [authz_ss.dependencies()],
2054                           name_suffix: 'fa',
2055                           build_by_default: false)
2057 authz = declare_dependency(link_whole: libauthz,
2058                            dependencies: qom)
2060 crypto_ss = crypto_ss.apply(config_host, strict: false)
2061 libcrypto = static_library('crypto', crypto_ss.sources() + genh,
2062                            dependencies: [crypto_ss.dependencies()],
2063                            name_suffix: 'fa',
2064                            build_by_default: false)
2066 crypto = declare_dependency(link_whole: libcrypto,
2067                             dependencies: [authz, qom])
2069 io_ss = io_ss.apply(config_host, strict: false)
2070 libio = static_library('io', io_ss.sources() + genh,
2071                        dependencies: [io_ss.dependencies()],
2072                        link_with: libqemuutil,
2073                        name_suffix: 'fa',
2074                        build_by_default: false)
2076 io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
2078 libmigration = static_library('migration', sources: migration_files + genh,
2079                               name_suffix: 'fa',
2080                               build_by_default: false)
2081 migration = declare_dependency(link_with: libmigration,
2082                                dependencies: [zlib, qom, io])
2083 softmmu_ss.add(migration)
2085 block_ss = block_ss.apply(config_host, strict: false)
2086 libblock = static_library('block', block_ss.sources() + genh,
2087                           dependencies: block_ss.dependencies(),
2088                           link_depends: block_syms,
2089                           name_suffix: 'fa',
2090                           build_by_default: false)
2092 block = declare_dependency(link_whole: [libblock],
2093                            link_args: '@block.syms',
2094                            dependencies: [crypto, io])
2096 blockdev_ss = blockdev_ss.apply(config_host, strict: false)
2097 libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
2098                              dependencies: blockdev_ss.dependencies(),
2099                              name_suffix: 'fa',
2100                              build_by_default: false)
2102 blockdev = declare_dependency(link_whole: [libblockdev],
2103                               dependencies: [block])
2105 qmp_ss = qmp_ss.apply(config_host, strict: false)
2106 libqmp = static_library('qmp', qmp_ss.sources() + genh,
2107                         dependencies: qmp_ss.dependencies(),
2108                         name_suffix: 'fa',
2109                         build_by_default: false)
2111 qmp = declare_dependency(link_whole: [libqmp])
2113 libchardev = static_library('chardev', chardev_ss.sources() + genh,
2114                             name_suffix: 'fa',
2115                             dependencies: [gnutls],
2116                             build_by_default: false)
2118 chardev = declare_dependency(link_whole: libchardev)
2120 libhwcore = static_library('hwcore', sources: hwcore_files + genh,
2121                            name_suffix: 'fa',
2122                            build_by_default: false)
2123 hwcore = declare_dependency(link_whole: libhwcore)
2124 common_ss.add(hwcore)
2126 ###########
2127 # Targets #
2128 ###########
2130 foreach m : block_mods + softmmu_mods
2131   shared_module(m.name(),
2132                 name_prefix: '',
2133                 link_whole: m,
2134                 install: true,
2135                 install_dir: qemu_moddir)
2136 endforeach
2138 softmmu_ss.add(authz, blockdev, chardev, crypto, io, qmp)
2139 common_ss.add(qom, qemuutil)
2141 common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
2142 common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
2144 common_all = common_ss.apply(config_all, strict: false)
2145 common_all = static_library('common',
2146                             build_by_default: false,
2147                             sources: common_all.sources() + genh,
2148                             implicit_include_directories: false,
2149                             dependencies: common_all.dependencies(),
2150                             name_suffix: 'fa')
2152 feature_to_c = find_program('scripts/feature_to_c.sh')
2154 emulators = {}
2155 foreach target : target_dirs
2156   config_target = config_target_mak[target]
2157   target_name = config_target['TARGET_NAME']
2158   arch = config_target['TARGET_BASE_ARCH']
2159   arch_srcs = [config_target_h[target]]
2160   arch_deps = []
2161   c_args = ['-DNEED_CPU_H',
2162             '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
2163             '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
2164   link_args = emulator_link_args
2166   config_target += config_host
2167   target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
2168   if targetos == 'linux'
2169     target_inc += include_directories('linux-headers', is_system: true)
2170   endif
2171   if target.endswith('-softmmu')
2172     qemu_target_name = 'qemu-system-' + target_name
2173     target_type='system'
2174     t = target_softmmu_arch[arch].apply(config_target, strict: false)
2175     arch_srcs += t.sources()
2176     arch_deps += t.dependencies()
2178     hw_dir = target_name == 'sparc64' ? 'sparc64' : arch
2179     hw = hw_arch[hw_dir].apply(config_target, strict: false)
2180     arch_srcs += hw.sources()
2181     arch_deps += hw.dependencies()
2183     arch_srcs += config_devices_h[target]
2184     link_args += ['@block.syms', '@qemu.syms']
2185   else
2186     abi = config_target['TARGET_ABI_DIR']
2187     target_type='user'
2188     qemu_target_name = 'qemu-' + target_name
2189     if arch in target_user_arch
2190       t = target_user_arch[arch].apply(config_target, strict: false)
2191       arch_srcs += t.sources()
2192       arch_deps += t.dependencies()
2193     endif
2194     if 'CONFIG_LINUX_USER' in config_target
2195       base_dir = 'linux-user'
2196       target_inc += include_directories('linux-user/host/' / config_host['ARCH'])
2197     else
2198       base_dir = 'bsd-user'
2199       target_inc += include_directories('bsd-user/freebsd')
2200     endif
2201     target_inc += include_directories(
2202       base_dir,
2203       base_dir / abi,
2204     )
2205     if 'CONFIG_LINUX_USER' in config_target
2206       dir = base_dir / abi
2207       arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
2208       if config_target.has_key('TARGET_SYSTBL_ABI')
2209         arch_srcs += \
2210           syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
2211                                              extra_args : config_target['TARGET_SYSTBL_ABI'])
2212       endif
2213     endif
2214   endif
2216   if 'TARGET_XML_FILES' in config_target
2217     gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
2218                                 output: target + '-gdbstub-xml.c',
2219                                 input: files(config_target['TARGET_XML_FILES'].split()),
2220                                 command: [feature_to_c, '@INPUT@'],
2221                                 capture: true)
2222     arch_srcs += gdbstub_xml
2223   endif
2225   t = target_arch[arch].apply(config_target, strict: false)
2226   arch_srcs += t.sources()
2227   arch_deps += t.dependencies()
2229   target_common = common_ss.apply(config_target, strict: false)
2230   objects = common_all.extract_objects(target_common.sources())
2231   deps = target_common.dependencies()
2233   target_specific = specific_ss.apply(config_target, strict: false)
2234   arch_srcs += target_specific.sources()
2235   arch_deps += target_specific.dependencies()
2237   lib = static_library('qemu-' + target,
2238                  sources: arch_srcs + genh,
2239                  dependencies: arch_deps,
2240                  objects: objects,
2241                  include_directories: target_inc,
2242                  c_args: c_args,
2243                  build_by_default: false,
2244                  name_suffix: 'fa')
2246   if target.endswith('-softmmu')
2247     execs = [{
2248       'name': 'qemu-system-' + target_name,
2249       'gui': false,
2250       'sources': files('softmmu/main.c'),
2251       'dependencies': []
2252     }]
2253     if targetos == 'windows' and (sdl.found() or gtk.found())
2254       execs += [{
2255         'name': 'qemu-system-' + target_name + 'w',
2256         'gui': true,
2257         'sources': files('softmmu/main.c'),
2258         'dependencies': []
2259       }]
2260     endif
2261     if config_host.has_key('CONFIG_FUZZ')
2262       specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
2263       execs += [{
2264         'name': 'qemu-fuzz-' + target_name,
2265         'gui': false,
2266         'sources': specific_fuzz.sources(),
2267         'dependencies': specific_fuzz.dependencies(),
2268       }]
2269     endif
2270   else
2271     execs = [{
2272       'name': 'qemu-' + target_name,
2273       'gui': false,
2274       'sources': [],
2275       'dependencies': []
2276     }]
2277   endif
2278   foreach exe: execs
2279     exe_name = exe['name']
2280     exe_sign = 'CONFIG_HVF' in config_target
2281     if exe_sign
2282       exe_name += '-unsigned'
2283     endif
2285     emulator = executable(exe_name, exe['sources'],
2286                install: true,
2287                c_args: c_args,
2288                dependencies: arch_deps + deps + exe['dependencies'],
2289                objects: lib.extract_all_objects(recursive: true),
2290                link_language: link_language,
2291                link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
2292                link_args: link_args,
2293                gui_app: exe['gui'])
2295     if exe_sign
2296       emulators += {exe['name'] : custom_target(exe['name'],
2297                    depends: emulator,
2298                    output: exe['name'],
2299                    command: [
2300                      meson.current_source_dir() / 'scripts/entitlement.sh',
2301                      meson.current_build_dir() / exe_name,
2302                      meson.current_build_dir() / exe['name'],
2303                      meson.current_source_dir() / 'accel/hvf/entitlements.plist'
2304                    ])
2305       }
2307       meson.add_install_script('scripts/entitlement.sh', '--install',
2308                                get_option('bindir') / exe_name,
2309                                get_option('bindir') / exe['name'],
2310                                meson.current_source_dir() / 'accel/hvf/entitlements.plist')
2311     else
2312       emulators += {exe['name']: emulator}
2313     endif
2315     if 'CONFIG_TRACE_SYSTEMTAP' in config_host
2316       foreach stp: [
2317         {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
2318         {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
2319         {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
2320         {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
2321       ]
2322         custom_target(exe['name'] + stp['ext'],
2323                       input: trace_events_all,
2324                       output: exe['name'] + stp['ext'],
2325                       install: stp['install'],
2326                       install_dir: get_option('datadir') / 'systemtap/tapset',
2327                       command: [
2328                         tracetool, '--group=all', '--format=' + stp['fmt'],
2329                         '--binary=' + stp['bin'],
2330                         '--target-name=' + target_name,
2331                         '--target-type=' + target_type,
2332                         '--probe-prefix=qemu.' + target_type + '.' + target_name,
2333                         '@INPUT@', '@OUTPUT@'
2334                       ],
2335                       depend_files: tracetool_depends)
2336       endforeach
2337     endif
2338   endforeach
2339 endforeach
2341 # Other build targets
2343 if 'CONFIG_PLUGIN' in config_host
2344   install_headers('include/qemu/qemu-plugin.h')
2345 endif
2347 if 'CONFIG_GUEST_AGENT' in config_host
2348   subdir('qga')
2349 elif get_option('guest_agent_msi').enabled()
2350   error('Guest agent MSI requested, but the guest agent is not being built')
2351 endif
2353 # Don't build qemu-keymap if xkbcommon is not explicitly enabled
2354 # when we don't build tools or system
2355 if xkbcommon.found()
2356   # used for the update-keymaps target, so include rules even if !have_tools
2357   qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
2358                            dependencies: [qemuutil, xkbcommon], install: have_tools)
2359 endif
2361 if have_tools
2362   qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
2363              dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
2364   qemu_io = executable('qemu-io', files('qemu-io.c'),
2365              dependencies: [block, qemuutil], install: true)
2366   qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
2367                dependencies: [blockdev, qemuutil, gnutls], install: true)
2369   subdir('storage-daemon')
2370   subdir('contrib/rdmacm-mux')
2371   subdir('contrib/elf2dmp')
2373   executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
2374              dependencies: qemuutil,
2375              install: true)
2377   if 'CONFIG_VHOST_USER' in config_host
2378     subdir('contrib/vhost-user-blk')
2379     subdir('contrib/vhost-user-gpu')
2380     subdir('contrib/vhost-user-input')
2381     subdir('contrib/vhost-user-scsi')
2382   endif
2384   if targetos == 'linux'
2385     executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
2386                dependencies: [qemuutil, libcap_ng],
2387                install: true,
2388                install_dir: get_option('libexecdir'))
2390     executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
2391                dependencies: [authz, crypto, io, qom, qemuutil,
2392                               libcap_ng, mpathpersist],
2393                install: true)
2394   endif
2396   if 'CONFIG_IVSHMEM' in config_host
2397     subdir('contrib/ivshmem-client')
2398     subdir('contrib/ivshmem-server')
2399   endif
2400 endif
2402 subdir('scripts')
2403 subdir('tools')
2404 subdir('pc-bios')
2405 subdir('docs')
2406 subdir('tests')
2407 if gtk.found()
2408   subdir('po')
2409 endif
2411 if host_machine.system() == 'windows'
2412   nsis_cmd = [
2413     find_program('scripts/nsis.py'),
2414     '@OUTPUT@',
2415     get_option('prefix'),
2416     meson.current_source_dir(),
2417     host_machine.cpu(),
2418     '--',
2419     '-DDISPLAYVERSION=' + meson.project_version(),
2420   ]
2421   if build_docs
2422     nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
2423   endif
2424   if gtk.found()
2425     nsis_cmd += '-DCONFIG_GTK=y'
2426   endif
2428   nsis = custom_target('nsis',
2429                        output: 'qemu-setup-' + meson.project_version() + '.exe',
2430                        input: files('qemu.nsi'),
2431                        build_always_stale: true,
2432                        command: nsis_cmd + ['@INPUT@'])
2433   alias_target('installer', nsis)
2434 endif
2436 #########################
2437 # Configuration summary #
2438 #########################
2440 # Directories
2441 summary_info = {}
2442 summary_info += {'Install prefix':    get_option('prefix')}
2443 summary_info += {'BIOS directory':    qemu_datadir}
2444 summary_info += {'firmware path':     get_option('qemu_firmwarepath')}
2445 summary_info += {'binary directory':  get_option('bindir')}
2446 summary_info += {'library directory': get_option('libdir')}
2447 summary_info += {'module directory':  qemu_moddir}
2448 summary_info += {'libexec directory': get_option('libexecdir')}
2449 summary_info += {'include directory': get_option('includedir')}
2450 summary_info += {'config directory':  get_option('sysconfdir')}
2451 if targetos != 'windows'
2452   summary_info += {'local state directory': get_option('localstatedir')}
2453   summary_info += {'Manual directory':      get_option('mandir')}
2454 else
2455   summary_info += {'local state directory': 'queried at runtime'}
2456 endif
2457 summary_info += {'Doc directory':     get_option('docdir')}
2458 summary_info += {'Build directory':   meson.current_build_dir()}
2459 summary_info += {'Source path':       meson.current_source_dir()}
2460 summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
2461 summary(summary_info, bool_yn: true, section: 'Directories')
2463 # Host binaries
2464 summary_info = {}
2465 summary_info += {'git':               config_host['GIT']}
2466 summary_info += {'make':              config_host['MAKE']}
2467 summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
2468 summary_info += {'sphinx-build':      sphinx_build.found()}
2469 if config_host.has_key('HAVE_GDB_BIN')
2470   summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
2471 endif
2472 summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
2473 if targetos == 'windows' and config_host.has_key('CONFIG_GUEST_AGENT')
2474   summary_info += {'wixl':            wixl.found() ? wixl.full_path() : false}
2475 endif
2476 if slirp_opt != 'disabled' and 'CONFIG_SLIRP_SMBD' in config_host
2477   summary_info += {'smbd':            config_host['CONFIG_SMBD_COMMAND']}
2478 endif
2479 summary(summary_info, bool_yn: true, section: 'Host binaries')
2481 # Configurable features
2482 summary_info = {}
2483 summary_info += {'Documentation':     build_docs}
2484 summary_info += {'system-mode emulation': have_system}
2485 summary_info += {'user-mode emulation': have_user}
2486 summary_info += {'block layer':       have_block}
2487 summary_info += {'Install blobs':     get_option('install_blobs')}
2488 summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
2489 if config_host.has_key('CONFIG_MODULES')
2490   summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')}
2491 endif
2492 summary_info += {'plugin support':    config_host.has_key('CONFIG_PLUGIN')}
2493 summary_info += {'fuzzing support':   config_host.has_key('CONFIG_FUZZ')}
2494 if have_system
2495   summary_info += {'Audio drivers':     config_host['CONFIG_AUDIO_DRIVERS']}
2496 endif
2497 summary_info += {'Trace backends':    config_host['TRACE_BACKENDS']}
2498 if config_host['TRACE_BACKENDS'].split().contains('simple')
2499   summary_info += {'Trace output file': config_host['CONFIG_TRACE_FILE'] + '-<pid>'}
2500 endif
2501 summary_info += {'QOM debugging':     config_host.has_key('CONFIG_QOM_CAST_DEBUG')}
2502 summary_info += {'vhost-kernel support': config_host.has_key('CONFIG_VHOST_KERNEL')}
2503 summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')}
2504 summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')}
2505 summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')}
2506 summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')}
2507 summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_USER')}
2508 summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
2509 summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')}
2510 summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')}
2511 summary_info += {'build guest agent': config_host.has_key('CONFIG_GUEST_AGENT')}
2512 summary(summary_info, bool_yn: true, section: 'Configurable features')
2514 # Compilation information
2515 summary_info = {}
2516 summary_info += {'host CPU':          cpu}
2517 summary_info += {'host endianness':   build_machine.endian()}
2518 summary_info += {'C compiler':        meson.get_compiler('c').cmd_array()[0]}
2519 summary_info += {'Host C compiler':   meson.get_compiler('c', native: true).cmd_array()[0]}
2520 if link_language == 'cpp'
2521   summary_info += {'C++ compiler':      meson.get_compiler('cpp').cmd_array()[0]}
2522 else
2523   summary_info += {'C++ compiler':      false}
2524 endif
2525 if targetos == 'darwin'
2526   summary_info += {'Objective-C compiler': meson.get_compiler('objc').cmd_array()[0]}
2527 endif
2528 if targetos == 'windows'
2529   if 'WIN_SDK' in config_host
2530     summary_info += {'Windows SDK':   config_host['WIN_SDK']}
2531   endif
2532 endif
2533 summary_info += {'ARFLAGS':           config_host['ARFLAGS']}
2534 summary_info += {'CFLAGS':            ' '.join(get_option('c_args')
2535                                                + ['-O' + get_option('optimization')]
2536                                                + (get_option('debug') ? ['-g'] : []))}
2537 if link_language == 'cpp'
2538   summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args')
2539                                                + ['-O' + get_option('optimization')]
2540                                                + (get_option('debug') ? ['-g'] : []))}
2541 endif
2542 link_args = get_option(link_language + '_link_args')
2543 if link_args.length() > 0
2544   summary_info += {'LDFLAGS':         ' '.join(link_args)}
2545 endif
2546 summary_info += {'QEMU_CFLAGS':       config_host['QEMU_CFLAGS']}
2547 summary_info += {'QEMU_LDFLAGS':      config_host['QEMU_LDFLAGS']}
2548 summary_info += {'profiler':          config_host.has_key('CONFIG_PROFILER')}
2549 summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
2550 summary_info += {'PIE':               get_option('b_pie')}
2551 summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
2552 summary_info += {'malloc trim support': has_malloc_trim}
2553 summary_info += {'membarrier':        config_host.has_key('CONFIG_MEMBARRIER')}
2554 summary_info += {'preadv support':    config_host_data.get('CONFIG_PREADV')}
2555 summary_info += {'fdatasync':         config_host.has_key('CONFIG_FDATASYNC')}
2556 summary_info += {'madvise':           config_host.has_key('CONFIG_MADVISE')}
2557 summary_info += {'posix_madvise':     config_host.has_key('CONFIG_POSIX_MADVISE')}
2558 summary_info += {'posix_memalign':    config_host.has_key('CONFIG_POSIX_MEMALIGN')}
2559 summary_info += {'debug stack usage': config_host.has_key('CONFIG_DEBUG_STACK_USAGE')}
2560 summary_info += {'mutex debugging':   config_host.has_key('CONFIG_DEBUG_MUTEX')}
2561 summary_info += {'memory allocator':  get_option('malloc')}
2562 summary_info += {'avx2 optimization': config_host.has_key('CONFIG_AVX2_OPT')}
2563 summary_info += {'avx512f optimization': config_host.has_key('CONFIG_AVX512F_OPT')}
2564 summary_info += {'gprof enabled':     config_host.has_key('CONFIG_GPROF')}
2565 summary_info += {'gcov':              get_option('b_coverage')}
2566 summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
2567 summary_info += {'CFI support':       get_option('cfi')}
2568 if get_option('cfi')
2569   summary_info += {'CFI debug support': get_option('cfi_debug')}
2570 endif
2571 summary_info += {'strip binaries':    get_option('strip')}
2572 summary_info += {'sparse':            sparse.found() ? sparse.full_path() : false}
2573 summary_info += {'mingw32 support':   targetos == 'windows'}
2575 # snarf the cross-compilation information for tests
2576 foreach target: target_dirs
2577   tcg_mak = meson.current_build_dir() / 'tests/tcg' / 'config-' + target + '.mak'
2578   if fs.exists(tcg_mak)
2579     config_cross_tcg = keyval.load(tcg_mak)
2580     target = config_cross_tcg['TARGET_NAME']
2581     compiler = ''
2582     if 'DOCKER_CROSS_CC_GUEST' in config_cross_tcg
2583       summary_info += {target + ' tests': config_cross_tcg['DOCKER_CROSS_CC_GUEST'] +
2584                                           ' via ' + config_cross_tcg['DOCKER_IMAGE']}
2585     elif 'CROSS_CC_GUEST' in config_cross_tcg
2586       summary_info += {target + ' tests'
2587                                 : config_cross_tcg['CROSS_CC_GUEST'] }
2588     endif
2589    endif
2590 endforeach
2592 summary(summary_info, bool_yn: true, section: 'Compilation')
2594 # Targets and accelerators
2595 summary_info = {}
2596 if have_system
2597   summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
2598   summary_info += {'HAX support':       config_all.has_key('CONFIG_HAX')}
2599   summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
2600   summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
2601   summary_info += {'NVMM support':      config_all.has_key('CONFIG_NVMM')}
2602   summary_info += {'Xen support':       config_host.has_key('CONFIG_XEN_BACKEND')}
2603   if config_host.has_key('CONFIG_XEN_BACKEND')
2604     summary_info += {'xen ctrl version':  config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
2605   endif
2606 endif
2607 summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
2608 if config_all.has_key('CONFIG_TCG')
2609   if get_option('tcg_interpreter')
2610     summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, experimental and slow)'}
2611   else
2612     summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
2613   endif
2614   summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
2615 endif
2616 summary_info += {'target list':       ' '.join(target_dirs)}
2617 if have_system
2618   summary_info += {'default devices':   get_option('default_devices')}
2619   summary_info += {'out of process emulation': multiprocess_allowed}
2620 endif
2621 summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
2623 # Block layer
2624 summary_info = {}
2625 summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
2626 summary_info += {'coroutine pool':    config_host['CONFIG_COROUTINE_POOL'] == '1'}
2627 if have_block
2628   summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']}
2629   summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']}
2630   summary_info += {'VirtFS support':    have_virtfs}
2631   summary_info += {'build virtiofs daemon': have_virtiofsd}
2632   summary_info += {'Live block migration': config_host.has_key('CONFIG_LIVE_BLOCK_MIGRATION')}
2633   summary_info += {'replication support': config_host.has_key('CONFIG_REPLICATION')}
2634   summary_info += {'bochs support':     config_host.has_key('CONFIG_BOCHS')}
2635   summary_info += {'cloop support':     config_host.has_key('CONFIG_CLOOP')}
2636   summary_info += {'dmg support':       config_host.has_key('CONFIG_DMG')}
2637   summary_info += {'qcow v1 support':   config_host.has_key('CONFIG_QCOW1')}
2638   summary_info += {'vdi support':       config_host.has_key('CONFIG_VDI')}
2639   summary_info += {'vvfat support':     config_host.has_key('CONFIG_VVFAT')}
2640   summary_info += {'qed support':       config_host.has_key('CONFIG_QED')}
2641   summary_info += {'parallels support': config_host.has_key('CONFIG_PARALLELS')}
2642   summary_info += {'FUSE exports':      fuse.found()}
2643 endif
2644 summary(summary_info, bool_yn: true, section: 'Block layer support')
2646 # Crypto
2647 summary_info = {}
2648 summary_info += {'TLS priority':      config_host['CONFIG_TLS_PRIORITY']}
2649 summary_info += {'GNUTLS support':    config_host.has_key('CONFIG_GNUTLS')}
2650 # TODO: add back version
2651 summary_info += {'libgcrypt':         config_host.has_key('CONFIG_GCRYPT')}
2652 if config_host.has_key('CONFIG_GCRYPT')
2653    summary_info += {'  hmac':            config_host.has_key('CONFIG_GCRYPT_HMAC')}
2654    summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
2655 endif
2656 # TODO: add back version
2657 summary_info += {'nettle':            config_host.has_key('CONFIG_NETTLE')}
2658 if config_host.has_key('CONFIG_NETTLE')
2659    summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
2660 endif
2661 summary_info += {'crypto afalg':      config_host.has_key('CONFIG_AF_ALG')}
2662 summary_info += {'rng-none':          config_host.has_key('CONFIG_RNG_NONE')}
2663 summary_info += {'Linux keyring':     config_host.has_key('CONFIG_SECRET_KEYRING')}
2664 summary(summary_info, bool_yn: true, section: 'Crypto')
2666 # Libraries
2667 summary_info = {}
2668 if targetos == 'darwin'
2669   summary_info += {'Cocoa support':   cocoa.found()}
2670 endif
2671 # TODO: add back version
2672 summary_info += {'SDL support':       sdl.found()}
2673 summary_info += {'SDL image support': sdl_image.found()}
2674 # TODO: add back version
2675 summary_info += {'GTK support':       gtk.found()}
2676 summary_info += {'pixman':            pixman.found()}
2677 # TODO: add back version
2678 summary_info += {'VTE support':       config_host.has_key('CONFIG_VTE')}
2679 # TODO: add back version
2680 summary_info += {'slirp support':     slirp_opt == 'disabled' ? false : slirp_opt}
2681 summary_info += {'libtasn1':          config_host.has_key('CONFIG_TASN1')}
2682 summary_info += {'PAM':               config_host.has_key('CONFIG_AUTH_PAM')}
2683 summary_info += {'iconv support':     iconv.found()}
2684 summary_info += {'curses support':    curses.found()}
2685 # TODO: add back version
2686 summary_info += {'virgl support':     config_host.has_key('CONFIG_VIRGL')}
2687 summary_info += {'curl support':      curl.found()}
2688 summary_info += {'Multipath support': mpathpersist.found()}
2689 summary_info += {'VNC support':       vnc.found()}
2690 if vnc.found()
2691   summary_info += {'VNC SASL support':  sasl.found()}
2692   summary_info += {'VNC JPEG support':  jpeg.found()}
2693   summary_info += {'VNC PNG support':   png.found()}
2694 endif
2695 summary_info += {'brlapi support':    brlapi.found()}
2696 summary_info += {'vde support':       config_host.has_key('CONFIG_VDE')}
2697 summary_info += {'netmap support':    config_host.has_key('CONFIG_NETMAP')}
2698 summary_info += {'Linux AIO support': config_host.has_key('CONFIG_LINUX_AIO')}
2699 summary_info += {'Linux io_uring support': config_host.has_key('CONFIG_LINUX_IO_URING')}
2700 summary_info += {'ATTR/XATTR support': libattr.found()}
2701 summary_info += {'RDMA support':      config_host.has_key('CONFIG_RDMA')}
2702 summary_info += {'PVRDMA support':    config_host.has_key('CONFIG_PVRDMA')}
2703 summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
2704 summary_info += {'libcap-ng support': libcap_ng.found()}
2705 # TODO: add back protocol and server version
2706 summary_info += {'spice support':     config_host.has_key('CONFIG_SPICE')}
2707 summary_info += {'rbd support':       rbd.found()}
2708 summary_info += {'xfsctl support':    config_host.has_key('CONFIG_XFS')}
2709 summary_info += {'smartcard support': config_host.has_key('CONFIG_SMARTCARD')}
2710 summary_info += {'U2F support':       u2f.found()}
2711 summary_info += {'libusb':            config_host.has_key('CONFIG_USB_LIBUSB')}
2712 summary_info += {'usb net redir':     config_host.has_key('CONFIG_USB_REDIR')}
2713 summary_info += {'OpenGL support':    config_host.has_key('CONFIG_OPENGL')}
2714 summary_info += {'GBM':               config_host.has_key('CONFIG_GBM')}
2715 summary_info += {'libiscsi support':  libiscsi.found()}
2716 summary_info += {'libnfs support':    libnfs.found()}
2717 if targetos == 'windows'
2718   if config_host.has_key('CONFIG_GUEST_AGENT')
2719     summary_info += {'QGA VSS support':   config_host.has_key('CONFIG_QGA_VSS')}
2720     summary_info += {'QGA w32 disk info': config_host.has_key('CONFIG_QGA_NTDDSCSI')}
2721   endif
2722 endif
2723 summary_info += {'seccomp support':   seccomp.found()}
2724 summary_info += {'GlusterFS support': glusterfs.found()}
2725 summary_info += {'TPM support':       config_host.has_key('CONFIG_TPM')}
2726 summary_info += {'libssh support':    config_host.has_key('CONFIG_LIBSSH')}
2727 summary_info += {'lzo support':       lzo.found()}
2728 summary_info += {'snappy support':    snappy.found()}
2729 summary_info += {'bzip2 support':     libbzip2.found()}
2730 summary_info += {'lzfse support':     liblzfse.found()}
2731 summary_info += {'zstd support':      zstd.found()}
2732 summary_info += {'NUMA host support': config_host.has_key('CONFIG_NUMA')}
2733 summary_info += {'libxml2':           config_host.has_key('CONFIG_LIBXML2')}
2734 summary_info += {'capstone':          capstone_opt == 'disabled' ? false : capstone_opt}
2735 summary_info += {'libpmem support':   config_host.has_key('CONFIG_LIBPMEM')}
2736 summary_info += {'libdaxctl support': config_host.has_key('CONFIG_LIBDAXCTL')}
2737 summary_info += {'libudev':           libudev.found()}
2738 summary_info += {'FUSE lseek':        fuse_lseek.found()}
2739 summary(summary_info, bool_yn: true, section: 'Dependencies')
2741 if not supported_cpus.contains(cpu)
2742   message()
2743   warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
2744   message()
2745   message('CPU host architecture ' + cpu + ' support is not currently maintained.')
2746   message('The QEMU project intends to remove support for this host CPU in')
2747   message('a future release if nobody volunteers to maintain it and to')
2748   message('provide a build host for our continuous integration setup.')
2749   message('configure has succeeded and you can continue to build, but')
2750   message('if you care about QEMU on this platform you should contact')
2751   message('us upstream at qemu-devel@nongnu.org.')
2752 endif
2754 if not supported_oses.contains(targetos)
2755   message()
2756   warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
2757   message()
2758   message('Host OS ' + targetos + 'support is not currently maintained.')
2759   message('The QEMU project intends to remove support for this host OS in')
2760   message('a future release if nobody volunteers to maintain it and to')
2761   message('provide a build host for our continuous integration setup.')
2762   message('configure has succeeded and you can continue to build, but')
2763   message('if you care about QEMU on this platform you should contact')
2764   message('us upstream at qemu-devel@nongnu.org.')
2765 endif