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