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