projectm/CMakeLists.txt
Kai Blaschke 1b8004f714
Improve vcpkg manifest, use features for build options.
Now pulling in the required vcpkg dependencies only if a certain build feature is requested.
2024-08-07 18:31:32 +02:00

301 lines
12 KiB
CMake

cmake_minimum_required(VERSION 3.21 FATAL_ERROR)
include(CMakeDependentOption)
include(CheckSymbolExists)
# Save the current source/binary dirs if we're in a subdirectory of a larger CMake project.
set(PROJECTM_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
set(PROJECTM_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}")
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED YES)
set(CMAKE_POSITION_INDEPENDENT_CODE YES)
# Don't export any symbols except those explicitly exported.
set(CMAKE_VISIBILITY_INLINES_HIDDEN YES)
set(CMAKE_C_VISIBILITY_PRESET hidden)
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
# General build options
option(ENABLE_SYSTEM_GLM "Enable use of system-install GLM library" OFF)
option(ENABLE_SYSTEM_PROJECTM_EVAL "Enable use of a system-installed/external projectM-eval library" ON)
option(ENABLE_DEBUG_POSTFIX "Add \"d\" (by default) after library names for debug builds." ON)
option(ENABLE_PLAYLIST "Enable building the playlist management library" ON)
option(ENABLE_BOOST_FILESYSTEM "Force the use of boost::filesystem, even if the compiler supports C++17." OFF)
option(ENABLE_SDL_UI "Build the SDL2-based developer test UI. Ignored when building with Emscripten or for Android." OFF)
option(BUILD_TESTING "Build the libprojectM test suite" OFF)
option(BUILD_DOCS "Build documentation" OFF)
# Enable vcpkg manifest features according to the build options set
if(ENABLE_SYSTEM_GLM)
list(APPEND VCPKG_MANIFEST_FEATURES external-glm)
endif()
if(ENABLE_SYSTEM_PROJECTM_EVAL)
list(APPEND VCPKG_MANIFEST_FEATURES external-evallib)
endif()
if(ENABLE_BOOST_FILESYSTEM)
list(APPEND VCPKG_MANIFEST_FEATURES boost-filesystem)
endif()
if(ENABLE_SDL_UI)
list(APPEND VCPKG_MANIFEST_FEATURES gui)
endif()
if(BUILD_TESTING)
list(APPEND VCPKG_MANIFEST_FEATURES test)
endif()
if(ENABLE_DEBUG_POSTFIX)
set(CMAKE_DEBUG_POSTFIX "d" CACHE STRING "Output file debug postfix. Default is \"d\".")
endif()
project(libprojectM
LANGUAGES C CXX
VERSION 4.1.0
)
# The API (SO) version for the shared library. Should be incremented whenever the binary interface changes
# in a non-backwards-compatible way, e.g. changing parameters or return values of existing functions or removing
# functions. Adding new function should be okay if documented.
set(PROJECTM_SO_VERSION "4")
# Base filename of all installed libraries. Also used as package name in pkgconfig.
set(PROJECTM_LIBRARY_BASE_OUTPUT_NAME "projectM-${PROJECT_VERSION_MAJOR}")
# The actual (full) library version of projectM
set(PROJECTM_LIB_VERSION "${CMAKE_PROJECT_VERSION}")
list(APPEND CMAKE_MODULE_PATH "${PROJECTM_SOURCE_DIR}/cmake")
include(VCSVersion)
include(GNUInstallDirs)
set(PROJECTM_BIN_DIR "${CMAKE_INSTALL_BINDIR}" CACHE STRING "Executable installation directory, relative to the install prefix.")
set(PROJECTM_LIB_DIR "${CMAKE_INSTALL_LIBDIR}" CACHE STRING "Library installation directory, relative to the install prefix.")
set(PROJECTM_INCLUDE_DIR "${CMAKE_INSTALL_INCLUDEDIR}" CACHE STRING "Header installation directory, relative to the install prefix.")
if(CMAKE_SYSTEM_NAME STREQUAL Windows)
set(PROJECTM_RUNTIME_DIR "${PROJECTM_BIN_DIR}")
else()
set(PROJECTM_RUNTIME_DIR "${PROJECTM_LIB_DIR}")
endif()
# Dummy file for merged static libs.
set(PROJECTM_DUMMY_SOURCE_FILE "${PROJECTM_BINARY_DIR}/dummy.cpp")
file(TOUCH "${PROJECTM_DUMMY_SOURCE_FILE}")
if(CMAKE_SYSTEM_NAME STREQUAL Emscripten)
set(ENABLE_EMSCRIPTEN ON CACHE BOOL "Build for web with emscripten. Will also build the SDL2-based entrypoint." FORCE)
option(USE_PTHREADS "Enable multithreading support" OFF)
else()
set(ENABLE_EMSCRIPTEN OFF CACHE BOOL "Build for web with emscripten. Requires emscripten toolset for building." FORCE)
endif()
# Compiler-/system-dependent options, including dependencies.
cmake_dependent_option(BUILD_SHARED_LIBS "Build and install libprojectM as a shared libraries. If OFF, builds as static libraries." ON "NOT ENABLE_EMSCRIPTEN" OFF)
cmake_dependent_option(ENABLE_GLES "Enable OpenGL ES support" OFF "NOT ENABLE_EMSCRIPTEN AND NOT CMAKE_SYSTEM_NAME STREQUAL Android" ON)
cmake_dependent_option(ENABLE_INSTALL "Enable installing projectM libraries and headers." OFF "NOT PROJECT_IS_TOP_LEVEL" ON)
# Experimental/unsupported features
option(ENABLE_CXX_INTERFACE "Enable exporting C++ symbols for ProjectM and PCM classes, not only the C API. Warning: This is not very portable." OFF)
if(ENABLE_SYSTEM_GLM)
find_package(GLM REQUIRED)
endif()
if(ENABLE_SYSTEM_PROJECTM_EVAL)
find_package(projectM-Eval)
endif()
if(NOT BUILD_SHARED_LIBS AND CMAKE_SYSTEM_NAME STREQUAL "Windows")
# Add "lib" in front of static library files to allow installing both shared and static libs in the same dir.
set(CMAKE_STATIC_LIBRARY_PREFIX lib)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL Darwin)
# Silence OpenGL API deprecation warnings on macOS.
add_compile_definitions(GL_SILENCE_DEPRECATION)
endif()
if(ENABLE_EMSCRIPTEN)
message(STATUS "${CMAKE_C_COMPILER} on ${CMAKE_SYSTEM_NAME}")
check_symbol_exists(__EMSCRIPTEN__ "" HAVE_EMSCRIPTEN)
if(NOT HAVE_EMSCRIPTEN)
message(FATAL_ERROR "You are not using an emscripten compiler.")
endif()
# emscripten uses different options to compile and link libraries, so we can't use find_package().
# Instead, specifying the required options directly to emcc is the way to go.
# Note: The "SHELL:" syntax is required to pass each argument as-is, but without quotes and CMake's de-duplication.
add_compile_options(
"SHELL:-s USE_SDL=2"
"SHELL:-s NO_DISABLE_EXCEPTION_CATCHING"
)
add_link_options(
"SHELL:-s USE_SDL=2"
"SHELL:-s MIN_WEBGL_VERSION=2"
"SHELL:-s MAX_WEBGL_VERSION=2"
"SHELL:-s FULL_ES2=1"
"SHELL:-s FULL_ES3=1"
"SHELL:-s ALLOW_MEMORY_GROWTH=1"
"SHELL:-s NO_DISABLE_EXCEPTION_CATCHING"
)
if(USE_PTHREADS)
add_compile_options("SHELL:-s USE_PTHREADS=1")
add_link_options("SHELL:-s USE_PTHREADS=1")
endif()
set(USE_GLES ON)
else()
if(ENABLE_SDL_UI)
find_package(SDL2 REQUIRED)
# Apply some fixes, as SDL2's CMake support is new and still a WiP.
include(SDL2Target)
endif()
if(ENABLE_GLES)
message(STATUS "Building for OpenGL Embedded Profile")
if(NOT CMAKE_SYSTEM_NAME STREQUAL Linux
AND NOT CMAKE_SYSTEM_NAME STREQUAL Android)
message(FATAL_ERROR "OpenGL ES 3 support is currently only available for Linux platforms. You're building for ${CMAKE_SYSTEM_NAME}.")
endif()
# We use a local find script for OpenGL::GLES3 until the proposed changes are merged upstream.
list(APPEND CMAKE_MODULE_PATH "${PROJECTM_SOURCE_DIR}/cmake/gles")
find_package(OpenGL REQUIRED COMPONENTS GLES3)
if(NOT TARGET OpenGL::GLES3)
message(FATAL_ERROR "No suitable GLES3 library was found.")
endif()
set(PROJECTM_OPENGL_LIBRARIES OpenGL::GLES3)
set(USE_GLES ON)
else()
message(STATUS "Building for OpenGL Core Profile")
find_package(OpenGL REQUIRED)
set(PROJECTM_OPENGL_LIBRARIES OpenGL::GL)
# GLX is required by SOIL2 on platforms with the X Window System (e.g. most Linux distributions)
if(TARGET OpenGL::GLX)
list(APPEND PROJECTM_OPENGL_LIBRARIES OpenGL::GLX)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
find_package(GLEW REQUIRED)
# Prefer shared, but check for static lib if shared is not available.
if(TARGET GLEW::glew)
list(APPEND PROJECTM_OPENGL_LIBRARIES GLEW::glew)
elseif(TARGET GLEW::glew_s)
list(APPEND PROJECTM_OPENGL_LIBRARIES GLEW::glew_s)
endif()
endif()
endif()
endif()
if(ENABLE_CXX_INTERFACE)
set(CMAKE_C_VISIBILITY_PRESET default)
set(CMAKE_CXX_VISIBILITY_PRESET default)
set(CMAKE_VISIBILITY_INLINES_HIDDEN OFF)
else()
set(CMAKE_C_VISIBILITY_PRESET hidden)
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
endif()
if(BUILD_DOCS)
find_package(Doxygen REQUIRED)
find_package(Sphinx REQUIRED breathe exhale)
set(DOXYGEN_GENERATE_HTML NO)
set(DOXYGEN_GENERATE_XML YES)
# All doxygen comments are in header files. Processing cpp files
# produces duplicate C++ function definitions in doxygen, resulting
# in various problems.
# See https://github.com/breathe-doc/breathe/issues/772
set(DOXYGEN_EXCLUDE_PATTERNS "*.cpp")
doxygen_add_docs(
projectm_doxygen
src
COMMENT "Generate HTML documentation")
sphinx_add_docs(
projectm_sphinx
BREATHE_PROJECTS projectm_doxygen
BUILDER html
SOURCE_DIRECTORY docs)
endif()
add_subdirectory(vendor)
include(features.cmake)
add_subdirectory(presets)
add_subdirectory(src)
if(BUILD_TESTING)
enable_testing()
add_subdirectory(tests)
endif()
message(STATUS "")
message(STATUS "libprojectM v${PROJECT_VERSION}")
message(STATUS "==============================================")
message(STATUS "")
message(STATUS " prefix: ${CMAKE_INSTALL_PREFIX}")
message(STATUS " libdir: ${PROJECTM_LIB_DIR}")
message(STATUS " includedir: ${PROJECTM_INCLUDE_DIR}")
message(STATUS " bindir: ${PROJECTM_BIN_DIR}")
message(STATUS "")
message(STATUS " compiler: ${CMAKE_CXX_COMPILER}")
message(STATUS " cflags: ${CMAKE_C_FLAGS}")
message(STATUS " cxxflags: ${CMAKE_CXX_FLAGS}")
message(STATUS " ldflags: ${CMAKE_SHARED_LINKER_FLAGS}")
message(STATUS "")
message(STATUS "Features:")
message(STATUS "==============================================")
message(STATUS "")
message(STATUS " Build shared libraries: ${BUILD_SHARED_LIBS}")
if(ENABLE_BOOST_FILESYSTEM)
message(STATUS " Filesystem support: Boost")
message(STATUS " Boost version: ${Boost_VERSION}")
else()
message(STATUS " Filesystem support: C++17 STL")
endif()
message(STATUS " SDL2: ${ENABLE_SDL_UI}")
if(ENABLE_SDL_UI)
message(STATUS " SDL2 version: ${SDL2_VERSION}")
endif()
message(STATUS " OpenGL ES: ${ENABLE_GLES}")
message(STATUS " Emscripten: ${ENABLE_EMSCRIPTEN}")
if(CMAKE_SYSTEM_NAME STREQUAL Emscripten)
message(STATUS " - PThreads: ${USE_PTHREADS}")
endif()
message(STATUS " Use system GLM: ${ENABLE_SYSTEM_GLM}")
message(STATUS " Use system projectM-eval: ${ENABLE_SYSTEM_PROJECTM_EVAL}")
message(STATUS " Link UI with shared lib: ${ENABLE_SHARED_LINKING}")
message(STATUS "")
message(STATUS "Targets and applications:")
message(STATUS "==============================================")
message(STATUS "")
message(STATUS " libprojectM: (always built)")
message(STATUS " Playlist library: ${ENABLE_PLAYLIST}")
message(STATUS " SDL2 Test UI: ${ENABLE_SDL_UI}")
message(STATUS " Tests: ${BUILD_TESTING}")
message(STATUS " Documentation: ${BUILD_DOCS}")
message(STATUS "")
if(ENABLE_CXX_INTERFACE)
message(AUTHOR_WARNING
"This build is configured to export C++ symbols for ProjectM and PCM classes in the shared library.\n"
"Using C++ STL types across library borders only works if all components were built "
"with the exact same toolchain and C++ language level, otherwise it will cause crashes.\n"
"Only use this if you know what you're doing. You have been warned!"
)
endif()
# Create CPack configuration
set(CPACK_PACKAGE_NAME "projectM")
set(CPACK_VERBATIM_VARIABLES YES)
include(CPack)