From e194ba7dafc56528b423fc2f1966c754be9f4f3a Mon Sep 17 00:00:00 2001 From: cbnolok Date: Mon, 7 Oct 2024 15:06:47 +0200 Subject: [PATCH] Fixed path concat regression and fixed come cmake options being loaded before being set. --- CMakeLists.txt | 101 +++++++++--------- cmake/toolchains/Windows-MSVC.cmake | 42 +++++--- .../include/Windows-Clang_common.inc.cmake | 6 +- .../include/Windows-GNU_common.inc.cmake | 2 +- src/common/CException.h | 6 +- src/common/crashdump/crashdump.h | 2 + src/common/sphere_library/CSFile.cpp | 7 +- src/game/CServer.cpp | 2 +- src/game/spheresvr.cpp | 8 +- src/sphere/threads.cpp | 4 +- 10 files changed, 104 insertions(+), 76 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 491c597a2..445f0334b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,47 +3,6 @@ cmake_minimum_required(VERSION 3.24) set(CMAKE_SUPPRESS_REGENERATION TRUE) # Supress the ZERO_CHECK generation -# -------------------- GUI checkboxes -------------------- -if(NOT MSVC) - set (CMAKE_BUILD_TYPE "Nightly" CACHE STRING "Which build type to build? Expected values: Debug, Nightly or Release.") -endif() - -option( - CMAKE_NO_GIT_REVISION - "Do not try to retrieve the current git revision. Useful for building source not git-cloned from Github." - 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(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(WIN32) - option(WIN32_SPAWN_CONSOLE "Spawn an additional console, useful for debugging." FALSE) -endif() - -option(USE_COMPILER_HARDENING_OPTIONS "Enable compiler (even runtime) safety checks and code hardening." FALSE) -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) - -set(ENABLED_SANITIZER CACHE INTERNAL BOOL FALSE) -if(USE_ASAN OR USE_MSAN OR USE_LSAN OR USE_MSAN) - set(ENABLED_SANITIZER TRUE) -endif() - # -------------------- Utility functions -------------------- function(booleanize_str_find VAR) @@ -63,9 +22,14 @@ if((NOT TOOLCHAIN_LOADED) AND (NOT ${CMAKE_TOOLCHAIN_FILE} STREQUAL "")) endif() 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) @@ -109,16 +73,57 @@ set(CMAKE_EXE_LINKER_FLAGS_RELEASE "") # 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 +) +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(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(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() + +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) + +set(ENABLED_SANITIZER CACHE INTERNAL BOOL FALSE) +if(USE_ASAN OR USE_MSAN OR USE_LSAN OR USE_MSAN) + set(ENABLED_SANITIZER TRUE) +endif() + + +# -------------------- Stuff to set right away, after having parsed the checkboxes/CLI arguments. set(is_win32_app_linker) -if(WIN32 AND NOT ${WIN32_SPAWN_CONSOLE}) +if(WIN32 AND NOT ${WIN_SPAWN_CONSOLE}) set(is_win32_app_linker WIN32) # if not set, it defaults to console subsystem endif() -# If we have not specified a toolchain, let's detect which one we should use, using the detected arch. -if(NOT TOOLCHAIN_LOADED) - include("cmake/DetectDefaultToolchain.cmake") -endif() # -------------------- Stuff that needs to be executed after PROJECT but before ADD_EXECUTABLE @@ -137,9 +142,9 @@ 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 - # TODO: add NightlyWithDebInfo ? 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( diff --git a/cmake/toolchains/Windows-MSVC.cmake b/cmake/toolchains/Windows-MSVC.cmake index 3994a6e7f..4df3bad9f 100644 --- a/cmake/toolchains/Windows-MSVC.cmake +++ b/cmake/toolchains/Windows-MSVC.cmake @@ -34,7 +34,7 @@ function(toolchain_exe_stuff) #-- Configure the Windows application type and add global linker flags. - if(${WIN32_SPAWN_CONSOLE}) + if(${WIN_SPAWN_CONSOLE}) add_link_options("LINKER:/ENTRY:WinMainCRTStartup") # Handled by is_win32_app_linker -> "LINKER:/SUBSYSTEM:CONSOLE" set(PREPROCESSOR_DEFS_EXTRA _WINDOWS_CONSOLE) #ELSE () @@ -102,16 +102,28 @@ function(toolchain_exe_stuff) endif() set(cxx_compiler_flags_common ${cxx_compiler_flags_common} /Zc:preprocessor ${local_msvc_compat_options}) - # Needed, otherwise throws a error... Regression? + # Needed, otherwise throws a error... Regression in CMake? set(CMAKE_C_FLAGS_DEBUG_INIT "" INTERNAL) set(CMAKE_CXX_FLAGS_DEBUG_INIT "" INTERNAL) + if(RUNTIME_STATIC_LINK) + set(local_msvc_cmdline_runtime_lib_debug /MTd) + set(local_msvc_cmdline_runtime_lib_nondebug /MT) + else() + set(local_msvc_cmdline_runtime_lib_debug /MDd) + set(local_msvc_cmdline_runtime_lib_nondebug /MD) + endif() + if(WIN_GENERATE_CRASHDUMP) + set(local_msvc_cmdline_exception_handler /EHa) + else() + set(local_msvc_exception_handler /EHsc) + endif() # gersemi: off target_compile_options(spheresvr PRIVATE ${cxx_compiler_flags_common} - $<$: $,/MT,/MD> /EHa /Oy /GL /GA /Gw /Gy /GF $,/O1 /Zi,/O2>> - $<$: $,/MT,/MD> /EHa /Oy /GL /GA /Gw /Gy /GF $,/O1 /Zi,/O2>> - $<$: $,/MTd,/MDd> /EHsc /Oy- /ob1 /Od /Gs $,/Zi,/ZI>> + $<$: ${local_msvc_cmdline_runtime_lib_nondebug} ${local_msvc_exception_handler} /Oy /GL /GA /Gw /Gy /GF $,/O1 /Zi,/O2>> + $<$: ${local_msvc_cmdline_runtime_lib_nondebug} ${local_msvc_exception_handler} /Oy /GL /GA /Gw /Gy /GF $,/O1 /Zi,/O2>> + $<$: ${local_msvc_cmdline_runtime_lib_debug} /EHsc /Oy- /ob1 /Od /Gs $,/Zi,/ZI>> # ASan (and compilation for ARM arch) doesn't support edit and continue option (ZI) ) # gersemi: on @@ -119,7 +131,6 @@ function(toolchain_exe_stuff) if("${ARCH}" STREQUAL "x86_64") target_compile_options(spheresvr PRIVATE /arch:SSE2) endif() - #-- Apply linker flags. # For some reason only THIS one isn't created, and CMake complains with an error... @@ -143,11 +154,13 @@ function(toolchain_exe_stuff) #-- Set define macros. # Common defines + #gersemi: off target_compile_definitions( spheresvr PRIVATE ${PREPROCESSOR_DEFS_EXTRA} - $<$>:_GITVERSION> + $<$>: + _GITVERSION> _CRT_SECURE_NO_WARNINGS # Temporary setting _CRT_SECURE_NO_WARNINGS to do not spam so much in the build proccess. _EXCEPTIONS_DEBUG @@ -157,15 +170,18 @@ function(toolchain_exe_stuff) # Removing WINSOCK warnings until the code gets updated or reviewed. # Per-build defines $<$>: - NDEBUG> + NDEBUG> $<$: - _NIGHTLYBUILD - THREAD_TRACK_CALLSTACK> + _NIGHTLYBUILD + THREAD_TRACK_CALLSTACK> $<$: - _DEBUG - THREAD_TRACK_CALLSTACK - _PACKETDUMP> + _DEBUG + THREAD_TRACK_CALLSTACK + _PACKETDUMP> + $<$: + WINDOWS_GENERATE_CRASHDUMP> ) + #gersemi: on #-- Custom output directory. diff --git a/cmake/toolchains/include/Windows-Clang_common.inc.cmake b/cmake/toolchains/include/Windows-Clang_common.inc.cmake index a01a37d09..bf2094af3 100644 --- a/cmake/toolchains/include/Windows-Clang_common.inc.cmake +++ b/cmake/toolchains/include/Windows-Clang_common.inc.cmake @@ -14,13 +14,13 @@ endfunction() function(toolchain_exe_stuff_common) #-- Configure the Windows application type and add global linker flags. - if(${WIN32_SPAWN_CONSOLE}) + if(${WIN_SPAWN_CONSOLE}) set(PREPROCESSOR_DEFS_EXTRA _WINDOWS_CONSOLE) if(${CLANG_USE_GCC_LINKER}) # --entry might not work - add_link_options("LINKER:--entry=WinMainCRTStartup") # Handled by is_win32_app_linker -> "LINKER:SHELL:-m$,CONSOLE,WINDOWS>" + add_link_options("LINKER:--entry=WinMainCRTStartup") # Handled by is_win32_app_linker -> "LINKER:SHELL:-m$,CONSOLE,WINDOWS>" else() - add_link_options("LINKER:/ENTRY:WinMainCRTStartup") # Handled by is_win32_app_linker -> "LINKER:SHELL:/SUBSYSTEM:$,CONSOLE,WINDOWS>" + add_link_options("LINKER:/ENTRY:WinMainCRTStartup") # Handled by is_win32_app_linker -> "LINKER:SHELL:/SUBSYSTEM:$,CONSOLE,WINDOWS>" endif() endif() diff --git a/cmake/toolchains/include/Windows-GNU_common.inc.cmake b/cmake/toolchains/include/Windows-GNU_common.inc.cmake index 0dfdb2968..c2a90d51f 100644 --- a/cmake/toolchains/include/Windows-GNU_common.inc.cmake +++ b/cmake/toolchains/include/Windows-GNU_common.inc.cmake @@ -9,7 +9,7 @@ function(toolchain_exe_stuff_common) #-- Configure the Windows application type. # Subsystem is already managed by is_win32_app_linker. GCC doesn't need us to specify the entry point. - #IF (${WIN32_SPAWN_CONSOLE}) + #IF (${WIN_SPAWN_CONSOLE}) # add_link_options ("LINKER:SHELL:-mconsole") # SET (PREPROCESSOR_DEFS_EXTRA _WINDOWS_CONSOLE) ##ELSE () diff --git a/src/common/CException.h b/src/common/CException.h index b141afcd3..4a121107f 100644 --- a/src/common/CException.h +++ b/src/common/CException.h @@ -13,13 +13,13 @@ # define WINDOWS_HAS_SEH 1 #endif -#if defined (WINDOWS_HAS_SEH) && defined(_NIGHTLYBUILD) +#if defined(WINDOWS_HAS_SEH) && defined(WINDOWS_GENERATE_CRASHDUMP) // We don't want this for Release build because, in order to call _set_se_translator, we should set the /EHa // compiler flag, which slows down code a bit. # define WINDOWS_SPHERE_SHOULD_HANDLE_STRUCTURED_EXCEPTIONS 1 -#endif +//#endif -#if defined(WINDOWS_SPHERE_SHOULD_HANDLE_STRUCTURED_EXCEPTIONS) && !defined(_NO_CRASHDUMP) +//2#if defined(WINDOWS_SPHERE_SHOULD_HANDLE_STRUCTURED_EXCEPTIONS) && defined(WINDOWS_GENERATE_CRASHDUMP) // Also, the crash dump generating code works only when Structured Exception Handling is enabled # define WINDOWS_SHOULD_EMIT_CRASH_DUMP 1 #endif diff --git a/src/common/crashdump/crashdump.h b/src/common/crashdump/crashdump.h index 5de0b33ef..401727ee7 100644 --- a/src/common/crashdump/crashdump.h +++ b/src/common/crashdump/crashdump.h @@ -3,6 +3,8 @@ #include +// TODO: enable creation of the crash dump also for mingw, since it can manage windows structured exceptions. + #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN // include just windows.h without the other winapi headers, we'll add them manually when needed #endif diff --git a/src/common/sphere_library/CSFile.cpp b/src/common/sphere_library/CSFile.cpp index 513bf8793..b652df0ec 100644 --- a/src/common/sphere_library/CSFile.cpp +++ b/src/common/sphere_library/CSFile.cpp @@ -438,14 +438,17 @@ CSString CSFile::GetMergedFileName( lpctstr pszBase, lpctstr pszName ) // static size_t len = 0; if ( pszBase && pszBase[0] ) { - len = Str_CopyLimitNull( ptcFilePath, pszBase, sizeof(ptcFilePath) - 1); // eventually, leave space for the (back)slash - if (len && ptcFilePath[len - 1] != '\\' && ptcFilePath[len - 1] != '/') + len = Str_CopyLimitNull(ptcFilePath, pszBase, sizeof(ptcFilePath) - 1); // eventually, leave space for the (back)slash + if ((len > 1) && (ptcFilePath[len - 1] != '\\') && (ptcFilePath[len - 1] != '/')) { + // Append the slash/backslash, overwriting the string terminator. #ifdef _WIN32 ptcFilePath[len] = '\\'; #else ptcFilePath[len] = '/'; #endif + // Add back the string terminator. We're sure we won't overflow since we passed sizeof(ptcFilePath) - 1. + ptcFilePath[len + 1] = '\0'; } } else diff --git a/src/game/CServer.cpp b/src/game/CServer.cpp index 5e35bacd6..e821780e3 100644 --- a/src/game/CServer.cpp +++ b/src/game/CServer.cpp @@ -2361,7 +2361,7 @@ bool CServer::CommandLine( int argc, tchar * argv[] ) } } continue; -#if defined(_WIN32) && !defined(_DEBUG) && !defined(_NO_CRASHDUMP) +#if defined(_WIN32) && !defined(_DEBUG) && defined(WINDOWS_GENERATE_CRASHDUMP) case 'E': CrashDump::Enable(); if (CrashDump::IsEnabled()) diff --git a/src/game/spheresvr.cpp b/src/game/spheresvr.cpp index 12708dc69..6f7fdeb5a 100644 --- a/src/game/spheresvr.cpp +++ b/src/game/spheresvr.cpp @@ -207,16 +207,16 @@ bool MainThread::shouldExit() noexcept static bool WritePidFile(int iMode = 0) { - lpctstr file = SPHERE_FILE ".pid"; + lpctstr fileName = SPHERE_FILE ".pid"; FILE* pidFile; if (iMode == 1) // delete { - return (STDFUNC_UNLINK(file) == 0); + return (STDFUNC_UNLINK(fileName) == 0); } else if (iMode == 2) // check for .pid file { - pidFile = fopen(file, "r"); + pidFile = fopen(fileName, "r"); if (pidFile) { g_Log.Event(LOGM_INIT, SPHERE_FILE ".pid already exists. Secondary launch or unclean shutdown?\n"); @@ -226,7 +226,7 @@ static bool WritePidFile(int iMode = 0) } else { - pidFile = fopen(file, "w"); + pidFile = fopen(fileName, "w"); if (pidFile) { pid_t spherepid = STDFUNC_GETPID(); diff --git a/src/sphere/threads.cpp b/src/sphere/threads.cpp index 9eb3d26f6..aacad6db1 100644 --- a/src/sphere/threads.cpp +++ b/src/sphere/threads.cpp @@ -178,7 +178,8 @@ void ThreadHolder::push(AbstractThread *thread) noexcept { //throw CSError(LOGL_FATAL, 0, "AbstractThread not being an AbstractSphereThread?"); STDERR_LOG("AbstractThread not being an AbstractSphereThread?"); - fExceptionThrown = true; + //fExceptionThrown = true; + goto soft_throw; } std::unique_lock lock(m_mutex); @@ -223,6 +224,7 @@ void ThreadHolder::push(AbstractThread *thread) noexcept if (fExceptionThrown) { +soft_throw: // Should never happen. RaiseImmediateAbort(); }