dosbox-staging/meson.build

1101 lines
31 KiB
Meson

project(
'dosbox-staging',
'c',
'cpp',
version: '0.81.0-alpha',
license: 'GPL-2.0-or-later',
meson_version: '>= 0.59.0',
default_options: [
'cpp_std=c++17',
'buildtype=release',
'b_ndebug=if-release',
'b_staticpic=false',
'b_pie=false',
'warning_level=3',
'glib:b_staticpic=true',
'glib:glib_assert=false',
'glib:glib_checks=false',
'glib:glib_debug=disabled',
'glib:libmount=disabled',
'glib:libelf=disabled',
'glib:nls=disabled',
'glib:tests=false',
'glib:warning_level=0',
'glib:xattr=false',
'gtest:warning_level=0',
'libjpeg-turbo:b_staticpic=true',
'libpng:b_staticpic=true',
'zlib-ng:c_std=c11',
],
)
# Gather internal resource dependencies
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# These are always present regardless of host, compiler, dependencies, or options.
#
data_dir = get_option('datadir')
licenses_dir = data_dir / 'licenses' / meson.project_name()
doc_dir = data_dir / 'doc' / meson.project_name()
install_man('docs/dosbox.1')
# Bundle licenses, but skip the ones that are not relevant for
# binary distribution or allow us to not distribute the license text.
install_data(
'LICENSE',
'licenses/BSD-2-Clause.txt',
'licenses/BSD-3-Clause.txt',
'licenses/GPL-2.0.txt',
'licenses/LGPL-2.1.txt',
'licenses/MIT.txt',
'licenses/Zlib.txt',
install_dir: licenses_dir,
)
install_data('AUTHORS', 'README', 'THANKS', install_dir: doc_dir)
subdir('contrib/linux')
subdir('contrib/icons')
subdir('contrib/resources')
# Gather OS family type
# ~~~~~~~~~~~~~~~~~~~~~
#
os_family_name = {
'linux': 'LINUX',
'windows': 'WIN32',
'cygwin': 'WIN32',
'darwin': 'MACOSX',
'freebsd': 'BSD',
'netbsd': 'BSD',
'openbsd': 'BSD',
'dragonfly': 'BSD',
}.get(host_machine.system(), 'UNKNOWN_OS')
# Gather compiler settings
# ~~~~~~~~~~~~~~~~~~~~~~~~
#
cc = meson.get_compiler('c')
cxx = meson.get_compiler('cpp')
prefers_static_libs = (get_option('default_library') == 'static')
summary('Build type', get_option('buildtype'), section: 'Build Summary')
summary('Install prefix', get_option('prefix'), section: 'Build Summary')
# extra build flags
extra_flags = [
'-Wno-unknown-pragmas',
'-fpch-preprocess',
]
warnings = []
# Enable additional warnings
foreach flag : [
'-Walloca',
'-Wctor-dtor-privacy',
'-Wdate-time',
'-Wdisabled-optimization',
'-Wduplicated-branches',
'-Weffc++',
'-Wextra-semi',
'-Wfloat-conversion',
'-Wlogical-op',
'-Wlogical-not-parentheses',
'-Wredundant-decls',
'-Wmismatched-tags',
'-Wsizeof-pointer-div',
'-Wstack-protector',
'-Wstrict-null-sentinel',
'-Wsuggest-override',
'-Wzero-as-null-pointer-constant',
]
if cxx.has_argument(flag)
warnings += flag
endif
endforeach
# Ignore some warnings enabled by default
foreach flag : ['-Wno-format-security']
if cxx.has_argument(flag)
warnings += flag
endif
endforeach
# generate linker map file
extra_link_flags = [
'-Wl,-map,dosbox.map',
'-Wl,-Map,dosbox.map',
'-Wl,--Map,dosbox.map',
]
# If the compiler provides std::filesystem, then we consider it modern enough
# that we can trust it's extra helpful warnings to let us improve the code quality.
if cxx.has_header('filesystem')
extra_flags += ['-Wmaybe-uninitialized', '-Weffc++', '-Wextra-semi']
else
# Otherwise, it's an old compiler and we're just trying to build, and don't
# care about fixing their warnings (some generate warnings from their own STL).
warning(
'Compiler lacks the C++17 std::filesystem - try to upgrade your compiler!',
)
endif
is_optimized_buildtype = (
get_option('buildtype') in ['release', 'minsize', 'debugoptimized']
)
if is_optimized_buildtype
# For optimized build types, we're not anticipating
# needing debuggable floating point signals.
# These safety measures are still enabled in debug builds,
# so if an issue is reported where these happen help, then
# testing with debug builds will make use of them.
#
extra_flags += [
'-fstrict-aliasing',
'-Wstrict-aliasing',
'-fmerge-all-constants',
'-fno-math-errno',
'-fno-signed-zeros',
'-fno-trapping-math',
'-fassociative-math',
'-freciprocal-math',
'-ffinite-math-only',
'-frename-registers',
'-ffunction-sections',
'-fdata-sections',
]
extra_link_flags += ['-Wl,--gc-sections']
endif
# Let sanitizer builds recover and continue
if get_option('b_sanitize') != 'none'
extra_flags += ['-fsanitize-recover=all']
endif
# Add Debug-specific flags here
if get_option('buildtype').startswith('debug')
# Use GCC's and Clang's maximum check flags except
# for macOS and Windows, where Xcode and MSYS2 both
# fails with undefined symbols.
if os_family_name not in ['MACOSX', 'WIN32']
extra_flags += [
'--enable-concept-checks',
'-D_GLIBCXX_ASSERTIONS=1',
'-D_GLIBCXX_DEBUG=1',
'-D_GLIBCXX_DEBUG_PEDANTIC=1',
'-D_GLIBCXX_SANITIZE_VECTOR=1',
'-D_LIBCPP_DEBUG=1',
]
endif
endif
if get_option('asm')
extra_flags += ['--save-temps', '/FAs']
endif
if get_option('time_trace')
extra_flags += ['-ftime-trace']
endif
# Don't flood us with hundreds of suggestions to use Microsoft-specific calls
if host_machine.system() == 'windows'
extra_flags += '-Wno-pedantic-ms-format'
endif
# Don't flood us with hundreds of suggestions to use snprintf on Apple + Clang
if host_machine.system() == 'darwin' and cxx.get_id() == 'clang'
extra_flags += '-Wno-deprecated-declarations'
endif
if prefers_static_libs
extra_flags += ['-static-libstdc++', '-static-libgcc']
if host_machine.system() != 'darwin'
extra_link_flags += ['-no-pie']
endif
else
extra_flags += [
'-shared-libstdc++',
'-shared-libgcc',
'-lstdc++_s',
'-fPIC',
]
endif
if get_option('narrowing_warnings')
extra_flags += ['-Wconversion', '-Wnarrowing']
endif
if get_option('autovec_info')
# At least O2 is needed enable auto-vectorizion
extra_flags += [
'-march=native',
'-O2',
'-Wno-system-headers',
'-Rpass-analysis=loop-vectorize',
'-fopt-info-vec-missed',
'-fopt-info-vec',
]
endif
# Tag BSD executables with the WX-needed bit
if os_family_name == 'BSD'
extra_link_flags += ['-Wl,-z,wxneeded']
endif
# Allow-list the flags against the compiler, and add them to the project
foreach flag : extra_flags
if cc.has_argument(flag)
add_project_arguments(flag, language: 'c')
endif
if cxx.has_argument(flag)
add_project_arguments(flag, language: 'cpp')
endif
endforeach
foreach flag : extra_link_flags
if cxx.has_link_argument(flag)
add_project_link_arguments(flag, language: 'cpp')
endif
endforeach
# Gather data to populate config.h
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# The actual config.h file will be generated after interpreting
# all the build files in all the subdirs.
#
conf_data = configuration_data()
conf_data.set('version', meson.project_version())
conf_data.set('project_name', meson.project_name())
conf_data.set_quoted(
'CUSTOM_DATADIR',
get_option('prefix') / get_option('datadir'),
)
conf_data.set10(os_family_name, true)
conf_data.set10('C_MODEM', get_option('use_sdl2_net'))
conf_data.set10('C_IPX', get_option('use_sdl2_net'))
conf_data.set10('C_SLIRP', get_option('use_slirp'))
conf_data.set10('C_NE2000', get_option('use_slirp'))
conf_data.set10('C_FLUIDSYNTH', get_option('use_fluidsynth'))
conf_data.set10('C_MT32EMU', get_option('use_mt32emu'))
conf_data.set10('C_TRACY', get_option('tracy'))
conf_data.set10('C_FPU', true)
conf_data.set10('C_FPU_X86', host_machine.cpu_family() in ['x86', 'x86_64'])
if get_option('enable_debugger') != 'none'
conf_data.set10('C_DEBUG', true)
endif
if get_option('enable_debugger') == 'heavy'
conf_data.set10('C_HEAVY_DEBUG', true)
endif
foreach osdef : ['LINUX', 'WIN32', 'MACOSX', 'BSD']
if conf_data.has(osdef)
conf_data.set10('C_DIRECTSERIAL', true)
endif
endforeach
if cc.has_function('clock_gettime', prefix: '#include <time.h>')
conf_data.set10('HAVE_CLOCK_GETTIME', true)
endif
if cc.has_function('__builtin_available')
conf_data.set10('HAVE_BUILTIN_AVAILABLE', true)
endif
if cc.has_function('__builtin___clear_cache')
conf_data.set10('HAVE_BUILTIN_CLEAR_CACHE', true)
endif
if cc.has_function('mprotect', prefix: '#include <sys/mman.h>')
conf_data.set10('HAVE_MPROTECT', true)
endif
if cc.has_function('mmap', prefix: '#include <sys/mman.h>')
conf_data.set10('HAVE_MMAP', true)
endif
if cc.has_header_symbol('sys/mman.h', 'MAP_JIT')
conf_data.set10('HAVE_MAP_JIT', true)
endif
if cc.has_function(
'pthread_jit_write_protect_np',
prefix: '#include <pthread.h>',
)
conf_data.set10('HAVE_PTHREAD_WRITE_PROTECT_NP', true)
endif
if cc.has_function(
'sys_icache_invalidate',
prefix: '#include <libkern/OSCacheControl.h>',
)
conf_data.set10('HAVE_SYS_ICACHE_INVALIDATE', true)
endif
if cxx.has_function(
'pthread_setname_np',
prefix: '#include <pthread.h>',
dependencies: dependency('threads'),
)
conf_data.set10('HAVE_PTHREAD_SETNAME_NP', true)
endif
if cc.has_function('realpath', prefix: '#include <stdlib.h>')
conf_data.set10('HAVE_REALPATH', true)
endif
# strnlen was originally a Linux-only function
if cc.has_function('strnlen', prefix: '#include <string.h>')
conf_data.set10('HAVE_STRNLEN', true)
endif
if cc.has_member('struct dirent', 'd_type', prefix: '#include <dirent.h>')
conf_data.set10('HAVE_STRUCT_DIRENT_D_TYPE', true)
endif
foreach header : ['libgen.h', 'pwd.h', 'strings.h', 'sys/xattr.h', 'netinet/in.h']
if cc.has_header(header)
conf_data.set10('HAVE_' + header.underscorify().to_upper(), true)
endif
endforeach
# Check for the actual calls we need in socket.h, because some systems
# have socket.h but are missing some calls.
if cc.has_header('sys/socket.h')
if (
cc.has_function('getpeername', prefix: '#include <sys/socket.h>')
and cc.has_function('getsockname', prefix: '#include <sys/socket.h>')
)
conf_data.set10('HAVE_SYS_SOCKET_H', true)
endif
endif
# Header windows.h defines old min/max macros, that conflict with C++11
# std::min/std::max. Defining NOMINMAX prevents these macros from appearing.
if cxx.get_id() == 'msvc'
conf_data.set10('NOMINMAX', true)
endif
if host_machine.system() in ['windows', 'cygwin']
conf_data.set10('_USE_MATH_DEFINES', true)
endif
if host_machine.endian() == 'big'
conf_data.set10('WORDS_BIGENDIAN', true)
endif
# Get host page size
# ~~~~~~~~~~~~~~~~~~
# When detecting the page size, we use Meson's configured
# compiler to make a system call because Meson will build and run
# it via the cross compiler (if one is in use), which is
# particularly important we get the destiantion machine's page
# size as opposed to the local build machine's page size.
#
pagesize = 4096
pagesize_option = get_option('pagesize')
if pagesize_option > 0
# User has provided the page size
pagesize = pagesize_option
else
# Detect the page size using a syscall via the cross compiler
pagesize_api = os_family_name == 'WIN32' ? 'windows' : 'posix'
pagesize_src = files('contrib/pagesize' / pagesize_api + '_pagesize.c')
pagesize_cmd = cc.run(
pagesize_src,
name: 'Query host page size',
)
if pagesize_cmd.returncode() == 0
pagesize = pagesize_cmd.stdout().strip().to_int()
else
error('''Unable to detect the host's page size''')
endif
endif
conf_data.set('PAGESIZE', pagesize)
summary('Host page size (bytes)', pagesize.to_string())
set_prio_code = '''
#include <sys/resource.h>
int main() {
return setpriority(PRIO_PROCESS, 0, PRIO_MIN + PRIO_MAX);
}
'''
if cc.compiles(set_prio_code, name: 'test for setpriority support')
conf_data.set10('HAVE_SETPRIORITY', true)
endif
# New compilers can check for this feature using __has_builtin, but this is
# broken prior to Clang 10 and GCC 10, so we prefer to have this compilation
# check for now:
builtin_expect_code = '''
void fun(bool test) {
// value of 'test' is usually going to be true
if (__builtin_expect(test, true)) {
/* likely branch */
} else {
/* unlikely branch */
}
}
'''
if cxx.compiles(builtin_expect_code, name: 'test for __builtin_expect support')
conf_data.set10('C_HAS_BUILTIN_EXPECT', true)
endif
atomic_code = '''
#include <atomic>
#include <cstdint>
int main() {
std::atomic<std::int32_t> x32 = 1;
std::atomic<std::int64_t> x64 = 1;
return static_cast<int>(x64.load() - x32.load());
}
'''
atomic_external_dep = dependency('atomic', required: false)
atomic_internal_dep = declare_dependency(link_args: '-latomic')
if cxx.links(
atomic_code,
dependencies: atomic_external_dep,
name: 'compiler supports atomic types using external library',
)
atomic_dep = atomic_external_dep
elif cxx.links(
atomic_code,
dependencies: atomic_internal_dep,
name: 'compiler supports atomic types using internal library',
)
atomic_dep = atomic_internal_dep
else
atomic_dep = dependency('atomic')
endif
# Gather external dependencies
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# system and compiler libraries
# Optional libraries
optional_dep = dependency('', required: false)
msg = 'You can disable this dependency with: -D@0@=false'
default_wrap_options = ['default_library=static', 'warning_level=0']
dl_dep = cc.find_library('dl', required: false)
stdcppfs_dep = cxx.find_library('stdc++fs', required: false)
threads_dep = dependency('threads')
# 3rd party libraries
static_libs_list = get_option('try_static_libs')
wants_tests = true
# tests are disabled for release builds unless requested
if get_option('buildtype') == 'release' and get_option('unit_tests').auto()
wants_tests = false
elif get_option('unit_tests').disabled()
wants_tests = false
endif
libiir_dep = dependency(
'iir',
version: ['>= 1.9.3', '< 2'],
default_options: default_wrap_options + ['tests=' + wants_tests.to_string()],
static: ('iir' in static_libs_list or prefers_static_libs),
include_type: 'system',
)
opus_dep = dependency(
'opusfile',
version: ['>= 0.8', '< 1'],
static: ('opusfile' in static_libs_list or prefers_static_libs),
include_type: 'system',
)
sdl2_dep = dependency(
'sdl2',
version: ['>= 2.0.5', '< 3'],
static: ('sdl2' in static_libs_list),
include_type: 'system',
)
# zlib
# ~~~~
zlib_dep = disabler()
zlib_ng_options = get_option('use_zlib_ng')
zlib_is_static = 'zlib' in static_libs_list or prefers_static_libs
try_system_zlib_ng = 'auto' in zlib_ng_options or 'system' in zlib_ng_options
try_builtin_zlib_ng = 'auto' in zlib_ng_options or 'built-in' in zlib_ng_options
system_zlib_ng_dep = disabler()
if try_system_zlib_ng
system_zlib_ng_dep = dependency(
'zlib-ng',
required: false,
fallback: [],
static: zlib_is_static,
include_type: 'system',
)
endif
if (system_zlib_ng_dep.found())
summary('zlib-ng provider', 'system library')
conf_data.set10('C_SYSTEM_ZLIB_NG', system_zlib_ng_dep.found())
elif (
# Otherwise consider the built-in, which is a whole-sale replacement for zlib
try_builtin_zlib_ng
and is_optimized_buildtype
and meson.version() >= '1.3.0'
)
cmake_bin = find_program('cmake', required: false)
cmake_module = import('cmake', required: false)
if cmake_bin.found() and cmake_module.found()
cmake_options = cmake_module.subproject_options()
zlib_ng_is_native = zlib_ng_options.contains('native')
zlib_ng_defines = {
'ZLIB_COMPAT': true,
'WITH_OPTIM': true,
'ZLIB_BUILD_STATIC': true,
'PIC': get_option('b_staticpic'),
'BUILD_SHARED_LIBS': false,
'WITH_GTEST': false,
'ZLIB_ENABLE_TESTS': false,
'WITH_NATIVE_INSTRUCTIONS': zlib_ng_is_native,
'WITH_SANITIZER': get_option('b_sanitize'),
}
foreach instruction_set : [
'avx2',
'avx512',
'avx512vnni',
'sse2',
'ssse3',
'sse42',
'pclmulqdq',
'vpclmulqdq',
'acle',
'neon',
'armv6',
'altivec',
'power8',
'rvv',
'crc32_vx',
'dfltcc_deflate',
'dfltcc_inflate',
]
cmake_define_key = 'WITH_' + instruction_set.to_upper()
cmake_define_value = (
zlib_ng_is_native
or zlib_ng_options.contains(instruction_set)
)
zlib_ng_defines += {cmake_define_key: cmake_define_value}
endforeach
cmake_options.add_cmake_defines(zlib_ng_defines)
zlib_ng_subproject = cmake_module.subproject(
'zlib-ng',
options: cmake_options,
)
zlib_dep = zlib_ng_subproject.get_variable('zlib_dep')
summary('zlib provider', 'built-in (zlib-ng)')
endif
endif
# Otherwise Use the system's zlib or fallback
if not zlib_dep.found()
zlib_dep = dependency(
'zlib',
version: ['>= 1.2.11', '< 2'],
required: true,
fallback: [],
static: zlib_is_static,
include_type: 'system',
)
summary('zlib provider', 'system library')
endif
# PNG
# ~~~
png_has_internal_dep = zlib_dep.type_name() == 'internal'
if png_has_internal_dep
png_dep = subproject(
'libpng',
default_options: default_wrap_options,
).get_variable('png_dep')
else
png_dep = dependency(
'libpng',
version: ['>= 1.2', '< 2'],
required: true,
fallback: [],
static: 'png' in static_libs_list or prefers_static_libs,
include_type: 'system',
)
endif
summary(
'PNG provider',
png_dep.type_name() == 'internal' ? 'built-in' : 'system library',
)
# SpeexDSP
# ~~~~~~~~
# Default to the system library
speexdsp_dep = dependency(
'speexdsp',
version: ['>= 1.2', '< 2'],
required: false,
fallback: [],
static: ('speexdsp' in static_libs_list or prefers_static_libs),
include_type: 'system',
)
# The library needs to be available and testable to be trusted
can_trust_system_speexdsp = (
speexdsp_dep.found()
and meson.can_run_host_binaries()
)
# Test the library. Trust is dropped if the test fails.
if can_trust_system_speexdsp
system_speexdsp_test = cxx.run(
files('contrib/check-speexdsp/test_speexdsp_float_api.cpp'),
dependencies: speexdsp_dep,
name: 'SpeexDSP system library has reliable floating-point API',
)
can_trust_system_speexdsp = (
system_speexdsp_test.compiled()
and system_speexdsp_test.returncode() == 0
)
if can_trust_system_speexdsp
speexdsp_summary_msg = 'system library'
endif
endif
# Use the wrap if the system doesn't have SpeexDSP, we couldn't test it, or testing failed
if not can_trust_system_speexdsp
speexdsp_dep = subproject(
'speexdsp',
default_options: default_wrap_options,
).get_variable('speexdsp_dep')
speexdsp_summary_msg = 'built-in'
endif
summary('SpeexDSP provider', speexdsp_summary_msg)
# File-descriptor manipulation routines, such as FD_ZERO, are used
# by Enet, slirp, and ManyMouse's X11 interface. Unfortunately these
# routines aren't universally available, such as on Android.
#
have_fd_zero = (
cc.has_header_symbol('sys/select.h', 'FD_ZERO')
or cc.has_header_symbol('winsock2.h', 'FD_ZERO')
)
# SDL Networking
sdl2_net_dep = optional_dep
sdl2_net_summary_msg = 'Disabled'
if get_option('use_sdl2_net')
sdl2_net_dep = dependency(
'SDL2_net',
version: ['>= 2.0.0', '< 3'],
static: ('sdl2_net' in static_libs_list),
not_found_message: msg.format('use_sdl2_net'),
include_type: 'system',
)
sdl2_net_summary_msg = sdl2_net_dep.found()
if sdl2_net_dep.found() and not have_fd_zero
sdl2_net_dep = optional_dep
sdl2_net_summary_msg = 'Disabled due to host missing file-descriptor routines'
endif
endif
summary('SDL_net 2.0 support', sdl2_net_summary_msg)
# slirp (depends on glib)
libslirp_dep = optional_dep
libslirp_summary_msg = 'Disabled'
if get_option('use_slirp')
libslirp_dep = dependency(
'slirp',
version: ['>= 4.6.1', '< 5'],
default_options: default_wrap_options,
static: ('slirp' in static_libs_list or prefers_static_libs),
not_found_message: msg.format('use_slirp'),
include_type: 'system',
)
libslirp_summary_msg = libslirp_dep.found()
if libslirp_dep.found() and not have_fd_zero
libslirp_summary_msg = 'Disabled due to host missing file-descriptor routines'
libslirp_dep = optional_dep
endif
endif
summary('slirp support', libslirp_summary_msg)
# OpenGL
opengl_dep = optional_dep
if get_option('use_opengl')
opengl_dep = dependency('gl', not_found_message: msg.format('use_opengl'))
endif
conf_data.set10('C_OPENGL', opengl_dep.found())
# FluidSynth (depends on glib)
fluid_dep = optional_dep
if get_option('use_fluidsynth')
fluid_dep = dependency(
'fluidsynth',
version: ['>= 2.2.3', '< 3'],
modules: ['FluidSynth::libfluidsynth'],
static: ('fluidsynth' in static_libs_list or prefers_static_libs),
not_found_message: msg.format('use_fluidsynth'),
default_options: [
'default_library=static',
'try-static-deps=true',
'enable-floats=true',
'openmp=disabled',
'enable-threads=false',
'tests=' + wants_tests.to_string(),
'warning_level=0',
],
include_type: 'system',
)
endif
summary('FluidSynth support', fluid_dep.found())
# mt32emu
mt32emu_dep = optional_dep
if get_option('use_mt32emu')
mt32emu_dep = dependency(
'mt32emu',
version: ['>= 2.5.3', '< 3'],
default_options: default_wrap_options,
static: ('mt32emu' in static_libs_list or prefers_static_libs),
not_found_message: msg.format('use_mt32emu'),
include_type: 'system',
)
endif
summary('mt32emu support', mt32emu_dep.found())
# Tracy
tracy_dep = optional_dep
if get_option('tracy')
tracy_dep = dependency(
'tracy',
version: ['>= 0.10', '< 1'],
default_options: default_wrap_options,
static: ('tracy' in static_libs_list or prefers_static_libs),
not_found_message: msg.format('tracy'),
include_type: 'system',
)
add_project_arguments('-g', language: ['c', 'cpp'])
add_project_arguments('-fno-omit-frame-pointer', language: ['c', 'cpp'])
endif
# macOS-only dependencies
coreaudio_dep = optional_dep
coremidi_dep = optional_dep
corefoundation_dep = optional_dep
iokit_dep = optional_dep
if host_machine.system() == 'darwin'
# ObjectiveC parsing, if possible
if cxx.has_argument('-lobjc')
add_project_arguments('-lobjc', language: 'cpp')
endif
# Core Audio
coreaudio_dep = dependency(
'appleframeworks',
modules: ['CoreAudio', 'AudioUnit', 'AudioToolbox'],
required: false,
include_type: 'system',
)
if coreaudio_dep.found()
if cxx.check_header('AudioToolbox/AUGraph.h')
conf_data.set10('C_COREAUDIO', true)
else
warning('''Core Audio disabled because header is unusable''')
coreaudio_dep = disabler()
endif
else
warning('''Core Audio disabled because Apple Framework missing''')
endif
summary('CoreAudio support', coreaudio_dep.found())
# Core MIDI
coremidi_dep = dependency(
'appleframeworks',
modules: ['CoreMIDI', 'CoreFoundation'],
required: false,
include_type: 'system',
)
if coremidi_dep.found()
if cxx.check_header('CoreMIDI/MIDIServices.h')
conf_data.set10('C_COREMIDI', true)
else
warning('''Core Audio disabled because header is unusable''')
coremidi_dep = disabler()
endif
else
warning('''Core MIDI disabled because Apple Framework missing''')
endif
summary('CoreMIDI support', coremidi_dep.found())
# IOKit
iokit_dep = dependency(
'appleframeworks',
modules: ['IOKit'],
required: false,
include_type: 'system',
)
if iokit_dep.found()
if cxx.check_header('IOKit/IOKitLib.h')
iokit_code = '''
#include <IOKit/hid/IOHIDLib.h>
int main() {
dispatch_block_t test_var;
return 0;
}
'''
is_iokit_compilable = cxx.links(
iokit_code,
name: 'compiler is capable of compiling IOKit',
)
if is_iokit_compilable
conf_data.set10('C_IOKIT', true)
else
warning('''IOKit disabled because compiler cannot handle it''')
iokit_dep = disabler()
endif
else
warning('''IOKit disabled because header is unusable''')
endif
else
warning('''IOKit disabled because Apple Framework missing''')
endif
summary('IOKit support', iokit_dep.found())
# Locale discovery
corefoundation_dep = dependency(
'appleframeworks',
modules: ['CoreFoundation'],
required: false,
include_type: 'system',
)
if corefoundation_dep.found()
if cxx.check_header('CoreFoundation/CoreFoundation.h')
conf_data.set10('C_COREFOUNDATION', true)
else
warning('''Core Foundation disabled because header is unusable''')
corefoundation_dep = disabler()
endif
else
warning('''Core Foundation disabled becaue Foundation missing''')
endif
summary('CoreFoundation support', corefoundation_dep.found())
# SDL CD dependency
coreservices_dep = dependency(
'appleframeworks',
modules: ['CoreServices'],
required: false,
include_type: 'system',
)
if coreservices_dep.found()
if cxx.check_header('CoreServices/CoreServices.h')
conf_data.set10('C_CORESERVICES', true)
else
warning('''Core Services disabled because header is unusable''')
coreservices_dep = disabler()
endif
else
warning('''Core Services disabled because Frameworks is missing''')
endif
summary('CoreServices support', coreservices_dep.found())
endif
# Determine if system is capable of using ManyMouse library
conf_data.set10('C_MANYMOUSE', true)
manymouse_summary_msg = 'True'
# ManyMouse optionally supports the X Input 2.0 protocol (regardless of OS)
xinput2_dep = optional_dep
xinput2_required = (get_option('use_xinput2') == 'true')
if xinput2_required or (get_option('use_xinput2') == 'auto')
xinput2_dep = dependency(
'xi',
version: ['>= 1.4', '< 2'],
required: xinput2_required,
include_type: 'system',
)
endif
conf_data.set10('SUPPORT_XINPUT2', xinput2_dep.found())
if os_family_name == 'MACOSX'
if not iokit_dep.found()
manymouse_summary_msg = 'Disabled due to host missing IOKit'
conf_data.set10('C_MANYMOUSE', false)
endif
endif
if os_family_name in ['LINUX', 'BSD']
if not have_fd_zero
manymouse_summary_msg = 'Disabled due to host missing file-descriptor routines'
conf_data.set10('C_MANYMOUSE', false)
endif
endif
summary('ManyMouse support', manymouse_summary_msg)
# Linux-only dependencies
alsa_dep = optional_dep
using_linux = (host_machine.system() == 'linux')
force_alsa = (get_option('use_alsa') == 'true')
if force_alsa or (using_linux and get_option('use_alsa') == 'auto')
alsa_dep = dependency(
'alsa',
version: ['>= 1', '< 2'],
include_type: 'system',
)
conf_data.set10('C_ALSA', true)
summary('ALSA support', alsa_dep.found())
endif
# Windows-only dependencies
winsock2_dep = optional_dep
winmm_dep = optional_dep
if host_machine.system() in ['windows', 'cygwin']
winsock2_dep = cxx.find_library('ws2_32', required: true)
summary('Winsock 2 support', winsock2_dep.found())
winmm_dep = cxx.find_library('winmm', required: true)
summary('Windows Multimedia support', winmm_dep.found())
endif
# Setup include directories
incdir = [
include_directories('include', '.'),
include_directories('src/libs', is_system: true),
]
# A list of DOSBox's internal libraries populated
# by each of the src/ subdir imports below.
internal_deps = []
# bundled dependencies, in dependency-order
#
subdir('src/libs/ghc')
subdir('src/libs/loguru')
subdir('src/libs/decoders')
subdir('src/libs/nuked')
subdir('src/libs/residfp')
subdir('src/libs/sdlcd')
subdir('src/libs/whereami')
subdir('src/libs/YM7128B_emu')
if conf_data.get('C_MANYMOUSE') != 0
subdir('src/libs/manymouse')
endif
# ZMBV and TalChorus use some support functionality from misc
subdir('src/misc')
subdir('src/libs/zmbv')
subdir('src/libs/tal-chorus')
# A list of DOSBox's bundled 3rd party dependencies,
# as defined by the above subdir includes. Used for
# both the executable and libdosbox (unit testing).
third_party_deps = [
atomic_dep,
stdcppfs_dep,
sdl2_dep,
threads_dep,
ghc_dep,
libiir_dep,
libloguru_dep,
libsdlcd_dep,
tracy_dep,
libwhereami_dep,
libtalchorus_dep,
]
if conf_data.get('C_MANYMOUSE') != 0
third_party_deps += manymouse_dep
endif
# internal libs
subdir('src/capture')
subdir('src/cpu')
subdir('src/dos')
subdir('src/fpu')
subdir('src/gui')
subdir('src/hardware')
subdir('src/ints')
subdir('src/midi')
subdir('src/shell')
# debugger-specific libs
if get_option('enable_debugger') != 'none'
subdir('src/libs/PDCurses')
subdir('src/debug')
third_party_deps += libpdcurses_dep
endif
# generate config.h
configure_file(
input: 'src/config.h.in',
output: 'config.h',
configuration: conf_data,
)
# Setup the executable and libraries
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
version_file = vcs_tag(input: 'src/version.cpp.in', output: 'version.cpp')
dosbox_sources = ['src/main.cpp', 'src/dosbox.cpp', version_file]
# Add Windows resources file if building on Windows
if host_machine.system() == 'windows'
winmod = import('windows')
res_file = winmod.compile_resources('src/winres.rc')
dosbox_sources += res_file
endif
executable(
'dosbox',
dosbox_sources,
dependencies: internal_deps + third_party_deps,
include_directories: incdir,
install: true,
cpp_args: warnings,
)
# create a library so we can test things inside DOSBOX dep path
libdosbox = static_library(
'dosbox',
['src/dosbox.cpp', version_file],
include_directories: incdir,
dependencies: internal_deps + third_party_deps,
)
dosbox_dep = declare_dependency(link_with: libdosbox)
# Setup unit tests
# ~~~~~~~~~~~~~~~~
# Some tests use relative paths; in meson 0.56.0 this can be replaced
# with meson.project_source_root().
#
if wants_tests
project_source_root = meson.current_source_dir()
subdir('tests')
endif