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