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