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