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