]> git.proxmox.com Git - mirror_qemu.git/blob - meson.build
Merge tag 'hw-misc-20240309' of https://github.com/philmd/qemu into staging
[mirror_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: get_option('cocoa'), 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 libbpf = dependency('libbpf', required: get_option('bpf'), method: 'pkg-config')
2010 if libbpf.found() and not cc.links('''
2011 #include <bpf/libbpf.h>
2012 int main(void)
2013 {
2014 bpf_object__destroy_skeleton(NULL);
2015 return 0;
2016 }''', dependencies: libbpf)
2017 libbpf = not_found
2018 if get_option('bpf').enabled()
2019 error('libbpf skeleton test failed')
2020 else
2021 warning('libbpf skeleton test failed, disabling')
2022 endif
2023 endif
2024
2025 # libxdp
2026 libxdp = not_found
2027 if not get_option('af_xdp').auto() or have_system
2028 libxdp = dependency('libxdp', required: get_option('af_xdp'),
2029 version: '>=1.4.0', method: 'pkg-config')
2030 endif
2031
2032 # libdw
2033 libdw = not_found
2034 if not get_option('libdw').auto() or \
2035 (not get_option('prefer_static') and (have_system or have_user))
2036 libdw = dependency('libdw',
2037 method: 'pkg-config',
2038 required: get_option('libdw'))
2039 endif
2040
2041 #################
2042 # config-host.h #
2043 #################
2044
2045 config_host_data = configuration_data()
2046
2047 audio_drivers_selected = []
2048 if have_system
2049 audio_drivers_available = {
2050 'alsa': alsa.found(),
2051 'coreaudio': coreaudio.found(),
2052 'dsound': dsound.found(),
2053 'jack': jack.found(),
2054 'oss': oss.found(),
2055 'pa': pulse.found(),
2056 'pipewire': pipewire.found(),
2057 'sdl': sdl.found(),
2058 'sndio': sndio.found(),
2059 }
2060 foreach k, v: audio_drivers_available
2061 config_host_data.set('CONFIG_AUDIO_' + k.to_upper(), v)
2062 endforeach
2063
2064 # Default to native drivers first, OSS second, SDL third
2065 audio_drivers_priority = \
2066 [ 'pa', 'coreaudio', 'dsound', 'sndio', 'oss' ] + \
2067 (host_os == 'linux' ? [] : [ 'sdl' ])
2068 audio_drivers_default = []
2069 foreach k: audio_drivers_priority
2070 if audio_drivers_available[k]
2071 audio_drivers_default += k
2072 endif
2073 endforeach
2074
2075 foreach k: get_option('audio_drv_list')
2076 if k == 'default'
2077 audio_drivers_selected += audio_drivers_default
2078 elif not audio_drivers_available[k]
2079 error('Audio driver "@0@" not available.'.format(k))
2080 else
2081 audio_drivers_selected += k
2082 endif
2083 endforeach
2084 endif
2085 config_host_data.set('CONFIG_AUDIO_DRIVERS',
2086 '"' + '", "'.join(audio_drivers_selected) + '", ')
2087
2088 have_host_block_device = (host_os != 'darwin' or
2089 cc.has_header('IOKit/storage/IOMedia.h'))
2090
2091 dbus_display = get_option('dbus_display') \
2092 .require(gio.version().version_compare('>=2.64'),
2093 error_message: '-display dbus requires glib>=2.64') \
2094 .require(gdbus_codegen.found(),
2095 error_message: gdbus_codegen_error.format('-display dbus')) \
2096 .allowed()
2097
2098 have_virtfs = get_option('virtfs') \
2099 .require(host_os == 'linux' or host_os == 'darwin',
2100 error_message: 'virtio-9p (virtfs) requires Linux or macOS') \
2101 .require(host_os == 'linux' or cc.has_function('pthread_fchdir_np'),
2102 error_message: 'virtio-9p (virtfs) on macOS requires the presence of pthread_fchdir_np') \
2103 .require(host_os == 'darwin' or libattr.found(),
2104 error_message: 'virtio-9p (virtfs) on Linux requires libattr-devel') \
2105 .disable_auto_if(not have_tools and not have_system) \
2106 .allowed()
2107
2108 have_virtfs_proxy_helper = get_option('virtfs_proxy_helper') \
2109 .require(host_os != 'darwin', error_message: 'the virtfs proxy helper is incompatible with macOS') \
2110 .require(have_virtfs, error_message: 'the virtfs proxy helper requires that virtfs is enabled') \
2111 .disable_auto_if(not have_tools) \
2112 .require(libcap_ng.found(), error_message: 'the virtfs proxy helper requires libcap-ng') \
2113 .allowed()
2114
2115 if get_option('block_drv_ro_whitelist') == ''
2116 config_host_data.set('CONFIG_BDRV_RO_WHITELIST', '')
2117 else
2118 config_host_data.set('CONFIG_BDRV_RO_WHITELIST',
2119 '"' + get_option('block_drv_ro_whitelist').replace(',', '", "') + '", ')
2120 endif
2121 if get_option('block_drv_rw_whitelist') == ''
2122 config_host_data.set('CONFIG_BDRV_RW_WHITELIST', '')
2123 else
2124 config_host_data.set('CONFIG_BDRV_RW_WHITELIST',
2125 '"' + get_option('block_drv_rw_whitelist').replace(',', '", "') + '", ')
2126 endif
2127
2128 foreach k : get_option('trace_backends')
2129 config_host_data.set('CONFIG_TRACE_' + k.to_upper(), true)
2130 endforeach
2131 config_host_data.set_quoted('CONFIG_TRACE_FILE', get_option('trace_file'))
2132 config_host_data.set_quoted('CONFIG_TLS_PRIORITY', get_option('tls_priority'))
2133 if iasl.found()
2134 config_host_data.set_quoted('CONFIG_IASL', iasl.full_path())
2135 endif
2136 config_host_data.set_quoted('CONFIG_BINDIR', get_option('prefix') / get_option('bindir'))
2137 config_host_data.set_quoted('CONFIG_PREFIX', get_option('prefix'))
2138 config_host_data.set_quoted('CONFIG_QEMU_CONFDIR', get_option('prefix') / qemu_confdir)
2139 config_host_data.set_quoted('CONFIG_QEMU_DATADIR', get_option('prefix') / qemu_datadir)
2140 config_host_data.set_quoted('CONFIG_QEMU_DESKTOPDIR', get_option('prefix') / qemu_desktopdir)
2141
2142 qemu_firmwarepath = ''
2143 foreach k : get_option('qemu_firmwarepath')
2144 qemu_firmwarepath += '"' + get_option('prefix') / k + '", '
2145 endforeach
2146 config_host_data.set('CONFIG_QEMU_FIRMWAREPATH', qemu_firmwarepath)
2147
2148 config_host_data.set_quoted('CONFIG_QEMU_HELPERDIR', get_option('prefix') / get_option('libexecdir'))
2149 config_host_data.set_quoted('CONFIG_QEMU_ICONDIR', get_option('prefix') / qemu_icondir)
2150 config_host_data.set_quoted('CONFIG_QEMU_LOCALEDIR', get_option('prefix') / get_option('localedir'))
2151 config_host_data.set_quoted('CONFIG_QEMU_LOCALSTATEDIR', get_option('prefix') / get_option('localstatedir'))
2152 config_host_data.set_quoted('CONFIG_QEMU_MODDIR', get_option('prefix') / qemu_moddir)
2153 config_host_data.set_quoted('CONFIG_SYSCONFDIR', get_option('prefix') / get_option('sysconfdir'))
2154
2155 if enable_modules
2156 config_host_data.set('CONFIG_STAMP', run_command(
2157 meson.current_source_dir() / 'scripts/qemu-stamp.py',
2158 meson.project_version(), get_option('pkgversion'), '--',
2159 meson.current_source_dir() / 'configure',
2160 capture: true, check: true).stdout().strip())
2161 endif
2162
2163 have_slirp_smbd = get_option('slirp_smbd') \
2164 .require(host_os != 'windows', error_message: 'Host smbd not supported on this platform.') \
2165 .allowed()
2166 if have_slirp_smbd
2167 smbd_path = get_option('smbd')
2168 if smbd_path == ''
2169 smbd_path = (host_os == 'sunos' ? '/usr/sfw/sbin/smbd' : '/usr/sbin/smbd')
2170 endif
2171 config_host_data.set_quoted('CONFIG_SMBD_COMMAND', smbd_path)
2172 endif
2173
2174 config_host_data.set('HOST_' + host_arch.to_upper(), 1)
2175
2176 kvm_targets_c = '""'
2177 if get_option('kvm').allowed() and host_os == 'linux'
2178 kvm_targets_c = '"' + '" ,"'.join(kvm_targets) + '"'
2179 endif
2180 config_host_data.set('CONFIG_KVM_TARGETS', kvm_targets_c)
2181
2182 if get_option('module_upgrades') and not enable_modules
2183 error('Cannot enable module-upgrades as modules are not enabled')
2184 endif
2185 config_host_data.set('CONFIG_MODULE_UPGRADES', get_option('module_upgrades'))
2186
2187 config_host_data.set('CONFIG_ATTR', libattr.found())
2188 config_host_data.set('CONFIG_BDRV_WHITELIST_TOOLS', get_option('block_drv_whitelist_in_tools'))
2189 config_host_data.set('CONFIG_BRLAPI', brlapi.found())
2190 config_host_data.set('CONFIG_BSD', host_os in bsd_oses)
2191 config_host_data.set('CONFIG_CAPSTONE', capstone.found())
2192 config_host_data.set('CONFIG_COCOA', cocoa.found())
2193 config_host_data.set('CONFIG_DARWIN', host_os == 'darwin')
2194 config_host_data.set('CONFIG_FUZZ', get_option('fuzzing'))
2195 config_host_data.set('CONFIG_GCOV', get_option('b_coverage'))
2196 config_host_data.set('CONFIG_LIBUDEV', libudev.found())
2197 config_host_data.set('CONFIG_LINUX', host_os == 'linux')
2198 config_host_data.set('CONFIG_POSIX', host_os != 'windows')
2199 config_host_data.set('CONFIG_WIN32', host_os == 'windows')
2200 config_host_data.set('CONFIG_LZO', lzo.found())
2201 config_host_data.set('CONFIG_MPATH', mpathpersist.found())
2202 config_host_data.set('CONFIG_BLKIO', blkio.found())
2203 if blkio.found()
2204 config_host_data.set('CONFIG_BLKIO_VHOST_VDPA_FD',
2205 blkio.version().version_compare('>=1.3.0'))
2206 endif
2207 config_host_data.set('CONFIG_CURL', curl.found())
2208 config_host_data.set('CONFIG_CURSES', curses.found())
2209 config_host_data.set('CONFIG_GBM', gbm.found())
2210 config_host_data.set('CONFIG_GIO', gio.found())
2211 config_host_data.set('CONFIG_GLUSTERFS', glusterfs.found())
2212 if glusterfs.found()
2213 config_host_data.set('CONFIG_GLUSTERFS_XLATOR_OPT', glusterfs.version().version_compare('>=4'))
2214 config_host_data.set('CONFIG_GLUSTERFS_DISCARD', glusterfs.version().version_compare('>=5'))
2215 config_host_data.set('CONFIG_GLUSTERFS_FALLOCATE', glusterfs.version().version_compare('>=6'))
2216 config_host_data.set('CONFIG_GLUSTERFS_ZEROFILL', glusterfs.version().version_compare('>=6'))
2217 config_host_data.set('CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT', glusterfs_ftruncate_has_stat)
2218 config_host_data.set('CONFIG_GLUSTERFS_IOCB_HAS_STAT', glusterfs_iocb_has_stat)
2219 endif
2220 config_host_data.set('CONFIG_GTK', gtk.found())
2221 config_host_data.set('CONFIG_VTE', vte.found())
2222 config_host_data.set('CONFIG_GTK_CLIPBOARD', have_gtk_clipboard)
2223 config_host_data.set('CONFIG_HEXAGON_IDEF_PARSER', get_option('hexagon_idef_parser'))
2224 config_host_data.set('CONFIG_LIBATTR', have_old_libattr)
2225 config_host_data.set('CONFIG_LIBCAP_NG', libcap_ng.found())
2226 config_host_data.set('CONFIG_EBPF', libbpf.found())
2227 config_host_data.set('CONFIG_AF_XDP', libxdp.found())
2228 config_host_data.set('CONFIG_LIBDAXCTL', libdaxctl.found())
2229 config_host_data.set('CONFIG_LIBISCSI', libiscsi.found())
2230 config_host_data.set('CONFIG_LIBNFS', libnfs.found())
2231 config_host_data.set('CONFIG_LIBSSH', libssh.found())
2232 config_host_data.set('CONFIG_LINUX_AIO', libaio.found())
2233 config_host_data.set('CONFIG_LINUX_IO_URING', linux_io_uring.found())
2234 config_host_data.set('CONFIG_LIBPMEM', libpmem.found())
2235 config_host_data.set('CONFIG_MODULES', enable_modules)
2236 config_host_data.set('CONFIG_NUMA', numa.found())
2237 if numa.found()
2238 config_host_data.set('HAVE_NUMA_HAS_PREFERRED_MANY',
2239 cc.has_function('numa_has_preferred_many',
2240 dependencies: numa))
2241 endif
2242 config_host_data.set('CONFIG_OPENGL', opengl.found())
2243 config_host_data.set('CONFIG_PLUGIN', get_option('plugins'))
2244 config_host_data.set('CONFIG_RBD', rbd.found())
2245 config_host_data.set('CONFIG_RDMA', rdma.found())
2246 config_host_data.set('CONFIG_RELOCATABLE', get_option('relocatable'))
2247 config_host_data.set('CONFIG_SAFESTACK', get_option('safe_stack'))
2248 config_host_data.set('CONFIG_SDL', sdl.found())
2249 config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found())
2250 config_host_data.set('CONFIG_SECCOMP', seccomp.found())
2251 if seccomp.found()
2252 config_host_data.set('CONFIG_SECCOMP_SYSRAWRC', seccomp_has_sysrawrc)
2253 endif
2254 config_host_data.set('CONFIG_PIXMAN', pixman.found())
2255 config_host_data.set('CONFIG_SLIRP', slirp.found())
2256 config_host_data.set('CONFIG_SNAPPY', snappy.found())
2257 config_host_data.set('CONFIG_SOLARIS', host_os == 'sunos')
2258 if get_option('tcg').allowed()
2259 config_host_data.set('CONFIG_TCG', 1)
2260 config_host_data.set('CONFIG_TCG_INTERPRETER', tcg_arch == 'tci')
2261 endif
2262 config_host_data.set('CONFIG_TPM', have_tpm)
2263 config_host_data.set('CONFIG_TSAN', get_option('tsan'))
2264 config_host_data.set('CONFIG_USB_LIBUSB', libusb.found())
2265 config_host_data.set('CONFIG_VDE', vde.found())
2266 config_host_data.set('CONFIG_VHOST', have_vhost)
2267 config_host_data.set('CONFIG_VHOST_NET', have_vhost_net)
2268 config_host_data.set('CONFIG_VHOST_NET_USER', have_vhost_net_user)
2269 config_host_data.set('CONFIG_VHOST_NET_VDPA', have_vhost_net_vdpa)
2270 config_host_data.set('CONFIG_VHOST_KERNEL', have_vhost_kernel)
2271 config_host_data.set('CONFIG_VHOST_USER', have_vhost_user)
2272 config_host_data.set('CONFIG_VHOST_CRYPTO', have_vhost_user_crypto)
2273 config_host_data.set('CONFIG_VHOST_VDPA', have_vhost_vdpa)
2274 config_host_data.set('CONFIG_VMNET', vmnet.found())
2275 config_host_data.set('CONFIG_VHOST_USER_BLK_SERVER', have_vhost_user_blk_server)
2276 config_host_data.set('CONFIG_VDUSE_BLK_EXPORT', have_vduse_blk_export)
2277 config_host_data.set('CONFIG_PNG', png.found())
2278 config_host_data.set('CONFIG_VNC', vnc.found())
2279 config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
2280 config_host_data.set('CONFIG_VNC_SASL', sasl.found())
2281 if virgl.found()
2282 config_host_data.set('HAVE_VIRGL_D3D_INFO_EXT',
2283 cc.has_member('struct virgl_renderer_resource_info_ext', 'd3d_tex2d',
2284 prefix: '#include <virglrenderer.h>',
2285 dependencies: virgl))
2286 endif
2287 config_host_data.set('CONFIG_VIRTFS', have_virtfs)
2288 config_host_data.set('CONFIG_VTE', vte.found())
2289 config_host_data.set('CONFIG_XKBCOMMON', xkbcommon.found())
2290 config_host_data.set('CONFIG_KEYUTILS', keyutils.found())
2291 config_host_data.set('CONFIG_GETTID', has_gettid)
2292 config_host_data.set('CONFIG_GNUTLS', gnutls.found())
2293 config_host_data.set('CONFIG_GNUTLS_CRYPTO', gnutls_crypto.found())
2294 config_host_data.set('CONFIG_TASN1', tasn1.found())
2295 config_host_data.set('CONFIG_GCRYPT', gcrypt.found())
2296 config_host_data.set('CONFIG_NETTLE', nettle.found())
2297 config_host_data.set('CONFIG_CRYPTO_SM4', crypto_sm4.found())
2298 config_host_data.set('CONFIG_HOGWEED', hogweed.found())
2299 config_host_data.set('CONFIG_QEMU_PRIVATE_XTS', xts == 'private')
2300 config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim)
2301 config_host_data.set('CONFIG_STATX', has_statx)
2302 config_host_data.set('CONFIG_STATX_MNT_ID', has_statx_mnt_id)
2303 config_host_data.set('CONFIG_ZSTD', zstd.found())
2304 config_host_data.set('CONFIG_FUSE', fuse.found())
2305 config_host_data.set('CONFIG_FUSE_LSEEK', fuse_lseek.found())
2306 config_host_data.set('CONFIG_SPICE_PROTOCOL', spice_protocol.found())
2307 if spice_protocol.found()
2308 config_host_data.set('CONFIG_SPICE_PROTOCOL_MAJOR', spice_protocol.version().split('.')[0])
2309 config_host_data.set('CONFIG_SPICE_PROTOCOL_MINOR', spice_protocol.version().split('.')[1])
2310 config_host_data.set('CONFIG_SPICE_PROTOCOL_MICRO', spice_protocol.version().split('.')[2])
2311 endif
2312 config_host_data.set('CONFIG_SPICE', spice.found())
2313 config_host_data.set('CONFIG_X11', x11.found())
2314 config_host_data.set('CONFIG_DBUS_DISPLAY', dbus_display)
2315 config_host_data.set('CONFIG_CFI', get_option('cfi'))
2316 config_host_data.set('CONFIG_SELINUX', selinux.found())
2317 config_host_data.set('CONFIG_XEN_BACKEND', xen.found())
2318 config_host_data.set('CONFIG_LIBDW', libdw.found())
2319 if xen.found()
2320 # protect from xen.version() having less than three components
2321 xen_version = xen.version().split('.') + ['0', '0']
2322 xen_ctrl_version = xen_version[0] + \
2323 ('0' + xen_version[1]).substring(-2) + \
2324 ('0' + xen_version[2]).substring(-2)
2325 config_host_data.set('CONFIG_XEN_CTRL_INTERFACE_VERSION', xen_ctrl_version)
2326 endif
2327 config_host_data.set('QEMU_VERSION', '"@0@"'.format(meson.project_version()))
2328 config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0])
2329 config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1])
2330 config_host_data.set('QEMU_VERSION_MICRO', meson.project_version().split('.')[2])
2331
2332 config_host_data.set_quoted('CONFIG_HOST_DSOSUF', host_dsosuf)
2333 config_host_data.set('HAVE_HOST_BLOCK_DEVICE', have_host_block_device)
2334
2335 have_coroutine_pool = get_option('coroutine_pool')
2336 if get_option('debug_stack_usage') and have_coroutine_pool
2337 message('Disabling coroutine pool to measure stack usage')
2338 have_coroutine_pool = false
2339 endif
2340 config_host_data.set('CONFIG_COROUTINE_POOL', have_coroutine_pool)
2341 config_host_data.set('CONFIG_DEBUG_GRAPH_LOCK', get_option('debug_graph_lock'))
2342 config_host_data.set('CONFIG_DEBUG_MUTEX', get_option('debug_mutex'))
2343 config_host_data.set('CONFIG_DEBUG_STACK_USAGE', get_option('debug_stack_usage'))
2344 config_host_data.set('CONFIG_DEBUG_TCG', get_option('debug_tcg'))
2345 config_host_data.set('CONFIG_LIVE_BLOCK_MIGRATION', get_option('live_block_migration').allowed())
2346 config_host_data.set('CONFIG_QOM_CAST_DEBUG', get_option('qom_cast_debug'))
2347 config_host_data.set('CONFIG_REPLICATION', get_option('replication').allowed())
2348
2349 # has_header
2350 config_host_data.set('CONFIG_EPOLL', cc.has_header('sys/epoll.h'))
2351 config_host_data.set('CONFIG_LINUX_MAGIC_H', cc.has_header('linux/magic.h'))
2352 config_host_data.set('CONFIG_VALGRIND_H', cc.has_header('valgrind/valgrind.h'))
2353 config_host_data.set('HAVE_BTRFS_H', cc.has_header('linux/btrfs.h'))
2354 config_host_data.set('HAVE_DRM_H', cc.has_header('libdrm/drm.h'))
2355 config_host_data.set('HAVE_PTY_H', cc.has_header('pty.h'))
2356 config_host_data.set('HAVE_SYS_DISK_H', cc.has_header('sys/disk.h'))
2357 config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h'))
2358 config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h'))
2359 if host_os == 'windows'
2360 config_host_data.set('HAVE_AFUNIX_H', cc.has_header('afunix.h'))
2361 endif
2362
2363 # has_function
2364 config_host_data.set('CONFIG_CLOSE_RANGE', cc.has_function('close_range'))
2365 config_host_data.set('CONFIG_ACCEPT4', cc.has_function('accept4'))
2366 config_host_data.set('CONFIG_CLOCK_ADJTIME', cc.has_function('clock_adjtime'))
2367 config_host_data.set('CONFIG_DUP3', cc.has_function('dup3'))
2368 config_host_data.set('CONFIG_FALLOCATE', cc.has_function('fallocate'))
2369 config_host_data.set('CONFIG_POSIX_FALLOCATE', cc.has_function('posix_fallocate'))
2370 config_host_data.set('CONFIG_GETCPU', cc.has_function('getcpu', prefix: gnu_source_prefix))
2371 config_host_data.set('CONFIG_SCHED_GETCPU', cc.has_function('sched_getcpu', prefix: '#include <sched.h>'))
2372 # Note that we need to specify prefix: here to avoid incorrectly
2373 # thinking that Windows has posix_memalign()
2374 config_host_data.set('CONFIG_POSIX_MEMALIGN', cc.has_function('posix_memalign', prefix: '#include <stdlib.h>'))
2375 config_host_data.set('CONFIG_ALIGNED_MALLOC', cc.has_function('_aligned_malloc'))
2376 config_host_data.set('CONFIG_VALLOC', cc.has_function('valloc'))
2377 config_host_data.set('CONFIG_MEMALIGN', cc.has_function('memalign'))
2378 config_host_data.set('CONFIG_PPOLL', cc.has_function('ppoll'))
2379 config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include <sys/uio.h>'))
2380 config_host_data.set('CONFIG_PTHREAD_FCHDIR_NP', cc.has_function('pthread_fchdir_np'))
2381 config_host_data.set('CONFIG_SENDFILE', cc.has_function('sendfile'))
2382 config_host_data.set('CONFIG_SETNS', cc.has_function('setns') and cc.has_function('unshare'))
2383 config_host_data.set('CONFIG_SYNCFS', cc.has_function('syncfs'))
2384 config_host_data.set('CONFIG_SYNC_FILE_RANGE', cc.has_function('sync_file_range'))
2385 config_host_data.set('CONFIG_TIMERFD', cc.has_function('timerfd_create'))
2386 config_host_data.set('HAVE_COPY_FILE_RANGE', cc.has_function('copy_file_range'))
2387 config_host_data.set('HAVE_GETIFADDRS', cc.has_function('getifaddrs'))
2388 config_host_data.set('HAVE_GLIB_WITH_SLICE_ALLOCATOR', glib_has_gslice)
2389 config_host_data.set('HAVE_OPENPTY', cc.has_function('openpty', dependencies: util))
2390 config_host_data.set('HAVE_STRCHRNUL', cc.has_function('strchrnul'))
2391 config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: '#include <stdlib.h>'))
2392 if rbd.found()
2393 config_host_data.set('HAVE_RBD_NAMESPACE_EXISTS',
2394 cc.has_function('rbd_namespace_exists',
2395 dependencies: rbd,
2396 prefix: '#include <rbd/librbd.h>'))
2397 endif
2398 if rdma.found()
2399 config_host_data.set('HAVE_IBV_ADVISE_MR',
2400 cc.has_function('ibv_advise_mr',
2401 dependencies: rdma,
2402 prefix: '#include <infiniband/verbs.h>'))
2403 endif
2404
2405 have_asan_fiber = false
2406 if get_option('sanitizers') and \
2407 not cc.has_function('__sanitizer_start_switch_fiber',
2408 args: '-fsanitize=address',
2409 prefix: '#include <sanitizer/asan_interface.h>')
2410 warning('Missing ASAN due to missing fiber annotation interface')
2411 warning('Without code annotation, the report may be inferior.')
2412 else
2413 have_asan_fiber = true
2414 endif
2415 config_host_data.set('CONFIG_ASAN_IFACE_FIBER', have_asan_fiber)
2416
2417 have_inotify_init = cc.has_header_symbol('sys/inotify.h', 'inotify_init')
2418 have_inotify_init1 = cc.has_header_symbol('sys/inotify.h', 'inotify_init1')
2419 inotify = not_found
2420 if (have_inotify_init or have_inotify_init1) and host_os == 'freebsd'
2421 # libinotify-kqueue
2422 inotify = cc.find_library('inotify')
2423 if have_inotify_init
2424 have_inotify_init = inotify.found()
2425 endif
2426 if have_inotify_init1
2427 have_inotify_init1 = inotify.found()
2428 endif
2429 endif
2430 config_host_data.set('CONFIG_INOTIFY', have_inotify_init)
2431 config_host_data.set('CONFIG_INOTIFY1', have_inotify_init1)
2432
2433 # has_header_symbol
2434 config_host_data.set('CONFIG_BLKZONED',
2435 cc.has_header_symbol('linux/blkzoned.h', 'BLKOPENZONE'))
2436 config_host_data.set('CONFIG_EPOLL_CREATE1',
2437 cc.has_header_symbol('sys/epoll.h', 'epoll_create1'))
2438 config_host_data.set('CONFIG_FALLOCATE_PUNCH_HOLE',
2439 cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_PUNCH_HOLE') and
2440 cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_KEEP_SIZE'))
2441 config_host_data.set('CONFIG_FALLOCATE_ZERO_RANGE',
2442 cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_ZERO_RANGE'))
2443 config_host_data.set('CONFIG_FIEMAP',
2444 cc.has_header('linux/fiemap.h') and
2445 cc.has_header_symbol('linux/fs.h', 'FS_IOC_FIEMAP'))
2446 config_host_data.set('CONFIG_GETRANDOM',
2447 cc.has_function('getrandom') and
2448 cc.has_header_symbol('sys/random.h', 'GRND_NONBLOCK'))
2449 config_host_data.set('CONFIG_PRCTL_PR_SET_TIMERSLACK',
2450 cc.has_header_symbol('sys/prctl.h', 'PR_SET_TIMERSLACK'))
2451 config_host_data.set('CONFIG_RTNETLINK',
2452 cc.has_header_symbol('linux/rtnetlink.h', 'IFLA_PROTO_DOWN'))
2453 config_host_data.set('CONFIG_SYSMACROS',
2454 cc.has_header_symbol('sys/sysmacros.h', 'makedev'))
2455 config_host_data.set('HAVE_OPTRESET',
2456 cc.has_header_symbol('getopt.h', 'optreset'))
2457 config_host_data.set('HAVE_IPPROTO_MPTCP',
2458 cc.has_header_symbol('netinet/in.h', 'IPPROTO_MPTCP'))
2459
2460 # has_member
2461 config_host_data.set('HAVE_SIGEV_NOTIFY_THREAD_ID',
2462 cc.has_member('struct sigevent', 'sigev_notify_thread_id',
2463 prefix: '#include <signal.h>'))
2464 config_host_data.set('HAVE_STRUCT_STAT_ST_ATIM',
2465 cc.has_member('struct stat', 'st_atim',
2466 prefix: '#include <sys/stat.h>'))
2467 config_host_data.set('HAVE_BLK_ZONE_REP_CAPACITY',
2468 cc.has_member('struct blk_zone', 'capacity',
2469 prefix: '#include <linux/blkzoned.h>'))
2470
2471 # has_type
2472 config_host_data.set('CONFIG_IOVEC',
2473 cc.has_type('struct iovec',
2474 prefix: '#include <sys/uio.h>'))
2475 config_host_data.set('HAVE_UTMPX',
2476 cc.has_type('struct utmpx',
2477 prefix: '#include <utmpx.h>'))
2478
2479 config_host_data.set('CONFIG_EVENTFD', cc.links('''
2480 #include <sys/eventfd.h>
2481 int main(void) { return eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); }'''))
2482 config_host_data.set('CONFIG_FDATASYNC', cc.links(gnu_source_prefix + '''
2483 #include <unistd.h>
2484 int main(void) {
2485 #if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
2486 return fdatasync(0);
2487 #else
2488 #error Not supported
2489 #endif
2490 }'''))
2491
2492 has_madvise = cc.links(gnu_source_prefix + '''
2493 #include <sys/types.h>
2494 #include <sys/mman.h>
2495 #include <stddef.h>
2496 int main(void) { return madvise(NULL, 0, MADV_DONTNEED); }''')
2497 missing_madvise_proto = false
2498 if has_madvise
2499 # Some platforms (illumos and Solaris before Solaris 11) provide madvise()
2500 # but forget to prototype it. In this case, has_madvise will be true (the
2501 # test program links despite a compile warning). To detect the
2502 # missing-prototype case, we try again with a definitely-bogus prototype.
2503 # This will only compile if the system headers don't provide the prototype;
2504 # otherwise the conflicting prototypes will cause a compiler error.
2505 missing_madvise_proto = cc.links(gnu_source_prefix + '''
2506 #include <sys/types.h>
2507 #include <sys/mman.h>
2508 #include <stddef.h>
2509 extern int madvise(int);
2510 int main(void) { return madvise(0); }''')
2511 endif
2512 config_host_data.set('CONFIG_MADVISE', has_madvise)
2513 config_host_data.set('HAVE_MADVISE_WITHOUT_PROTOTYPE', missing_madvise_proto)
2514
2515 config_host_data.set('CONFIG_MEMFD', cc.links(gnu_source_prefix + '''
2516 #include <sys/mman.h>
2517 int main(void) { return memfd_create("foo", MFD_ALLOW_SEALING); }'''))
2518 config_host_data.set('CONFIG_OPEN_BY_HANDLE', cc.links(gnu_source_prefix + '''
2519 #include <fcntl.h>
2520 #if !defined(AT_EMPTY_PATH)
2521 # error missing definition
2522 #else
2523 int main(void) { struct file_handle fh; return open_by_handle_at(0, &fh, 0); }
2524 #endif'''))
2525 config_host_data.set('CONFIG_POSIX_MADVISE', cc.links(gnu_source_prefix + '''
2526 #include <sys/mman.h>
2527 #include <stddef.h>
2528 int main(void) { return posix_madvise(NULL, 0, POSIX_MADV_DONTNEED); }'''))
2529
2530 config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_W_TID', cc.links(gnu_source_prefix + '''
2531 #include <pthread.h>
2532
2533 static void *f(void *p) { return NULL; }
2534 int main(void)
2535 {
2536 pthread_t thread;
2537 pthread_create(&thread, 0, f, 0);
2538 pthread_setname_np(thread, "QEMU");
2539 return 0;
2540 }''', dependencies: threads))
2541 config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_WO_TID', cc.links(gnu_source_prefix + '''
2542 #include <pthread.h>
2543
2544 static void *f(void *p) { pthread_setname_np("QEMU"); return NULL; }
2545 int main(void)
2546 {
2547 pthread_t thread;
2548 pthread_create(&thread, 0, f, 0);
2549 return 0;
2550 }''', dependencies: threads))
2551 config_host_data.set('CONFIG_PTHREAD_SET_NAME_NP', cc.links(gnu_source_prefix + '''
2552 #include <pthread.h>
2553 #include <pthread_np.h>
2554
2555 static void *f(void *p) { return NULL; }
2556 int main(void)
2557 {
2558 pthread_t thread;
2559 pthread_create(&thread, 0, f, 0);
2560 pthread_set_name_np(thread, "QEMU");
2561 return 0;
2562 }''', dependencies: threads))
2563 config_host_data.set('CONFIG_PTHREAD_CONDATTR_SETCLOCK', cc.links(gnu_source_prefix + '''
2564 #include <pthread.h>
2565 #include <time.h>
2566
2567 int main(void)
2568 {
2569 pthread_condattr_t attr
2570 pthread_condattr_init(&attr);
2571 pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
2572 return 0;
2573 }''', dependencies: threads))
2574 config_host_data.set('CONFIG_PTHREAD_AFFINITY_NP', cc.links(gnu_source_prefix + '''
2575 #include <pthread.h>
2576
2577 static void *f(void *p) { return NULL; }
2578 int main(void)
2579 {
2580 int setsize = CPU_ALLOC_SIZE(64);
2581 pthread_t thread;
2582 cpu_set_t *cpuset;
2583 pthread_create(&thread, 0, f, 0);
2584 cpuset = CPU_ALLOC(64);
2585 CPU_ZERO_S(setsize, cpuset);
2586 pthread_setaffinity_np(thread, setsize, cpuset);
2587 pthread_getaffinity_np(thread, setsize, cpuset);
2588 CPU_FREE(cpuset);
2589 return 0;
2590 }''', dependencies: threads))
2591 config_host_data.set('CONFIG_SIGNALFD', cc.links(gnu_source_prefix + '''
2592 #include <sys/signalfd.h>
2593 #include <stddef.h>
2594 int main(void) { return signalfd(-1, NULL, SFD_CLOEXEC); }'''))
2595 config_host_data.set('CONFIG_SPLICE', cc.links(gnu_source_prefix + '''
2596 #include <unistd.h>
2597 #include <fcntl.h>
2598 #include <limits.h>
2599
2600 int main(void)
2601 {
2602 int len, fd = 0;
2603 len = tee(STDIN_FILENO, STDOUT_FILENO, INT_MAX, SPLICE_F_NONBLOCK);
2604 splice(STDIN_FILENO, NULL, fd, NULL, len, SPLICE_F_MOVE);
2605 return 0;
2606 }'''))
2607
2608 config_host_data.set('HAVE_MLOCKALL', cc.links(gnu_source_prefix + '''
2609 #include <sys/mman.h>
2610 int main(void) {
2611 return mlockall(MCL_FUTURE);
2612 }'''))
2613
2614 have_l2tpv3 = false
2615 if get_option('l2tpv3').allowed() and have_system
2616 have_l2tpv3 = cc.has_type('struct mmsghdr',
2617 prefix: gnu_source_prefix + '''
2618 #include <sys/socket.h>
2619 #include <linux/ip.h>''')
2620 endif
2621 config_host_data.set('CONFIG_L2TPV3', have_l2tpv3)
2622
2623 have_netmap = false
2624 if get_option('netmap').allowed() and have_system
2625 have_netmap = cc.compiles('''
2626 #include <inttypes.h>
2627 #include <net/if.h>
2628 #include <net/netmap.h>
2629 #include <net/netmap_user.h>
2630 #if (NETMAP_API < 11) || (NETMAP_API > 15)
2631 #error
2632 #endif
2633 int main(void) { return 0; }''')
2634 if not have_netmap and get_option('netmap').enabled()
2635 error('Netmap headers not available')
2636 endif
2637 endif
2638 config_host_data.set('CONFIG_NETMAP', have_netmap)
2639
2640 # Work around a system header bug with some kernel/XFS header
2641 # versions where they both try to define 'struct fsxattr':
2642 # xfs headers will not try to redefine structs from linux headers
2643 # if this macro is set.
2644 config_host_data.set('HAVE_FSXATTR', cc.links('''
2645 #include <linux/fs.h>
2646 struct fsxattr foo;
2647 int main(void) {
2648 return 0;
2649 }'''))
2650
2651 # Some versions of Mac OS X incorrectly define SIZE_MAX
2652 config_host_data.set('HAVE_BROKEN_SIZE_MAX', not cc.compiles('''
2653 #include <stdint.h>
2654 #include <stdio.h>
2655 int main(void) {
2656 return printf("%zu", SIZE_MAX);
2657 }''', args: ['-Werror']))
2658
2659 # See if 64-bit atomic operations are supported.
2660 # Note that without __atomic builtins, we can only
2661 # assume atomic loads/stores max at pointer size.
2662 config_host_data.set('CONFIG_ATOMIC64', cc.links('''
2663 #include <stdint.h>
2664 int main(void)
2665 {
2666 uint64_t x = 0, y = 0;
2667 y = __atomic_load_n(&x, __ATOMIC_RELAXED);
2668 __atomic_store_n(&x, y, __ATOMIC_RELAXED);
2669 __atomic_compare_exchange_n(&x, &y, x, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
2670 __atomic_exchange_n(&x, y, __ATOMIC_RELAXED);
2671 __atomic_fetch_add(&x, y, __ATOMIC_RELAXED);
2672 return 0;
2673 }'''))
2674
2675 has_int128_type = cc.compiles('''
2676 __int128_t a;
2677 __uint128_t b;
2678 int main(void) { b = a; }''')
2679 config_host_data.set('CONFIG_INT128_TYPE', has_int128_type)
2680
2681 has_int128 = has_int128_type and cc.links('''
2682 __int128_t a;
2683 __uint128_t b;
2684 int main (void) {
2685 a = a + b;
2686 b = a * b;
2687 a = a * a;
2688 return 0;
2689 }''')
2690 config_host_data.set('CONFIG_INT128', has_int128)
2691
2692 if has_int128_type
2693 # "do we have 128-bit atomics which are handled inline and specifically not
2694 # via libatomic". The reason we can't use libatomic is documented in the
2695 # comment starting "GCC is a house divided" in include/qemu/atomic128.h.
2696 # We only care about these operations on 16-byte aligned pointers, so
2697 # force 16-byte alignment of the pointer, which may be greater than
2698 # __alignof(unsigned __int128) for the host.
2699 atomic_test_128 = '''
2700 int main(int ac, char **av) {
2701 __uint128_t *p = __builtin_assume_aligned(av[ac - 1], 16);
2702 p[1] = __atomic_load_n(&p[0], __ATOMIC_RELAXED);
2703 __atomic_store_n(&p[2], p[3], __ATOMIC_RELAXED);
2704 __atomic_compare_exchange_n(&p[4], &p[5], p[6], 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
2705 return 0;
2706 }'''
2707 has_atomic128 = cc.links(atomic_test_128)
2708
2709 config_host_data.set('CONFIG_ATOMIC128', has_atomic128)
2710
2711 if not has_atomic128
2712 # Even with __builtin_assume_aligned, the above test may have failed
2713 # without optimization enabled. Try again with optimizations locally
2714 # enabled for the function. See
2715 # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107389
2716 has_atomic128_opt = cc.links('__attribute__((optimize("O1")))' + atomic_test_128)
2717 config_host_data.set('CONFIG_ATOMIC128_OPT', has_atomic128_opt)
2718
2719 if not has_atomic128_opt
2720 config_host_data.set('CONFIG_CMPXCHG128', cc.links('''
2721 int main(void)
2722 {
2723 __uint128_t x = 0, y = 0;
2724 __sync_val_compare_and_swap_16(&x, y, x);
2725 return 0;
2726 }
2727 '''))
2728 endif
2729 endif
2730 endif
2731
2732 config_host_data.set('CONFIG_GETAUXVAL', cc.links(gnu_source_prefix + '''
2733 #include <sys/auxv.h>
2734 int main(void) {
2735 return getauxval(AT_HWCAP) == 0;
2736 }'''))
2737
2738 config_host_data.set('CONFIG_USBFS', have_linux_user and cc.compiles('''
2739 #include <linux/usbdevice_fs.h>
2740
2741 #ifndef USBDEVFS_GET_CAPABILITIES
2742 #error "USBDEVFS_GET_CAPABILITIES undefined"
2743 #endif
2744
2745 #ifndef USBDEVFS_DISCONNECT_CLAIM
2746 #error "USBDEVFS_DISCONNECT_CLAIM undefined"
2747 #endif
2748
2749 int main(void) { return 0; }'''))
2750
2751 have_keyring = get_option('keyring') \
2752 .require(host_os == 'linux', error_message: 'keyring is only available on Linux') \
2753 .require(cc.compiles('''
2754 #include <errno.h>
2755 #include <asm/unistd.h>
2756 #include <linux/keyctl.h>
2757 #include <sys/syscall.h>
2758 #include <unistd.h>
2759 int main(void) {
2760 return syscall(__NR_keyctl, KEYCTL_READ, 0, NULL, NULL, 0);
2761 }'''), error_message: 'keyctl syscall not available on this system').allowed()
2762 config_host_data.set('CONFIG_SECRET_KEYRING', have_keyring)
2763
2764 have_cpuid_h = cc.links('''
2765 #include <cpuid.h>
2766 int main(void) {
2767 unsigned a, b, c, d;
2768 unsigned max = __get_cpuid_max(0, 0);
2769
2770 if (max >= 1) {
2771 __cpuid(1, a, b, c, d);
2772 }
2773
2774 if (max >= 7) {
2775 __cpuid_count(7, 0, a, b, c, d);
2776 }
2777
2778 return 0;
2779 }''')
2780 config_host_data.set('CONFIG_CPUID_H', have_cpuid_h)
2781
2782 config_host_data.set('CONFIG_AVX2_OPT', get_option('avx2') \
2783 .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX2') \
2784 .require(cc.links('''
2785 #include <cpuid.h>
2786 #include <immintrin.h>
2787 static int __attribute__((target("avx2"))) bar(void *a) {
2788 __m256i x = *(__m256i *)a;
2789 return _mm256_testz_si256(x, x);
2790 }
2791 int main(int argc, char *argv[]) { return bar(argv[argc - 1]); }
2792 '''), error_message: 'AVX2 not available').allowed())
2793
2794 config_host_data.set('CONFIG_AVX512F_OPT', get_option('avx512f') \
2795 .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX512F') \
2796 .require(cc.links('''
2797 #include <cpuid.h>
2798 #include <immintrin.h>
2799 static int __attribute__((target("avx512f"))) bar(void *a) {
2800 __m512i x = *(__m512i *)a;
2801 return _mm512_test_epi64_mask(x, x);
2802 }
2803 int main(int argc, char *argv[]) { return bar(argv[argc - 1]); }
2804 '''), error_message: 'AVX512F not available').allowed())
2805
2806 config_host_data.set('CONFIG_AVX512BW_OPT', get_option('avx512bw') \
2807 .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX512BW') \
2808 .require(cc.links('''
2809 #include <cpuid.h>
2810 #include <immintrin.h>
2811 static int __attribute__((target("avx512bw"))) bar(void *a) {
2812 __m512i *x = a;
2813 __m512i res= _mm512_abs_epi8(*x);
2814 return res[1];
2815 }
2816 int main(int argc, char *argv[]) { return bar(argv[0]); }
2817 '''), error_message: 'AVX512BW not available').allowed())
2818
2819 # For both AArch64 and AArch32, detect if builtins are available.
2820 config_host_data.set('CONFIG_ARM_AES_BUILTIN', cc.compiles('''
2821 #include <arm_neon.h>
2822 #ifndef __ARM_FEATURE_AES
2823 __attribute__((target("+crypto")))
2824 #endif
2825 void foo(uint8x16_t *p) { *p = vaesmcq_u8(*p); }
2826 '''))
2827
2828 have_pvrdma = get_option('pvrdma') \
2829 .require(rdma.found(), error_message: 'PVRDMA requires OpenFabrics libraries') \
2830 .require(cc.compiles(gnu_source_prefix + '''
2831 #include <sys/mman.h>
2832 int main(void)
2833 {
2834 char buf = 0;
2835 void *addr = &buf;
2836 addr = mremap(addr, 0, 1, MREMAP_MAYMOVE | MREMAP_FIXED);
2837
2838 return 0;
2839 }'''), error_message: 'PVRDMA requires mremap').allowed()
2840
2841 if have_pvrdma
2842 config_host_data.set('LEGACY_RDMA_REG_MR', not cc.links('''
2843 #include <infiniband/verbs.h>
2844 int main(void)
2845 {
2846 struct ibv_mr *mr;
2847 struct ibv_pd *pd = NULL;
2848 size_t length = 10;
2849 uint64_t iova = 0;
2850 int access = 0;
2851 void *addr = NULL;
2852
2853 mr = ibv_reg_mr_iova(pd, addr, length, iova, access);
2854 ibv_dereg_mr(mr);
2855 return 0;
2856 }'''))
2857 endif
2858
2859 if get_option('membarrier').disabled()
2860 have_membarrier = false
2861 elif host_os == 'windows'
2862 have_membarrier = true
2863 elif host_os == 'linux'
2864 have_membarrier = cc.compiles('''
2865 #include <linux/membarrier.h>
2866 #include <sys/syscall.h>
2867 #include <unistd.h>
2868 #include <stdlib.h>
2869 int main(void) {
2870 syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0);
2871 syscall(__NR_membarrier, MEMBARRIER_CMD_SHARED, 0);
2872 exit(0);
2873 }''')
2874 endif
2875 config_host_data.set('CONFIG_MEMBARRIER', get_option('membarrier') \
2876 .require(have_membarrier, error_message: 'membarrier system call not available') \
2877 .allowed())
2878
2879 have_afalg = get_option('crypto_afalg') \
2880 .require(cc.compiles(gnu_source_prefix + '''
2881 #include <errno.h>
2882 #include <sys/types.h>
2883 #include <sys/socket.h>
2884 #include <linux/if_alg.h>
2885 int main(void) {
2886 int sock;
2887 sock = socket(AF_ALG, SOCK_SEQPACKET, 0);
2888 return sock;
2889 }
2890 '''), error_message: 'AF_ALG requested but could not be detected').allowed()
2891 config_host_data.set('CONFIG_AF_ALG', have_afalg)
2892
2893 config_host_data.set('CONFIG_AF_VSOCK', cc.has_header_symbol(
2894 'linux/vm_sockets.h', 'AF_VSOCK',
2895 prefix: '#include <sys/socket.h>',
2896 ))
2897
2898 have_vss = false
2899 have_vss_sdk = false # old xp/2003 SDK
2900 if host_os == 'windows' and 'cpp' in all_languages
2901 have_vss = cxx.compiles('''
2902 #define __MIDL_user_allocate_free_DEFINED__
2903 #include <vss.h>
2904 int main(void) { return VSS_CTX_BACKUP; }''')
2905 have_vss_sdk = cxx.has_header('vscoordint.h')
2906 endif
2907 config_host_data.set('HAVE_VSS_SDK', have_vss_sdk)
2908
2909 # Older versions of MinGW do not import _lock_file and _unlock_file properly.
2910 # This was fixed for v6.0.0 with commit b48e3ac8969d.
2911 if host_os == 'windows'
2912 config_host_data.set('HAVE__LOCK_FILE', cc.links('''
2913 #include <stdio.h>
2914 int main(void) {
2915 _lock_file(NULL);
2916 _unlock_file(NULL);
2917 return 0;
2918 }''', name: '_lock_file and _unlock_file'))
2919 endif
2920
2921 if host_os == 'windows'
2922 mingw_has_setjmp_longjmp = cc.links('''
2923 #include <setjmp.h>
2924 int main(void) {
2925 /*
2926 * These functions are not available in setjmp header, but may be
2927 * available at link time, from libmingwex.a.
2928 */
2929 extern int __mingw_setjmp(jmp_buf);
2930 extern void __attribute__((noreturn)) __mingw_longjmp(jmp_buf, int);
2931 jmp_buf env;
2932 __mingw_setjmp(env);
2933 __mingw_longjmp(env, 0);
2934 }
2935 ''', name: 'mingw setjmp and longjmp')
2936
2937 if cpu == 'aarch64' and not mingw_has_setjmp_longjmp
2938 error('mingw must provide setjmp/longjmp for windows-arm64')
2939 endif
2940 endif
2941
2942 ########################
2943 # Target configuration #
2944 ########################
2945
2946 minikconf = find_program('scripts/minikconf.py')
2947
2948 config_all_accel = {}
2949 config_all_devices = {}
2950 config_devices_mak_list = []
2951 config_devices_h = {}
2952 config_target_h = {}
2953 config_target_mak = {}
2954
2955 disassemblers = {
2956 'alpha' : ['CONFIG_ALPHA_DIS'],
2957 'avr' : ['CONFIG_AVR_DIS'],
2958 'cris' : ['CONFIG_CRIS_DIS'],
2959 'hexagon' : ['CONFIG_HEXAGON_DIS'],
2960 'hppa' : ['CONFIG_HPPA_DIS'],
2961 'i386' : ['CONFIG_I386_DIS'],
2962 'x86_64' : ['CONFIG_I386_DIS'],
2963 'm68k' : ['CONFIG_M68K_DIS'],
2964 'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
2965 'mips' : ['CONFIG_MIPS_DIS'],
2966 'nios2' : ['CONFIG_NIOS2_DIS'],
2967 'or1k' : ['CONFIG_OPENRISC_DIS'],
2968 'ppc' : ['CONFIG_PPC_DIS'],
2969 'riscv' : ['CONFIG_RISCV_DIS'],
2970 'rx' : ['CONFIG_RX_DIS'],
2971 's390' : ['CONFIG_S390_DIS'],
2972 'sh4' : ['CONFIG_SH4_DIS'],
2973 'sparc' : ['CONFIG_SPARC_DIS'],
2974 'xtensa' : ['CONFIG_XTENSA_DIS'],
2975 'loongarch' : ['CONFIG_LOONGARCH_DIS'],
2976 }
2977
2978 have_ivshmem = config_host_data.get('CONFIG_EVENTFD')
2979 host_kconfig = \
2980 (get_option('fuzzing') ? ['CONFIG_FUZZ=y'] : []) + \
2981 (have_tpm ? ['CONFIG_TPM=y'] : []) + \
2982 (pixman.found() ? ['CONFIG_PIXMAN=y'] : []) + \
2983 (spice.found() ? ['CONFIG_SPICE=y'] : []) + \
2984 (have_ivshmem ? ['CONFIG_IVSHMEM=y'] : []) + \
2985 (opengl.found() ? ['CONFIG_OPENGL=y'] : []) + \
2986 (x11.found() ? ['CONFIG_X11=y'] : []) + \
2987 (have_vhost_user ? ['CONFIG_VHOST_USER=y'] : []) + \
2988 (have_vhost_vdpa ? ['CONFIG_VHOST_VDPA=y'] : []) + \
2989 (have_vhost_kernel ? ['CONFIG_VHOST_KERNEL=y'] : []) + \
2990 (have_virtfs ? ['CONFIG_VIRTFS=y'] : []) + \
2991 (host_os == 'linux' ? ['CONFIG_LINUX=y'] : []) + \
2992 (have_pvrdma ? ['CONFIG_PVRDMA=y'] : []) + \
2993 (multiprocess_allowed ? ['CONFIG_MULTIPROCESS_ALLOWED=y'] : []) + \
2994 (vfio_user_server_allowed ? ['CONFIG_VFIO_USER_SERVER_ALLOWED=y'] : []) + \
2995 (hv_balloon ? ['CONFIG_HV_BALLOON_POSSIBLE=y'] : [])
2996
2997 ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ]
2998
2999 default_targets = 'CONFIG_DEFAULT_TARGETS' in config_host
3000 actual_target_dirs = []
3001 fdt_required = []
3002 foreach target : target_dirs
3003 config_target = { 'TARGET_NAME': target.split('-')[0] }
3004 if target.endswith('linux-user')
3005 if host_os != 'linux'
3006 if default_targets
3007 continue
3008 endif
3009 error('Target @0@ is only available on a Linux host'.format(target))
3010 endif
3011 config_target += { 'CONFIG_LINUX_USER': 'y' }
3012 elif target.endswith('bsd-user')
3013 if host_os not in bsd_oses
3014 if default_targets
3015 continue
3016 endif
3017 error('Target @0@ is only available on a BSD host'.format(target))
3018 endif
3019 config_target += { 'CONFIG_BSD_USER': 'y' }
3020 elif target.endswith('softmmu')
3021 config_target += { 'CONFIG_SYSTEM_ONLY': 'y' }
3022 config_target += { 'CONFIG_SOFTMMU': 'y' }
3023 endif
3024 if target.endswith('-user')
3025 config_target += {
3026 'CONFIG_USER_ONLY': 'y',
3027 'CONFIG_QEMU_INTERP_PREFIX':
3028 get_option('interp_prefix').replace('%M', config_target['TARGET_NAME'])
3029 }
3030 endif
3031
3032 accel_kconfig = []
3033 foreach sym: accelerators
3034 if sym == 'CONFIG_TCG' or target in accelerator_targets.get(sym, [])
3035 config_target += { sym: 'y' }
3036 config_all_accel += { sym: 'y' }
3037 if target in modular_tcg
3038 config_target += { 'CONFIG_TCG_MODULAR': 'y' }
3039 else
3040 config_target += { 'CONFIG_TCG_BUILTIN': 'y' }
3041 endif
3042 accel_kconfig += [ sym + '=y' ]
3043 endif
3044 endforeach
3045 if accel_kconfig.length() == 0
3046 if default_targets
3047 continue
3048 endif
3049 error('No accelerator available for target @0@'.format(target))
3050 endif
3051
3052 actual_target_dirs += target
3053 config_target += keyval.load('configs/targets' / target + '.mak')
3054 config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
3055
3056 if 'TARGET_NEED_FDT' in config_target
3057 fdt_required += target
3058 endif
3059
3060 # Add default keys
3061 if 'TARGET_BASE_ARCH' not in config_target
3062 config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
3063 endif
3064 if 'TARGET_ABI_DIR' not in config_target
3065 config_target += {'TARGET_ABI_DIR': config_target['TARGET_ARCH']}
3066 endif
3067 if 'TARGET_BIG_ENDIAN' not in config_target
3068 config_target += {'TARGET_BIG_ENDIAN': 'n'}
3069 endif
3070
3071 foreach k, v: disassemblers
3072 if host_arch.startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k)
3073 foreach sym: v
3074 config_target += { sym: 'y' }
3075 endforeach
3076 endif
3077 endforeach
3078
3079 config_target_data = configuration_data()
3080 foreach k, v: config_target
3081 if not k.startswith('TARGET_') and not k.startswith('CONFIG_')
3082 # do nothing
3083 elif ignored.contains(k)
3084 # do nothing
3085 elif k == 'TARGET_BASE_ARCH'
3086 # Note that TARGET_BASE_ARCH ends up in config-target.h but it is
3087 # not used to select files from sourcesets.
3088 config_target_data.set('TARGET_' + v.to_upper(), 1)
3089 elif k == 'TARGET_NAME' or k == 'CONFIG_QEMU_INTERP_PREFIX'
3090 config_target_data.set_quoted(k, v)
3091 elif v == 'y'
3092 config_target_data.set(k, 1)
3093 elif v == 'n'
3094 config_target_data.set(k, 0)
3095 else
3096 config_target_data.set(k, v)
3097 endif
3098 endforeach
3099 config_target_data.set('QEMU_ARCH',
3100 'QEMU_ARCH_' + config_target['TARGET_BASE_ARCH'].to_upper())
3101 config_target_h += {target: configure_file(output: target + '-config-target.h',
3102 configuration: config_target_data)}
3103
3104 if target.endswith('-softmmu')
3105 config_input = meson.get_external_property(target, 'default')
3106 config_devices_mak = target + '-config-devices.mak'
3107 config_devices_mak = configure_file(
3108 input: ['configs/devices' / target / config_input + '.mak', 'Kconfig'],
3109 output: config_devices_mak,
3110 depfile: config_devices_mak + '.d',
3111 capture: true,
3112 command: [minikconf,
3113 get_option('default_devices') ? '--defconfig' : '--allnoconfig',
3114 config_devices_mak, '@DEPFILE@', '@INPUT@',
3115 host_kconfig, accel_kconfig,
3116 'CONFIG_' + config_target['TARGET_ARCH'].to_upper() + '=y'])
3117
3118 config_devices_data = configuration_data()
3119 config_devices = keyval.load(config_devices_mak)
3120 foreach k, v: config_devices
3121 config_devices_data.set(k, 1)
3122 endforeach
3123 config_devices_mak_list += config_devices_mak
3124 config_devices_h += {target: configure_file(output: target + '-config-devices.h',
3125 configuration: config_devices_data)}
3126 config_target += config_devices
3127 config_all_devices += config_devices
3128 endif
3129 config_target_mak += {target: config_target}
3130 endforeach
3131 target_dirs = actual_target_dirs
3132
3133 target_configs_h = []
3134 foreach target: target_dirs
3135 target_configs_h += config_target_h[target]
3136 target_configs_h += config_devices_h.get(target, [])
3137 endforeach
3138 genh += custom_target('config-poison.h',
3139 input: [target_configs_h],
3140 output: 'config-poison.h',
3141 capture: true,
3142 command: [find_program('scripts/make-config-poison.sh'),
3143 target_configs_h])
3144
3145 ###############
3146 # Subprojects #
3147 ###############
3148
3149 libvfio_user_dep = not_found
3150 if have_system and vfio_user_server_allowed
3151 libvfio_user_proj = subproject('libvfio-user', required: true)
3152 libvfio_user_dep = libvfio_user_proj.get_variable('libvfio_user_dep')
3153 endif
3154
3155 fdt = not_found
3156 fdt_opt = get_option('fdt')
3157 if fdt_required.length() > 0 or fdt_opt == 'enabled'
3158 if fdt_opt == 'disabled'
3159 error('fdt disabled but required by targets ' + ', '.join(fdt_required))
3160 endif
3161
3162 if fdt_opt in ['enabled', 'auto', 'system']
3163 if get_option('wrap_mode') == 'nodownload'
3164 fdt_opt = 'system'
3165 endif
3166 fdt = cc.find_library('fdt', required: fdt_opt == 'system')
3167 if fdt.found() and cc.links('''
3168 #include <libfdt.h>
3169 #include <libfdt_env.h>
3170 int main(void) { fdt_find_max_phandle(NULL, NULL); return 0; }''',
3171 dependencies: fdt)
3172 fdt_opt = 'system'
3173 elif fdt_opt == 'system'
3174 error('system libfdt requested, but it is too old (1.5.1 or newer required)')
3175 else
3176 fdt_opt = 'internal'
3177 fdt = not_found
3178 endif
3179 endif
3180 if not fdt.found()
3181 assert(fdt_opt == 'internal')
3182 libfdt_proj = subproject('dtc', required: true,
3183 default_options: ['tools=false', 'yaml=disabled',
3184 'python=disabled', 'default_library=static'])
3185 fdt = libfdt_proj.get_variable('libfdt_dep')
3186 endif
3187 else
3188 fdt_opt = 'disabled'
3189 endif
3190
3191 config_host_data.set('CONFIG_FDT', fdt.found())
3192
3193 vhost_user = not_found
3194 if host_os == 'linux' and have_vhost_user
3195 libvhost_user = subproject('libvhost-user')
3196 vhost_user = libvhost_user.get_variable('vhost_user_dep')
3197 endif
3198
3199 libvduse = not_found
3200 if have_libvduse
3201 libvduse_proj = subproject('libvduse')
3202 libvduse = libvduse_proj.get_variable('libvduse_dep')
3203 endif
3204
3205 #####################
3206 # Generated sources #
3207 #####################
3208
3209 genh += configure_file(output: 'config-host.h', configuration: config_host_data)
3210
3211 hxtool = find_program('scripts/hxtool')
3212 shaderinclude = find_program('scripts/shaderinclude.py')
3213 qapi_gen = find_program('scripts/qapi-gen.py')
3214 qapi_gen_depends = [ meson.current_source_dir() / 'scripts/qapi/__init__.py',
3215 meson.current_source_dir() / 'scripts/qapi/commands.py',
3216 meson.current_source_dir() / 'scripts/qapi/common.py',
3217 meson.current_source_dir() / 'scripts/qapi/error.py',
3218 meson.current_source_dir() / 'scripts/qapi/events.py',
3219 meson.current_source_dir() / 'scripts/qapi/expr.py',
3220 meson.current_source_dir() / 'scripts/qapi/gen.py',
3221 meson.current_source_dir() / 'scripts/qapi/introspect.py',
3222 meson.current_source_dir() / 'scripts/qapi/main.py',
3223 meson.current_source_dir() / 'scripts/qapi/parser.py',
3224 meson.current_source_dir() / 'scripts/qapi/schema.py',
3225 meson.current_source_dir() / 'scripts/qapi/source.py',
3226 meson.current_source_dir() / 'scripts/qapi/types.py',
3227 meson.current_source_dir() / 'scripts/qapi/visit.py',
3228 meson.current_source_dir() / 'scripts/qapi-gen.py'
3229 ]
3230
3231 tracetool = [
3232 python, files('scripts/tracetool.py'),
3233 '--backend=' + ','.join(get_option('trace_backends'))
3234 ]
3235 tracetool_depends = files(
3236 'scripts/tracetool/backend/log.py',
3237 'scripts/tracetool/backend/__init__.py',
3238 'scripts/tracetool/backend/dtrace.py',
3239 'scripts/tracetool/backend/ftrace.py',
3240 'scripts/tracetool/backend/simple.py',
3241 'scripts/tracetool/backend/syslog.py',
3242 'scripts/tracetool/backend/ust.py',
3243 'scripts/tracetool/format/ust_events_c.py',
3244 'scripts/tracetool/format/ust_events_h.py',
3245 'scripts/tracetool/format/__init__.py',
3246 'scripts/tracetool/format/d.py',
3247 'scripts/tracetool/format/simpletrace_stap.py',
3248 'scripts/tracetool/format/c.py',
3249 'scripts/tracetool/format/h.py',
3250 'scripts/tracetool/format/log_stap.py',
3251 'scripts/tracetool/format/stap.py',
3252 'scripts/tracetool/__init__.py',
3253 'scripts/tracetool/vcpu.py'
3254 )
3255
3256 qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
3257 meson.current_source_dir(),
3258 get_option('pkgversion'), meson.project_version()]
3259 qemu_version = custom_target('qemu-version.h',
3260 output: 'qemu-version.h',
3261 command: qemu_version_cmd,
3262 capture: true,
3263 build_by_default: true,
3264 build_always_stale: true)
3265 genh += qemu_version
3266
3267 hxdep = []
3268 hx_headers = [
3269 ['qemu-options.hx', 'qemu-options.def'],
3270 ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
3271 ]
3272 if have_system
3273 hx_headers += [
3274 ['hmp-commands.hx', 'hmp-commands.h'],
3275 ['hmp-commands-info.hx', 'hmp-commands-info.h'],
3276 ]
3277 endif
3278 foreach d : hx_headers
3279 hxdep += custom_target(d[1],
3280 input: files(d[0]),
3281 output: d[1],
3282 capture: true,
3283 command: [hxtool, '-h', '@INPUT0@'])
3284 endforeach
3285 genh += hxdep
3286
3287 ###############
3288 # Trace files #
3289 ###############
3290
3291 # TODO: add each directory to the subdirs from its own meson.build, once
3292 # we have those
3293 trace_events_subdirs = [
3294 'crypto',
3295 'qapi',
3296 'qom',
3297 'monitor',
3298 'util',
3299 'gdbstub',
3300 ]
3301 if have_linux_user
3302 trace_events_subdirs += [ 'linux-user' ]
3303 endif
3304 if have_bsd_user
3305 trace_events_subdirs += [ 'bsd-user' ]
3306 endif
3307 if have_block
3308 trace_events_subdirs += [
3309 'authz',
3310 'block',
3311 'io',
3312 'nbd',
3313 'scsi',
3314 ]
3315 endif
3316 if have_system
3317 trace_events_subdirs += [
3318 'accel/kvm',
3319 'audio',
3320 'backends',
3321 'backends/tpm',
3322 'chardev',
3323 'ebpf',
3324 'hw/9pfs',
3325 'hw/acpi',
3326 'hw/adc',
3327 'hw/alpha',
3328 'hw/arm',
3329 'hw/audio',
3330 'hw/block',
3331 'hw/char',
3332 'hw/display',
3333 'hw/dma',
3334 'hw/fsi',
3335 'hw/hyperv',
3336 'hw/i2c',
3337 'hw/i386',
3338 'hw/i386/xen',
3339 'hw/i386/kvm',
3340 'hw/ide',
3341 'hw/input',
3342 'hw/intc',
3343 'hw/isa',
3344 'hw/mem',
3345 'hw/mips',
3346 'hw/misc',
3347 'hw/misc/macio',
3348 'hw/net',
3349 'hw/net/can',
3350 'hw/nubus',
3351 'hw/nvme',
3352 'hw/nvram',
3353 'hw/pci',
3354 'hw/pci-host',
3355 'hw/ppc',
3356 'hw/rdma',
3357 'hw/rdma/vmw',
3358 'hw/rtc',
3359 'hw/s390x',
3360 'hw/scsi',
3361 'hw/sd',
3362 'hw/sh4',
3363 'hw/sparc',
3364 'hw/sparc64',
3365 'hw/ssi',
3366 'hw/timer',
3367 'hw/tpm',
3368 'hw/ufs',
3369 'hw/usb',
3370 'hw/vfio',
3371 'hw/virtio',
3372 'hw/watchdog',
3373 'hw/xen',
3374 'hw/gpio',
3375 'migration',
3376 'net',
3377 'system',
3378 'ui',
3379 'hw/remote',
3380 ]
3381 endif
3382 if have_system or have_user
3383 trace_events_subdirs += [
3384 'accel/tcg',
3385 'hw/core',
3386 'target/arm',
3387 'target/arm/hvf',
3388 'target/hppa',
3389 'target/i386',
3390 'target/i386/kvm',
3391 'target/loongarch',
3392 'target/mips/tcg',
3393 'target/nios2',
3394 'target/ppc',
3395 'target/riscv',
3396 'target/s390x',
3397 'target/s390x/kvm',
3398 'target/sparc',
3399 ]
3400 endif
3401
3402 ###################
3403 # Collect sources #
3404 ###################
3405
3406 authz_ss = ss.source_set()
3407 blockdev_ss = ss.source_set()
3408 block_ss = ss.source_set()
3409 chardev_ss = ss.source_set()
3410 common_ss = ss.source_set()
3411 crypto_ss = ss.source_set()
3412 hwcore_ss = ss.source_set()
3413 io_ss = ss.source_set()
3414 qmp_ss = ss.source_set()
3415 qom_ss = ss.source_set()
3416 system_ss = ss.source_set()
3417 specific_fuzz_ss = ss.source_set()
3418 specific_ss = ss.source_set()
3419 stub_ss = ss.source_set()
3420 trace_ss = ss.source_set()
3421 user_ss = ss.source_set()
3422 util_ss = ss.source_set()
3423
3424 # accel modules
3425 qtest_module_ss = ss.source_set()
3426 tcg_module_ss = ss.source_set()
3427
3428 modules = {}
3429 target_modules = {}
3430 hw_arch = {}
3431 target_arch = {}
3432 target_system_arch = {}
3433 target_user_arch = {}
3434
3435 # NOTE: the trace/ subdirectory needs the qapi_trace_events variable
3436 # that is filled in by qapi/.
3437 subdir('qapi')
3438 subdir('qobject')
3439 subdir('stubs')
3440 subdir('trace')
3441 subdir('util')
3442 subdir('qom')
3443 subdir('authz')
3444 subdir('crypto')
3445 subdir('ui')
3446 subdir('hw')
3447 subdir('gdbstub')
3448
3449 if enable_modules
3450 libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
3451 modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
3452 endif
3453
3454 qom_ss = qom_ss.apply({})
3455 libqom = static_library('qom', qom_ss.sources() + genh,
3456 dependencies: [qom_ss.dependencies()],
3457 name_suffix: 'fa',
3458 build_by_default: false)
3459 qom = declare_dependency(link_whole: libqom)
3460
3461 event_loop_base = files('event-loop-base.c')
3462 event_loop_base = static_library('event-loop-base',
3463 sources: event_loop_base + genh,
3464 name_suffix: 'fa',
3465 build_by_default: false)
3466 event_loop_base = declare_dependency(link_whole: event_loop_base,
3467 dependencies: [qom])
3468
3469 stub_ss = stub_ss.apply({})
3470
3471 util_ss.add_all(trace_ss)
3472 util_ss = util_ss.apply({})
3473 libqemuutil = static_library('qemuutil',
3474 build_by_default: false,
3475 sources: util_ss.sources() + stub_ss.sources() + genh,
3476 dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc, pixman])
3477 qemuutil = declare_dependency(link_with: libqemuutil,
3478 sources: genh + version_res,
3479 dependencies: [event_loop_base])
3480
3481 if have_system or have_user
3482 decodetree = generator(find_program('scripts/decodetree.py'),
3483 output: 'decode-@BASENAME@.c.inc',
3484 arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
3485 subdir('libdecnumber')
3486 subdir('target')
3487 endif
3488
3489 subdir('audio')
3490 subdir('io')
3491 subdir('chardev')
3492 subdir('fsdev')
3493 subdir('dump')
3494
3495 if have_block
3496 block_ss.add(files(
3497 'block.c',
3498 'blockjob.c',
3499 'job.c',
3500 'qemu-io-cmds.c',
3501 ))
3502 if config_host_data.get('CONFIG_REPLICATION')
3503 block_ss.add(files('replication.c'))
3504 endif
3505
3506 subdir('nbd')
3507 subdir('scsi')
3508 subdir('block')
3509
3510 blockdev_ss.add(files(
3511 'blockdev.c',
3512 'blockdev-nbd.c',
3513 'iothread.c',
3514 'job-qmp.c',
3515 ), gnutls)
3516
3517 # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
3518 # os-win32.c does not
3519 if host_os == 'windows'
3520 system_ss.add(files('os-win32.c'))
3521 else
3522 blockdev_ss.add(files('os-posix.c'))
3523 endif
3524 endif
3525
3526 common_ss.add(files('cpu-common.c'))
3527 specific_ss.add(files('cpu-target.c'))
3528
3529 subdir('system')
3530
3531 # Work around a gcc bug/misfeature wherein constant propagation looks
3532 # through an alias:
3533 # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99696
3534 # to guess that a const variable is always zero. Without lto, this is
3535 # impossible, as the alias is restricted to page-vary-common.c. Indeed,
3536 # without lto, not even the alias is required -- we simply use different
3537 # declarations in different compilation units.
3538 pagevary = files('page-vary-common.c')
3539 if get_option('b_lto')
3540 pagevary_flags = ['-fno-lto']
3541 if get_option('cfi')
3542 pagevary_flags += '-fno-sanitize=cfi-icall'
3543 endif
3544 pagevary = static_library('page-vary-common', sources: pagevary + genh,
3545 c_args: pagevary_flags)
3546 pagevary = declare_dependency(link_with: pagevary)
3547 endif
3548 common_ss.add(pagevary)
3549 specific_ss.add(files('page-vary-target.c'))
3550
3551 subdir('backends')
3552 subdir('disas')
3553 subdir('migration')
3554 subdir('monitor')
3555 subdir('net')
3556 subdir('replay')
3557 subdir('semihosting')
3558 subdir('stats')
3559 subdir('tcg')
3560 subdir('fpu')
3561 subdir('accel')
3562 subdir('plugins')
3563 subdir('ebpf')
3564
3565 common_user_inc = []
3566
3567 subdir('common-user')
3568 subdir('bsd-user')
3569 subdir('linux-user')
3570
3571 # needed for fuzzing binaries
3572 subdir('tests/qtest/libqos')
3573 subdir('tests/qtest/fuzz')
3574
3575 # accel modules
3576 tcg_real_module_ss = ss.source_set()
3577 tcg_real_module_ss.add_all(when: 'CONFIG_TCG_MODULAR', if_true: tcg_module_ss)
3578 specific_ss.add_all(when: 'CONFIG_TCG_BUILTIN', if_true: tcg_module_ss)
3579 target_modules += { 'accel' : { 'qtest': qtest_module_ss,
3580 'tcg': tcg_real_module_ss }}
3581
3582 ##############################################
3583 # Internal static_libraries and dependencies #
3584 ##############################################
3585
3586 modinfo_collect = find_program('scripts/modinfo-collect.py')
3587 modinfo_generate = find_program('scripts/modinfo-generate.py')
3588 modinfo_files = []
3589
3590 block_mods = []
3591 system_mods = []
3592 foreach d, list : modules
3593 if not (d == 'block' ? have_block : have_system)
3594 continue
3595 endif
3596
3597 foreach m, module_ss : list
3598 if enable_modules
3599 module_ss = module_ss.apply(config_all_devices, strict: false)
3600 sl = static_library(d + '-' + m, [genh, module_ss.sources()],
3601 dependencies: [modulecommon, module_ss.dependencies()], pic: true)
3602 if d == 'block'
3603 block_mods += sl
3604 else
3605 system_mods += sl
3606 endif
3607 if module_ss.sources() != []
3608 # FIXME: Should use sl.extract_all_objects(recursive: true) as
3609 # input. Sources can be used multiple times but objects are
3610 # unique when it comes to lookup in compile_commands.json.
3611 # Depnds on a mesion version with
3612 # https://github.com/mesonbuild/meson/pull/8900
3613 modinfo_files += custom_target(d + '-' + m + '.modinfo',
3614 output: d + '-' + m + '.modinfo',
3615 input: module_ss.sources() + genh,
3616 capture: true,
3617 command: [modinfo_collect, module_ss.sources()])
3618 endif
3619 else
3620 if d == 'block'
3621 block_ss.add_all(module_ss)
3622 else
3623 system_ss.add_all(module_ss)
3624 endif
3625 endif
3626 endforeach
3627 endforeach
3628
3629 foreach d, list : target_modules
3630 foreach m, module_ss : list
3631 if enable_modules
3632 foreach target : target_dirs
3633 if target.endswith('-softmmu')
3634 config_target = config_target_mak[target]
3635 target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3636 c_args = ['-DNEED_CPU_H',
3637 '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3638 '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3639 target_module_ss = module_ss.apply(config_target, strict: false)
3640 if target_module_ss.sources() != []
3641 module_name = d + '-' + m + '-' + config_target['TARGET_NAME']
3642 sl = static_library(module_name,
3643 [genh, target_module_ss.sources()],
3644 dependencies: [modulecommon, target_module_ss.dependencies()],
3645 include_directories: target_inc,
3646 c_args: c_args,
3647 pic: true)
3648 system_mods += sl
3649 # FIXME: Should use sl.extract_all_objects(recursive: true) too.
3650 modinfo_files += custom_target(module_name + '.modinfo',
3651 output: module_name + '.modinfo',
3652 input: target_module_ss.sources() + genh,
3653 capture: true,
3654 command: [modinfo_collect, '--target', target, target_module_ss.sources()])
3655 endif
3656 endif
3657 endforeach
3658 else
3659 specific_ss.add_all(module_ss)
3660 endif
3661 endforeach
3662 endforeach
3663
3664 if enable_modules
3665 foreach target : target_dirs
3666 if target.endswith('-softmmu')
3667 config_target = config_target_mak[target]
3668 config_devices_mak = target + '-config-devices.mak'
3669 modinfo_src = custom_target('modinfo-' + target + '.c',
3670 output: 'modinfo-' + target + '.c',
3671 input: modinfo_files,
3672 command: [modinfo_generate, '--devices', config_devices_mak, '@INPUT@'],
3673 capture: true)
3674
3675 modinfo_lib = static_library('modinfo-' + target + '.c', modinfo_src)
3676 modinfo_dep = declare_dependency(link_with: modinfo_lib)
3677
3678 arch = config_target['TARGET_NAME'] == 'sparc64' ? 'sparc64' : config_target['TARGET_BASE_ARCH']
3679 hw_arch[arch].add(modinfo_dep)
3680 endif
3681 endforeach
3682 endif
3683
3684 nm = find_program('nm')
3685 undefsym = find_program('scripts/undefsym.py')
3686 block_syms = custom_target('block.syms', output: 'block.syms',
3687 input: [libqemuutil, block_mods],
3688 capture: true,
3689 command: [undefsym, nm, '@INPUT@'])
3690 qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
3691 input: [libqemuutil, system_mods],
3692 capture: true,
3693 command: [undefsym, nm, '@INPUT@'])
3694
3695 authz_ss = authz_ss.apply({})
3696 libauthz = static_library('authz', authz_ss.sources() + genh,
3697 dependencies: [authz_ss.dependencies()],
3698 name_suffix: 'fa',
3699 build_by_default: false)
3700
3701 authz = declare_dependency(link_whole: libauthz,
3702 dependencies: qom)
3703
3704 crypto_ss = crypto_ss.apply({})
3705 libcrypto = static_library('crypto', crypto_ss.sources() + genh,
3706 dependencies: [crypto_ss.dependencies()],
3707 name_suffix: 'fa',
3708 build_by_default: false)
3709
3710 crypto = declare_dependency(link_whole: libcrypto,
3711 dependencies: [authz, qom])
3712
3713 io_ss = io_ss.apply({})
3714 libio = static_library('io', io_ss.sources() + genh,
3715 dependencies: [io_ss.dependencies()],
3716 link_with: libqemuutil,
3717 name_suffix: 'fa',
3718 build_by_default: false)
3719
3720 io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
3721
3722 libmigration = static_library('migration', sources: migration_files + genh,
3723 name_suffix: 'fa',
3724 build_by_default: false)
3725 migration = declare_dependency(link_with: libmigration,
3726 dependencies: [zlib, qom, io])
3727 system_ss.add(migration)
3728
3729 block_ss = block_ss.apply({})
3730 libblock = static_library('block', block_ss.sources() + genh,
3731 dependencies: block_ss.dependencies(),
3732 link_depends: block_syms,
3733 name_suffix: 'fa',
3734 build_by_default: false)
3735
3736 block = declare_dependency(link_whole: [libblock],
3737 link_args: '@block.syms',
3738 dependencies: [crypto, io])
3739
3740 blockdev_ss = blockdev_ss.apply({})
3741 libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
3742 dependencies: blockdev_ss.dependencies(),
3743 name_suffix: 'fa',
3744 build_by_default: false)
3745
3746 blockdev = declare_dependency(link_whole: [libblockdev],
3747 dependencies: [block, event_loop_base])
3748
3749 qmp_ss = qmp_ss.apply({})
3750 libqmp = static_library('qmp', qmp_ss.sources() + genh,
3751 dependencies: qmp_ss.dependencies(),
3752 name_suffix: 'fa',
3753 build_by_default: false)
3754
3755 qmp = declare_dependency(link_whole: [libqmp])
3756
3757 libchardev = static_library('chardev', chardev_ss.sources() + genh,
3758 name_suffix: 'fa',
3759 dependencies: chardev_ss.dependencies(),
3760 build_by_default: false)
3761
3762 chardev = declare_dependency(link_whole: libchardev)
3763
3764 hwcore_ss = hwcore_ss.apply({})
3765 libhwcore = static_library('hwcore', sources: hwcore_ss.sources() + genh,
3766 name_suffix: 'fa',
3767 build_by_default: false)
3768 hwcore = declare_dependency(link_whole: libhwcore)
3769 common_ss.add(hwcore)
3770
3771 ###########
3772 # Targets #
3773 ###########
3774
3775 emulator_modules = []
3776 foreach m : block_mods + system_mods
3777 emulator_modules += shared_module(m.name(),
3778 build_by_default: true,
3779 name_prefix: '',
3780 link_whole: m,
3781 install: true,
3782 install_dir: qemu_moddir)
3783 endforeach
3784 if emulator_modules.length() > 0
3785 alias_target('modules', emulator_modules)
3786 endif
3787
3788 system_ss.add(authz, blockdev, chardev, crypto, io, qmp)
3789 common_ss.add(qom, qemuutil)
3790
3791 common_ss.add_all(when: 'CONFIG_SYSTEM_ONLY', if_true: [system_ss])
3792 common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
3793
3794 # Note that this library is never used directly (only through extract_objects)
3795 # and is not built by default; therefore, source files not used by the build
3796 # configuration will be in build.ninja, but are never built by default.
3797 common_all = static_library('common',
3798 build_by_default: false,
3799 sources: common_ss.all_sources() + genh,
3800 include_directories: common_user_inc,
3801 implicit_include_directories: false,
3802 dependencies: common_ss.all_dependencies(),
3803 name_suffix: 'fa')
3804
3805 feature_to_c = find_program('scripts/feature_to_c.py')
3806
3807 if host_os == 'darwin'
3808 entitlement = find_program('scripts/entitlement.sh')
3809 endif
3810
3811 emulators = {}
3812 foreach target : target_dirs
3813 config_target = config_target_mak[target]
3814 target_name = config_target['TARGET_NAME']
3815 target_base_arch = config_target['TARGET_BASE_ARCH']
3816 arch_srcs = [config_target_h[target]]
3817 arch_deps = []
3818 c_args = ['-DNEED_CPU_H',
3819 '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3820 '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3821 link_args = emulator_link_args
3822
3823 target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3824 if host_os == 'linux'
3825 target_inc += include_directories('linux-headers', is_system: true)
3826 endif
3827 if target.endswith('-softmmu')
3828 target_type='system'
3829 t = target_system_arch[target_base_arch].apply(config_target, strict: false)
3830 arch_srcs += t.sources()
3831 arch_deps += t.dependencies()
3832
3833 hw_dir = target_name == 'sparc64' ? 'sparc64' : target_base_arch
3834 if hw_arch.has_key(hw_dir)
3835 hw = hw_arch[hw_dir].apply(config_target, strict: false)
3836 arch_srcs += hw.sources()
3837 arch_deps += hw.dependencies()
3838 endif
3839
3840 arch_srcs += config_devices_h[target]
3841 link_args += ['@block.syms', '@qemu.syms']
3842 else
3843 abi = config_target['TARGET_ABI_DIR']
3844 target_type='user'
3845 target_inc += common_user_inc
3846 if target_base_arch in target_user_arch
3847 t = target_user_arch[target_base_arch].apply(config_target, strict: false)
3848 arch_srcs += t.sources()
3849 arch_deps += t.dependencies()
3850 endif
3851 if 'CONFIG_LINUX_USER' in config_target
3852 base_dir = 'linux-user'
3853 endif
3854 if 'CONFIG_BSD_USER' in config_target
3855 base_dir = 'bsd-user'
3856 target_inc += include_directories('bsd-user/' / host_os)
3857 target_inc += include_directories('bsd-user/host/' / host_arch)
3858 dir = base_dir / abi
3859 arch_srcs += files(dir / 'signal.c', dir / 'target_arch_cpu.c')
3860 endif
3861 target_inc += include_directories(
3862 base_dir,
3863 base_dir / abi,
3864 )
3865 if 'CONFIG_LINUX_USER' in config_target
3866 dir = base_dir / abi
3867 arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
3868 if config_target.has_key('TARGET_SYSTBL_ABI')
3869 arch_srcs += \
3870 syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
3871 extra_args : config_target['TARGET_SYSTBL_ABI'])
3872 endif
3873 endif
3874 endif
3875
3876 if 'TARGET_XML_FILES' in config_target
3877 gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
3878 output: target + '-gdbstub-xml.c',
3879 input: files(config_target['TARGET_XML_FILES'].split()),
3880 command: [feature_to_c, '@INPUT@'],
3881 capture: true)
3882 arch_srcs += gdbstub_xml
3883 endif
3884
3885 t = target_arch[target_base_arch].apply(config_target, strict: false)
3886 arch_srcs += t.sources()
3887 arch_deps += t.dependencies()
3888
3889 target_common = common_ss.apply(config_target, strict: false)
3890 objects = common_all.extract_objects(target_common.sources())
3891 deps = target_common.dependencies()
3892
3893 target_specific = specific_ss.apply(config_target, strict: false)
3894 arch_srcs += target_specific.sources()
3895 arch_deps += target_specific.dependencies()
3896
3897 lib = static_library('qemu-' + target,
3898 sources: arch_srcs + genh,
3899 dependencies: arch_deps,
3900 objects: objects,
3901 include_directories: target_inc,
3902 c_args: c_args,
3903 build_by_default: false,
3904 name_suffix: 'fa')
3905
3906 if target.endswith('-softmmu')
3907 execs = [{
3908 'name': 'qemu-system-' + target_name,
3909 'win_subsystem': 'console',
3910 'sources': files('system/main.c'),
3911 'dependencies': []
3912 }]
3913 if host_os == 'windows' and (sdl.found() or gtk.found())
3914 execs += [{
3915 'name': 'qemu-system-' + target_name + 'w',
3916 'win_subsystem': 'windows',
3917 'sources': files('system/main.c'),
3918 'dependencies': []
3919 }]
3920 endif
3921 if get_option('fuzzing')
3922 specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
3923 execs += [{
3924 'name': 'qemu-fuzz-' + target_name,
3925 'win_subsystem': 'console',
3926 'sources': specific_fuzz.sources(),
3927 'dependencies': specific_fuzz.dependencies(),
3928 }]
3929 endif
3930 else
3931 execs = [{
3932 'name': 'qemu-' + target_name,
3933 'win_subsystem': 'console',
3934 'sources': [],
3935 'dependencies': []
3936 }]
3937 endif
3938 foreach exe: execs
3939 exe_name = exe['name']
3940 if host_os == 'darwin'
3941 exe_name += '-unsigned'
3942 endif
3943
3944 emulator = executable(exe_name, exe['sources'],
3945 install: true,
3946 c_args: c_args,
3947 dependencies: arch_deps + deps + exe['dependencies'],
3948 objects: lib.extract_all_objects(recursive: true),
3949 link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
3950 link_args: link_args,
3951 win_subsystem: exe['win_subsystem'])
3952
3953 if host_os == 'darwin'
3954 icon = 'pc-bios/qemu.rsrc'
3955 build_input = [emulator, files(icon)]
3956 install_input = [
3957 get_option('bindir') / exe_name,
3958 meson.current_source_dir() / icon
3959 ]
3960 if 'CONFIG_HVF' in config_target
3961 entitlements = 'accel/hvf/entitlements.plist'
3962 build_input += files(entitlements)
3963 install_input += meson.current_source_dir() / entitlements
3964 endif
3965
3966 emulators += {exe['name'] : custom_target(exe['name'],
3967 input: build_input,
3968 output: exe['name'],
3969 command: [entitlement, '@OUTPUT@', '@INPUT@'])
3970 }
3971
3972 meson.add_install_script(entitlement, '--install',
3973 get_option('bindir') / exe['name'],
3974 install_input)
3975 else
3976 emulators += {exe['name']: emulator}
3977 endif
3978
3979 if stap.found()
3980 foreach stp: [
3981 {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
3982 {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
3983 {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
3984 {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
3985 ]
3986 custom_target(exe['name'] + stp['ext'],
3987 input: trace_events_all,
3988 output: exe['name'] + stp['ext'],
3989 install: stp['install'],
3990 install_dir: get_option('datadir') / 'systemtap/tapset',
3991 command: [
3992 tracetool, '--group=all', '--format=' + stp['fmt'],
3993 '--binary=' + stp['bin'],
3994 '--target-name=' + target_name,
3995 '--target-type=' + target_type,
3996 '--probe-prefix=qemu.' + target_type + '.' + target_name,
3997 '@INPUT@', '@OUTPUT@'
3998 ],
3999 depend_files: tracetool_depends)
4000 endforeach
4001 endif
4002 endforeach
4003 endforeach
4004
4005 # Other build targets
4006
4007 if get_option('plugins')
4008 install_headers('include/qemu/qemu-plugin.h')
4009 if host_os == 'windows'
4010 # On windows, we want to deliver the qemu_plugin_api.lib file in the qemu installer,
4011 # so that plugin authors can compile against it.
4012 install_data(win32_qemu_plugin_api_lib, install_dir: 'lib')
4013 endif
4014 endif
4015
4016 subdir('qga')
4017
4018 # Don't build qemu-keymap if xkbcommon is not explicitly enabled
4019 # when we don't build tools or system
4020 if xkbcommon.found()
4021 # used for the update-keymaps target, so include rules even if !have_tools
4022 qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
4023 dependencies: [qemuutil, xkbcommon], install: have_tools)
4024 endif
4025
4026 if have_tools
4027 qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
4028 dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
4029 qemu_io = executable('qemu-io', files('qemu-io.c'),
4030 dependencies: [block, qemuutil], install: true)
4031 qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
4032 dependencies: [blockdev, qemuutil, gnutls, selinux],
4033 install: true)
4034
4035 subdir('storage-daemon')
4036 subdir('contrib/rdmacm-mux')
4037 subdir('contrib/elf2dmp')
4038
4039 executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
4040 dependencies: qemuutil,
4041 install: true)
4042
4043 if have_vhost_user
4044 subdir('contrib/vhost-user-blk')
4045 subdir('contrib/vhost-user-gpu')
4046 subdir('contrib/vhost-user-input')
4047 subdir('contrib/vhost-user-scsi')
4048 endif
4049
4050 if host_os == 'linux'
4051 executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
4052 dependencies: [qemuutil, libcap_ng],
4053 install: true,
4054 install_dir: get_option('libexecdir'))
4055
4056 executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
4057 dependencies: [authz, crypto, io, qom, qemuutil,
4058 libcap_ng, mpathpersist],
4059 install: true)
4060 endif
4061
4062 if have_ivshmem
4063 subdir('contrib/ivshmem-client')
4064 subdir('contrib/ivshmem-server')
4065 endif
4066 endif
4067
4068 subdir('scripts')
4069 subdir('tools')
4070 subdir('pc-bios')
4071 subdir('docs')
4072 subdir('tests')
4073 if gtk.found()
4074 subdir('po')
4075 endif
4076
4077 if host_machine.system() == 'windows'
4078 nsis_cmd = [
4079 find_program('scripts/nsis.py'),
4080 '@OUTPUT@',
4081 get_option('prefix'),
4082 meson.current_source_dir(),
4083 glib_pc.get_variable('bindir'),
4084 host_machine.cpu(),
4085 '--',
4086 '-DDISPLAYVERSION=' + meson.project_version(),
4087 ]
4088 if build_docs
4089 nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
4090 endif
4091 if gtk.found()
4092 nsis_cmd += '-DCONFIG_GTK=y'
4093 endif
4094
4095 nsis = custom_target('nsis',
4096 output: 'qemu-setup-' + meson.project_version() + '.exe',
4097 input: files('qemu.nsi'),
4098 build_always_stale: true,
4099 command: nsis_cmd + ['@INPUT@'])
4100 alias_target('installer', nsis)
4101 endif
4102
4103 #########################
4104 # Configuration summary #
4105 #########################
4106
4107 # Build environment
4108 summary_info = {}
4109 summary_info += {'Build directory': meson.current_build_dir()}
4110 summary_info += {'Source path': meson.current_source_dir()}
4111 summary_info += {'Download dependencies': get_option('wrap_mode') != 'nodownload'}
4112 summary(summary_info, bool_yn: true, section: 'Build environment')
4113
4114 # Directories
4115 summary_info += {'Install prefix': get_option('prefix')}
4116 summary_info += {'BIOS directory': qemu_datadir}
4117 pathsep = host_os == 'windows' ? ';' : ':'
4118 summary_info += {'firmware path': pathsep.join(get_option('qemu_firmwarepath'))}
4119 summary_info += {'binary directory': get_option('prefix') / get_option('bindir')}
4120 summary_info += {'library directory': get_option('prefix') / get_option('libdir')}
4121 summary_info += {'module directory': qemu_moddir}
4122 summary_info += {'libexec directory': get_option('prefix') / get_option('libexecdir')}
4123 summary_info += {'include directory': get_option('prefix') / get_option('includedir')}
4124 summary_info += {'config directory': get_option('prefix') / get_option('sysconfdir')}
4125 if host_os != 'windows'
4126 summary_info += {'local state directory': get_option('prefix') / get_option('localstatedir')}
4127 summary_info += {'Manual directory': get_option('prefix') / get_option('mandir')}
4128 else
4129 summary_info += {'local state directory': 'queried at runtime'}
4130 endif
4131 summary_info += {'Doc directory': get_option('prefix') / get_option('docdir')}
4132 summary(summary_info, bool_yn: true, section: 'Directories')
4133
4134 # Host binaries
4135 summary_info = {}
4136 summary_info += {'python': '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
4137 summary_info += {'sphinx-build': sphinx_build}
4138
4139 # FIXME: the [binaries] section of machine files, which can be probed
4140 # with find_program(), would be great for passing gdb and genisoimage
4141 # paths from configure to Meson. However, there seems to be no way to
4142 # hide a program (for example if gdb is too old).
4143 if config_host.has_key('GDB')
4144 summary_info += {'gdb': config_host['GDB']}
4145 endif
4146 summary_info += {'iasl': iasl}
4147 summary_info += {'genisoimage': config_host['GENISOIMAGE']}
4148 if host_os == 'windows' and have_ga
4149 summary_info += {'wixl': wixl}
4150 endif
4151 if slirp.found() and have_system
4152 summary_info += {'smbd': have_slirp_smbd ? smbd_path : false}
4153 endif
4154 summary(summary_info, bool_yn: true, section: 'Host binaries')
4155
4156 # Configurable features
4157 summary_info = {}
4158 summary_info += {'Documentation': build_docs}
4159 summary_info += {'system-mode emulation': have_system}
4160 summary_info += {'user-mode emulation': have_user}
4161 summary_info += {'block layer': have_block}
4162 summary_info += {'Install blobs': get_option('install_blobs')}
4163 summary_info += {'module support': enable_modules}
4164 if enable_modules
4165 summary_info += {'alternative module path': get_option('module_upgrades')}
4166 endif
4167 summary_info += {'fuzzing support': get_option('fuzzing')}
4168 if have_system
4169 summary_info += {'Audio drivers': ' '.join(audio_drivers_selected)}
4170 endif
4171 summary_info += {'Trace backends': ','.join(get_option('trace_backends'))}
4172 if 'simple' in get_option('trace_backends')
4173 summary_info += {'Trace output file': get_option('trace_file') + '-<pid>'}
4174 endif
4175 summary_info += {'D-Bus display': dbus_display}
4176 summary_info += {'QOM debugging': get_option('qom_cast_debug')}
4177 summary_info += {'Relocatable install': get_option('relocatable')}
4178 summary_info += {'vhost-kernel support': have_vhost_kernel}
4179 summary_info += {'vhost-net support': have_vhost_net}
4180 summary_info += {'vhost-user support': have_vhost_user}
4181 summary_info += {'vhost-user-crypto support': have_vhost_user_crypto}
4182 summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
4183 summary_info += {'vhost-vdpa support': have_vhost_vdpa}
4184 summary_info += {'build guest agent': have_ga}
4185 summary(summary_info, bool_yn: true, section: 'Configurable features')
4186
4187 # Compilation information
4188 summary_info = {}
4189 summary_info += {'host CPU': cpu}
4190 summary_info += {'host endianness': build_machine.endian()}
4191 summary_info += {'C compiler': ' '.join(meson.get_compiler('c').cmd_array())}
4192 summary_info += {'Host C compiler': ' '.join(meson.get_compiler('c', native: true).cmd_array())}
4193 if 'cpp' in all_languages
4194 summary_info += {'C++ compiler': ' '.join(meson.get_compiler('cpp').cmd_array())}
4195 else
4196 summary_info += {'C++ compiler': false}
4197 endif
4198 if 'objc' in all_languages
4199 summary_info += {'Objective-C compiler': ' '.join(meson.get_compiler('objc').cmd_array())}
4200 else
4201 summary_info += {'Objective-C compiler': false}
4202 endif
4203 option_cflags = (get_option('debug') ? ['-g'] : [])
4204 if get_option('optimization') != 'plain'
4205 option_cflags += ['-O' + get_option('optimization')]
4206 endif
4207 summary_info += {'CFLAGS': ' '.join(get_option('c_args') + option_cflags)}
4208 if 'cpp' in all_languages
4209 summary_info += {'CXXFLAGS': ' '.join(get_option('cpp_args') + option_cflags)}
4210 endif
4211 if 'objc' in all_languages
4212 summary_info += {'OBJCFLAGS': ' '.join(get_option('objc_args') + option_cflags)}
4213 endif
4214 link_args = get_option('c_link_args')
4215 if link_args.length() > 0
4216 summary_info += {'LDFLAGS': ' '.join(link_args)}
4217 endif
4218 summary_info += {'QEMU_CFLAGS': ' '.join(qemu_common_flags + qemu_cflags)}
4219 if 'cpp' in all_languages
4220 summary_info += {'QEMU_CXXFLAGS': ' '.join(qemu_common_flags + qemu_cxxflags)}
4221 endif
4222 if 'objc' in all_languages
4223 summary_info += {'QEMU_OBJCFLAGS': ' '.join(qemu_common_flags)}
4224 endif
4225 summary_info += {'QEMU_LDFLAGS': ' '.join(qemu_ldflags)}
4226 summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
4227 summary_info += {'PIE': get_option('b_pie')}
4228 summary_info += {'static build': get_option('prefer_static')}
4229 summary_info += {'malloc trim support': has_malloc_trim}
4230 summary_info += {'membarrier': have_membarrier}
4231 summary_info += {'debug graph lock': get_option('debug_graph_lock')}
4232 summary_info += {'debug stack usage': get_option('debug_stack_usage')}
4233 summary_info += {'mutex debugging': get_option('debug_mutex')}
4234 summary_info += {'memory allocator': get_option('malloc')}
4235 summary_info += {'avx2 optimization': config_host_data.get('CONFIG_AVX2_OPT')}
4236 summary_info += {'avx512bw optimization': config_host_data.get('CONFIG_AVX512BW_OPT')}
4237 summary_info += {'avx512f optimization': config_host_data.get('CONFIG_AVX512F_OPT')}
4238 summary_info += {'gcov': get_option('b_coverage')}
4239 summary_info += {'thread sanitizer': get_option('tsan')}
4240 summary_info += {'CFI support': get_option('cfi')}
4241 if get_option('cfi')
4242 summary_info += {'CFI debug support': get_option('cfi_debug')}
4243 endif
4244 summary_info += {'strip binaries': get_option('strip')}
4245 summary_info += {'sparse': sparse}
4246 summary_info += {'mingw32 support': host_os == 'windows'}
4247 summary(summary_info, bool_yn: true, section: 'Compilation')
4248
4249 # snarf the cross-compilation information for tests
4250 summary_info = {}
4251 have_cross = false
4252 foreach target: target_dirs
4253 tcg_mak = meson.current_build_dir() / 'tests/tcg' / target / 'config-target.mak'
4254 if fs.exists(tcg_mak)
4255 config_cross_tcg = keyval.load(tcg_mak)
4256 if 'CC' in config_cross_tcg
4257 summary_info += {config_cross_tcg['TARGET_NAME']: config_cross_tcg['CC']}
4258 have_cross = true
4259 endif
4260 endif
4261 endforeach
4262 if have_cross
4263 summary(summary_info, bool_yn: true, section: 'Cross compilers')
4264 endif
4265
4266 # Targets and accelerators
4267 summary_info = {}
4268 if have_system
4269 summary_info += {'KVM support': config_all_accel.has_key('CONFIG_KVM')}
4270 summary_info += {'HVF support': config_all_accel.has_key('CONFIG_HVF')}
4271 summary_info += {'WHPX support': config_all_accel.has_key('CONFIG_WHPX')}
4272 summary_info += {'NVMM support': config_all_accel.has_key('CONFIG_NVMM')}
4273 summary_info += {'Xen support': xen.found()}
4274 if xen.found()
4275 summary_info += {'xen ctrl version': xen.version()}
4276 endif
4277 summary_info += {'Xen emulation': config_all_devices.has_key('CONFIG_XEN_EMU')}
4278 endif
4279 summary_info += {'TCG support': config_all_accel.has_key('CONFIG_TCG')}
4280 if config_all_accel.has_key('CONFIG_TCG')
4281 if get_option('tcg_interpreter')
4282 summary_info += {'TCG backend': 'TCI (TCG with bytecode interpreter, slow)'}
4283 else
4284 summary_info += {'TCG backend': 'native (@0@)'.format(cpu)}
4285 endif
4286 summary_info += {'TCG plugins': get_option('plugins')}
4287 summary_info += {'TCG debug enabled': get_option('debug_tcg')}
4288 endif
4289 summary_info += {'target list': ' '.join(target_dirs)}
4290 if have_system
4291 summary_info += {'default devices': get_option('default_devices')}
4292 summary_info += {'out of process emulation': multiprocess_allowed}
4293 summary_info += {'vfio-user server': vfio_user_server_allowed}
4294 endif
4295 summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
4296
4297 # Block layer
4298 summary_info = {}
4299 summary_info += {'coroutine backend': coroutine_backend}
4300 summary_info += {'coroutine pool': have_coroutine_pool}
4301 if have_block
4302 summary_info += {'Block whitelist (rw)': get_option('block_drv_rw_whitelist')}
4303 summary_info += {'Block whitelist (ro)': get_option('block_drv_ro_whitelist')}
4304 summary_info += {'Use block whitelist in tools': get_option('block_drv_whitelist_in_tools')}
4305 summary_info += {'VirtFS (9P) support': have_virtfs}
4306 summary_info += {'VirtFS (9P) Proxy Helper support (deprecated)': have_virtfs_proxy_helper}
4307 summary_info += {'Live block migration': config_host_data.get('CONFIG_LIVE_BLOCK_MIGRATION')}
4308 summary_info += {'replication support': config_host_data.get('CONFIG_REPLICATION')}
4309 summary_info += {'bochs support': get_option('bochs').allowed()}
4310 summary_info += {'cloop support': get_option('cloop').allowed()}
4311 summary_info += {'dmg support': get_option('dmg').allowed()}
4312 summary_info += {'qcow v1 support': get_option('qcow1').allowed()}
4313 summary_info += {'vdi support': get_option('vdi').allowed()}
4314 summary_info += {'vhdx support': get_option('vhdx').allowed()}
4315 summary_info += {'vmdk support': get_option('vmdk').allowed()}
4316 summary_info += {'vpc support': get_option('vpc').allowed()}
4317 summary_info += {'vvfat support': get_option('vvfat').allowed()}
4318 summary_info += {'qed support': get_option('qed').allowed()}
4319 summary_info += {'parallels support': get_option('parallels').allowed()}
4320 summary_info += {'FUSE exports': fuse}
4321 summary_info += {'VDUSE block exports': have_vduse_blk_export}
4322 endif
4323 summary(summary_info, bool_yn: true, section: 'Block layer support')
4324
4325 # Crypto
4326 summary_info = {}
4327 summary_info += {'TLS priority': get_option('tls_priority')}
4328 summary_info += {'GNUTLS support': gnutls}
4329 if gnutls.found()
4330 summary_info += {' GNUTLS crypto': gnutls_crypto.found()}
4331 endif
4332 summary_info += {'libgcrypt': gcrypt}
4333 summary_info += {'nettle': nettle}
4334 if nettle.found()
4335 summary_info += {' XTS': xts != 'private'}
4336 endif
4337 summary_info += {'SM4 ALG support': crypto_sm4}
4338 summary_info += {'AF_ALG support': have_afalg}
4339 summary_info += {'rng-none': get_option('rng_none')}
4340 summary_info += {'Linux keyring': have_keyring}
4341 summary_info += {'Linux keyutils': keyutils}
4342 summary(summary_info, bool_yn: true, section: 'Crypto')
4343
4344 # UI
4345 summary_info = {}
4346 if host_os == 'darwin'
4347 summary_info += {'Cocoa support': cocoa}
4348 endif
4349 summary_info += {'SDL support': sdl}
4350 summary_info += {'SDL image support': sdl_image}
4351 summary_info += {'GTK support': gtk}
4352 summary_info += {'pixman': pixman}
4353 summary_info += {'VTE support': vte}
4354 summary_info += {'PNG support': png}
4355 summary_info += {'VNC support': vnc}
4356 if vnc.found()
4357 summary_info += {'VNC SASL support': sasl}
4358 summary_info += {'VNC JPEG support': jpeg}
4359 endif
4360 summary_info += {'spice protocol support': spice_protocol}
4361 if spice_protocol.found()
4362 summary_info += {' spice server support': spice}
4363 endif
4364 summary_info += {'curses support': curses}
4365 summary_info += {'brlapi support': brlapi}
4366 summary(summary_info, bool_yn: true, section: 'User interface')
4367
4368 # Graphics backends
4369 summary_info = {}
4370 summary_info += {'VirGL support': virgl}
4371 summary_info += {'Rutabaga support': rutabaga}
4372 summary(summary_info, bool_yn: true, section: 'Graphics backends')
4373
4374 # Audio backends
4375 summary_info = {}
4376 if host_os not in ['darwin', 'haiku', 'windows']
4377 summary_info += {'OSS support': oss}
4378 summary_info += {'sndio support': sndio}
4379 elif host_os == 'darwin'
4380 summary_info += {'CoreAudio support': coreaudio}
4381 elif host_os == 'windows'
4382 summary_info += {'DirectSound support': dsound}
4383 endif
4384 if host_os == 'linux'
4385 summary_info += {'ALSA support': alsa}
4386 summary_info += {'PulseAudio support': pulse}
4387 endif
4388 summary_info += {'PipeWire support': pipewire}
4389 summary_info += {'JACK support': jack}
4390 summary(summary_info, bool_yn: true, section: 'Audio backends')
4391
4392 # Network backends
4393 summary_info = {}
4394 if host_os == 'darwin'
4395 summary_info += {'vmnet.framework support': vmnet}
4396 endif
4397 summary_info += {'AF_XDP support': libxdp}
4398 summary_info += {'slirp support': slirp}
4399 summary_info += {'vde support': vde}
4400 summary_info += {'netmap support': have_netmap}
4401 summary_info += {'l2tpv3 support': have_l2tpv3}
4402 summary(summary_info, bool_yn: true, section: 'Network backends')
4403
4404 # Libraries
4405 summary_info = {}
4406 summary_info += {'libtasn1': tasn1}
4407 summary_info += {'PAM': pam}
4408 summary_info += {'iconv support': iconv}
4409 summary_info += {'blkio support': blkio}
4410 summary_info += {'curl support': curl}
4411 summary_info += {'Multipath support': mpathpersist}
4412 summary_info += {'Linux AIO support': libaio}
4413 summary_info += {'Linux io_uring support': linux_io_uring}
4414 summary_info += {'ATTR/XATTR support': libattr}
4415 summary_info += {'RDMA support': rdma}
4416 summary_info += {'PVRDMA support': have_pvrdma}
4417 summary_info += {'fdt support': fdt_opt == 'disabled' ? false : fdt_opt}
4418 summary_info += {'libcap-ng support': libcap_ng}
4419 summary_info += {'bpf support': libbpf}
4420 summary_info += {'rbd support': rbd}
4421 summary_info += {'smartcard support': cacard}
4422 summary_info += {'U2F support': u2f}
4423 summary_info += {'libusb': libusb}
4424 summary_info += {'usb net redir': usbredir}
4425 summary_info += {'OpenGL support (epoxy)': opengl}
4426 summary_info += {'GBM': gbm}
4427 summary_info += {'libiscsi support': libiscsi}
4428 summary_info += {'libnfs support': libnfs}
4429 if host_os == 'windows'
4430 if have_ga
4431 summary_info += {'QGA VSS support': have_qga_vss}
4432 endif
4433 endif
4434 summary_info += {'seccomp support': seccomp}
4435 summary_info += {'GlusterFS support': glusterfs}
4436 summary_info += {'hv-balloon support': hv_balloon}
4437 summary_info += {'TPM support': have_tpm}
4438 summary_info += {'libssh support': libssh}
4439 summary_info += {'lzo support': lzo}
4440 summary_info += {'snappy support': snappy}
4441 summary_info += {'bzip2 support': libbzip2}
4442 summary_info += {'lzfse support': liblzfse}
4443 summary_info += {'zstd support': zstd}
4444 summary_info += {'NUMA host support': numa}
4445 summary_info += {'capstone': capstone}
4446 summary_info += {'libpmem support': libpmem}
4447 summary_info += {'libdaxctl support': libdaxctl}
4448 summary_info += {'libudev': libudev}
4449 # Dummy dependency, keep .found()
4450 summary_info += {'FUSE lseek': fuse_lseek.found()}
4451 summary_info += {'selinux': selinux}
4452 summary_info += {'libdw': libdw}
4453 if host_os == 'freebsd'
4454 summary_info += {'libinotify-kqueue': inotify}
4455 endif
4456 summary(summary_info, bool_yn: true, section: 'Dependencies')
4457
4458 if host_arch == 'unknown'
4459 message()
4460 warning('UNSUPPORTED HOST CPU')
4461 message()
4462 message('Support for CPU host architecture ' + cpu + ' is not currently')
4463 message('maintained. The QEMU project does not guarantee that QEMU will')
4464 message('compile or work on this host CPU. You can help by volunteering')
4465 message('to maintain it and providing a build host for our continuous')
4466 message('integration setup.')
4467 if get_option('tcg').allowed() and target_dirs.length() > 0
4468 message()
4469 message('configure has succeeded and you can continue to build, but')
4470 message('QEMU will use a slow interpreter to emulate the target CPU.')
4471 endif
4472 endif
4473
4474 if not supported_oses.contains(host_os)
4475 message()
4476 warning('UNSUPPORTED HOST OS')
4477 message()
4478 message('Support for host OS ' + host_os + 'is not currently maintained.')
4479 message('configure has succeeded and you can continue to build, but')
4480 message('the QEMU project does not guarantee that QEMU will compile or')
4481 message('work on this operating system. You can help by volunteering')
4482 message('to maintain it and providing a build host for our continuous')
4483 message('integration setup. This will ensure that future versions of QEMU')
4484 message('will keep working on ' + host_os + '.')
4485 endif
4486
4487 if host_arch == 'unknown' or not supported_oses.contains(host_os)
4488 message()
4489 message('If you want to help supporting QEMU on this platform, please')
4490 message('contact the developers at qemu-devel@nongnu.org.')
4491 endif
4492
4493 actually_reloc = get_option('relocatable')
4494 # check if get_relocated_path() is actually able to relocate paths
4495 if get_option('relocatable') and \
4496 not (get_option('prefix') / get_option('bindir')).startswith(get_option('prefix') / '')
4497 message()
4498 warning('bindir not included within prefix, the installation will not be relocatable.')
4499 actually_reloc = false
4500 endif
4501 if not actually_reloc and (host_os == 'windows' or get_option('relocatable'))
4502 if host_os == 'windows'
4503 message()
4504 warning('Windows installs should usually be relocatable.')
4505 endif
4506 message()
4507 message('QEMU will have to be installed under ' + get_option('prefix') + '.')
4508 message('Use --disable-relocatable to remove this warning.')
4509 endif