project('qemu', ['c'], meson_version: '>=0.55.0', default_options: ['warning_level=1', 'c_std=gnu99', 'cpp_std=gnu++11', 'b_colorout=auto'], version: run_command('head', meson.source_root() / 'VERSION').stdout().strip()) not_found = dependency('', required: false) if meson.version().version_compare('>=0.56.0') keyval = import('keyval') else keyval = import('unstable-keyval') endif ss = import('sourceset') fs = import('fs') sh = find_program('sh') cc = meson.get_compiler('c') config_host = keyval.load(meson.current_build_dir() / 'config-host.mak') enable_modules = 'CONFIG_MODULES' in config_host enable_static = 'CONFIG_STATIC' in config_host build_docs = 'BUILD_DOCS' in config_host if get_option('qemu_suffix').startswith('/') error('qemu_suffix cannot start with a /') endif qemu_datadir = get_option('datadir') / get_option('qemu_suffix') qemu_docdir = get_option('docdir') / get_option('qemu_suffix') config_host_data = configuration_data() genh = [] target_dirs = config_host['TARGET_DIRS'].split() have_user = false have_system = false foreach target : target_dirs have_user = have_user or target.endswith('-user') have_system = have_system or target.endswith('-softmmu') endforeach have_tools = 'CONFIG_TOOLS' in config_host have_block = have_system or have_tools python = import('python').find_installation() supported_oses = ['windows', 'freebsd', 'netbsd', 'openbsd', 'darwin', 'sunos', 'linux'] supported_cpus = ['ppc', 'ppc64', 's390x', 'sparc64', 'riscv32', 'riscv64', 'x86', 'x86_64', 'arm', 'aarch64', 'mips', 'mips64', 'sparc', 'sparc64'] cpu = host_machine.cpu_family() targetos = host_machine.system() configure_file(input: files('scripts/ninjatool.py'), output: 'ninjatool', configuration: config_host) if cpu in ['x86', 'x86_64'] kvm_targets = ['i386-softmmu', 'x86_64-softmmu'] elif cpu == 'aarch64' kvm_targets = ['aarch64-softmmu'] elif cpu == 's390x' kvm_targets = ['s390x-softmmu'] elif cpu in ['ppc', 'ppc64'] kvm_targets = ['ppc-softmmu', 'ppc64-softmmu'] else kvm_targets = [] endif accelerator_targets = { 'CONFIG_KVM': kvm_targets } if cpu in ['x86', 'x86_64'] accelerator_targets += { 'CONFIG_HAX': ['i386-softmmu', 'x86_64-softmmu'], 'CONFIG_XEN': ['i386-softmmu', 'x86_64-softmmu'], 'CONFIG_HVF': ['x86_64-softmmu'], 'CONFIG_WHPX': ['i386-softmmu', 'x86_64-softmmu'], } endif ################## # Compiler flags # ################## # Specify linker-script with add_project_link_arguments so that it is not placed # within a linker --start-group/--end-group pair if 'CONFIG_FUZZ' in config_host add_project_link_arguments(['-Wl,-T,', (meson.current_source_dir() / 'tests/qtest/fuzz/fork_fuzz.ld')], native: false, language: ['c', 'cpp', 'objc']) endif add_project_arguments(config_host['QEMU_CFLAGS'].split(), native: false, language: ['c', 'objc']) add_project_arguments(config_host['QEMU_CXXFLAGS'].split(), native: false, language: 'cpp') add_project_link_arguments(config_host['QEMU_LDFLAGS'].split(), native: false, language: ['c', 'cpp', 'objc']) add_project_arguments(config_host['QEMU_INCLUDES'].split(), language: ['c', 'cpp', 'objc']) link_language = meson.get_external_property('link_language', 'cpp') if link_language == 'cpp' add_languages('cpp', required: true, native: false) endif if host_machine.system() == 'darwin' add_languages('objc', required: false, native: false) endif sparse = find_program('cgcc', required: get_option('sparse')) if sparse.found() run_target('sparse', command: [find_program('scripts/check_sparse.py'), 'compile_commands.json', sparse.full_path(), '-Wbitwise', '-Wno-transparent-union', '-Wno-old-initializer', '-Wno-non-pointer-null']) endif ########################################### # Target-specific checks and dependencies # ########################################### if targetos != 'linux' and get_option('mpath').enabled() error('Multipath is supported only on Linux') endif m = cc.find_library('m', required: false) util = cc.find_library('util', required: false) winmm = [] socket = [] version_res = [] coref = [] iokit = [] emulator_link_args = [] cocoa = not_found hvf = not_found if targetos == 'windows' socket = cc.find_library('ws2_32') winmm = cc.find_library('winmm') win = import('windows') version_res = win.compile_resources('version.rc', depend_files: files('pc-bios/qemu-nsis.ico'), include_directories: include_directories('.')) elif targetos == 'darwin' coref = dependency('appleframeworks', modules: 'CoreFoundation') iokit = dependency('appleframeworks', modules: 'IOKit') cocoa = dependency('appleframeworks', modules: 'Cocoa', required: get_option('cocoa')) elif targetos == 'sunos' socket = [cc.find_library('socket'), cc.find_library('nsl'), cc.find_library('resolv')] elif targetos == 'haiku' socket = [cc.find_library('posix_error_mapper'), cc.find_library('network'), cc.find_library('bsd')] elif targetos == 'openbsd' if not get_option('tcg').disabled() and target_dirs.length() > 0 # Disable OpenBSD W^X if available emulator_link_args = cc.get_supported_link_arguments('-Wl,-z,wxneeded') endif endif accelerators = [] if not get_option('kvm').disabled() and targetos == 'linux' accelerators += 'CONFIG_KVM' endif if not get_option('xen').disabled() and 'CONFIG_XEN_BACKEND' in config_host accelerators += 'CONFIG_XEN' have_xen_pci_passthrough = not get_option('xen_pci_passthrough').disabled() and targetos == 'linux' else have_xen_pci_passthrough = false endif if not get_option('whpx').disabled() and targetos == 'windows' if get_option('whpx').enabled() and cpu != 'x86_64' error('WHPX requires 64-bit host') elif cc.has_header('WinHvPlatform.h', required: get_option('whpx')) and \ cc.has_header('WinHvEmulation.h', required: get_option('whpx')) accelerators += 'CONFIG_WHPX' endif endif if not get_option('hvf').disabled() hvf = dependency('appleframeworks', modules: 'Hypervisor', required: get_option('hvf')) if hvf.found() accelerators += 'CONFIG_HVF' endif endif if not get_option('hax').disabled() if get_option('hax').enabled() or targetos in ['windows', 'darwin', 'netbsd'] accelerators += 'CONFIG_HAX' endif endif if not get_option('tcg').disabled() if cpu not in supported_cpus if 'CONFIG_TCG_INTERPRETER' in config_host warning('Unsupported CPU @0@, will use TCG with TCI (experimental)'.format(cpu)) else error('Unsupported CPU @0@, try --enable-tcg-interpreter'.format(cpu)) endif endif accelerators += 'CONFIG_TCG' config_host += { 'CONFIG_TCG': 'y' } endif if 'CONFIG_KVM' not in accelerators and get_option('kvm').enabled() error('KVM not available on this platform') endif if 'CONFIG_HVF' not in accelerators and get_option('hvf').enabled() error('HVF not available on this platform') endif if 'CONFIG_WHPX' not in accelerators and get_option('whpx').enabled() error('WHPX not available on this platform') endif if not have_xen_pci_passthrough and get_option('xen_pci_passthrough').enabled() if 'CONFIG_XEN' in accelerators error('Xen PCI passthrough not available on this platform') else error('Xen PCI passthrough requested but Xen not enabled') endif endif if not cocoa.found() and get_option('cocoa').enabled() error('Cocoa not available on this platform') endif ################ # Dependencies # ################ # The path to glib.h is added to all compilation commands. This was # grandfathered in from the QEMU Makefiles. add_project_arguments(config_host['GLIB_CFLAGS'].split(), native: false, language: ['c', 'cpp', 'objc']) glib = declare_dependency(link_args: config_host['GLIB_LIBS'].split()) gio = not_found if 'CONFIG_GIO' in config_host gio = declare_dependency(compile_args: config_host['GIO_CFLAGS'].split(), link_args: config_host['GIO_LIBS'].split()) endif lttng = not_found if 'CONFIG_TRACE_UST' in config_host lttng = declare_dependency(link_args: config_host['LTTNG_UST_LIBS'].split()) endif urcubp = not_found if 'CONFIG_TRACE_UST' in config_host urcubp = declare_dependency(link_args: config_host['URCU_BP_LIBS'].split()) endif gcrypt = not_found if 'CONFIG_GCRYPT' in config_host gcrypt = declare_dependency(compile_args: config_host['GCRYPT_CFLAGS'].split(), link_args: config_host['GCRYPT_LIBS'].split()) endif nettle = not_found if 'CONFIG_NETTLE' in config_host nettle = declare_dependency(compile_args: config_host['NETTLE_CFLAGS'].split(), link_args: config_host['NETTLE_LIBS'].split()) endif gnutls = not_found if 'CONFIG_GNUTLS' in config_host gnutls = declare_dependency(compile_args: config_host['GNUTLS_CFLAGS'].split(), link_args: config_host['GNUTLS_LIBS'].split()) endif pixman = not_found if have_system or have_tools pixman = dependency('pixman-1', required: have_system, version:'>=0.21.8', method: 'pkg-config', static: enable_static) endif pam = not_found if 'CONFIG_AUTH_PAM' in config_host pam = cc.find_library('pam') endif libaio = cc.find_library('aio', required: false) zlib = dependency('zlib', required: true, static: enable_static) linux_io_uring = not_found if 'CONFIG_LINUX_IO_URING' in config_host linux_io_uring = declare_dependency(compile_args: config_host['LINUX_IO_URING_CFLAGS'].split(), link_args: config_host['LINUX_IO_URING_LIBS'].split()) endif libxml2 = not_found if 'CONFIG_LIBXML2' in config_host libxml2 = declare_dependency(compile_args: config_host['LIBXML2_CFLAGS'].split(), link_args: config_host['LIBXML2_LIBS'].split()) endif libnfs = not_found if 'CONFIG_LIBNFS' in config_host libnfs = declare_dependency(link_args: config_host['LIBNFS_LIBS'].split()) endif libattr = not_found if 'CONFIG_ATTR' in config_host libattr = declare_dependency(link_args: config_host['LIBATTR_LIBS'].split()) endif seccomp = not_found if 'CONFIG_SECCOMP' in config_host seccomp = declare_dependency(compile_args: config_host['SECCOMP_CFLAGS'].split(), link_args: config_host['SECCOMP_LIBS'].split()) endif libcap_ng = not_found if 'CONFIG_LIBCAP_NG' in config_host libcap_ng = declare_dependency(link_args: config_host['LIBCAP_NG_LIBS'].split()) endif if get_option('xkbcommon').auto() and not have_system and not have_tools xkbcommon = not_found else xkbcommon = dependency('xkbcommon', required: get_option('xkbcommon'), method: 'pkg-config', static: enable_static) endif vde = not_found if config_host.has_key('CONFIG_VDE') vde = declare_dependency(link_args: config_host['VDE_LIBS'].split()) endif pulse = not_found if 'CONFIG_LIBPULSE' in config_host pulse = declare_dependency(compile_args: config_host['PULSE_CFLAGS'].split(), link_args: config_host['PULSE_LIBS'].split()) endif alsa = not_found if 'CONFIG_ALSA' in config_host alsa = declare_dependency(compile_args: config_host['ALSA_CFLAGS'].split(), link_args: config_host['ALSA_LIBS'].split()) endif jack = not_found if 'CONFIG_LIBJACK' in config_host jack = declare_dependency(link_args: config_host['JACK_LIBS'].split()) endif spice = not_found if 'CONFIG_SPICE' in config_host spice = declare_dependency(compile_args: config_host['SPICE_CFLAGS'].split(), link_args: config_host['SPICE_LIBS'].split()) endif rt = cc.find_library('rt', required: false) libdl = not_found if 'CONFIG_PLUGIN' in config_host libdl = cc.find_library('dl', required: true) endif libiscsi = not_found if 'CONFIG_LIBISCSI' in config_host libiscsi = declare_dependency(compile_args: config_host['LIBISCSI_CFLAGS'].split(), link_args: config_host['LIBISCSI_LIBS'].split()) endif zstd = not_found if 'CONFIG_ZSTD' in config_host zstd = declare_dependency(compile_args: config_host['ZSTD_CFLAGS'].split(), link_args: config_host['ZSTD_LIBS'].split()) endif gbm = not_found if 'CONFIG_GBM' in config_host gbm = declare_dependency(compile_args: config_host['GBM_CFLAGS'].split(), link_args: config_host['GBM_LIBS'].split()) endif virgl = not_found if 'CONFIG_VIRGL' in config_host virgl = declare_dependency(compile_args: config_host['VIRGL_CFLAGS'].split(), link_args: config_host['VIRGL_LIBS'].split()) endif curl = not_found if 'CONFIG_CURL' in config_host curl = declare_dependency(compile_args: config_host['CURL_CFLAGS'].split(), link_args: config_host['CURL_LIBS'].split()) endif libudev = not_found if targetos == 'linux' and (have_system or have_tools) libudev = dependency('libudev', required: get_option('mpath').enabled(), static: enable_static) endif mpathpersist = not_found mpathpersist_new_api = false if targetos == 'linux' and have_tools and not get_option('mpath').disabled() mpath_test_source_new = ''' #include #include unsigned mpath_mx_alloc_len = 1024; int logsink; static struct config *multipath_conf; extern struct udev *udev; extern struct config *get_multipath_config(void); extern void put_multipath_config(struct config *conf); struct udev *udev; struct config *get_multipath_config(void) { return multipath_conf; } void put_multipath_config(struct config *conf) { } int main(void) { udev = udev_new(); multipath_conf = mpath_lib_init(); return 0; }''' mpath_test_source_old = ''' #include #include unsigned mpath_mx_alloc_len = 1024; int logsink; int main(void) { struct udev *udev = udev_new(); mpath_lib_init(udev); return 0; }''' mpathlibs = [libudev] if enable_static mpathlibs += cc.find_library('devmapper', required: get_option('mpath'), static: enable_static) endif mpathlibs += cc.find_library('multipath', required: get_option('mpath'), static: enable_static) mpathlibs += cc.find_library('mpathpersist', required: get_option('mpath'), static: enable_static) foreach lib: mpathlibs if not lib.found() mpathlibs = [] break endif endforeach if mpathlibs.length() > 0 if cc.links(mpath_test_source_new, dependencies: mpathlibs) mpathpersist = declare_dependency(dependencies: mpathlibs) mpathpersist_new_api = true elif cc.links(mpath_test_source_old, dependencies: mpathlibs) mpathpersist = declare_dependency(dependencies: mpathlibs) else if get_option('mpath').enabled() error('Cannot detect libmpathpersist API') else warning('Cannot detect libmpathpersist API, disabling') endif endif endif endif brlapi = not_found if 'CONFIG_BRLAPI' in config_host brlapi = declare_dependency(link_args: config_host['BRLAPI_LIBS'].split()) endif sdl = not_found if have_system sdl = dependency('sdl2', required: get_option('sdl'), static: enable_static) sdl_image = not_found endif if sdl.found() # work around 2.0.8 bug sdl = declare_dependency(compile_args: '-Wno-undef', dependencies: sdl) sdl_image = dependency('SDL2_image', required: get_option('sdl_image'), method: 'pkg-config', static: enable_static) else if get_option('sdl_image').enabled() error('sdl-image required, but SDL was @0@'.format( get_option('sdl').disabled() ? 'disabled' : 'not found')) endif sdl_image = not_found endif rbd = not_found if 'CONFIG_RBD' in config_host rbd = declare_dependency(link_args: config_host['RBD_LIBS'].split()) endif glusterfs = not_found if 'CONFIG_GLUSTERFS' in config_host glusterfs = declare_dependency(compile_args: config_host['GLUSTERFS_CFLAGS'].split(), link_args: config_host['GLUSTERFS_LIBS'].split()) endif libssh = not_found if 'CONFIG_LIBSSH' in config_host libssh = declare_dependency(compile_args: config_host['LIBSSH_CFLAGS'].split(), link_args: config_host['LIBSSH_LIBS'].split()) endif libbzip2 = not_found if 'CONFIG_BZIP2' in config_host libbzip2 = declare_dependency(link_args: config_host['BZIP2_LIBS'].split()) endif liblzfse = not_found if 'CONFIG_LZFSE' in config_host liblzfse = declare_dependency(link_args: config_host['LZFSE_LIBS'].split()) endif oss = not_found if 'CONFIG_AUDIO_OSS' in config_host oss = declare_dependency(link_args: config_host['OSS_LIBS'].split()) endif dsound = not_found if 'CONFIG_AUDIO_DSOUND' in config_host dsound = declare_dependency(link_args: config_host['DSOUND_LIBS'].split()) endif coreaudio = not_found if 'CONFIG_AUDIO_COREAUDIO' in config_host coreaudio = declare_dependency(link_args: config_host['COREAUDIO_LIBS'].split()) endif opengl = not_found if 'CONFIG_OPENGL' in config_host opengl = declare_dependency(compile_args: config_host['OPENGL_CFLAGS'].split(), link_args: config_host['OPENGL_LIBS'].split()) endif gtk = not_found if 'CONFIG_GTK' in config_host gtk = declare_dependency(compile_args: config_host['GTK_CFLAGS'].split(), link_args: config_host['GTK_LIBS'].split()) endif vte = not_found if 'CONFIG_VTE' in config_host vte = declare_dependency(compile_args: config_host['VTE_CFLAGS'].split(), link_args: config_host['VTE_LIBS'].split()) endif x11 = not_found if 'CONFIG_X11' in config_host x11 = declare_dependency(compile_args: config_host['X11_CFLAGS'].split(), link_args: config_host['X11_LIBS'].split()) endif curses = not_found if 'CONFIG_CURSES' in config_host curses = declare_dependency(compile_args: config_host['CURSES_CFLAGS'].split(), link_args: config_host['CURSES_LIBS'].split()) endif iconv = not_found if 'CONFIG_ICONV' in config_host iconv = declare_dependency(compile_args: config_host['ICONV_CFLAGS'].split(), link_args: config_host['ICONV_LIBS'].split()) endif vnc = not_found png = not_found jpeg = not_found sasl = not_found if get_option('vnc').enabled() vnc = declare_dependency() # dummy dependency png = dependency('libpng', required: get_option('vnc_png'), method: 'pkg-config', static: enable_static) jpeg = cc.find_library('jpeg', has_headers: ['jpeglib.h'], required: get_option('vnc_jpeg'), static: enable_static) sasl = cc.find_library('sasl2', has_headers: ['sasl/sasl.h'], required: get_option('vnc_sasl'), static: enable_static) if sasl.found() sasl = declare_dependency(dependencies: sasl, compile_args: '-DSTRUCT_IOVEC_DEFINED') endif endif snappy = not_found if 'CONFIG_SNAPPY' in config_host snappy = declare_dependency(link_args: config_host['SNAPPY_LIBS'].split()) endif lzo = not_found if 'CONFIG_LZO' in config_host lzo = declare_dependency(link_args: config_host['LZO_LIBS'].split()) endif rdma = not_found if 'CONFIG_RDMA' in config_host rdma = declare_dependency(link_args: config_host['RDMA_LIBS'].split()) endif numa = not_found if 'CONFIG_NUMA' in config_host numa = declare_dependency(link_args: config_host['NUMA_LIBS'].split()) endif xen = not_found if 'CONFIG_XEN_BACKEND' in config_host xen = declare_dependency(compile_args: config_host['XEN_CFLAGS'].split(), link_args: config_host['XEN_LIBS'].split()) endif cacard = not_found if 'CONFIG_SMARTCARD' in config_host cacard = declare_dependency(compile_args: config_host['SMARTCARD_CFLAGS'].split(), link_args: config_host['SMARTCARD_LIBS'].split()) endif u2f = not_found if have_system u2f = dependency('u2f-emu', required: get_option('u2f'), method: 'pkg-config', static: enable_static) endif usbredir = not_found if 'CONFIG_USB_REDIR' in config_host usbredir = declare_dependency(compile_args: config_host['USB_REDIR_CFLAGS'].split(), link_args: config_host['USB_REDIR_LIBS'].split()) endif libusb = not_found if 'CONFIG_USB_LIBUSB' in config_host libusb = declare_dependency(compile_args: config_host['LIBUSB_CFLAGS'].split(), link_args: config_host['LIBUSB_LIBS'].split()) endif libpmem = not_found if 'CONFIG_LIBPMEM' in config_host libpmem = declare_dependency(compile_args: config_host['LIBPMEM_CFLAGS'].split(), link_args: config_host['LIBPMEM_LIBS'].split()) endif libdaxctl = not_found if 'CONFIG_LIBDAXCTL' in config_host libdaxctl = declare_dependency(link_args: config_host['LIBDAXCTL_LIBS'].split()) endif tasn1 = not_found if 'CONFIG_TASN1' in config_host tasn1 = declare_dependency(compile_args: config_host['TASN1_CFLAGS'].split(), link_args: config_host['TASN1_LIBS'].split()) endif keyutils = dependency('libkeyutils', required: false, method: 'pkg-config', static: enable_static) has_gettid = cc.has_function('gettid') # Malloc tests malloc = [] if get_option('malloc') == 'system' has_malloc_trim = \ not get_option('malloc_trim').disabled() and \ cc.links('''#include int main(void) { malloc_trim(0); return 0; }''') else has_malloc_trim = false malloc = cc.find_library(get_option('malloc'), required: true) endif if not has_malloc_trim and get_option('malloc_trim').enabled() if get_option('malloc') == 'system' error('malloc_trim not available on this platform.') else error('malloc_trim not available with non-libc memory allocator') endif endif # Create config-host.h config_host_data.set('CONFIG_COCOA', cocoa.found()) config_host_data.set('CONFIG_LIBUDEV', libudev.found()) config_host_data.set('CONFIG_MPATH', mpathpersist.found()) config_host_data.set('CONFIG_MPATH_NEW_API', mpathpersist_new_api) config_host_data.set('CONFIG_SDL', sdl.found()) config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found()) config_host_data.set('CONFIG_VNC', vnc.found()) config_host_data.set('CONFIG_VNC_JPEG', jpeg.found()) config_host_data.set('CONFIG_VNC_PNG', png.found()) config_host_data.set('CONFIG_VNC_SASL', sasl.found()) config_host_data.set('CONFIG_XKBCOMMON', xkbcommon.found()) config_host_data.set('CONFIG_KEYUTILS', keyutils.found()) config_host_data.set('CONFIG_GETTID', has_gettid) config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim) config_host_data.set('QEMU_VERSION', '"@0@"'.format(meson.project_version())) config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0]) config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1]) config_host_data.set('QEMU_VERSION_MICRO', meson.project_version().split('.')[2]) ignored = ['CONFIG_QEMU_INTERP_PREFIX'] # actually per-target arrays = ['CONFIG_AUDIO_DRIVERS', 'CONFIG_BDRV_RW_WHITELIST', 'CONFIG_BDRV_RO_WHITELIST'] strings = ['HOST_DSOSUF', 'CONFIG_IASL', 'bindir', 'prefix', 'qemu_confdir', 'qemu_datadir', 'qemu_moddir', 'qemu_localstatedir', 'qemu_helperdir', 'qemu_localedir', 'qemu_icondir', 'qemu_desktopdir', 'qemu_firmwarepath', 'sysconfdir'] foreach k, v: config_host if ignored.contains(k) # do nothing elif arrays.contains(k) if v != '' v = '"' + '", "'.join(v.split()) + '", ' endif config_host_data.set(k, v) elif k == 'ARCH' config_host_data.set('HOST_' + v.to_upper(), 1) elif strings.contains(k) if not k.startswith('CONFIG_') k = 'CONFIG_' + k.to_upper() endif config_host_data.set_quoted(k, v) elif k.startswith('CONFIG_') or k.startswith('HAVE_') or k.startswith('HOST_') config_host_data.set(k, v == 'y' ? 1 : v) endif endforeach minikconf = find_program('scripts/minikconf.py') config_all = {} config_all_devices = {} config_all_disas = {} config_devices_mak_list = [] config_devices_h = {} config_target_h = {} config_target_mak = {} disassemblers = { 'alpha' : ['CONFIG_ALPHA_DIS'], 'arm' : ['CONFIG_ARM_DIS'], 'avr' : ['CONFIG_AVR_DIS'], 'cris' : ['CONFIG_CRIS_DIS'], 'hppa' : ['CONFIG_HPPA_DIS'], 'i386' : ['CONFIG_I386_DIS'], 'x86_64' : ['CONFIG_I386_DIS'], 'x32' : ['CONFIG_I386_DIS'], 'lm32' : ['CONFIG_LM32_DIS'], 'm68k' : ['CONFIG_M68K_DIS'], 'microblaze' : ['CONFIG_MICROBLAZE_DIS'], 'mips' : ['CONFIG_MIPS_DIS'], 'moxie' : ['CONFIG_MOXIE_DIS'], 'nios2' : ['CONFIG_NIOS2_DIS'], 'or1k' : ['CONFIG_OPENRISC_DIS'], 'ppc' : ['CONFIG_PPC_DIS'], 'riscv' : ['CONFIG_RISCV_DIS'], 'rx' : ['CONFIG_RX_DIS'], 's390' : ['CONFIG_S390_DIS'], 'sh4' : ['CONFIG_SH4_DIS'], 'sparc' : ['CONFIG_SPARC_DIS'], 'xtensa' : ['CONFIG_XTENSA_DIS'], } if link_language == 'cpp' disassemblers += { 'aarch64' : [ 'CONFIG_ARM_A64_DIS'], 'arm' : [ 'CONFIG_ARM_DIS', 'CONFIG_ARM_A64_DIS'], 'mips' : [ 'CONFIG_MIPS_DIS', 'CONFIG_NANOMIPS_DIS'], } endif kconfig_external_symbols = [ 'CONFIG_KVM', 'CONFIG_XEN', 'CONFIG_TPM', 'CONFIG_SPICE', 'CONFIG_IVSHMEM', 'CONFIG_OPENGL', 'CONFIG_X11', 'CONFIG_VHOST_USER', 'CONFIG_VHOST_VDPA', 'CONFIG_VHOST_KERNEL', 'CONFIG_VIRTFS', 'CONFIG_LINUX', 'CONFIG_PVRDMA', ] ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ] default_targets = 'CONFIG_DEFAULT_TARGETS' in config_host actual_target_dirs = [] fdt_required = [] foreach target : target_dirs config_target = { 'TARGET_NAME': target.split('-')[0] } if target.endswith('linux-user') if targetos != 'linux' if default_targets continue endif error('Target @0@ is only available on a Linux host'.format(target)) endif config_target += { 'CONFIG_LINUX_USER': 'y' } elif target.endswith('bsd-user') if 'CONFIG_BSD' not in config_host if default_targets continue endif error('Target @0@ is only available on a BSD host'.format(target)) endif config_target += { 'CONFIG_BSD_USER': 'y' } elif target.endswith('softmmu') config_target += { 'CONFIG_SOFTMMU': 'y' } endif if target.endswith('-user') config_target += { 'CONFIG_USER_ONLY': 'y', 'CONFIG_QEMU_INTERP_PREFIX': config_host['CONFIG_QEMU_INTERP_PREFIX'].format(config_target['TARGET_NAME']) } endif have_accel = false foreach sym: accelerators if sym == 'CONFIG_TCG' or target in accelerator_targets.get(sym, []) config_target += { sym: 'y' } config_all += { sym: 'y' } if sym == 'CONFIG_XEN' and have_xen_pci_passthrough config_target += { 'CONFIG_XEN_PCI_PASSTHROUGH': 'y' } endif have_accel = true endif endforeach if not have_accel if default_targets continue endif error('No accelerator available for target @0@'.format(target)) endif actual_target_dirs += target config_target += keyval.load('default-configs/targets' / target + '.mak') config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' } if 'TARGET_NEED_FDT' in config_target fdt_required += target endif # Add default keys if 'TARGET_BASE_ARCH' not in config_target config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']} endif if 'TARGET_ABI_DIR' not in config_target config_target += {'TARGET_ABI_DIR': config_target['TARGET_ARCH']} endif foreach k, v: disassemblers if config_host['ARCH'].startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k) foreach sym: v config_target += { sym: 'y' } config_all_disas += { sym: 'y' } endforeach endif endforeach config_target_data = configuration_data() foreach k, v: config_target if not k.startswith('TARGET_') and not k.startswith('CONFIG_') # do nothing elif ignored.contains(k) # do nothing elif k == 'TARGET_BASE_ARCH' # Note that TARGET_BASE_ARCH ends up in config-target.h but it is # not used to select files from sourcesets. config_target_data.set('TARGET_' + v.to_upper(), 1) elif k == 'TARGET_NAME' or k == 'CONFIG_QEMU_INTERP_PREFIX' config_target_data.set_quoted(k, v) elif v == 'y' config_target_data.set(k, 1) else config_target_data.set(k, v) endif endforeach config_target_h += {target: configure_file(output: target + '-config-target.h', configuration: config_target_data)} if target.endswith('-softmmu') base_kconfig = [] foreach sym : kconfig_external_symbols if sym in config_target or sym in config_host base_kconfig += '@0@=y'.format(sym) endif endforeach config_devices_mak = target + '-config-devices.mak' config_devices_mak = configure_file( input: ['default-configs/devices' / target + '.mak', 'Kconfig'], output: config_devices_mak, depfile: config_devices_mak + '.d', capture: true, command: [minikconf, config_host['CONFIG_MINIKCONF_MODE'], config_devices_mak, '@DEPFILE@', '@INPUT@', base_kconfig]) config_devices_data = configuration_data() config_devices = keyval.load(config_devices_mak) foreach k, v: config_devices config_devices_data.set(k, 1) endforeach config_devices_mak_list += config_devices_mak config_devices_h += {target: configure_file(output: target + '-config-devices.h', configuration: config_devices_data)} config_target += config_devices config_all_devices += config_devices endif config_target_mak += {target: config_target} endforeach target_dirs = actual_target_dirs # This configuration is used to build files that are shared by # multiple binaries, and then extracted out of the "common" # static_library target. # # We do not use all_sources()/all_dependencies(), because it would # build literally all source files, including devices only used by # targets that are not built for this compilation. The CONFIG_ALL # pseudo symbol replaces it. config_all += config_all_devices config_all += config_host config_all += config_all_disas config_all += { 'CONFIG_XEN': config_host.has_key('CONFIG_XEN_BACKEND'), 'CONFIG_SOFTMMU': have_system, 'CONFIG_USER_ONLY': have_user, 'CONFIG_ALL': true, } # Submodules capstone = not_found capstone_opt = get_option('capstone') if capstone_opt in ['enabled', 'auto', 'system'] have_internal = fs.exists(meson.current_source_dir() / 'capstone/Makefile') capstone = dependency('capstone', version: '>=4.0', static: enable_static, method: 'pkg-config', required: capstone_opt == 'system' or capstone_opt == 'enabled' and not have_internal) if capstone.found() capstone_opt = 'system' elif have_internal capstone_opt = 'internal' else capstone_opt = 'disabled' endif endif if capstone_opt == 'internal' capstone_data = configuration_data() capstone_data.set('CAPSTONE_USE_SYS_DYN_MEM', '1') capstone_files = files( 'capstone/cs.c', 'capstone/MCInst.c', 'capstone/MCInstrDesc.c', 'capstone/MCRegisterInfo.c', 'capstone/SStream.c', 'capstone/utils.c' ) if 'CONFIG_ARM_DIS' in config_all_disas capstone_data.set('CAPSTONE_HAS_ARM', '1') capstone_files += files( 'capstone/arch/ARM/ARMDisassembler.c', 'capstone/arch/ARM/ARMInstPrinter.c', 'capstone/arch/ARM/ARMMapping.c', 'capstone/arch/ARM/ARMModule.c' ) endif # FIXME: This config entry currently depends on a c++ compiler. # Which is needed for building libvixl, but not for capstone. if 'CONFIG_ARM_A64_DIS' in config_all_disas capstone_data.set('CAPSTONE_HAS_ARM64', '1') capstone_files += files( 'capstone/arch/AArch64/AArch64BaseInfo.c', 'capstone/arch/AArch64/AArch64Disassembler.c', 'capstone/arch/AArch64/AArch64InstPrinter.c', 'capstone/arch/AArch64/AArch64Mapping.c', 'capstone/arch/AArch64/AArch64Module.c' ) endif if 'CONFIG_PPC_DIS' in config_all_disas capstone_data.set('CAPSTONE_HAS_POWERPC', '1') capstone_files += files( 'capstone/arch/PowerPC/PPCDisassembler.c', 'capstone/arch/PowerPC/PPCInstPrinter.c', 'capstone/arch/PowerPC/PPCMapping.c', 'capstone/arch/PowerPC/PPCModule.c' ) endif if 'CONFIG_S390_DIS' in config_all_disas capstone_data.set('CAPSTONE_HAS_SYSZ', '1') capstone_files += files( 'capstone/arch/SystemZ/SystemZDisassembler.c', 'capstone/arch/SystemZ/SystemZInstPrinter.c', 'capstone/arch/SystemZ/SystemZMapping.c', 'capstone/arch/SystemZ/SystemZModule.c', 'capstone/arch/SystemZ/SystemZMCTargetDesc.c' ) endif if 'CONFIG_I386_DIS' in config_all_disas capstone_data.set('CAPSTONE_HAS_X86', 1) capstone_files += files( 'capstone/arch/X86/X86Disassembler.c', 'capstone/arch/X86/X86DisassemblerDecoder.c', 'capstone/arch/X86/X86ATTInstPrinter.c', 'capstone/arch/X86/X86IntelInstPrinter.c', 'capstone/arch/X86/X86InstPrinterCommon.c', 'capstone/arch/X86/X86Mapping.c', 'capstone/arch/X86/X86Module.c' ) endif configure_file(output: 'capstone-defs.h', configuration: capstone_data) capstone_cargs = [ # FIXME: There does not seem to be a way to completely replace the c_args # that come from add_project_arguments() -- we can only add to them. # So: disable all warnings with a big hammer. '-Wno-error', '-w', # Include all configuration defines via a header file, which will wind up # as a dependency on the object file, and thus changes here will result # in a rebuild. '-include', 'capstone-defs.h' ] libcapstone = static_library('capstone', sources: capstone_files, c_args: capstone_cargs, include_directories: 'capstone/include') capstone = declare_dependency(link_with: libcapstone, include_directories: 'capstone/include/capstone') endif slirp = not_found slirp_opt = 'disabled' if have_system slirp_opt = get_option('slirp') if slirp_opt in ['enabled', 'auto', 'system'] have_internal = fs.exists(meson.current_source_dir() / 'slirp/meson.build') slirp = dependency('slirp', static: enable_static, method: 'pkg-config', required: slirp_opt == 'system' or slirp_opt == 'enabled' and not have_internal) if slirp.found() slirp_opt = 'system' elif have_internal slirp_opt = 'internal' else slirp_opt = 'disabled' endif endif if slirp_opt == 'internal' slirp_deps = [] if targetos == 'windows' slirp_deps = cc.find_library('iphlpapi') endif slirp_conf = configuration_data() slirp_conf.set('SLIRP_MAJOR_VERSION', meson.project_version().split('.')[0]) slirp_conf.set('SLIRP_MINOR_VERSION', meson.project_version().split('.')[1]) slirp_conf.set('SLIRP_MICRO_VERSION', meson.project_version().split('.')[2]) slirp_conf.set_quoted('SLIRP_VERSION_STRING', meson.project_version()) slirp_cargs = ['-DG_LOG_DOMAIN="Slirp"'] slirp_files = [ 'slirp/src/arp_table.c', 'slirp/src/bootp.c', 'slirp/src/cksum.c', 'slirp/src/dhcpv6.c', 'slirp/src/dnssearch.c', 'slirp/src/if.c', 'slirp/src/ip6_icmp.c', 'slirp/src/ip6_input.c', 'slirp/src/ip6_output.c', 'slirp/src/ip_icmp.c', 'slirp/src/ip_input.c', 'slirp/src/ip_output.c', 'slirp/src/mbuf.c', 'slirp/src/misc.c', 'slirp/src/ncsi.c', 'slirp/src/ndp_table.c', 'slirp/src/sbuf.c', 'slirp/src/slirp.c', 'slirp/src/socket.c', 'slirp/src/state.c', 'slirp/src/stream.c', 'slirp/src/tcp_input.c', 'slirp/src/tcp_output.c', 'slirp/src/tcp_subr.c', 'slirp/src/tcp_timer.c', 'slirp/src/tftp.c', 'slirp/src/udp.c', 'slirp/src/udp6.c', 'slirp/src/util.c', 'slirp/src/version.c', 'slirp/src/vmstate.c', ] configure_file( input : 'slirp/src/libslirp-version.h.in', output : 'libslirp-version.h', configuration: slirp_conf) slirp_inc = include_directories('slirp', 'slirp/src') libslirp = static_library('slirp', sources: slirp_files, c_args: slirp_cargs, include_directories: slirp_inc) slirp = declare_dependency(link_with: libslirp, dependencies: slirp_deps, include_directories: slirp_inc) endif endif fdt = not_found fdt_opt = get_option('fdt') if have_system if fdt_opt in ['enabled', 'auto', 'system'] have_internal = fs.exists(meson.current_source_dir() / 'dtc/libfdt/Makefile.libfdt') fdt = cc.find_library('fdt', static: enable_static, required: fdt_opt == 'system' or fdt_opt == 'enabled' and not have_internal) if fdt.found() and cc.links(''' #include #include int main(void) { fdt_check_full(NULL, 0); return 0; }''', dependencies: fdt) fdt_opt = 'system' elif have_internal fdt_opt = 'internal' else fdt_opt = 'disabled' endif endif if fdt_opt == 'internal' fdt_files = files( 'dtc/libfdt/fdt.c', 'dtc/libfdt/fdt_ro.c', 'dtc/libfdt/fdt_wip.c', 'dtc/libfdt/fdt_sw.c', 'dtc/libfdt/fdt_rw.c', 'dtc/libfdt/fdt_strerror.c', 'dtc/libfdt/fdt_empty_tree.c', 'dtc/libfdt/fdt_addresses.c', 'dtc/libfdt/fdt_overlay.c', 'dtc/libfdt/fdt_check.c', ) fdt_inc = include_directories('dtc/libfdt') libfdt = static_library('fdt', sources: fdt_files, include_directories: fdt_inc) fdt = declare_dependency(link_with: libfdt, include_directories: fdt_inc) endif endif if not fdt.found() and fdt_required.length() > 0 error('fdt not available but required by targets ' + ', '.join(fdt_required)) endif config_host_data.set('CONFIG_CAPSTONE', capstone.found()) config_host_data.set('CONFIG_FDT', fdt.found()) config_host_data.set('CONFIG_SLIRP', slirp.found()) genh += configure_file(output: 'config-host.h', configuration: config_host_data) # Generators hxtool = find_program('scripts/hxtool') shaderinclude = find_program('scripts/shaderinclude.pl') qapi_gen = find_program('scripts/qapi-gen.py') qapi_gen_depends = [ meson.source_root() / 'scripts/qapi/__init__.py', meson.source_root() / 'scripts/qapi/commands.py', meson.source_root() / 'scripts/qapi/common.py', meson.source_root() / 'scripts/qapi/error.py', meson.source_root() / 'scripts/qapi/events.py', meson.source_root() / 'scripts/qapi/expr.py', meson.source_root() / 'scripts/qapi/gen.py', meson.source_root() / 'scripts/qapi/introspect.py', meson.source_root() / 'scripts/qapi/parser.py', meson.source_root() / 'scripts/qapi/schema.py', meson.source_root() / 'scripts/qapi/source.py', meson.source_root() / 'scripts/qapi/types.py', meson.source_root() / 'scripts/qapi/visit.py', meson.source_root() / 'scripts/qapi/common.py', meson.source_root() / 'scripts/qapi-gen.py' ] tracetool = [ python, files('scripts/tracetool.py'), '--backend=' + config_host['TRACE_BACKENDS'] ] qemu_version_cmd = [find_program('scripts/qemu-version.sh'), meson.current_source_dir(), config_host['PKGVERSION'], meson.project_version()] qemu_version = custom_target('qemu-version.h', output: 'qemu-version.h', command: qemu_version_cmd, capture: true, build_by_default: true, build_always_stale: true) genh += qemu_version hxdep = [] hx_headers = [ ['qemu-options.hx', 'qemu-options.def'], ['qemu-img-cmds.hx', 'qemu-img-cmds.h'], ] if have_system hx_headers += [ ['hmp-commands.hx', 'hmp-commands.h'], ['hmp-commands-info.hx', 'hmp-commands-info.h'], ] endif foreach d : hx_headers hxdep += custom_target(d[1], input: files(d[0]), output: d[1], capture: true, build_by_default: true, # to be removed when added to a target command: [hxtool, '-h', '@INPUT0@']) endforeach genh += hxdep SPHINX_ARGS = [config_host['SPHINX_BUILD'], '-Dversion=' + meson.project_version(), '-Drelease=' + config_host['PKGVERSION']] if get_option('werror') SPHINX_ARGS += [ '-W' ] endif sphinx_extn_depends = [ meson.source_root() / 'docs/sphinx/depfile.py', meson.source_root() / 'docs/sphinx/hxtool.py', meson.source_root() / 'docs/sphinx/kerneldoc.py', meson.source_root() / 'docs/sphinx/kernellog.py', meson.source_root() / 'docs/sphinx/qapidoc.py', meson.source_root() / 'docs/sphinx/qmp_lexer.py', qapi_gen_depends ] # Collect sourcesets. util_ss = ss.source_set() stub_ss = ss.source_set() trace_ss = ss.source_set() block_ss = ss.source_set() blockdev_ss = ss.source_set() qmp_ss = ss.source_set() common_ss = ss.source_set() softmmu_ss = ss.source_set() user_ss = ss.source_set() bsd_user_ss = ss.source_set() linux_user_ss = ss.source_set() specific_ss = ss.source_set() specific_fuzz_ss = ss.source_set() modules = {} hw_arch = {} target_arch = {} target_softmmu_arch = {} ############### # Trace files # ############### # TODO: add each directory to the subdirs from its own meson.build, once # we have those trace_events_subdirs = [ 'accel/kvm', 'accel/tcg', 'crypto', 'monitor', ] if have_user trace_events_subdirs += [ 'linux-user' ] endif if have_block trace_events_subdirs += [ 'authz', 'block', 'io', 'nbd', 'scsi', ] endif if have_system trace_events_subdirs += [ 'audio', 'backends', 'backends/tpm', 'chardev', 'hw/9pfs', 'hw/acpi', 'hw/alpha', 'hw/arm', 'hw/audio', 'hw/block', 'hw/block/dataplane', 'hw/char', 'hw/display', 'hw/dma', 'hw/hppa', 'hw/hyperv', 'hw/i2c', 'hw/i386', 'hw/i386/xen', 'hw/ide', 'hw/input', 'hw/intc', 'hw/isa', 'hw/mem', 'hw/mips', 'hw/misc', 'hw/misc/macio', 'hw/net', 'hw/nvram', 'hw/pci', 'hw/pci-host', 'hw/ppc', 'hw/rdma', 'hw/rdma/vmw', 'hw/rtc', 'hw/s390x', 'hw/scsi', 'hw/sd', 'hw/sparc', 'hw/sparc64', 'hw/ssi', 'hw/timer', 'hw/tpm', 'hw/usb', 'hw/vfio', 'hw/virtio', 'hw/watchdog', 'hw/xen', 'hw/gpio', 'migration', 'net', 'softmmu', 'ui', ] endif trace_events_subdirs += [ 'hw/core', 'qapi', 'qom', 'target/arm', 'target/hppa', 'target/i386', 'target/mips', 'target/ppc', 'target/riscv', 'target/s390x', 'target/sparc', 'util', ] subdir('qapi') subdir('qobject') subdir('stubs') subdir('trace') subdir('util') subdir('qom') subdir('authz') subdir('crypto') subdir('ui') if enable_modules libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO') modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO') endif # Build targets from sourcesets stub_ss = stub_ss.apply(config_all, strict: false) util_ss.add_all(trace_ss) util_ss = util_ss.apply(config_all, strict: false) libqemuutil = static_library('qemuutil', sources: util_ss.sources() + stub_ss.sources() + genh, dependencies: [util_ss.dependencies(), m, glib, socket, malloc]) qemuutil = declare_dependency(link_with: libqemuutil, sources: genh + version_res) decodetree = generator(find_program('scripts/decodetree.py'), output: 'decode-@BASENAME@.c.inc', arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@']) subdir('audio') subdir('io') subdir('chardev') subdir('fsdev') subdir('libdecnumber') subdir('target') subdir('dump') block_ss.add(files( 'block.c', 'blockdev-nbd.c', 'blockjob.c', 'job.c', 'qemu-io-cmds.c', )) block_ss.add(when: 'CONFIG_REPLICATION', if_true: files('replication.c')) subdir('nbd') subdir('scsi') subdir('block') blockdev_ss.add(files( 'blockdev.c', 'iothread.c', 'job-qmp.c', )) # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon, # os-win32.c does not blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c')) softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')]) softmmu_ss.add_all(blockdev_ss) softmmu_ss.add(files( 'bootdevice.c', 'dma-helpers.c', 'qdev-monitor.c', ), sdl) softmmu_ss.add(when: 'CONFIG_TPM', if_true: files('tpm.c')) softmmu_ss.add(when: 'CONFIG_SECCOMP', if_true: [files('qemu-seccomp.c'), seccomp]) softmmu_ss.add(when: fdt, if_true: files('device_tree.c')) common_ss.add(files('cpus-common.c')) subdir('softmmu') common_ss.add(capstone) specific_ss.add(files('disas.c', 'exec.c', 'gdbstub.c'), capstone, libpmem, libdaxctl) specific_ss.add(files('exec-vary.c')) specific_ss.add(when: 'CONFIG_TCG', if_true: files( 'fpu/softfloat.c', 'tcg/optimize.c', 'tcg/tcg-common.c', 'tcg/tcg-op-gvec.c', 'tcg/tcg-op-vec.c', 'tcg/tcg-op.c', 'tcg/tcg.c', )) specific_ss.add(when: 'CONFIG_TCG_INTERPRETER', if_true: files('disas/tci.c', 'tcg/tci.c')) subdir('backends') subdir('disas') subdir('migration') subdir('monitor') subdir('net') subdir('replay') subdir('hw') subdir('accel') subdir('plugins') subdir('bsd-user') subdir('linux-user') bsd_user_ss.add(files('gdbstub.c')) specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss) linux_user_ss.add(files('gdbstub.c', 'thunk.c')) specific_ss.add_all(when: 'CONFIG_LINUX_USER', if_true: linux_user_ss) # needed for fuzzing binaries subdir('tests/qtest/libqos') subdir('tests/qtest/fuzz') block_mods = [] softmmu_mods = [] foreach d, list : modules foreach m, module_ss : list if enable_modules and targetos != 'windows' module_ss = module_ss.apply(config_all, strict: false) sl = static_library(d + '-' + m, [genh, module_ss.sources()], dependencies: [modulecommon, module_ss.dependencies()], pic: true) if d == 'block' block_mods += sl else softmmu_mods += sl endif else if d == 'block' block_ss.add_all(module_ss) else softmmu_ss.add_all(module_ss) endif endif endforeach endforeach nm = find_program('nm') undefsym = find_program('scripts/undefsym.py') block_syms = custom_target('block.syms', output: 'block.syms', input: [libqemuutil, block_mods], capture: true, command: [undefsym, nm, '@INPUT@']) qemu_syms = custom_target('qemu.syms', output: 'qemu.syms', input: [libqemuutil, softmmu_mods], capture: true, command: [undefsym, nm, '@INPUT@']) block_ss = block_ss.apply(config_host, strict: false) libblock = static_library('block', block_ss.sources() + genh, dependencies: block_ss.dependencies(), link_depends: block_syms, name_suffix: 'fa', build_by_default: false) block = declare_dependency(link_whole: [libblock], link_args: '@block.syms', dependencies: [crypto, io]) qmp_ss = qmp_ss.apply(config_host, strict: false) libqmp = static_library('qmp', qmp_ss.sources() + genh, dependencies: qmp_ss.dependencies(), name_suffix: 'fa', build_by_default: false) qmp = declare_dependency(link_whole: [libqmp]) foreach m : block_mods + softmmu_mods shared_module(m.name(), name_prefix: '', link_whole: m, install: true, install_dir: config_host['qemu_moddir']) endforeach softmmu_ss.add(authz, block, chardev, crypto, io, qmp) common_ss.add(qom, qemuutil) common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss]) common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss) common_all = common_ss.apply(config_all, strict: false) common_all = static_library('common', build_by_default: false, sources: common_all.sources() + genh, dependencies: common_all.dependencies(), name_suffix: 'fa') feature_to_c = find_program('scripts/feature_to_c.sh') emulators = {} foreach target : target_dirs config_target = config_target_mak[target] target_name = config_target['TARGET_NAME'] arch = config_target['TARGET_BASE_ARCH'] arch_srcs = [config_target_h[target]] arch_deps = [] c_args = ['-DNEED_CPU_H', '-DCONFIG_TARGET="@0@-config-target.h"'.format(target), '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)] link_args = emulator_link_args config_target += config_host target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])] if targetos == 'linux' target_inc += include_directories('linux-headers', is_system: true) endif if target.endswith('-softmmu') qemu_target_name = 'qemu-system-' + target_name target_type='system' t = target_softmmu_arch[arch].apply(config_target, strict: false) arch_srcs += t.sources() arch_deps += t.dependencies() hw_dir = target_name == 'sparc64' ? 'sparc64' : arch hw = hw_arch[hw_dir].apply(config_target, strict: false) arch_srcs += hw.sources() arch_deps += hw.dependencies() arch_srcs += config_devices_h[target] link_args += ['@block.syms', '@qemu.syms'] else abi = config_target['TARGET_ABI_DIR'] target_type='user' qemu_target_name = 'qemu-' + target_name if 'CONFIG_LINUX_USER' in config_target base_dir = 'linux-user' target_inc += include_directories('linux-user/host/' / config_host['ARCH']) else base_dir = 'bsd-user' endif target_inc += include_directories( base_dir, base_dir / abi, ) if 'CONFIG_LINUX_USER' in config_target dir = base_dir / abi arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c') if config_target.has_key('TARGET_SYSTBL_ABI') arch_srcs += \ syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'], extra_args : config_target['TARGET_SYSTBL_ABI']) endif endif endif if 'TARGET_XML_FILES' in config_target gdbstub_xml = custom_target(target + '-gdbstub-xml.c', output: target + '-gdbstub-xml.c', input: files(config_target['TARGET_XML_FILES'].split()), command: [feature_to_c, '@INPUT@'], capture: true) arch_srcs += gdbstub_xml endif t = target_arch[arch].apply(config_target, strict: false) arch_srcs += t.sources() arch_deps += t.dependencies() target_common = common_ss.apply(config_target, strict: false) objects = common_all.extract_objects(target_common.sources()) deps = target_common.dependencies() target_specific = specific_ss.apply(config_target, strict: false) arch_srcs += target_specific.sources() arch_deps += target_specific.dependencies() lib = static_library('qemu-' + target, sources: arch_srcs + genh, dependencies: arch_deps, objects: objects, include_directories: target_inc, c_args: c_args, build_by_default: false, name_suffix: 'fa') if target.endswith('-softmmu') execs = [{ 'name': 'qemu-system-' + target_name, 'gui': false, 'sources': files('softmmu/main.c'), 'dependencies': [] }] if targetos == 'windows' and (sdl.found() or gtk.found()) execs += [{ 'name': 'qemu-system-' + target_name + 'w', 'gui': true, 'sources': files('softmmu/main.c'), 'dependencies': [] }] endif if config_host.has_key('CONFIG_FUZZ') specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false) execs += [{ 'name': 'qemu-fuzz-' + target_name, 'gui': false, 'sources': specific_fuzz.sources(), 'dependencies': specific_fuzz.dependencies(), }] endif else execs = [{ 'name': 'qemu-' + target_name, 'gui': false, 'sources': [], 'dependencies': [] }] endif foreach exe: execs emulators += {exe['name']: executable(exe['name'], exe['sources'], install: true, c_args: c_args, dependencies: arch_deps + deps + exe['dependencies'], objects: lib.extract_all_objects(recursive: true), link_language: link_language, link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []), link_args: link_args, gui_app: exe['gui']) } if 'CONFIG_TRACE_SYSTEMTAP' in config_host foreach stp: [ {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false}, {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true}, {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true}, {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true}, ] custom_target(exe['name'] + stp['ext'], input: trace_events_all, output: exe['name'] + stp['ext'], capture: true, install: stp['install'], install_dir: qemu_datadir / '../systemtap/tapset', command: [ tracetool, '--group=all', '--format=' + stp['fmt'], '--binary=' + stp['bin'], '--target-name=' + target_name, '--target-type=' + target_type, '--probe-prefix=qemu.' + target_type + '.' + target_name, '@INPUT@', ]) endforeach endif endforeach endforeach # Other build targets if 'CONFIG_PLUGIN' in config_host install_headers('include/qemu/qemu-plugin.h') endif if 'CONFIG_GUEST_AGENT' in config_host subdir('qga') endif # Don't build qemu-keymap if xkbcommon is not explicitly enabled # when we don't build tools or system if xkbcommon.found() # used for the update-keymaps target, so include rules even if !have_tools qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh, dependencies: [qemuutil, xkbcommon], install: have_tools) endif if have_tools qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep], dependencies: [authz, block, crypto, io, qom, qemuutil], install: true) qemu_io = executable('qemu-io', files('qemu-io.c'), dependencies: [block, qemuutil], install: true) qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'), dependencies: [block, qemuutil], install: true) subdir('storage-daemon') subdir('contrib/rdmacm-mux') subdir('contrib/elf2dmp') executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'), dependencies: qemuutil, install: true) if 'CONFIG_VHOST_USER' in config_host subdir('contrib/libvhost-user') subdir('contrib/vhost-user-blk') subdir('contrib/vhost-user-gpu') subdir('contrib/vhost-user-input') subdir('contrib/vhost-user-scsi') endif if targetos == 'linux' executable('qemu-bridge-helper', files('qemu-bridge-helper.c'), dependencies: [qemuutil, libcap_ng], install: true, install_dir: get_option('libexecdir')) executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'), dependencies: [authz, crypto, io, qom, qemuutil, libcap_ng, mpathpersist], install: true) endif if 'CONFIG_IVSHMEM' in config_host subdir('contrib/ivshmem-client') subdir('contrib/ivshmem-server') endif endif subdir('scripts') subdir('tools') subdir('pc-bios') subdir('tests') subdir('docs') if 'CONFIG_GTK' in config_host subdir('po') endif if host_machine.system() == 'windows' nsis_cmd = [ find_program('scripts/nsis.py'), '@OUTPUT@', get_option('prefix'), meson.current_source_dir(), host_machine.cpu_family(), '--', '-DDISPLAYVERSION=' + meson.project_version(), ] if build_docs nsis_cmd += '-DCONFIG_DOCUMENTATION=y' endif if 'CONFIG_GTK' in config_host nsis_cmd += '-DCONFIG_GTK=y' endif nsis = custom_target('nsis', output: 'qemu-setup-' + meson.project_version() + '.exe', input: files('qemu.nsi'), build_always_stale: true, command: nsis_cmd + ['@INPUT@']) alias_target('installer', nsis) endif summary_info = {} summary_info += {'Install prefix': config_host['prefix']} summary_info += {'BIOS directory': config_host['qemu_datadir']} summary_info += {'firmware path': config_host['qemu_firmwarepath']} summary_info += {'binary directory': config_host['bindir']} summary_info += {'library directory': config_host['libdir']} summary_info += {'module directory': config_host['qemu_moddir']} summary_info += {'libexec directory': config_host['libexecdir']} summary_info += {'include directory': config_host['includedir']} summary_info += {'config directory': config_host['sysconfdir']} if targetos != 'windows' summary_info += {'local state directory': config_host['qemu_localstatedir']} summary_info += {'Manual directory': get_option('mandir')} else summary_info += {'local state directory': 'queried at runtime'} endif summary_info += {'Doc directory': get_option('docdir')} summary_info += {'Build directory': meson.current_build_dir()} summary_info += {'Source path': meson.current_source_dir()} summary_info += {'GIT binary': config_host['GIT']} summary_info += {'GIT submodules': config_host['GIT_SUBMODULES']} summary_info += {'C compiler': meson.get_compiler('c').cmd_array()[0]} summary_info += {'Host C compiler': meson.get_compiler('c', native: true).cmd_array()[0]} if link_language == 'cpp' summary_info += {'C++ compiler': meson.get_compiler('cpp').cmd_array()[0]} else summary_info += {'C++ compiler': false} endif if targetos == 'darwin' summary_info += {'Objective-C compiler': meson.get_compiler('objc').cmd_array()[0]} endif summary_info += {'ARFLAGS': config_host['ARFLAGS']} summary_info += {'CFLAGS': config_host['CFLAGS']} summary_info += {'QEMU_CFLAGS': config_host['QEMU_CFLAGS']} summary_info += {'QEMU_LDFLAGS': config_host['QEMU_LDFLAGS']} summary_info += {'make': config_host['MAKE']} summary_info += {'python': '@0@ (version: @1@)'.format(python.full_path(), python.language_version())} summary_info += {'sphinx-build': config_host['SPHINX_BUILD']} summary_info += {'genisoimage': config_host['GENISOIMAGE']} # TODO: add back version summary_info += {'slirp support': slirp_opt == 'disabled' ? false : slirp_opt} if slirp_opt != 'disabled' summary_info += {'smbd': config_host['CONFIG_SMBD_COMMAND']} endif summary_info += {'module support': config_host.has_key('CONFIG_MODULES')} if config_host.has_key('CONFIG_MODULES') summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')} endif summary_info += {'host CPU': cpu} summary_info += {'host endianness': build_machine.endian()} summary_info += {'target list': ' '.join(target_dirs)} summary_info += {'gprof enabled': config_host.has_key('CONFIG_GPROF')} summary_info += {'sparse enabled': sparse.found()} summary_info += {'strip binaries': get_option('strip')} summary_info += {'profiler': config_host.has_key('CONFIG_PROFILER')} summary_info += {'static build': config_host.has_key('CONFIG_STATIC')} if targetos == 'darwin' summary_info += {'Cocoa support': config_host.has_key('CONFIG_COCOA')} endif # TODO: add back version summary_info += {'SDL support': sdl.found()} summary_info += {'SDL image support': sdl_image.found()} # TODO: add back version summary_info += {'GTK support': config_host.has_key('CONFIG_GTK')} summary_info += {'GTK GL support': config_host.has_key('CONFIG_GTK_GL')} summary_info += {'pixman': pixman.found()} # TODO: add back version summary_info += {'VTE support': config_host.has_key('CONFIG_VTE')} summary_info += {'TLS priority': config_host['CONFIG_TLS_PRIORITY']} summary_info += {'GNUTLS support': config_host.has_key('CONFIG_GNUTLS')} # TODO: add back version summary_info += {'libgcrypt': config_host.has_key('CONFIG_GCRYPT')} if config_host.has_key('CONFIG_GCRYPT') summary_info += {' hmac': config_host.has_key('CONFIG_GCRYPT_HMAC')} summary_info += {' XTS': not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')} endif # TODO: add back version summary_info += {'nettle': config_host.has_key('CONFIG_NETTLE')} if config_host.has_key('CONFIG_NETTLE') summary_info += {' XTS': not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')} endif summary_info += {'libtasn1': config_host.has_key('CONFIG_TASN1')} summary_info += {'PAM': config_host.has_key('CONFIG_AUTH_PAM')} summary_info += {'iconv support': config_host.has_key('CONFIG_ICONV')} summary_info += {'curses support': config_host.has_key('CONFIG_CURSES')} # TODO: add back version summary_info += {'virgl support': config_host.has_key('CONFIG_VIRGL')} summary_info += {'curl support': config_host.has_key('CONFIG_CURL')} summary_info += {'mingw32 support': targetos == 'windows'} summary_info += {'Audio drivers': config_host['CONFIG_AUDIO_DRIVERS']} summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']} summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']} summary_info += {'VirtFS support': config_host.has_key('CONFIG_VIRTFS')} summary_info += {'Multipath support': mpathpersist.found()} summary_info += {'VNC support': vnc.found()} if vnc.found() summary_info += {'VNC SASL support': sasl.found()} summary_info += {'VNC JPEG support': jpeg.found()} summary_info += {'VNC PNG support': png.found()} endif summary_info += {'xen support': config_host.has_key('CONFIG_XEN_BACKEND')} if config_host.has_key('CONFIG_XEN_BACKEND') summary_info += {'xen ctrl version': config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']} endif summary_info += {'brlapi support': config_host.has_key('CONFIG_BRLAPI')} summary_info += {'Documentation': config_host.has_key('BUILD_DOCS')} summary_info += {'PIE': get_option('b_pie')} summary_info += {'vde support': config_host.has_key('CONFIG_VDE')} summary_info += {'netmap support': config_host.has_key('CONFIG_NETMAP')} summary_info += {'Linux AIO support': config_host.has_key('CONFIG_LINUX_AIO')} summary_info += {'Linux io_uring support': config_host.has_key('CONFIG_LINUX_IO_URING')} summary_info += {'ATTR/XATTR support': config_host.has_key('CONFIG_ATTR')} summary_info += {'Install blobs': config_host.has_key('INSTALL_BLOBS')} summary_info += {'KVM support': config_all.has_key('CONFIG_KVM')} summary_info += {'HAX support': config_all.has_key('CONFIG_HAX')} summary_info += {'HVF support': config_all.has_key('CONFIG_HVF')} summary_info += {'WHPX support': config_all.has_key('CONFIG_WHPX')} summary_info += {'TCG support': config_all.has_key('CONFIG_TCG')} if config_all.has_key('CONFIG_TCG') summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')} summary_info += {'TCG interpreter': config_host.has_key('CONFIG_TCG_INTERPRETER')} endif summary_info += {'malloc trim support': has_malloc_trim} summary_info += {'RDMA support': config_host.has_key('CONFIG_RDMA')} summary_info += {'PVRDMA support': config_host.has_key('CONFIG_PVRDMA')} summary_info += {'fdt support': fdt_opt == 'disabled' ? false : fdt_opt} summary_info += {'membarrier': config_host.has_key('CONFIG_MEMBARRIER')} summary_info += {'preadv support': config_host.has_key('CONFIG_PREADV')} summary_info += {'fdatasync': config_host.has_key('CONFIG_FDATASYNC')} summary_info += {'madvise': config_host.has_key('CONFIG_MADVISE')} summary_info += {'posix_madvise': config_host.has_key('CONFIG_POSIX_MADVISE')} summary_info += {'posix_memalign': config_host.has_key('CONFIG_POSIX_MEMALIGN')} summary_info += {'libcap-ng support': config_host.has_key('CONFIG_LIBCAP_NG')} summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')} summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')} summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')} summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')} summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_KERNEL')} summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')} summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')} summary_info += {'Trace backends': config_host['TRACE_BACKENDS']} if config_host['TRACE_BACKENDS'].split().contains('simple') summary_info += {'Trace output file': config_host['CONFIG_TRACE_FILE'] + '-'} endif # TODO: add back protocol and server version summary_info += {'spice support': config_host.has_key('CONFIG_SPICE')} summary_info += {'rbd support': config_host.has_key('CONFIG_RBD')} summary_info += {'xfsctl support': config_host.has_key('CONFIG_XFS')} summary_info += {'smartcard support': config_host.has_key('CONFIG_SMARTCARD')} summary_info += {'U2F support': u2f.found()} summary_info += {'libusb': config_host.has_key('CONFIG_USB_LIBUSB')} summary_info += {'usb net redir': config_host.has_key('CONFIG_USB_REDIR')} summary_info += {'OpenGL support': config_host.has_key('CONFIG_OPENGL')} summary_info += {'OpenGL dmabufs': config_host.has_key('CONFIG_OPENGL_DMABUF')} summary_info += {'libiscsi support': config_host.has_key('CONFIG_LIBISCSI')} summary_info += {'libnfs support': config_host.has_key('CONFIG_LIBNFS')} summary_info += {'build guest agent': config_host.has_key('CONFIG_GUEST_AGENT')} if targetos == 'windows' if 'WIN_SDK' in config_host summary_info += {'Windows SDK': config_host['WIN_SDK']} endif summary_info += {'QGA VSS support': config_host.has_key('CONFIG_QGA_VSS')} summary_info += {'QGA w32 disk info': config_host.has_key('CONFIG_QGA_NTDDSCSI')} summary_info += {'QGA MSI support': config_host.has_key('CONFIG_QGA_MSI')} endif summary_info += {'seccomp support': config_host.has_key('CONFIG_SECCOMP')} summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']} summary_info += {'coroutine pool': config_host['CONFIG_COROUTINE_POOL'] == '1'} summary_info += {'debug stack usage': config_host.has_key('CONFIG_DEBUG_STACK_USAGE')} summary_info += {'mutex debugging': config_host.has_key('CONFIG_DEBUG_MUTEX')} summary_info += {'crypto afalg': config_host.has_key('CONFIG_AF_ALG')} summary_info += {'GlusterFS support': config_host.has_key('CONFIG_GLUSTERFS')} summary_info += {'gcov': get_option('b_coverage')} summary_info += {'TPM support': config_host.has_key('CONFIG_TPM')} summary_info += {'libssh support': config_host.has_key('CONFIG_LIBSSH')} summary_info += {'QOM debugging': config_host.has_key('CONFIG_QOM_CAST_DEBUG')} summary_info += {'Live block migration': config_host.has_key('CONFIG_LIVE_BLOCK_MIGRATION')} summary_info += {'lzo support': config_host.has_key('CONFIG_LZO')} summary_info += {'snappy support': config_host.has_key('CONFIG_SNAPPY')} summary_info += {'bzip2 support': config_host.has_key('CONFIG_BZIP2')} summary_info += {'lzfse support': config_host.has_key('CONFIG_LZFSE')} summary_info += {'zstd support': config_host.has_key('CONFIG_ZSTD')} summary_info += {'NUMA host support': config_host.has_key('CONFIG_NUMA')} summary_info += {'libxml2': config_host.has_key('CONFIG_LIBXML2')} summary_info += {'memory allocator': get_option('malloc')} summary_info += {'avx2 optimization': config_host.has_key('CONFIG_AVX2_OPT')} summary_info += {'avx512f optimization': config_host.has_key('CONFIG_AVX512F_OPT')} summary_info += {'replication support': config_host.has_key('CONFIG_REPLICATION')} summary_info += {'bochs support': config_host.has_key('CONFIG_BOCHS')} summary_info += {'cloop support': config_host.has_key('CONFIG_CLOOP')} summary_info += {'dmg support': config_host.has_key('CONFIG_DMG')} summary_info += {'qcow v1 support': config_host.has_key('CONFIG_QCOW1')} summary_info += {'vdi support': config_host.has_key('CONFIG_VDI')} summary_info += {'vvfat support': config_host.has_key('CONFIG_VVFAT')} summary_info += {'qed support': config_host.has_key('CONFIG_QED')} summary_info += {'parallels support': config_host.has_key('CONFIG_PARALLELS')} summary_info += {'sheepdog support': config_host.has_key('CONFIG_SHEEPDOG')} summary_info += {'capstone': capstone_opt == 'disabled' ? false : capstone_opt} summary_info += {'libpmem support': config_host.has_key('CONFIG_LIBPMEM')} summary_info += {'libdaxctl support': config_host.has_key('CONFIG_LIBDAXCTL')} summary_info += {'libudev': libudev.found()} summary_info += {'default devices': config_host['CONFIG_MINIKCONF_MODE'] == '--defconfig'} summary_info += {'plugin support': config_host.has_key('CONFIG_PLUGIN')} summary_info += {'fuzzing support': config_host.has_key('CONFIG_FUZZ')} if config_host.has_key('HAVE_GDB_BIN') summary_info += {'gdb': config_host['HAVE_GDB_BIN']} endif summary_info += {'thread sanitizer': config_host.has_key('CONFIG_TSAN')} summary_info += {'rng-none': config_host.has_key('CONFIG_RNG_NONE')} summary_info += {'Linux keyring': config_host.has_key('CONFIG_SECRET_KEYRING')} summary(summary_info, bool_yn: true) if not supported_cpus.contains(cpu) message() warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!') message() message('CPU host architecture ' + cpu + ' support is not currently maintained.') message('The QEMU project intends to remove support for this host CPU in') message('a future release if nobody volunteers to maintain it and to') message('provide a build host for our continuous integration setup.') message('configure has succeeded and you can continue to build, but') message('if you care about QEMU on this platform you should contact') message('us upstream at qemu-devel@nongnu.org.') endif if not supported_oses.contains(targetos) message() warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!') message() message('Host OS ' + targetos + 'support is not currently maintained.') message('The QEMU project intends to remove support for this host OS in') message('a future release if nobody volunteers to maintain it and to') message('provide a build host for our continuous integration setup.') message('configure has succeeded and you can continue to build, but') message('if you care about QEMU on this platform you should contact') message('us upstream at qemu-devel@nongnu.org.') endif