cmake_minimum_required(VERSION 3.14) # find_package() uses uppercase _ROOT variables. if(POLICY CMP0144) cmake_policy(SET CMP0144 NEW) endif() project( snapcast LANGUAGES CXX VERSION 0.31.0) set(PROJECT_DESCRIPTION "Multiroom client-server audio player") set(PROJECT_URL "https://github.com/badaix/snapcast") option(BUILD_SHARED_LIBS "Build snapcast in a shared context" ON) option(BUILD_STATIC_LIBS "Build snapcast in a static context" ON) option(BUILD_TESTS "Build tests (in test/snapcast_test)" OFF) option(WERROR "Treat warnings as errors" OFF) option(ASAN "Enable AddressSanitizer" OFF) option(TSAN "Enable ThreadSanitizer" OFF) option(UBSAN "Enable UndefinedBehaviorSanitizer" OFF) option(TIDY "Enable clang tidy" OFF) if(REVISION) add_compile_definitions(REVISION=\"${REVISION}\") endif() if(TIDY) find_program(CLANG_TIDY "clang-tidy") if(CLANG_TIDY) set(CMAKE_CXX_CLANG_TIDY "clang-tidy") endif() endif() if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set(MACOSX TRUE) elseif(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") set(FREEBSD TRUE) if(BUILD_CLIENT) message( FATAL_ERROR "Snapclient not yet supported for FreeBSD, use \"-DBUILD_CLIENT=OFF\"") endif() elseif(${CMAKE_SYSTEM_NAME} MATCHES "Android") set(ANDROID TRUE) endif() if(MSVC) # warning level 4 and all warnings as errors warning C4505: 'getArch': # unreferenced local function has been removed warning C4458: declaration of # 'size' hides class member warning C4459: declaration of 'query' hides global # declaration add_compile_options(/W4 /wd4458 /wd4459 /wd4505) if(WERROR) add_compile_options(/WX) endif() else() # lots of warnings and all warnings as errors add_compile_options(-Wall -Wextra -pedantic -Wno-unused-function) if(MACOSX) add_compile_options(-Wno-deprecated-declarations) endif() if(WERROR) add_compile_options(-Werror) endif() if(ASAN) add_compile_options(-fsanitize=address) add_link_options(-fsanitize=address) endif() if(TSAN) add_compile_options(-fsanitize=thread) add_link_options(-fsanitize=thread) endif() if(UBSAN) add_compile_options(-fsanitize=undefined) add_link_options(-fsanitize=undefined) endif() endif() include(GNUInstallDirs) include(${CMAKE_SOURCE_DIR}/cmake/cppcheck.cmake) include(${CMAKE_SOURCE_DIR}/cmake/reformat.cmake) if(NOT WIN32) option(BUILD_SERVER "Build Snapserver" ON) # no Windows server for now endif() option(BUILD_CLIENT "Build Snapclient" ON) option(BUILD_WITH_FLAC "Build with FLAC support" ON) option(BUILD_WITH_VORBIS "Build with VORBIS support" ON) option(BUILD_WITH_TREMOR "Build with vorbis using TREMOR" ON) option(BUILD_WITH_OPUS "Build with OPUS support" ON) option(BUILD_WITH_AVAHI "Build with AVAHI support" ON) option(BUILD_WITH_EXPAT "Build with EXPAT support" ON) option(BUILD_WITH_PULSE "Build with PulseAudio support" ON) option(BUILD_WITH_JACK "Build with JACK support" ON) if(NOT BUILD_SHARED_LIBS AND NOT BUILD_STATIC_LIBS) message( FATAL_ERROR "One or both of BUILD_SHARED_LIBS or BUILD_STATIC_LIBS must be set to ON to build" ) endif() if(NOT BUILD_CLIENT AND NOT BUILD_SERVER) message( FATAL_ERROR "One or both of BUILD_CLIENT or BUILD_SERVER must be set to ON to build") endif() # Configure paths if(NOT DEFINED CMAKE_INSTALL_BINDIR) set(CMAKE_INSTALL_BINDIR bin CACHE PATH "Output directory for binary files") endif() if(NOT DEFINED CMAKE_INSTALL_LIBDIR) set(CMAKE_INSTALL_LIBDIR lib CACHE PATH "Output directory for libraries") endif() if(NOT DEFINED CMAKE_INSTALL_INCLUDEDIR) set(CMAKE_INSTALL_INCLUDEDIR include CACHE PATH "Output directory for header files") endif() set(INCLUDE_DIRS "${CMAKE_SOURCE_DIR}" "${CMAKE_INSTALL_INCLUDEDIR}") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/") add_compile_definitions(VERSION="${PROJECT_VERSION}") if(NOT ANDROID) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) endif() # Configure compiler options set(CMAKE_CXX_STANDARD 17) include(${CMAKE_SOURCE_DIR}/cmake/TargetArch.cmake) target_architecture(HOST_ARCH) # message(STATUS "System name: ${CMAKE_SYSTEM_NAME}") message(STATUS "Architecture: ${HOST_ARCH}") # message(STATUS "System processor: ${CMAKE_SYSTEM_PROCESSOR}") if(ARCH) message(STATUS "Using arch: ${ARCH}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=${ARCH}") endif() include(CheckAtomic) include(TestBigEndian) test_big_endian(BIGENDIAN) if(${BIGENDIAN}) add_compile_definitions(IS_BIG_ENDIAN) endif(${BIGENDIAN}) # Check dependencies if(NOT WIN32) # no PkgConfig on Windows... find_package(PkgConfig REQUIRED) endif() find_package(Threads REQUIRED) include(CMakePushCheckState) include(CheckIncludeFileCXX) include_directories(${INCLUDE_DIRS}) include(${CMAKE_SOURCE_DIR}/cmake/CheckCXX11StringSupport.cmake) check_cxx11_string_support(HAS_CXX11_STRING_SUPPORT) if(NOT HAS_CXX11_STRING_SUPPORT) add_compile_definitions(NO_CPP11_STRING) endif() if(NOT WIN32 AND NOT ANDROID) if(MACOSX) set(BONJOUR_FOUND true) if(BONJOUR_FOUND) add_compile_definitions(HAS_BONJOUR) endif(BONJOUR_FOUND) add_compile_definitions(FREEBSD MACOS HAS_DAEMON) link_directories("/usr/local/lib") list(APPEND INCLUDE_DIRS "/usr/local/include") else() pkg_search_module(ALSA REQUIRED alsa) if(ALSA_FOUND) add_compile_definitions(HAS_ALSA) endif(ALSA_FOUND) if(BUILD_WITH_JACK) pkg_search_module(JACK jack) if(JACK_FOUND) add_compile_definitions(HAS_JACK) endif(JACK_FOUND) endif(BUILD_WITH_JACK) if(BUILD_WITH_PULSE) pkg_search_module(PULSE libpulse) if(PULSE_FOUND) add_compile_definitions(HAS_PULSE) endif(PULSE_FOUND) endif(BUILD_WITH_PULSE) if(BUILD_WITH_AVAHI) pkg_search_module(AVAHI avahi-client) if(AVAHI_FOUND) add_compile_definitions(HAS_AVAHI) else() message(STATUS "avahi-client not found") endif(AVAHI_FOUND) endif(BUILD_WITH_AVAHI) add_compile_definitions(HAS_DAEMON) if(FREEBSD) add_compile_definitions(FREEBSD) link_directories("/usr/local/lib") list(APPEND INCLUDE_DIRS "/usr/local/include") endif() endif() pkg_search_module(SOXR soxr) if(SOXR_FOUND) add_compile_definitions(HAS_SOXR) else() message(STATUS "soxr not found") endif(SOXR_FOUND) if(BUILD_WITH_FLAC) pkg_search_module(FLAC flac) if(FLAC_FOUND) add_compile_definitions(HAS_FLAC) else() message(STATUS "flac not found") endif(FLAC_FOUND) endif() if(BUILD_WITH_VORBIS OR BUILD_WITH_TREMOR) pkg_search_module(OGG ogg) if(OGG_FOUND) add_compile_definitions(HAS_OGG) else() message(STATUS "ogg not found") endif(OGG_FOUND) endif() if(BUILD_WITH_VORBIS) pkg_search_module(VORBIS vorbis) if(VORBIS_FOUND) add_compile_definitions(HAS_VORBIS) endif(VORBIS_FOUND) endif() if(BUILD_WITH_TREMOR) pkg_search_module(TREMOR vorbisidec) if(TREMOR_FOUND) add_compile_definitions(HAS_TREMOR) endif(TREMOR_FOUND) endif() if((BUILD_WITH_VORBIS OR BUILD_WITH_TREMOR) AND NOT VORBIS_FOUND AND NOT TREMOR_FOUND) message(STATUS "tremor and vorbis not found") endif() if(BUILD_WITH_VORBIS) pkg_search_module(VORBISENC vorbisenc) if(VORBISENC_FOUND) add_compile_definitions(HAS_VORBIS_ENC) else() message(STATUS "vorbisenc not found") endif(VORBISENC_FOUND) endif() if(BUILD_WITH_OPUS) pkg_search_module(OPUS opus) if(OPUS_FOUND) add_compile_definitions(HAS_OPUS) else() message(STATUS "opus not found") endif(OPUS_FOUND) endif() if(BUILD_WITH_EXPAT) pkg_search_module(EXPAT expat) if(EXPAT_FOUND) add_compile_definitions(HAS_EXPAT) else() message(STATUS "expat not found") endif(EXPAT_FOUND) endif() endif() if(NOT ANDROID) find_package(Boost 1.74 REQUIRED) else() find_package(oboe REQUIRED CONFIG) find_package(flac REQUIRED CONFIG) find_package(ogg REQUIRED CONFIG) find_package(opus REQUIRED CONFIG) find_package(soxr REQUIRED CONFIG) find_package(tremor REQUIRED CONFIG) find_package(boost REQUIRED CONFIG) add_compile_definitions(HAS_OBOE) add_compile_definitions(HAS_OPENSL) add_compile_definitions(HAS_FLAC) add_compile_definitions(HAS_OGG) add_compile_definitions(HAS_OPUS) add_compile_definitions(HAS_SOXR) add_compile_definitions(HAS_TREMOR) endif() add_compile_definitions(BOOST_ERROR_CODE_HEADER_ONLY BOOST_ASIO_NO_TS_EXECUTORS) if(WIN32) include(FindPackageHandleStandardArgs) set(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) find_path(FLAC_INCLUDE_DIRS FLAC/all.h) find_library(FLAC_LIBRARIES FLAC) find_package_handle_standard_args(FLAC REQUIRED FLAC_INCLUDE_DIRS FLAC_LIBRARIES) find_path(OGG_INCLUDE_DIRS ogg/ogg.h) find_library(OGG_LIBRARIES ogg) find_package_handle_standard_args(Ogg REQUIRED OGG_INCLUDE_DIRS OGG_LIBRARIES) find_path(VORBIS_INCLUDE_DIRS vorbis/vorbisenc.h) find_library(VORBIS_LIBRARIES vorbis) find_package_handle_standard_args(Vorbis REQUIRED VORBIS_INCLUDE_DIRS VORBIS_LIBRARIES) find_path(OPUS_INCLUDE_DIRS opus/opus.h) find_library(OPUS_LIBRARIES opus) find_package_handle_standard_args(Opus REQUIRED OPUS_INCLUDE_DIRS OPUS_LIBRARIES) find_path(SOXR_INCLUDE_DIRS soxr.h) find_library(SOXR_LIBRARIES soxr) find_package_handle_standard_args(Soxr REQUIRED SOXR_INCLUDE_DIRS SOXR_LIBRARIES) add_compile_definitions( NTDDI_VERSION=0x06020000 _WIN32_WINNT=0x0602 WINVER=0x0602 WINDOWS WIN32_LEAN_AND_MEAN UNICODE # _UNICODE _CRT_SECURE_NO_WARNINGS) add_compile_definitions( HAS_OGG HAS_VORBIS HAS_FLAC HAS_VORBIS_ENC HAS_OPUS HAS_WASAPI HAS_SOXR) endif() list(APPEND CMAKE_REQUIRED_INCLUDES "${INCLUDE_DIRS}") # include(${CMAKE_SOURCE_DIR}/cmake/SystemdService.cmake) add_subdirectory(common) if(BUILD_SERVER) add_subdirectory(server) endif() if(BUILD_CLIENT) add_subdirectory(client) endif() if(BUILD_TESTS) add_subdirectory(test) endif(BUILD_TESTS)