From 5e70ee29cc64ac1f660fff6de65a4f28a1a552b7 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 20 Jan 2024 16:40:32 -0800 Subject: [PATCH] Build SDL with the static C runtime on Visual Studio --- .github/workflows/msvc.yml | 2 - CMakeLists.txt | 5 +- VisualC/SDL/SDL.vcxproj | 12 ++--- .../build_config/SDL_build_config_windows.h | 6 ++- src/stdlib/SDL_memcpy.c | 6 +-- src/stdlib/SDL_memset.c | 6 +-- test/testautomation_stdlib.c | 50 ++++++++++++++++--- 7 files changed, 60 insertions(+), 27 deletions(-) diff --git a/.github/workflows/msvc.yml b/.github/workflows/msvc.yml index 9195a94e6..f807a1ce8 100644 --- a/.github/workflows/msvc.yml +++ b/.github/workflows/msvc.yml @@ -17,8 +17,6 @@ jobs: platform: - { name: Windows (x64), flags: -A x64, project: VisualC/SDL.sln, projectflags: '/p:Platform=x64', artifact: 'SDL-VC-x64' } - { name: Windows (x86), flags: -A Win32, project: VisualC/SDL.sln, projectflags: '/p:Platform=Win32', artifact: 'SDL-VC-x86' } - - { name: Windows static VCRT (x64), flags: -A x64 -DSDL_FORCE_STATIC_VCRT=ON, artifact: 'SDL-VC-static-VCRT-x64' } - - { name: Windows static VCRT (x86), flags: -A Win32 -DSDL_FORCE_STATIC_VCRT=ON, artifact: 'SDL-VC-static-VCRT-x86' } - { name: Windows (clang-cl x64), flags: -T ClangCL -A x64, artifact: 'SDL-clang-cl-x64' } - { name: Windows (clang-cl x86), flags: -T ClangCL -A Win32, artifact: 'SDL-clang-cl-x86' } - { name: Windows (ARM), flags: -A ARM, artifact: 'SDL-VC-arm32', notests: true } diff --git a/CMakeLists.txt b/CMakeLists.txt index 598500555..8c2af3355 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -154,13 +154,12 @@ endif() set(SDL_LIBC_DEFAULT ON) set(SDL_SYSTEM_ICONV_DEFAULT ON) if(WINDOWS) - set(SDL_LIBC_DEFAULT OFF) set(SDL_SYSTEM_ICONV_DEFAULT OFF) endif() if(MSVC) - option(SDL_FORCE_STATIC_VCRT "Force /MT for static VC runtimes" OFF) - if(SDL_FORCE_STATIC_VCRT) + dep_option(SDL_STATIC_VCRT "Use /MT for static VC runtimes" ON "NOT WINDOWS_STORE" OFF) + if(SDL_STATIC_VCRT) if(NOT DEFINED CMAKE_MSVC_RUNTIME_LIBRARY) set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") endif() diff --git a/VisualC/SDL/SDL.vcxproj b/VisualC/SDL/SDL.vcxproj index 6a79e1f2e..4c0bea8a1 100644 --- a/VisualC/SDL/SDL.vcxproj +++ b/VisualC/SDL/SDL.vcxproj @@ -119,18 +119,17 @@ StreamingSIMDExtensions Level3 OldStyle - true OnlyExplicitInline Use SDL_internal.h true + MultiThreadedDebug _DEBUG;%(PreprocessorDefinitions) setupapi.lib;winmm.lib;imm32.lib;version.lib;%(AdditionalDependencies) - true true Windows @@ -151,18 +150,17 @@ false Level3 OldStyle - true OnlyExplicitInline Use SDL_internal.h true + MultiThreadedDebug _DEBUG;%(PreprocessorDefinitions) setupapi.lib;winmm.lib;imm32.lib;version.lib;%(AdditionalDependencies) - true true Windows @@ -187,18 +185,17 @@ StreamingSIMDExtensions Level3 ProgramDatabase - true OnlyExplicitInline Use SDL_internal.h true + MultiThreaded NDEBUG;%(PreprocessorDefinitions) setupapi.lib;winmm.lib;imm32.lib;version.lib;%(AdditionalDependencies) - true true Windows true @@ -220,18 +217,17 @@ false Level3 ProgramDatabase - true OnlyExplicitInline Use SDL_internal.h true + MultiThreaded NDEBUG;%(PreprocessorDefinitions) setupapi.lib;winmm.lib;imm32.lib;version.lib;%(AdditionalDependencies) - true true Windows true diff --git a/include/build_config/SDL_build_config_windows.h b/include/build_config/SDL_build_config_windows.h index 833d5111d..96f98fac1 100644 --- a/include/build_config/SDL_build_config_windows.h +++ b/include/build_config/SDL_build_config_windows.h @@ -111,7 +111,8 @@ typedef unsigned int uintptr_t; # define SDL_DISABLE_AVX 1 #endif -/* This is disabled by default to avoid C runtime dependencies and manifest requirements */ +/* This can be disabled to avoid C runtime dependencies and manifest requirements */ +#define HAVE_LIBC #ifdef HAVE_LIBC /* Useful headers */ #define HAVE_CTYPE_H 1 @@ -162,6 +163,9 @@ typedef unsigned int uintptr_t; #define HAVE__WCSICMP 1 #define HAVE__WCSNICMP 1 #define HAVE__WCSDUP 1 +#define HAVE_SSCANF 1 +#define HAVE_VSSCANF 1 +#define HAVE_VSNPRINTF 1 #define HAVE_ACOS 1 #define HAVE_ASIN 1 #define HAVE_ATAN 1 diff --git a/src/stdlib/SDL_memcpy.c b/src/stdlib/SDL_memcpy.c index 456b1d032..139eb420d 100644 --- a/src/stdlib/SDL_memcpy.c +++ b/src/stdlib/SDL_memcpy.c @@ -80,8 +80,8 @@ void *SDL_memcpy(SDL_OUT_BYTECAP(len) void *dst, SDL_IN_BYTECAP(len) const void } /* The optimizer on Visual Studio 2005 and later generates memcpy() and memset() calls. - Always provide it for the SDL3 DLL, but skip it when building static lib w/ static runtime. */ -#if defined(_MSC_VER) && (_MSC_VER >= 1400) && (!defined(_MT) || defined(DLL_EXPORT)) + We will provide our own implementation if we're not building with a C runtime. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(_MT) /* NOLINTNEXTLINE(readability-redundant-declaration) */ extern void *memcpy(void *dst, const void *src, size_t len); #ifndef __INTEL_LLVM_COMPILER @@ -96,4 +96,4 @@ void *memcpy(void *dst, const void *src, size_t len) { return SDL_memcpy(dst, src, len); } -#endif /* (_MSC_VER >= 1400) && (!defined(_MT) || defined(DLL_EXPORT)) */ +#endif /* (_MSC_VER >= 1400) && !defined(_MT) */ diff --git a/src/stdlib/SDL_memset.c b/src/stdlib/SDL_memset.c index 30d2d6a57..0c3579f86 100644 --- a/src/stdlib/SDL_memset.c +++ b/src/stdlib/SDL_memset.c @@ -117,8 +117,8 @@ void *SDL_memset4(void *dst, Uint32 val, size_t dwords) } /* The optimizer on Visual Studio 2005 and later generates memcpy() and memset() calls. - Always provide it for the SDL3 DLL, but skip it when building static lib w/ static runtime. */ -#if defined(_MSC_VER) && (_MSC_VER >= 1400) && (!defined(_MT) || defined(DLL_EXPORT)) + We will provide our own implementation if we're not building with a C runtime. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(_MT) /* NOLINTNEXTLINE(readability-redundant-declaration) */ extern void *memset(void *dst, int c, size_t len); #ifndef __INTEL_LLVM_COMPILER @@ -133,5 +133,5 @@ void *memset(void *dst, int c, size_t len) { return SDL_memset(dst, c, len); } -#endif /* (_MSC_VER >= 1400) && (!defined(_MT) || defined(DLL_EXPORT)) */ +#endif /* (_MSC_VER >= 1400) && !defined(_MT) */ diff --git a/test/testautomation_stdlib.c b/test/testautomation_stdlib.c index e447cf42c..adf4bb685 100644 --- a/test/testautomation_stdlib.c +++ b/test/testautomation_stdlib.c @@ -141,7 +141,7 @@ static int stdlib_snprintf(void *arg) int result; int predicted; char text[1024]; - const char *expected; + const char *expected, *expected2, *expected3, *expected4, *expected5; size_t size; result = SDL_snprintf(text, sizeof(text), "%s", "foo"); @@ -310,22 +310,58 @@ static int stdlib_snprintf(void *arg) result = SDL_snprintf(text, sizeof(text), "%p", (void *)0x1234abcd); expected = "0x1234abcd"; + expected2 = "1234ABCD"; + expected3 = "000000001234ABCD"; + expected4 = "1234abcd"; + expected5 = "000000001234abcd"; SDLTest_AssertPass("Call to SDL_snprintf(text, sizeof(text), \"%%p\", 0x1234abcd)"); - SDLTest_AssertCheck(SDL_strcmp(text, expected) == 0, "Check text, expected: '%s', got: '%s'", expected, text); - SDLTest_AssertCheck(result == SDL_strlen(expected), "Check result value, expected: %d, got: %d", (int)SDL_strlen(expected), result); + SDLTest_AssertCheck(SDL_strcmp(text, expected) == 0 || + SDL_strcmp(text, expected2) == 0 || + SDL_strcmp(text, expected3) == 0 || + SDL_strcmp(text, expected4) == 0 || + SDL_strcmp(text, expected5) == 0, + "Check text, expected: '%s', got: '%s'", expected, text); + SDLTest_AssertCheck(result == SDL_strlen(expected) || + result == SDL_strlen(expected2) || + result == SDL_strlen(expected3) || + result == SDL_strlen(expected4) || + result == SDL_strlen(expected5), + "Check result value, expected: %d, got: %d", (int)SDL_strlen(expected), result); result = SDL_snprintf(text, sizeof(text), "A %p B", (void *)0x1234abcd); expected = "A 0x1234abcd B"; + expected2 = "A 1234ABCD B"; + expected3 = "A 000000001234ABCD B"; + expected4 = "A 1234abcd B"; + expected5 = "A 000000001234abcd B"; SDLTest_AssertPass("Call to SDL_snprintf(text, sizeof(text), \"A %%p B\", 0x1234abcd)"); - SDLTest_AssertCheck(SDL_strcmp(text, expected) == 0, "Check text, expected: '%s', got: '%s'", expected, text); - SDLTest_AssertCheck(result == SDL_strlen(expected), "Check result value, expected: %d, got: %d", (int)SDL_strlen(expected), result); + SDLTest_AssertCheck(SDL_strcmp(text, expected) == 0 || + SDL_strcmp(text, expected2) == 0 || + SDL_strcmp(text, expected3) == 0 || + SDL_strcmp(text, expected4) == 0 || + SDL_strcmp(text, expected5) == 0, + "Check text, expected: '%s', got: '%s'", expected, text); + SDLTest_AssertCheck(result == SDL_strlen(expected) || + result == SDL_strlen(expected2) || + result == SDL_strlen(expected3) || + result == SDL_strlen(expected4) || + result == SDL_strlen(expected5), + "Check result value, expected: %d, got: %d", (int)SDL_strlen(expected), result); if (sizeof(void *) >= 8) { result = SDL_snprintf(text, sizeof(text), "%p", (void *)0x1ba07bddf60L); expected = "0x1ba07bddf60"; + expected2 = "000001BA07BDDF60"; + expected3 = "000001ba07bddf60"; SDLTest_AssertPass("Call to SDL_snprintf(text, sizeof(text), \"%%p\", 0x1ba07bddf60)"); - SDLTest_AssertCheck(SDL_strcmp(text, expected) == 0, "Check text, expected: '%s', got: '%s'", expected, text); - SDLTest_AssertCheck(result == SDL_strlen(expected), "Check result value, expected: %d, got: %d", (int)SDL_strlen(expected), result); + SDLTest_AssertCheck(SDL_strcmp(text, expected) == 0 || + SDL_strcmp(text, expected2) == 0 || + SDL_strcmp(text, expected3) == 0, + "Check text, expected: '%s', got: '%s'", expected, text); + SDLTest_AssertCheck(result == SDL_strlen(expected) || + result == SDL_strlen(expected2) || + result == SDL_strlen(expected3), + "Check result value, expected: %d, got: %d", (int)SDL_strlen(expected), result); } return TEST_COMPLETED; }