mpd/meson.build
Max Kellermann 3cc770a00b remove obsolete Boost dependency
Boost makes building a piece of software much more difficult than
necessary.  It's a huge library, and just uncompressing it takes a
considerable amount of time. MPD only used a tiny fraction of it, yet
its header bloat made the MPD build very slow.  Locating Boost was
difficult due to its arcane build system and its resistance to use
pkg-config; it's always a special case.  MPD could never use features
of newer Boost versions because Linux distributions always shipped old
Boost versions.  Boost made everything complicated and slow.

So, finally, after getting rid of GLib (commit ccdb94b06c), switching
to C++ and using Boost (commit 0801b3f495), we've finally get rid of
it 8 years later.

Unfortunately, I had to reimplement parts of it along the way
(e.g. IntrusiveList).  Kind of NIH, but on the other hand, compiling
MPD has become much easier for users.
2023-01-23 15:06:58 +01:00

586 lines
13 KiB
Meson

project(
'mpd',
['c', 'cpp'],
version: '0.24',
meson_version: '>= 0.56.0',
default_options: [
'c_std=c11',
'build.c_std=c11',
'cpp_std=c++2a',
'build.cpp_std=c++2a',
'warning_level=3',
# If we build those libraries as Meson subproject, they shall be
# linked statically into the MPD executable.
'expat:default_library=static',
'fmt:default_library=static',
'gtest:default_library=static',
'sqlite3:default_library=static',
'vorbis:default_library=static',
# Not interested in compiler warnings from subprojects.
'expat:werror=false',
'expat:warning_level=0',
'fmt:warning_level=0',
'gtest:warning_level=0',
'sqlite3:warning_level=0',
'vorbis:warning_level=0',
],
license: 'GPLv2+',
)
version_cxx = vcs_tag(input: 'src/GitVersion.cxx', output: 'GitVersion.cxx')
compiler = meson.get_compiler('cpp')
c_compiler = meson.get_compiler('c')
if compiler.get_id() == 'gcc' and compiler.version().version_compare('<8')
warning('Your GCC version is too old. You need at least version 8.')
elif compiler.get_id() == 'clang' and compiler.version().version_compare('<7')
warning('Your clang version is too old. You need at least version 7.')
endif
version_conf = configuration_data()
version_conf.set_quoted('PACKAGE', meson.project_name())
version_conf.set_quoted('PACKAGE_NAME', meson.project_name())
version_conf.set_quoted('VERSION', meson.project_version())
version_conf.set_quoted('PROTOCOL_VERSION', '0.24.0')
configure_file(output: 'Version.h', configuration: version_conf)
conf = configuration_data()
conf.set_quoted('SYSTEM_CONFIG_FILE_LOCATION', join_paths(get_option('prefix'), get_option('sysconfdir'), 'mpd.conf'))
common_cppflags = [
'-D_GNU_SOURCE',
]
test_global_common_flags = [
'-fvisibility=hidden',
]
test_common_flags = [
'-ffast-math',
'-ftree-vectorize',
'-Wcast-qual',
'-Wdouble-promotion',
'-Wmissing-declarations',
'-Wshadow',
'-Wunused',
'-Wvla',
'-Wwrite-strings',
# clang specific warning options:
'-Wunreachable-code-aggressive',
'-Wused-but-marked-unused',
# suppress bogus GCC12 warnings in libfmt headers
'-Wno-stringop-overflow',
]
test_global_cxxflags = test_global_common_flags + [
]
test_global_cflags = test_global_common_flags + [
]
test_cxxflags = test_common_flags + [
'-fno-threadsafe-statics',
'-fmerge-all-constants',
'-Wcomma-subscript',
'-Wextra-semi',
'-Wmismatched-tags',
'-Woverloaded-virtual',
'-Wsign-promo',
'-Wvolatile',
'-Wvirtual-inheritance',
# a vtable without a dtor is just fine
'-Wno-non-virtual-dtor',
# clang specific warning options:
'-Wcomma',
'-Wheader-hygiene',
'-Winconsistent-missing-destructor-override',
]
if compiler.get_id() != 'gcc' or compiler.version().version_compare('>=9')
# The GCC 8 implementation of this flag is buggy: it complains even
# if "final" is present, which implies "override".
test_cxxflags += '-Wsuggest-override'
endif
test_cflags = test_common_flags + [
'-Wmissing-prototypes',
'-Wstrict-prototypes',
]
test_ldflags = [
# make relocations read-only (hardening)
'-Wl,-z,relro',
# no lazy binding, please - not worth it for a daemon
'-Wl,-z,now',
]
if get_option('buildtype') != 'debug'
test_global_cxxflags += [
'-ffunction-sections',
'-fdata-sections',
]
test_global_cflags += [
'-ffunction-sections',
'-fdata-sections',
]
test_ldflags += [
'-Wl,--gc-sections',
]
endif
if get_option('fuzzer')
fuzzer_flags = ['-fsanitize=fuzzer']
if get_option('b_sanitize') == 'none'
fuzzer_flags += ['-fsanitize=address,undefined']
endif
add_global_arguments(fuzzer_flags, language: 'cpp')
add_global_arguments(fuzzer_flags, language: 'c')
add_global_link_arguments(fuzzer_flags, language: 'cpp')
endif
add_global_arguments(compiler.get_supported_arguments(test_global_cxxflags), language: 'cpp')
add_global_arguments(c_compiler.get_supported_arguments(test_global_cflags), language: 'c')
add_project_arguments(compiler.get_supported_arguments(test_cxxflags), language: 'cpp')
add_project_arguments(c_compiler.get_supported_arguments(test_cflags), language: 'c')
add_project_link_arguments(compiler.get_supported_link_arguments(test_ldflags), language: 'cpp')
is_linux = host_machine.system() == 'linux'
is_android = get_option('android_ndk') != ''
is_darwin = host_machine.system() == 'darwin'
is_windows = host_machine.system() == 'windows'
if is_android
common_cppflags += '-DANDROID'
endif
if is_windows
common_cppflags += [
# enable Windows Vista APIs
'-DWINVER=0x0600', '-D_WIN32_WINNT=0x0600',
# enable Unicode support (TCHAR=wchar_t) in the Windows API (macro
# "UNICODE) and the C library (macro "_UNICODE")
'-DUNICODE', '-D_UNICODE',
# enable strict type checking in the Windows API headers
'-DSTRICT',
# reduce header bloat by disabling obscure and obsolete Windows
# APIs
'-DWIN32_LEAN_AND_MEAN',
# disable more Windows APIs which are not used by MPD
'-DNOGDI', '-DNOBITMAP', '-DNOCOMM',
'-DNOUSER',
# reduce COM header bloat
'-DCOM_NO_WINDOWS_H',
# disable Internet Explorer specific APIs
'-D_WIN32_IE=0',
]
subdir('win32')
endif
if is_android
subdir('android')
endif
add_global_arguments(common_cppflags, language: 'c')
add_global_arguments(common_cppflags, language: 'cpp')
enable_daemon = not is_windows and not is_android and get_option('daemon')
conf.set('ENABLE_DAEMON', enable_daemon)
conf.set('HAVE_GETPWNAM_R', compiler.has_function('getpwnam_r'))
conf.set('HAVE_INITGROUPS', compiler.has_function('initgroups'))
conf.set('HAVE_FNMATCH', compiler.has_function('fnmatch'))
# Explicitly exclude Windows in this check because
# https://github.com/mesonbuild/meson/issues/3672 (reported in 2018,
# still not fixed in 2020) causes Meson to believe it exists, because
# __builtin_strndup() exists (but strndup() still cannot be used).
conf.set('HAVE_STRNDUP', not is_windows and compiler.has_function('strndup', prefix: '#define _GNU_SOURCE\n#include <string.h>'))
conf.set('HAVE_STRCASESTR', compiler.has_function('strcasestr'))
conf.set('HAVE_PRCTL', is_linux)
if not get_option('syslog').disabled()
if compiler.has_function('syslog')
conf.set('HAVE_SYSLOG', true)
elif get_option('syslog').enabled()
error('syslog() not found')
endif
endif
enable_database = get_option('database')
conf.set('ENABLE_DATABASE', enable_database)
enable_inotify = get_option('inotify') and is_linux and enable_database
conf.set('ENABLE_INOTIFY', enable_inotify)
conf.set('ENABLE_DSD', get_option('dsd'))
inc = include_directories(
'src',
# for the generated config.h
'.',
)
subdir('src/lib/fmt')
log = static_library(
'log',
'src/Log.cxx',
'src/LogBackend.cxx',
include_directories: inc,
dependencies: fmt_dep,
)
log_dep = declare_dependency(
link_with: log,
dependencies: fmt_dep,
)
sources = [
version_cxx,
'src/Main.cxx',
'src/protocol/ArgParser.cxx',
'src/command/CommandError.cxx',
'src/command/PositionArg.cxx',
'src/command/AllCommands.cxx',
'src/command/QueueCommands.cxx',
'src/command/TagCommands.cxx',
'src/command/PlayerCommands.cxx',
'src/command/PlaylistCommands.cxx',
'src/command/FileCommands.cxx',
'src/command/OutputCommands.cxx',
'src/command/MessageCommands.cxx',
'src/command/ClientCommands.cxx',
'src/command/PartitionCommands.cxx',
'src/command/OtherCommands.cxx',
'src/command/CommandListBuilder.cxx',
'src/config/PartitionConfig.cxx',
'src/config/PlayerConfig.cxx',
'src/config/ReplayGainConfig.cxx',
'src/Idle.cxx',
'src/IdleFlags.cxx',
'src/decoder/Thread.cxx',
'src/decoder/Control.cxx',
'src/decoder/Bridge.cxx',
'src/decoder/DecoderPrint.cxx',
'src/client/Listener.cxx',
'src/client/Client.cxx',
'src/client/Config.cxx',
'src/client/Domain.cxx',
'src/client/Event.cxx',
'src/client/Expire.cxx',
'src/client/Idle.cxx',
'src/client/List.cxx',
'src/client/New.cxx',
'src/client/Process.cxx',
'src/client/Read.cxx',
'src/client/Write.cxx',
'src/client/Message.cxx',
'src/client/Subscribe.cxx',
'src/client/File.cxx',
'src/client/Response.cxx',
'src/client/ThreadBackgroundCommand.cxx',
'src/Listen.cxx',
'src/LogInit.cxx',
'src/ls.cxx',
'src/Instance.cxx',
'src/MusicBuffer.cxx',
'src/MusicPipe.cxx',
'src/MusicChunk.cxx',
'src/MusicChunkPtr.cxx',
'src/Mapper.cxx',
'src/Partition.cxx',
'src/Permission.cxx',
'src/player/CrossFade.cxx',
'src/player/Thread.cxx',
'src/player/Control.cxx',
'src/PlaylistError.cxx',
'src/PlaylistPrint.cxx',
'src/PlaylistSave.cxx',
'src/playlist/PlaylistStream.cxx',
'src/playlist/PlaylistMapper.cxx',
'src/playlist/PlaylistAny.cxx',
'src/playlist/PlaylistSong.cxx',
'src/playlist/PlaylistQueue.cxx',
'src/playlist/Print.cxx',
'src/db/PlaylistVector.cxx',
'src/queue/Queue.cxx',
'src/queue/Print.cxx',
'src/queue/Save.cxx',
'src/queue/Selection.cxx',
'src/queue/Playlist.cxx',
'src/queue/PlaylistControl.cxx',
'src/queue/PlaylistEdit.cxx',
'src/queue/PlaylistTag.cxx',
'src/queue/PlaylistState.cxx',
'src/LocateUri.cxx',
'src/SongUpdate.cxx',
'src/SongLoader.cxx',
'src/SongPrint.cxx',
'src/SongSave.cxx',
'src/StateFile.cxx',
'src/StateFileConfig.cxx',
'src/Stats.cxx',
'src/TagPrint.cxx',
'src/TagSave.cxx',
'src/TagFile.cxx',
'src/TagStream.cxx',
'src/TagAny.cxx',
'src/TimePrint.cxx',
'src/mixer/Memento.cxx',
'src/PlaylistFile.cxx',
]
if is_windows
sources += [
'src/win32/Win32Main.cxx',
]
endif
if not is_android
sources += [
'src/CommandLine.cxx',
'src/unix/SignalHandlers.cxx',
]
else
sources += [
'src/android/Context.cxx',
'src/android/AudioManager.cxx',
'src/android/Environment.cxx',
'src/android/LogListener.cxx',
]
endif
if enable_daemon
sources += 'src/unix/Daemon.cxx'
endif
if enable_database
sources += [
'src/storage/StorageState.cxx',
'src/queue/PlaylistUpdate.cxx',
'src/command/StorageCommands.cxx',
'src/command/DatabaseCommands.cxx',
]
endif
subdir('src/util')
subdir('src/cmdline')
subdir('src/time')
subdir('src/io')
subdir('src/io/uring')
subdir('src/system')
subdir('src/thread')
subdir('src/net')
subdir('src/event')
subdir('src/win32')
subdir('src/apple')
subdir('src/pcm')
subdir('src/lib/dbus')
subdir('src/lib/icu')
subdir('src/lib/smbclient')
subdir('src/lib/zlib')
subdir('src/lib/alsa')
subdir('src/lib/chromaprint')
subdir('src/lib/curl')
subdir('src/lib/expat')
subdir('src/lib/ffmpeg')
subdir('src/lib/gcrypt')
subdir('src/lib/nfs')
subdir('src/lib/oss')
subdir('src/lib/pcre')
subdir('src/lib/pipewire')
subdir('src/lib/pulse')
subdir('src/lib/sndio')
subdir('src/lib/sqlite')
subdir('src/lib/systemd')
subdir('src/lib/upnp')
subdir('src/lib/yajl')
subdir('src/lib/crypto')
subdir('src/zeroconf')
subdir('src/fs')
subdir('src/config')
subdir('src/tag')
subdir('src/neighbor')
subdir('src/input')
subdir('src/archive')
subdir('src/filter')
subdir('src/mixer')
subdir('src/output')
subdir('src/lib/xiph')
subdir('src/decoder')
subdir('src/encoder')
subdir('src/song')
subdir('src/playlist')
if curl_dep.found()
sources += 'src/RemoteTagCache.cxx'
endif
if sqlite_dep.found()
sources += [
'src/command/StickerCommands.cxx',
'src/sticker/Database.cxx',
'src/sticker/Print.cxx',
'src/sticker/SongSticker.cxx',
]
endif
if chromaprint_dep.found()
sources += [
'src/command/FingerprintCommands.cxx',
'src/lib/chromaprint/DecoderClient.cxx',
]
endif
basic = static_library(
'basic',
'src/ReplayGainMode.cxx',
'src/SingleMode.cxx',
'src/ConsumeMode.cxx',
include_directories: inc,
)
basic_dep = declare_dependency(
link_with: basic,
)
if enable_database
subdir('src/storage')
else
storage_glue_dep = dependency('', required: false)
endif
subdir('src/db')
if neighbor_glue_dep.found()
sources += 'src/command/NeighborCommands.cxx'
endif
if archive_glue_dep.found()
sources += [
'src/TagArchive.cxx',
]
if enable_database
sources += ['src/db/update/Archive.cxx']
endif
endif
if is_windows
sources += windows_resources
endif
link_args = []
more_deps = []
if is_android
subdir('src/java')
target_type = 'shared_library'
target_name = 'mpd'
link_args += [
'-Wl,--no-undefined,-shared,-Bsymbolic',
'-llog',
'-lz',
]
more_deps += [
declare_dependency(sources: [classes_jar]),
java_dep,
]
else
target_type = 'executable'
target_name = 'mpd'
endif
mpd = build_target(
target_name,
sources,
target_type: target_type,
include_directories: inc,
dependencies: [
cmdline_dep,
basic_dep,
config_dep,
dbus_dep,
fs_dep,
net_dep,
util_dep,
event_dep,
thread_dep,
neighbor_glue_dep,
input_glue_dep,
archive_glue_dep,
output_glue_dep,
mixer_glue_dep,
decoder_glue_dep,
encoder_glue_dep,
playlist_glue_dep,
db_glue_dep,
storage_glue_dep,
song_dep,
systemd_dep,
sqlite_dep,
zeroconf_dep,
more_deps,
chromaprint_dep,
fmt_dep,
],
link_args: link_args,
build_by_default: not get_option('fuzzer'),
install: not is_android
)
if is_android
subdir('android/apk')
endif
configure_file(output: 'config.h', configuration: conf)
if systemd_dep.found()
subdir('systemd')
endif
install_data(
'mpd.svg',
install_dir: join_paths(get_option('datadir'), 'icons', 'hicolor', 'scalable', 'apps'),
)
install_data(
'AUTHORS', 'COPYING', 'NEWS', 'README.md',
install_dir: join_paths(get_option('datadir'), 'doc', meson.project_name()),
)
subdir('doc')
if get_option('test')
subdir('test')
endif
if get_option('fuzzer')
subdir('test/fuzzer')
endif