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