From 5e25161a10d62d2c77c03a66d8be0e8c65363959 Mon Sep 17 00:00:00 2001 From: Misa Date: Tue, 28 Jun 2022 17:49:03 -0700 Subject: [PATCH] Add `/MT` flag for MSVC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This flag makes it so the MSVC runtime libraries are statically linked. This avoids needing Windows users to have these libraries installed. Apparently /MT stands for "MultiThreaded", and there's a bit of a history there where originally by default you could only have a single-threaded library, and then the multi-threaded flags were added in later. First I tried doing target_compile_options on VVVVVV, but then got a linker error. Then I tried doing add_compile_options because I figured /MT had to be applied everywhere, and it seemed to work, but it still linked to the runtime libraries. Apparently it was being overridden. Then I tried target_compile_options again but this time did it to everything, and that linked correctly and also removed the runtime dependency. I would've tried using the MSVC_RUNTIME_LIBRARY property - along with the CMP0091 policy - but those were only introduced in CMake 3.15. You can verify that a binary is built without dependencies by installing LLVM and running llvm-readobj --needed-libs path/to/binary. This is the output for a binary with runtime dependencies: infoteddy@fedorarune  ~/d  llvm-readobj --needed-libs VVVVVV.exe File: VVVVVV.exe Format: COFF-i386 Arch: i386 AddressSize: 32bit NeededLibraries [ ADVAPI32.dll KERNEL32.dll MSVCP140.dll SDL2.dll SHELL32.dll USER32.dll VCRUNTIME140.dll api-ms-win-crt-heap-l1-1-0.dll api-ms-win-crt-locale-l1-1-0.dll api-ms-win-crt-math-l1-1-0.dll api-ms-win-crt-runtime-l1-1-0.dll api-ms-win-crt-stdio-l1-1-0.dll api-ms-win-crt-string-l1-1-0.dll api-ms-win-crt-time-l1-1-0.dll api-ms-win-crt-utility-l1-1-0.dll ] And this is the output for a binary with those dependencies having been statically-linked in: infoteddy@fedorarune  ~/d  llvm-readobj --needed-libs VVVVVV.exe File: VVVVVV.exe Format: COFF-i386 Arch: i386 AddressSize: 32bit NeededLibraries [ ADVAPI32.dll KERNEL32.dll SDL2.dll SHELL32.dll USER32.dll ] --- desktop_version/CMakeLists.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/desktop_version/CMakeLists.txt b/desktop_version/CMakeLists.txt index d6b8726c..55a53186 100644 --- a/desktop_version/CMakeLists.txt +++ b/desktop_version/CMakeLists.txt @@ -314,6 +314,20 @@ else() target_link_libraries(VVVVVV physfs tinyxml2 utf8cpp lodepng-static FAudio) endif() +if(MSVC) + # Statically link Microsoft's runtime library so end users don't have to install it + target_compile_options(VVVVVV PRIVATE /MT) + + # /MT must also be applied to every statically-linked library, else you get a linker error + if(BUNDLE_DEPENDENCIES) + target_compile_options(tinyxml2-static PRIVATE /MT) + target_compile_options(physfs-static PRIVATE /MT) + target_compile_options(faudio-static PRIVATE /MT) + endif() + + target_compile_options(lodepng-static PRIVATE /MT) +endif() + # SDL2 Dependency (Detection pulled from FAudio) if(DEFINED SDL2_INCLUDE_DIRS AND DEFINED SDL2_LIBRARIES) message(STATUS "Using pre-defined SDL2 variables SDL2_INCLUDE_DIRS and SDL2_LIBRARIES")