|
| 1 | +#[=======================================================================[.rst: |
| 2 | +
|
| 3 | +msvcHack.cmake |
| 4 | +-------------- |
| 5 | +
|
| 6 | +There are a couple of things that CMake does which mess up the build and are |
| 7 | +hard to work around. This cmake script is an attempt to document and work |
| 8 | +around those shortcomings. |
| 9 | +
|
| 10 | +MSVC Runtime Selection |
| 11 | +---------------------- |
| 12 | +
|
| 13 | +There are two main ways to set the msvc runtime library; |
| 14 | +Using ``target_compile_options()`` to add the flags |
| 15 | +or using the ``CMAKE_MSVC_RUNTIME_LIBRARY`` property_ abstraction, introduced |
| 16 | +in CMake version 3.15 with the policy CMP0091_ to remove the flags from |
| 17 | +``CMAKE_<LANG>_FLAGS_<CONFIG>``. |
| 18 | +
|
| 19 | +Default: ``CMAKE_MSVC_RUNTIME_LIBRARY="MultiThreaded$<$<CONFIG:Debug>:Debug>DLL"`` |
| 20 | +
|
| 21 | +This initializes each target's ``MSVC_RUNTIME_LIBRARY`` property at the time of |
| 22 | +target creation. |
| 23 | +
|
| 24 | +it is stated in the msvc_ documentation that: "All modules passed to a given |
| 25 | +invocation of the linker must have been compiled with the same runtime library |
| 26 | +compiler option (/MD, /MT, /LD)." |
| 27 | +
|
| 28 | +This creates a conundrum for us, the ``CMAKE_MSVC_RUNTIME_LIBRARY`` needs to be |
| 29 | +correct at the time the target is created, but we have no control over the |
| 30 | +consumers CMake scripts, and the per-target ``MSVC_RUNTIME_LIBRARY`` property |
| 31 | +is not transient. |
| 32 | +
|
| 33 | +It has been raised that not using ``CMAKE_MSVC_RUNTIME_LIBRARY`` can also cause |
| 34 | +issues_ when a dependency( independent to godot-cpp ) that doesn't set any |
| 35 | +runtime flags, which relies purely on the ``CMAKE_MSVC_RUNTIME_LIBRARY`` |
| 36 | +variable will very likely not have the correct msvc runtime flags set. |
| 37 | +
|
| 38 | +So we'll set ``CMAKE_MSVC_RUNTIME_LIBRARY`` as CACHE STRING so that it will be |
| 39 | +available for consumer target definitions, but also be able to be overridden if |
| 40 | +needed. |
| 41 | +
|
| 42 | +Additionally we message consumers notifying them and pointing to this |
| 43 | +documentation. |
| 44 | +
|
| 45 | +.. _CMP0091:https://cmake.org/cmake/help/latest/policy/CMP0091.html |
| 46 | +.. _property:https://cmake.org/cmake/help/latest/variable/CMAKE_MSVC_RUNTIME_LIBRARY.html |
| 47 | +.. https://discourse.cmake.org/t/mt-staticrelease-doesnt-match-value-md-dynamicrelease/5428/4 |
| 48 | +.. _msvc: https://learn.microsoft.com/en-us/cpp/build/reference/md-mt-ld-use-run-time-library |
| 49 | +.. _issues: https://github.com/godotengine/godot-cpp/issues/1699 |
| 50 | +
|
| 51 | +Run-Time Error Checks |
| 52 | +--------------------- |
| 53 | +
|
| 54 | +The MSVC compiler flag_ /RTC[] is Used to enable and disable the run-time error |
| 55 | +checks feature, in conjunction with the runtime_checks pragma. |
| 56 | +
|
| 57 | +.. _flag: https://learn.microsoft.com/en-us/cpp/build/reference/rtc-run-time-error-checks?view=msvc-170 |
| 58 | +
|
| 59 | +If enabled it triggers a stacktrace when a template_debug godot loads an |
| 60 | +gdextension. Unfortunately CMake adds this flag to Debug builds, and there |
| 61 | +is no simple solution for removing it. The solution here, is drawn from |
| 62 | +others experiences 1_, 2_. |
| 63 | +
|
| 64 | +.. _1: https://discourse.cmake.org/t/how-do-i-remove-compile-options-from-target/5965 |
| 65 | +.. _2: https://stackoverflow.com/questions/74426638/how-to-remove-rtc1-from-specific-target-or-file-in-cmake |
| 66 | +
|
| 67 | +There are two locations where the RTC options appear, and they are both within |
| 68 | +the same macro in the file_: Platform/Windows-MSVC.cmake |
| 69 | +
|
| 70 | +.. _file: https://gitlab.kitware.com/cmake/cmake/-/blob/566e96d42db35e2c88ceb5d0f3de49736295c496/Modules/Platform/Windows-MSVC.cmake |
| 71 | +
|
| 72 | +FUTURE: CMake introduced the ``CMAKE_MSVC_RUNTIME_CHECKS`` option_ in v4.0 |
| 73 | +.. _option: https://cmake.org/cmake/help/latest/variable/CMAKE_MSVC_RUNTIME_CHECKS.html |
| 74 | +
|
| 75 | +]=======================================================================] |
| 76 | + |
| 77 | +if(MSVC) |
| 78 | + message( |
| 79 | + STATUS |
| 80 | + "NOTE: We know its bad etiquette to set global build variables, however,\n" |
| 81 | + "\tCMAKE_MSVC_RUNTIME_LIBRARY needs to be set to something specific for godot-cpp, and\n" |
| 82 | + "\tCMAKE_CXX_FLAGS_DEBUG needs /RTC1 removed as it triggers a segfaut on when template_debug loads\n" |
| 83 | + "\tPlease ensure that any targets that are linking with godot-cpp are defined after godot-cpp\n" |
| 84 | + "\tFor more information please read godot-cpp/cmake/msvcHack.cmake" |
| 85 | + ) |
| 86 | + |
| 87 | + if(CMAKE_VS_PLATFORM_TOOLSET MATCHES "v[0-9]+_clang_.*") # The same condition that Windows-MSVC.cmake uses |
| 88 | + else() |
| 89 | + string(REPLACE "/RTC1" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") |
| 90 | + string(REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") |
| 91 | + endif() |
| 92 | + |
| 93 | + set(CMAKE_MSVC_RUNTIME_LIBRARY |
| 94 | + "MultiThreaded$<IF:$<BOOL:${GODOTCPP_DEBUG_CRT}>,DebugDLL,$<$<NOT:$<BOOL:${GODOTCPP_USE_STATIC_CPP}>>:DLL>>" |
| 95 | + CACHE STRING |
| 96 | + "Select the MSVC runtime library for use by compilers targeting the MSVC ABI." |
| 97 | + ) |
| 98 | +endif() |
0 commit comments