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