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