dosbox-staging/meson.build

1102 lines
31 KiB
Meson
Raw Permalink Normal View History

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')
2021-12-12 11:27:58 -08:00
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',
]
2023-07-05 23:45:24 -06:00
warnings = []
2023-09-06 17:47:14 +10:00
# Enable additional warnings
2023-07-05 23:45:24 -06:00
foreach flag : [
'-Walloca',
'-Wctor-dtor-privacy',
'-Wdate-time',
'-Wdisabled-optimization',
'-Wduplicated-branches',
'-Weffc++',
'-Wextra-semi',
'-Wfloat-conversion',
2023-07-05 23:45:24 -06:00
'-Wlogical-op',
'-Wlogical-not-parentheses',
2023-07-22 20:40:48 -06:00
'-Wredundant-decls',
2023-07-05 23:45:24 -06:00
'-Wmismatched-tags',
'-Wsizeof-pointer-div',
'-Wstack-protector',
'-Wstrict-null-sentinel',
'-Wsuggest-override',
'-Wzero-as-null-pointer-constant',
2023-09-06 17:47:14 +10:00
]
if cxx.has_argument(flag)
warnings += flag
2023-09-06 17:47:14 +10:00
endif
endforeach
# Ignore some warnings enabled by default
foreach flag : ['-Wno-format-security']
2023-07-05 23:45:24 -06:00
if cxx.has_argument(flag)
warnings += flag
2023-07-05 23:45:24 -06:00
endif
endforeach
2022-12-06 12:21:16 -06:00
# 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')
2023-07-05 23:45:24 -06:00
# 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',
2023-05-30 06:14:20 -07:00
'-D_GLIBCXX_ASSERTIONS=1',
'-D_GLIBCXX_DEBUG=1',
2023-05-30 06:14:20 -07:00
'-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
2021-12-12 11:27:58 -08:00
if prefers_static_libs
extra_flags += ['-static-libstdc++', '-static-libgcc']
if host_machine.system() != 'darwin'
extra_link_flags += ['-no-pie']
endif
2021-12-12 11:27:58 -08:00
else
extra_flags += [
'-shared-libstdc++',
'-shared-libgcc',
'-lstdc++_s',
'-fPIC',
]
2021-12-12 11:27:58 -08:00
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
2022-08-18 11:19:34 -07:00
# 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
2021-11-02 13:17:37 -07:00
endforeach
2022-08-18 11:19:34 -07:00
foreach flag : extra_link_flags
if cxx.has_link_argument(flag)
add_project_link_arguments(flag, language: 'cpp')
endif
2022-08-18 11:19:34 -07:00
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'))
2021-12-02 12:19:25 -08:00
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'))
2022-08-04 13:58:40 -07:00
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'])
2021-01-14 21:53:42 +01:00
if get_option('enable_debugger') != 'none'
conf_data.set10('C_DEBUG', true)
endif
2021-01-14 21:53:42 +01:00
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
2021-06-01 09:02:39 -05:00
if cc.has_function('__builtin_available')
conf_data.set10('HAVE_BUILTIN_AVAILABLE', true)
2021-06-01 09:02:39 -05:00
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)
2021-06-01 09:02:39 -05:00
endif
if cc.has_header_symbol('sys/mman.h', 'MAP_JIT')
conf_data.set10('HAVE_MAP_JIT', true)
2021-06-01 09:02:39 -05:00
endif
if cc.has_function(
'pthread_jit_write_protect_np',
prefix: '#include <pthread.h>',
)
conf_data.set10('HAVE_PTHREAD_WRITE_PROTECT_NP', true)
2021-06-01 09:02:39 -05:00
endif
if cc.has_function(
'sys_icache_invalidate',
prefix: '#include <libkern/OSCacheControl.h>',
)
conf_data.set10('HAVE_SYS_ICACHE_INVALIDATE', true)
2021-06-01 09:02:39 -05:00
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
2020-12-23 07:51:26 +01:00
if host_machine.endian() == 'big'
conf_data.set10('WORDS_BIGENDIAN', true)
2020-12-23 07:51:26 +01:00
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())
2021-01-13 02:04:50 +01:00
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)
2021-01-13 02:04:50 +01:00
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())
2022-07-29 15:50:23 -07:00
# 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())
2022-08-04 13:58:40 -07:00
# Tracy
tracy_dep = optional_dep
2022-06-28 20:26:07 -05:00
if get_option('tracy')
tracy_dep = dependency(
'tracy',
2023-10-17 07:02:01 -05:00
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'])
2022-06-28 20:26:07 -05:00
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'
Check the usability of Apple's audio headers in Meson Also add ObjectiveC parsing on macOS if possible. Apple sometimes pollutes their headers with non-standard content that only compiles using their modified compiler. Because of this, simply testing for the presence of the CoreMIDI header is insufficient; instead, we need to make sure the compiler can actually process it. This will protect GCC from errors like this: /libmidi.a.p/midi.cpp.o -MF src/midi/libmidi.a.p/midi.cpp.o.d -o src/midi/libmidi.a.p/midi.cpp.o -c ../src/midi/midi.cpp In file included from ../src/midi/midi_coremidi.h:29, from ../src/midi/midi.cpp:84: /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/CoreMIDI.framework/Headers/MIDIServices.h:304:2: error: expected unqualified-id before '^' token 304 | (^MIDINotifyBlock)(const MIDINotification *message); | ^ /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/CoreMIDI.framework/Headers/MIDIServices.h:304:2: error: expected ')' before '^' token 304 | (^MIDINotifyBlock)(const MIDINotification *message); | ~^ ) /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/CoreMIDI.framework/Headers/MIDIServices.h:347:2: error: expected unqualified-id before '^' token 347 | (^MIDIReadBlock)(const MIDIPacketList *pktlist, void * __nullable srcConnRefCon); | ^ /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/CoreMIDI.framework/Headers/MIDIServices.h:347:2: error: expected ')' before '^' token 347 | (^MIDIReadBlock)(const MIDIPacketList *pktlist, void * __nullable srcConnRefCon); | ~^ ) In file included from ../src/midi/midi_coremidi.h:29, from ../src/midi/midi.cpp:84: /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/CoreMIDI.framework/Headers/MIDIServices.h:1190:41: error: 'MIDINotifyBlock' has not been declared 1190 | MIDINotifyBlock __nullable notifyBlock ) API_AVAILABLE(macos(10.11), ios(9.0), tvos(12.0));
2021-11-03 09:41:31 -07:00
# 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
Check the usability of Apple's audio headers in Meson Also add ObjectiveC parsing on macOS if possible. Apple sometimes pollutes their headers with non-standard content that only compiles using their modified compiler. Because of this, simply testing for the presence of the CoreMIDI header is insufficient; instead, we need to make sure the compiler can actually process it. This will protect GCC from errors like this: /libmidi.a.p/midi.cpp.o -MF src/midi/libmidi.a.p/midi.cpp.o.d -o src/midi/libmidi.a.p/midi.cpp.o -c ../src/midi/midi.cpp In file included from ../src/midi/midi_coremidi.h:29, from ../src/midi/midi.cpp:84: /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/CoreMIDI.framework/Headers/MIDIServices.h:304:2: error: expected unqualified-id before '^' token 304 | (^MIDINotifyBlock)(const MIDINotification *message); | ^ /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/CoreMIDI.framework/Headers/MIDIServices.h:304:2: error: expected ')' before '^' token 304 | (^MIDINotifyBlock)(const MIDINotification *message); | ~^ ) /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/CoreMIDI.framework/Headers/MIDIServices.h:347:2: error: expected unqualified-id before '^' token 347 | (^MIDIReadBlock)(const MIDIPacketList *pktlist, void * __nullable srcConnRefCon); | ^ /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/CoreMIDI.framework/Headers/MIDIServices.h:347:2: error: expected ')' before '^' token 347 | (^MIDIReadBlock)(const MIDIPacketList *pktlist, void * __nullable srcConnRefCon); | ~^ ) In file included from ../src/midi/midi_coremidi.h:29, from ../src/midi/midi.cpp:84: /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/CoreMIDI.framework/Headers/MIDIServices.h:1190:41: error: 'MIDINotifyBlock' has not been declared 1190 | MIDINotifyBlock __nullable notifyBlock ) API_AVAILABLE(macos(10.11), ios(9.0), tvos(12.0));
2021-11-03 09:41:31 -07:00
else
warning('''Core Audio disabled because Apple Framework missing''')
Check the usability of Apple's audio headers in Meson Also add ObjectiveC parsing on macOS if possible. Apple sometimes pollutes their headers with non-standard content that only compiles using their modified compiler. Because of this, simply testing for the presence of the CoreMIDI header is insufficient; instead, we need to make sure the compiler can actually process it. This will protect GCC from errors like this: /libmidi.a.p/midi.cpp.o -MF src/midi/libmidi.a.p/midi.cpp.o.d -o src/midi/libmidi.a.p/midi.cpp.o -c ../src/midi/midi.cpp In file included from ../src/midi/midi_coremidi.h:29, from ../src/midi/midi.cpp:84: /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/CoreMIDI.framework/Headers/MIDIServices.h:304:2: error: expected unqualified-id before '^' token 304 | (^MIDINotifyBlock)(const MIDINotification *message); | ^ /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/CoreMIDI.framework/Headers/MIDIServices.h:304:2: error: expected ')' before '^' token 304 | (^MIDINotifyBlock)(const MIDINotification *message); | ~^ ) /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/CoreMIDI.framework/Headers/MIDIServices.h:347:2: error: expected unqualified-id before '^' token 347 | (^MIDIReadBlock)(const MIDIPacketList *pktlist, void * __nullable srcConnRefCon); | ^ /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/CoreMIDI.framework/Headers/MIDIServices.h:347:2: error: expected ')' before '^' token 347 | (^MIDIReadBlock)(const MIDIPacketList *pktlist, void * __nullable srcConnRefCon); | ~^ ) In file included from ../src/midi/midi_coremidi.h:29, from ../src/midi/midi.cpp:84: /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/CoreMIDI.framework/Headers/MIDIServices.h:1190:41: error: 'MIDINotifyBlock' has not been declared 1190 | MIDINotifyBlock __nullable notifyBlock ) API_AVAILABLE(macos(10.11), ios(9.0), tvos(12.0));
2021-11-03 09:41:31 -07:00
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
Check the usability of Apple's audio headers in Meson Also add ObjectiveC parsing on macOS if possible. Apple sometimes pollutes their headers with non-standard content that only compiles using their modified compiler. Because of this, simply testing for the presence of the CoreMIDI header is insufficient; instead, we need to make sure the compiler can actually process it. This will protect GCC from errors like this: /libmidi.a.p/midi.cpp.o -MF src/midi/libmidi.a.p/midi.cpp.o.d -o src/midi/libmidi.a.p/midi.cpp.o -c ../src/midi/midi.cpp In file included from ../src/midi/midi_coremidi.h:29, from ../src/midi/midi.cpp:84: /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/CoreMIDI.framework/Headers/MIDIServices.h:304:2: error: expected unqualified-id before '^' token 304 | (^MIDINotifyBlock)(const MIDINotification *message); | ^ /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/CoreMIDI.framework/Headers/MIDIServices.h:304:2: error: expected ')' before '^' token 304 | (^MIDINotifyBlock)(const MIDINotification *message); | ~^ ) /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/CoreMIDI.framework/Headers/MIDIServices.h:347:2: error: expected unqualified-id before '^' token 347 | (^MIDIReadBlock)(const MIDIPacketList *pktlist, void * __nullable srcConnRefCon); | ^ /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/CoreMIDI.framework/Headers/MIDIServices.h:347:2: error: expected ')' before '^' token 347 | (^MIDIReadBlock)(const MIDIPacketList *pktlist, void * __nullable srcConnRefCon); | ~^ ) In file included from ../src/midi/midi_coremidi.h:29, from ../src/midi/midi.cpp:84: /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/CoreMIDI.framework/Headers/MIDIServices.h:1190:41: error: 'MIDINotifyBlock' has not been declared 1190 | MIDINotifyBlock __nullable notifyBlock ) API_AVAILABLE(macos(10.11), ios(9.0), tvos(12.0));
2021-11-03 09:41:31 -07:00
else
warning('''Core MIDI disabled because Apple Framework missing''')
Check the usability of Apple's audio headers in Meson Also add ObjectiveC parsing on macOS if possible. Apple sometimes pollutes their headers with non-standard content that only compiles using their modified compiler. Because of this, simply testing for the presence of the CoreMIDI header is insufficient; instead, we need to make sure the compiler can actually process it. This will protect GCC from errors like this: /libmidi.a.p/midi.cpp.o -MF src/midi/libmidi.a.p/midi.cpp.o.d -o src/midi/libmidi.a.p/midi.cpp.o -c ../src/midi/midi.cpp In file included from ../src/midi/midi_coremidi.h:29, from ../src/midi/midi.cpp:84: /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/CoreMIDI.framework/Headers/MIDIServices.h:304:2: error: expected unqualified-id before '^' token 304 | (^MIDINotifyBlock)(const MIDINotification *message); | ^ /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/CoreMIDI.framework/Headers/MIDIServices.h:304:2: error: expected ')' before '^' token 304 | (^MIDINotifyBlock)(const MIDINotification *message); | ~^ ) /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/CoreMIDI.framework/Headers/MIDIServices.h:347:2: error: expected unqualified-id before '^' token 347 | (^MIDIReadBlock)(const MIDIPacketList *pktlist, void * __nullable srcConnRefCon); | ^ /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/CoreMIDI.framework/Headers/MIDIServices.h:347:2: error: expected ')' before '^' token 347 | (^MIDIReadBlock)(const MIDIPacketList *pktlist, void * __nullable srcConnRefCon); | ~^ ) In file included from ../src/midi/midi_coremidi.h:29, from ../src/midi/midi.cpp:84: /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/CoreMIDI.framework/Headers/MIDIServices.h:1190:41: error: 'MIDINotifyBlock' has not been declared 1190 | MIDINotifyBlock __nullable notifyBlock ) API_AVAILABLE(macos(10.11), ios(9.0), tvos(12.0));
2021-11-03 09:41:31 -07:00
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 = '''
2022-10-12 12:45:03 +02:00
#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
2021-12-11 19:20:43 -08:00
else
warning('''Core Foundation disabled becaue Foundation missing''')
2021-12-11 19:20:43 -08:00
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
2022-02-15 19:37:18 -05:00
else
warning('''Core Services disabled because Frameworks is missing''')
2022-02-15 19:37:18 -05:00
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 = []
2021-08-24 12:09:11 -05:00
# bundled dependencies, in dependency-order
#
subdir('src/libs/ghc')
2021-08-24 12:09:11 -05:00
subdir('src/libs/loguru')
subdir('src/libs/decoders')
subdir('src/libs/nuked')
subdir('src/libs/residfp')
2022-02-11 16:58:46 -05:00
subdir('src/libs/sdlcd')
subdir('src/libs/whereami')
2022-06-10 13:25:04 +10:00
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')
2022-07-17 21:16:36 +10:00
subdir('src/libs/tal-chorus')
2022-06-10 13:25:04 +10:00
# A list of DOSBox's bundled 3rd party dependencies,
# as defined by the above subdir includes. Used for
2022-07-17 21:16:36 +10:00
# 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,
2023-07-05 23:45:24 -06:00
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