mirror of
https://github.com/SphereServer/Source-X
synced 2026-08-13 10:23:05 -04:00
315 lines
12 KiB
CMake
315 lines
12 KiB
CMake
# Main config #
|
|
|
|
cmake_minimum_required(VERSION 3.29)
|
|
set(CMAKE_SUPPRESS_REGENERATION TRUE) # Supress the ZERO_CHECK generation
|
|
|
|
# -------------------- Utility functions --------------------
|
|
|
|
function(booleanize_str_find VAR)
|
|
if(${VAR} EQUAL -1)
|
|
unset(${VAR} PARENT_SCOPE)
|
|
else()
|
|
set(${VAR} 1 PARENT_SCOPE)
|
|
endif()
|
|
endfunction()
|
|
|
|
# -------------------- Start: initializations --------------------
|
|
|
|
# Should i load the toolchain passed as argument?
|
|
if((NOT TOOLCHAIN_LOADED) AND (NOT ${CMAKE_TOOLCHAIN_FILE} STREQUAL ""))
|
|
include(${CMAKE_TOOLCHAIN_FILE})
|
|
toolchain_force_compiler()
|
|
endif()
|
|
|
|
# Remove default, global compiler and linker flags set by CMake.
|
|
# Init: must come before project() command
|
|
set(CMAKE_C_FLAGS_INIT "")
|
|
set(CMAKE_CXX_FLAGS_INIT "")
|
|
set(CMAKE_EXE_LINKER_FLAGS_INIT "")
|
|
# Generic
|
|
set(CMAKE_CXX_FLAGS "")
|
|
set(CMAKE_C_FLAGS "")
|
|
set(CMAKE_EXE_LINKER_FLAGS "")
|
|
set(CMAKE_SHARED_LINKER_FLAGS "")
|
|
# Also clear build-type specific flags
|
|
set(CMAKE_CXX_FLAGS_DEBUG "")
|
|
set(CMAKE_CXX_FLAGS_RELEASE "")
|
|
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "")
|
|
set(CMAKE_CXX_FLAGS_MINSIZEREL "")
|
|
|
|
message(STATUS "Scanning system build tools...")
|
|
project(SphereServer CXX C) # does a scan for C++ and C compilers
|
|
|
|
# If we have not specified a toolchain, let's detect which one we should use, using the detected arch.
|
|
# We need to do this after "project", otherwise CMake doesn't know where it's running.
|
|
if(NOT TOOLCHAIN_LOADED)
|
|
include("cmake/DetectDefaultToolchain.cmake")
|
|
endif()
|
|
|
|
|
|
# Setup global flags, to be done before creating targets.
|
|
|
|
if(NOT DEFINED CMAKE_CXX_STANDARD)
|
|
# only set CMAKE_CXX_STANDARD if not already set
|
|
# this allows the standard to be set by the caller, for example with -DCMAKE_CXX_STANDARD:STRING=20
|
|
set(CMAKE_CXX_STANDARD 20)
|
|
elseif(CMAKE_CXX_STANDARD LESS 20)
|
|
message(WARNING "Current C++ standard ({CMAKE_CXX_STANDARD}) too low, defaulting to the minimum supported, 20.")
|
|
set(CMAKE_CXX_STANDARD 20)
|
|
endif()
|
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
|
set(CMAKE_CXX_SCAN_FOR_MODULES OFF) # disable C++ module scanning
|
|
set(CMAKE_CXX_VISIBILITY_PRESET "hidden")
|
|
set(CMAKE_VISIBILITY_INLINES_HIDDEN "YES")
|
|
|
|
# Need to clear shared library flags. If not, cmake sets -rdynamic and this
|
|
# add to the executable the full symbol table (included unused symbols).
|
|
# This is a problem because the binary is >700 KB bigger.
|
|
set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
|
|
set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
|
|
|
|
# In some cases, CMake also sets other predefined flags, which we don't want.
|
|
#[[
|
|
set(CMAKE_C_FLAGS_DEBUG "")
|
|
set(CMAKE_C_FLAGS_NIGHTLY "")
|
|
set(CMAKE_C_FLAGS_RELEASE "")
|
|
|
|
set(CMAKE_CXX_FLAGS_DEBUG "")
|
|
set(CMAKE_CXX_FLAGS_NIGHTLY "")
|
|
set(CMAKE_CXX_FLAGS_RELEASE "")
|
|
|
|
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "")
|
|
set(CMAKE_EXE_LINKER_FLAGS_NIGHTLY "")
|
|
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "")
|
|
]]
|
|
# Example: using MSVC, /RTC1 is globally added (all projects) to DEBUG builds. It's mostly fine, except in some cases where we don't want it...
|
|
# We might want to delete only /RTC* flags, instead of erasing all of them altogether.
|
|
#STRING (REGEX REPLACE "/RTC(su|[1su])" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
|
|
#STRING (REGEX REPLACE "/RTC(su|[1su])" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
|
|
|
|
# Also, it fails to create those predefined flags, which it needs, for custom build types (e.g. Nightly).
|
|
set(CMAKE_EXE_LINKER_FLAGS_NIGHTLY "")
|
|
|
|
|
|
# -------------------- GUI checkboxes --------------------
|
|
|
|
option(
|
|
CMAKE_NO_GIT_REVISION
|
|
"Do not try to retrieve the current git revision. Useful for building source not git-cloned from Github."
|
|
FALSE
|
|
)
|
|
if(WIN32)
|
|
option(WIN_SPAWN_CONSOLE "Spawn an additional console, useful for debugging." FALSE)
|
|
if(MSVC)
|
|
option(WIN_GENERATE_CRASHDUMP "For non-Debug builds, add Windows Structured Exception Handling and generate a Crash Dump if a fatal SE is thrown." FALSE)
|
|
endif()
|
|
endif()
|
|
option(FORCE_DEBUG_INFO "Force generation of debug info, useful for profiling Nightly/Release builds." FALSE)
|
|
option(CROSSCOMPILE "Are we compiling for a different target architecture?" FALSE)
|
|
option(
|
|
RUNTIME_STATIC_LINK
|
|
"Statically link inside the executable the runtime libraries? (MSVC, libc/libcc, libstdc++)."
|
|
FALSE
|
|
)
|
|
option(CMAKE_EXPORT_COMPILE_COMMANDS "Export compiler commands to compile_commands.json" TRUE)
|
|
set(CMAKE_LINKER_TYPE "DEFAULT" CACHE STRING "Linker to be used for the linking step.")
|
|
|
|
set(predef_LIB_LIBEV_BUILD FALSE)
|
|
if(NOT WIN32)
|
|
set(predef_LIB_LIBEV_BUILD TRUE)
|
|
endif()
|
|
option(LIB_LIBEV_BUILD "Build libev." ${predef_LIB_LIBEV_BUILD})
|
|
option(LIB_SQLITE_BUILD "Build sqlite." TRUE)
|
|
option(LIB_ZLIB_BUILD "Build zlib." TRUE)
|
|
|
|
if(NOT MSVC)
|
|
option(USE_COMPILER_HARDENING_OPTIONS "Enable compiler (even runtime) safety checks and code hardening." FALSE)
|
|
endif()
|
|
option(USE_ASAN "Enable AddressSanitizer." FALSE)
|
|
option(USE_UBSAN "Enable Undefined Behavior Sanitizer." FALSE)
|
|
option(USE_LSAN "Enable LeakSanitizer." FALSE)
|
|
option(USE_MSAN "Enable MemorySanitizer." FALSE)
|
|
|
|
option(UNIT_TESTING "Create an executable for unit tests." FALSE)
|
|
|
|
option(USE_CPPCHECK "Perform static analysis with CppCheck." FALSE)
|
|
|
|
set(ENABLED_SANITIZER FALSE CACHE INTERNAL BOOL "Am i using a sanitizer?")
|
|
if(USE_ASAN OR USE_MSAN OR USE_LSAN OR USE_MSAN)
|
|
set(ENABLED_SANITIZER TRUE)
|
|
endif()
|
|
|
|
if(USE_CPPCHECK)
|
|
include("cmake/CppCheck.cmake")
|
|
endif()
|
|
|
|
# -------------------- Stuff to set right away, after having parsed the checkboxes/CLI arguments.
|
|
|
|
set(is_win32_app_linker)
|
|
if(WIN32 AND NOT ${WIN_SPAWN_CONSOLE})
|
|
set(is_win32_app_linker WIN32) # if not set, it defaults to console subsystem
|
|
endif()
|
|
|
|
|
|
# -------------------- Stuff that needs to be executed after PROJECT but before ADD_EXECUTABLE
|
|
|
|
message(STATUS)
|
|
toolchain_after_project()
|
|
|
|
string(FIND "${CMAKE_GENERATOR}" "Makefiles" GEN_IS_MAKEFILE)
|
|
string(FIND "${CMAKE_GENERATOR}" "Ninja" GEN_IS_NINJA)
|
|
booleanize_str_find(GEN_IS_MAKEFILE)
|
|
booleanize_str_find(GEN_IS_NINJA)
|
|
|
|
if((GEN_IS_MAKEFILE OR GEN_IS_NINJA) AND (NOT MSVC))
|
|
set(SINGLE_TARGET 1)
|
|
endif()
|
|
|
|
# TODO: check if Ninja can handle different targets.
|
|
if(SINGLE_TARGET)
|
|
# If you want to manually specify the build type, call cmake with parameter: -DCMAKE_BUILD_TYPE=something
|
|
message(STATUS "Single-target build system (${CMAKE_GENERATOR}) detected: generating multiple projects!")
|
|
set (CMAKE_BUILD_TYPE "Nightly" CACHE STRING "Set the build type. Expected values: Debug, Nightly or Release.") # Set only if unset.
|
|
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Nightly" "Release")
|
|
if(NOT ${CMAKE_BUILD_TYPE} STREQUAL "")
|
|
if(
|
|
(NOT ${CMAKE_BUILD_TYPE} STREQUAL "Release")
|
|
AND (NOT ${CMAKE_BUILD_TYPE} STREQUAL "Debug")
|
|
AND (NOT ${CMAKE_BUILD_TYPE} STREQUAL "Nightly")
|
|
)
|
|
message(WARNING "Invalid parameter CMAKE_BUILD_TYPE (${CMAKE_BUILD_TYPE}), defaulting to Nightly.")
|
|
# -> needed only for MAKEFILE-STYLE generators, which can't switch between different configs
|
|
set(CMAKE_BUILD_TYPE "Nightly" CACHE STRING "" FORCE)
|
|
else()
|
|
message(STATUS "Generating only specified project: ${CMAKE_BUILD_TYPE}.")
|
|
endif()
|
|
else()
|
|
message(STATUS "No target specified: building all the projects (Release, Debug, Nightly).")
|
|
# The only situation supported here is using MSVC, and /MP (multi-core) is set in its compiler flags.
|
|
endif()
|
|
|
|
if(GEN_IS_MAKEFILE)
|
|
# Setting parallel make; ninja does that by default.
|
|
include(ProcessorCount)
|
|
processorcount(MAKE_THREADS)
|
|
if(NOT MAKE_THREADS EQUAL 0)
|
|
math(EXPR MAKE_THREADS "${MAKE_THREADS} + (${MAKE_THREADS}/2)") # Suggested number of threads: cores * 1.5
|
|
set(CMAKE_MAKE_PROGRAM "${CMAKE_MAKE_PROGRAM} -j${MAKE_THREADS}")
|
|
else()
|
|
message(STATUS "Can't determine CPU cores number. Parallel compilation turned off.")
|
|
endif()
|
|
endif()
|
|
else(SINGLE_TARGET)
|
|
message(STATUS "Multi-target build system detected: generating single project with multiple targets!")
|
|
set(CMAKE_CONFIGURATION_TYPES "Debug;Release;Nightly" CACHE STRING "" FORCE)
|
|
endif(SINGLE_TARGET)
|
|
|
|
|
|
# Include the list of all Sphere source files
|
|
include("src/CMakeSources.cmake")
|
|
|
|
if(UNIT_TESTING)
|
|
# Add the unit tests source files, to compile them and add to the IDe project files list
|
|
include("tests/CMakeSources.cmake")
|
|
endif()
|
|
|
|
# Configure output binaries
|
|
set(TARGETS "" CACHE INTERNAL "List of Sphere targets to build.")
|
|
if(SINGLE_TARGET)
|
|
if(("${CMAKE_BUILD_TYPE}" STREQUAL "") OR (${CMAKE_BUILD_TYPE} MATCHES "(R|r?)elease"))
|
|
set(TARGETS ${TARGETS} spheresvr_release)
|
|
add_executable(
|
|
spheresvr_release
|
|
${is_win32_app_linker}
|
|
${SPHERE_SOURCES} ${SPHERE_HEADERS}
|
|
#${docs_TEXT}
|
|
)
|
|
set_target_properties(spheresvr_release PROPERTIES OUTPUT_NAME SphereSvrX${ARCH_BITS}_release)
|
|
|
|
if(NOT ${FORCE_DEBUG_INFO})
|
|
add_custom_command(TARGET spheresvr_release POST_BUILD
|
|
COMMAND ${CMAKE_STRIP} $<TARGET_FILE:spheresvr_release>
|
|
COMMENT "Stripping executable"
|
|
)
|
|
endif()
|
|
endif()
|
|
if(("${CMAKE_BUILD_TYPE}" STREQUAL "") OR (${CMAKE_BUILD_TYPE} MATCHES "(N|n?)ightly"))
|
|
set(TARGETS ${TARGETS} spheresvr_nightly)
|
|
add_executable(
|
|
spheresvr_nightly
|
|
${is_win32_app_linker}
|
|
${SPHERE_SOURCES} ${SPHERE_HEADERS}
|
|
#${docs_TEXT}
|
|
)
|
|
set_target_properties(spheresvr_nightly PROPERTIES OUTPUT_NAME SphereSvrX${ARCH_BITS}_nightly)
|
|
|
|
if(NOT ${FORCE_DEBUG_INFO})
|
|
add_custom_command(TARGET spheresvr_nightly POST_BUILD
|
|
COMMAND ${CMAKE_STRIP} $<TARGET_FILE:spheresvr_nightly>
|
|
COMMENT "Stripping executable"
|
|
)
|
|
endif()
|
|
endif()
|
|
if(("${CMAKE_BUILD_TYPE}" STREQUAL "") OR (${CMAKE_BUILD_TYPE} MATCHES "(D|d?)ebug"))
|
|
set(TARGETS ${TARGETS} spheresvr_debug)
|
|
add_executable(
|
|
spheresvr_debug
|
|
${is_win32_app_linker}
|
|
${SPHERE_SOURCES} ${SPHERE_HEADERS}
|
|
#${docs_TEXT}
|
|
)
|
|
set_target_properties(spheresvr_debug PROPERTIES OUTPUT_NAME SphereSvrX${ARCH_BITS}_debug)
|
|
endif()
|
|
else(SINGLE_TARGET)
|
|
set(TARGETS ${TARGETS} spheresvr)
|
|
add_executable(spheresvr
|
|
${is_win32_app_linker}
|
|
${SPHERE_SOURCES} ${SPHERE_HEADERS}
|
|
${docs_TEXT}
|
|
)
|
|
set_target_properties(spheresvr PROPERTIES OUTPUT_NAME_RELEASE SphereSvrX${ARCH_BITS}_release)
|
|
set_target_properties(spheresvr PROPERTIES OUTPUT_NAME_NIGHTLY SphereSvrX${ARCH_BITS}_nightly)
|
|
set_target_properties(spheresvr PROPERTIES OUTPUT_NAME_DEBUG SphereSvrX${ARCH_BITS}_debug)
|
|
|
|
# To be tested
|
|
#add_custom_command(TARGET spheresvr POST_BUILD
|
|
# $<$<CONFIG:Release>:COMMAND ${CMAKE_STRIP} $<TARGET_FILE:spheresvr>>
|
|
# $<$<CONFIG:Nightly>:COMMAND ${CMAKE_STRIP} $<TARGET_FILE:spheresvr>>
|
|
# COMMENT "Stripping executable"
|
|
#)
|
|
endif(SINGLE_TARGET)
|
|
|
|
foreach(tgt ${TARGETS})
|
|
#set_target_properties(${tgt} PROPERTIES CXX_EXTENSIONS OFF)
|
|
#target_compile_features(${tgt} PUBLIC cxx_std_20)
|
|
target_precompile_headers(${tgt} ${pch_list})
|
|
endforeach()
|
|
|
|
|
|
# --------------------
|
|
|
|
message(STATUS)
|
|
include("${CMAKE_SOURCE_DIR}/cmake/CommonCompilerFlags.cmake")
|
|
|
|
# --------------------
|
|
|
|
# Now include external libraries
|
|
|
|
message(STATUS)
|
|
message(STATUS "Configuring external libraries...")
|
|
add_subdirectory(lib)
|
|
|
|
toolchain_exe_stuff() # stuff to be executed after ADD_EXECUTABLE
|
|
|
|
if(UNIT_TESTING)
|
|
include("tests/CMakeLists.txt") # quick and dirty
|
|
setup_tests()
|
|
endif()
|
|
|
|
# Get the Git revision number
|
|
message(STATUS)
|
|
message(STATUS "Retrieving git data...")
|
|
include("cmake/GitStatus.cmake")
|
|
message(STATUS)
|
|
|