Files
Fletcher Dunn fd9100873b Remove custom MSVC CRT management
Use CMake's built-in CMAKE_MSVC_RUNTIME_LIBRARY instead.
This requires CMake 3.15), so bump cmake_minimum_required accordingly.
2026-05-03 21:00:32 -07:00

229 lines
9.0 KiB
CMake

cmake_minimum_required(VERSION 3.15)
# If vcpkg present as submodule, bring in the toolchain
if( EXISTS ${CMAKE_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake )
message(STATUS "Found ${CMAKE_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake; using it!")
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake
CACHE STRING "Vcpkg toolchain file")
endif()
include(CheckIPOSupported)
include(CMakeDependentOption)
include(CMakePushCheckState)
include(CheckSymbolExists)
# CMP0069: INTERPROCEDURAL_OPTIMIZATION is enforced when enabled.
# This variable is needed for abseil, which has a different
# cmake_minimum_required version set (3.5).
set(CMAKE_POLICY_DEFAULT_CMP0069 NEW)
# Put all the output from all projects into the same folder
#set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
project(GameNetworkingSockets C CXX)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
include(DefaultBuildType)
find_package(Sanitizers)
if(SANITIZE_ADDRESS OR SANITIZE_THREAD OR SANITIZE_MEMORY OR SANITIZE_UNDEFINED)
set(SANITIZE ON)
endif()
add_definitions( -DVALVE_CRYPTO_ENABLE_25519 )
if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
add_definitions(
-D_CRT_SECURE_NO_WARNINGS
-D_CRT_NONSTDC_NO_WARNINGS
)
endif()
option(BUILD_STATIC_LIB "Build the static link version of the client library" ON)
option(BUILD_SHARED_LIB "Build the shared library version of the client library" ON)
option(BUILD_EXAMPLES "Build the included examples" OFF)
option(BUILD_TESTS "Build crypto, pki and network connection tests" OFF)
option(BUILD_TOOLS "Build cert management tool" OFF)
option(LTO "Enable Link-Time Optimization" OFF)
option(ENABLE_ICE "Enable support for NAT-punched P2P connections using ICE protocol. Build native ICE client" ON)
option(USE_STEAMWEBRTC "Build Google's WebRTC library to get ICE support for P2P" OFF)
option(Protobuf_USE_STATIC_LIBS "Link with protobuf statically" OFF)
#
# Primary crypto library (for AES, SHA256, etc)
#
set(useCryptoOptions OpenSSL libsodium BCrypt)
set(USE_CRYPTO "OpenSSL" CACHE STRING "Crypto library to use for AES/SHA256")
set_property(CACHE USE_CRYPTO PROPERTY STRINGS ${useCryptoOptions})
list(FIND useCryptoOptions "${USE_CRYPTO}" useCryptoIndex)
if(useCryptoIndex EQUAL -1)
message(FATAL_ERROR "USE_CRYPTO must be one of: ${useCryptoOptions}")
endif()
if(USE_CRYPTO STREQUAL "BCrypt" AND NOT WIN32)
message(FATAL_ERROR "USE_CRYPTO=\"BCrypt\" is only valid on Windows")
endif()
if(LTO)
check_ipo_supported()
endif()
if (WIN32)
#
# Strip compiler flags which conflict with ones we explicitly set. If we don't
# do this, then we get a warning on every file we compile for the library.
#
string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
string(REPLACE "/GR" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
if (USE_CRYPTO STREQUAL "BCrypt")
#
# Check whether BCrypt can be used with this SDK version
#
try_compile(BCRYPT_AVAILABLE "${CMAKE_CURRENT_BINARY_DIR}/tryCompile" SOURCES "${CMAKE_CURRENT_LIST_DIR}/cmake/tryCompileTestBCrypt.cpp" LINK_LIBRARIES bcrypt OUTPUT_VARIABLE BCRYPT_AVAILABILITY_TEST_MESSAGES)
if (NOT BCRYPT_AVAILABLE)
message(STATUS ${BCRYPT_AVAILABILITY_TEST_MESSAGES})
message(FATAL_ERROR "You're on Windows but BCrypt seems to be unavailable, you will need OpenSSL")
endif()
endif()
endif()
if (USE_CRYPTO STREQUAL "OpenSSL")
# Match the OpenSSL runtime to our setting.
# Note that once found the library paths are cached and will not change if the option is changed.
if (MSVC AND CMAKE_MSVC_RUNTIME_LIBRARY MATCHES "^MultiThreaded($|Debug$)")
set(OPENSSL_MSVC_STATIC_RT TRUE)
endif()
find_package(OpenSSL REQUIRED)
message( STATUS "OPENSSL_INCLUDE_DIR = ${OPENSSL_INCLUDE_DIR}" )
# Ensure the OpenSSL version is recent enough. We need a bunch of EVP
# functionality.
cmake_push_check_state()
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
set(CMAKE_REQUIRED_LIBRARIES OpenSSL::Crypto)
if(WIN32 AND OPENSSL_USE_STATIC_LIBS)
list(APPEND CMAKE_REQUIRED_LIBRARIES ws2_32 crypt32)
endif()
check_symbol_exists(EVP_MD_CTX_free openssl/evp.h OPENSSL_NEW_ENOUGH)
if (NOT OPENSSL_NEW_ENOUGH)
message(FATAL_ERROR "Cannot find EVP_MD_CTX_free in OpenSSL headers/libs for the target architecture. Check that you're using OpenSSL 1.1.0 or later.")
endif()
cmake_pop_check_state()
cmake_push_check_state()
set(CMAKE_REQUIRED_LIBRARIES OpenSSL::Crypto)
if(WIN32 AND OPENSSL_USE_STATIC_LIBS)
list(APPEND CMAKE_REQUIRED_LIBRARIES ws2_32 crypt32)
endif()
if(USE_CRYPTO25519 STREQUAL "OpenSSL")
check_symbol_exists(EVP_PKEY_get_raw_public_key openssl/evp.h OPENSSL_HAS_25519_RAW)
endif()
cmake_pop_check_state()
endif()
if(USE_CRYPTO25519 STREQUAL "OpenSSL" AND NOT OPENSSL_HAS_25519_RAW)
message(FATAL_ERROR "Cannot find (EVP_PKEY_get_raw_public_key in OpenSSL headers/libs for the target architecture. Please use -DUSE_CRYPTO25519=Reference or upgrade OpenSSL to 1.1.1 or later")
endif()
if(USE_CRYPTO STREQUAL "libsodium" OR USE_CRYPTO25519 STREQUAL "libsodium")
find_package(sodium REQUIRED)
endif()
if(USE_CRYPTO STREQUAL "libsodium")
if(NOT CMAKE_SYSTEM_PROCESSOR MATCHES "amd64.*|x86_64.*|AMD64.*|i686.*|i386.*|x86.*")
message(FATAL_ERROR "-DUSE_CRYPTO=libsodium invalid, libsodium AES implementation only works on x86/x86_64 CPUs")
endif()
endif()
# We always need at least sse2 on x86
if(CMAKE_SYSTEM_PROCESSOR MATCHES "amd64.*|x86_64.*|AMD64.*|i686.*|i386.*|x86.*")
set(TARGET_ARCH_FLAGS "-msse2")
endif()
function(set_target_common_gns_properties TGT)
target_compile_definitions( ${TGT} PRIVATE GOOGLE_PROTOBUF_NO_RTTI )
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
# Reduce binary size by allowing for a pseudo-"function-level linking" analog
target_compile_options(${TGT} PRIVATE -ffunction-sections -fdata-sections ${TARGET_ARCH_FLAGS})
endif()
if(CMAKE_SYSTEM_NAME MATCHES Linux)
target_compile_definitions(${TGT} PUBLIC LINUX)
elseif(CMAKE_SYSTEM_NAME MATCHES Darwin)
target_compile_definitions(${TGT} PUBLIC OSX)
elseif(CMAKE_SYSTEM_NAME MATCHES FreeBSD)
target_compile_definitions(${TGT} PUBLIC FREEBSD)
elseif(CMAKE_SYSTEM_NAME MATCHES OpenBSD)
target_compile_definitions(${TGT} PUBLIC OPENBSD)
elseif(CMAKE_SYSTEM_NAME MATCHES Windows)
target_compile_definitions(${TGT} PUBLIC _WINDOWS)
if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
if(NOT Protobuf_USE_STATIC_LIBS)
target_compile_definitions(${TGT} PRIVATE PROTOBUF_USE_DLLS)
endif()
target_compile_options(${TGT} PRIVATE
/EHs-c- # Disable C++ exceptions
# Below are warnings we can't fix and don't want to see (mostly from protobuf, some from MSVC standard library)
/wd4146 # include/google/protobuf/wire_format_lite.h(863): warning C4146: unary minus operator applied to unsigned type, result still unsigned
/wd4530 # .../xlocale(319): warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc
/wd4244 # google/protobuf/wire_format_lite.h(935): warning C4244: 'argument': conversion from 'google::protobuf::uint64' to 'google::protobuf::uint32', possible loss of data
/wd4251 # 'google::protobuf::io::CodedOutputStream::default_serialization_deterministic_': struct 'std::atomic<bool>' needs to have dll-interface to be used by clients of class
/wd4267 # google/protobuf/has_bits.h(73): warning C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data
)
# Disable RTTI except in Debug, because we use dynamic_cast in assert_cast
target_compile_options(${TGT} PRIVATE $<IF:$<CONFIG:Debug>,/GR,/GR->)
else()
target_compile_definitions(${TGT} PRIVATE
__STDC_FORMAT_MACROS=1
__USE_MINGW_ANSI_STDIO=0
)
target_compile_options(${TGT} PRIVATE -fno-stack-protector)
endif()
else()
message(FATAL_ERROR "Could not identify your target operating system")
endif()
if(NOT CMAKE_SYSTEM_NAME MATCHES Windows)
target_compile_options(${TGT} PRIVATE -fstack-protector-strong)
endif()
if(LTO)
set_target_properties(${TGT} PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()
set_target_properties(${TGT} PROPERTIES
CXX_STANDARD 11
)
endfunction()
if(BUILD_EXAMPLES)
if ( NOT BUILD_SHARED_LIB )
# See also portfile.cmake
message(FATAL_ERROR "Must build shared lib (-DBUILD_SHARED_LIB=ON) to build examples")
endif()
endif()
add_subdirectory(examples) # examples/CMakeLists will check what's defined and only add appropriate targets
if(BUILD_TESTS)
if ( NOT BUILD_STATIC_LIB )
# See also portfile.cmake
message(FATAL_ERROR "Must build static lib (-DBUILD_STATIC_LIB=ON) to build tests")
endif()
enable_testing()
add_subdirectory(tests)
endif()
add_subdirectory(src)
#message(STATUS "---------------------------------------------------------")
message(STATUS "Crypto library for AES/SHA256: ${USE_CRYPTO}")
message(STATUS "Crypto library for ed25519/curve25519: ${USE_CRYPTO25519}")
message(STATUS "Link-time optimization: ${LTO}")
#message(STATUS "---------------------------------------------------------")