From 2a0c0d58bc8bfd98c11506e82d6729ef6038a158 Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Wed, 10 Jun 2026 11:27:14 +0300 Subject: [PATCH 1/6] Fix Linux/clang detection in CMake Replace the CMake>=3.25-only LINUX variable with UNIX AND NOT APPLE, and the non-existent CLANG variable with a CMAKE_CXX_COMPILER_ID match so the clang libc++ flags are actually applied. Co-Authored-By: Claude Opus 4.8 (1M context) --- CMakeLists.txt | 4 +++- sample/CMakeLists.txt | 4 ++-- sample_shared/CMakeLists.txt | 6 ++++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dd173c58..32bb790b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -193,7 +193,9 @@ elseif(APPLE) create_source_groups(MACOS_SOURCES) -elseif(LINUX) +elseif(UNIX AND NOT APPLE) + # Linux (the LINUX variable only exists in CMake >= 3.25; UNIX AND NOT APPLE + # works on all supported versions, so GUID_STDLIB is always defined here). set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGUID_STDLIB -std=c++17") if (CMAKE_CXX_COMPILER MATCHES "clang") diff --git a/sample/CMakeLists.txt b/sample/CMakeLists.txt index f8015670..1c7fef42 100644 --- a/sample/CMakeLists.txt +++ b/sample/CMakeLists.txt @@ -7,10 +7,10 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/Release") set(CMAKE_CXX_STANDARD 17) -if(LINUX) +if(UNIX AND NOT APPLE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") - if(CLANG) + if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") endif() diff --git a/sample_shared/CMakeLists.txt b/sample_shared/CMakeLists.txt index ed1e7821..c9cae162 100644 --- a/sample_shared/CMakeLists.txt +++ b/sample_shared/CMakeLists.txt @@ -6,10 +6,12 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/Release") set(CMAKE_CXX_STANDARD 17) -if(LINUX) +if(UNIX AND NOT APPLE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") - if(CLANG) + # Match the library's standard-library choice so the sample's ABI lines up + # with libGameAnalytics when built with clang. + if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") endif() endif() From 653c115970ed166849e74ae1cd3908eac9ca7d70 Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Wed, 10 Jun 2026 11:27:21 +0300 Subject: [PATCH 2/6] Use static-md vcpkg triplet for Windows shared builds Statically link curl/openssl/zlib into the DLL so the Unity plugin is a single self-contained GameAnalytics.dll. The -static-md variant keeps the dynamic CRT (/MD) to match shared builds. Co-Authored-By: Claude Opus 4.8 (1M context) --- setup.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/setup.py b/setup.py index bc97e123..aee990bf 100644 --- a/setup.py +++ b/setup.py @@ -101,6 +101,14 @@ def main(): triplet = f'{arch}-{platform}' + # On Windows, statically link curl/openssl/zlib into the DLL so the Unity + # plugin is a single self-contained GameAnalytics.dll (mirrors macOS, where + # vcpkg's default triplet already produces static deps). The "-static-md" + # variant keeps the dynamic CRT (/MD), matching CMAKE_MSVC_RUNTIME_LIBRARY + # for shared builds; plain "-static" would use /MT and conflict. + if args.platform.startswith('win') and args.shared: + triplet = f'{arch}-windows-static-md' + if args.platform == 'osx': osx_arch = arch if arch == 'arm64' else 'x86_64' # no official universal triplet for osx vcpkg cmake_command += f' -DVCPKG_HOST_TRIPLET={triplet}' From c91c88a130d7f25b3e1665514098cadca55b576a Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Wed, 10 Jun 2026 11:27:21 +0300 Subject: [PATCH 3/6] Self-heal incompatible cached SDK config Discard an unparseable cached config (e.g. legacy C# base64 format) instead of logging it as an error; a fresh config is fetched on init and rewritten as JSON. Co-Authored-By: Claude Opus 4.8 (1M context) --- source/gameanalytics/GAState.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/gameanalytics/GAState.cpp b/source/gameanalytics/GAState.cpp index f1e8d8de..ae1b6efe 100644 --- a/source/gameanalytics/GAState.cpp +++ b/source/gameanalytics/GAState.cpp @@ -637,7 +637,11 @@ namespace gameanalytics } catch (json::exception& e) { - logging::GALogger::e(e.what()); + // Cached config is unparseable (e.g. written by the legacy C# SDK + // in binary-base64 instead of JSON). Discard the stale row; a fresh + // config is fetched on init and rewritten as JSON, so this self-heals. + logging::GALogger::d("Discarding incompatible cached sdk config: %s", e.what()); + store::GAStore::setState("sdk_config_cached", ""); } } From c247cbc43b5dd0340979bcfd1f1e0f4d22690572 Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Wed, 10 Jun 2026 13:37:10 +0300 Subject: [PATCH 4/6] Update GALinux.cpp --- source/gameanalytics/Platform/GALinux.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/source/gameanalytics/Platform/GALinux.cpp b/source/gameanalytics/Platform/GALinux.cpp index 417afb80..ea3a7c5f 100644 --- a/source/gameanalytics/Platform/GALinux.cpp +++ b/source/gameanalytics/Platform/GALinux.cpp @@ -81,9 +81,19 @@ std::string gameanalytics::GAPlatformLinux::getOSVersion() std::string version; int const strSize = strlen(info.release); + int dotCount = 0; for (size_t i = 0; i < strSize; ++i) { - if (!isdigit(info.release[i]) && info.release[i] != '.') + if (info.release[i] == '.') + { + ++dotCount; + if (dotCount == 3) + { + version = std::string(info.release, info.release + i); + break; + } + } + else if (!isdigit(info.release[i])) { version = std::string(info.release, info.release + i); break; From d17034008fd1d20b65f16fff443ab4bb7010023b Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Mon, 10 Aug 2026 15:38:40 +0300 Subject: [PATCH 5/6] fix linux --- CMakeLists.txt | 5 ++--- sample_shared/CMakeLists.txt | 2 -- setup.py | 6 +----- source/gameanalytics/GAState.cpp | 4 +--- source/gameanalytics/Platform/GALinux.cpp | 14 ++++++++------ 5 files changed, 12 insertions(+), 19 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 32bb790b..e4603c81 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -194,11 +194,10 @@ elseif(APPLE) create_source_groups(MACOS_SOURCES) elseif(UNIX AND NOT APPLE) - # Linux (the LINUX variable only exists in CMake >= 3.25; UNIX AND NOT APPLE - # works on all supported versions, so GUID_STDLIB is always defined here). + # Linux set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGUID_STDLIB -std=c++17") - if (CMAKE_CXX_COMPILER MATCHES "clang") + if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") message(STATUS "Detected Clang compiler: ${CMAKE_CXX_COMPILER}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") endif() diff --git a/sample_shared/CMakeLists.txt b/sample_shared/CMakeLists.txt index c9cae162..b0107ac4 100644 --- a/sample_shared/CMakeLists.txt +++ b/sample_shared/CMakeLists.txt @@ -9,8 +9,6 @@ set(CMAKE_CXX_STANDARD 17) if(UNIX AND NOT APPLE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") - # Match the library's standard-library choice so the sample's ABI lines up - # with libGameAnalytics when built with clang. if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") endif() diff --git a/setup.py b/setup.py index aee990bf..df76841f 100644 --- a/setup.py +++ b/setup.py @@ -101,11 +101,7 @@ def main(): triplet = f'{arch}-{platform}' - # On Windows, statically link curl/openssl/zlib into the DLL so the Unity - # plugin is a single self-contained GameAnalytics.dll (mirrors macOS, where - # vcpkg's default triplet already produces static deps). The "-static-md" - # variant keeps the dynamic CRT (/MD), matching CMAKE_MSVC_RUNTIME_LIBRARY - # for shared builds; plain "-static" would use /MT and conflict. + # static deps, dynamic CRT (/MD) if args.platform.startswith('win') and args.shared: triplet = f'{arch}-windows-static-md' diff --git a/source/gameanalytics/GAState.cpp b/source/gameanalytics/GAState.cpp index ae1b6efe..1e29be83 100644 --- a/source/gameanalytics/GAState.cpp +++ b/source/gameanalytics/GAState.cpp @@ -637,9 +637,7 @@ namespace gameanalytics } catch (json::exception& e) { - // Cached config is unparseable (e.g. written by the legacy C# SDK - // in binary-base64 instead of JSON). Discard the stale row; a fresh - // config is fetched on init and rewritten as JSON, so this self-heals. + // discard unparseable cached config logging::GALogger::d("Discarding incompatible cached sdk config: %s", e.what()); store::GAStore::setState("sdk_config_cached", ""); } diff --git a/source/gameanalytics/Platform/GALinux.cpp b/source/gameanalytics/Platform/GALinux.cpp index ea3a7c5f..4862b49d 100644 --- a/source/gameanalytics/Platform/GALinux.cpp +++ b/source/gameanalytics/Platform/GALinux.cpp @@ -78,24 +78,26 @@ std::string gameanalytics::GAPlatformLinux::getOSVersion() struct utsname info; uname(&info); - std::string version; - int const strSize = strlen(info.release); + std::string version = info.release; + size_t const strSize = version.size(); int dotCount = 0; for (size_t i = 0; i < strSize; ++i) { - if (info.release[i] == '.') + char const c = version[i]; + + if (c == '.') { ++dotCount; if (dotCount == 3) { - version = std::string(info.release, info.release + i); + version.resize(i); break; } } - else if (!isdigit(info.release[i])) + else if (!isdigit(static_cast(c))) { - version = std::string(info.release, info.release + i); + version.resize(i); break; } } From 124b4b50f6440edf8dbc23798c36cbd4fdfac44b Mon Sep 17 00:00:00 2001 From: Andrei Dabija Date: Mon, 10 Aug 2026 15:44:51 +0300 Subject: [PATCH 6/6] fix cpp static to use /MT --- setup.py | 6 +++--- source/gameanalytics/GAState.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/setup.py b/setup.py index df76841f..b5402a6f 100644 --- a/setup.py +++ b/setup.py @@ -101,9 +101,9 @@ def main(): triplet = f'{arch}-{platform}' - # static deps, dynamic CRT (/MD) - if args.platform.startswith('win') and args.shared: - triplet = f'{arch}-windows-static-md' + # match CMAKE_MSVC_RUNTIME_LIBRARY: /MD shared, /MT static + if args.platform.startswith('win'): + triplet = f'{arch}-windows-static-md' if args.shared else f'{arch}-windows-static' if args.platform == 'osx': osx_arch = arch if arch == 'arm64' else 'x86_64' # no official universal triplet for osx vcpkg diff --git a/source/gameanalytics/GAState.cpp b/source/gameanalytics/GAState.cpp index 1e29be83..ae6f694a 100644 --- a/source/gameanalytics/GAState.cpp +++ b/source/gameanalytics/GAState.cpp @@ -638,7 +638,7 @@ namespace gameanalytics catch (json::exception& e) { // discard unparseable cached config - logging::GALogger::d("Discarding incompatible cached sdk config: %s", e.what()); + logging::GALogger::w("Discarding incompatible cached sdk config: %s", e.what()); store::GAStore::setState("sdk_config_cached", ""); } }