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