BobBuildTool/basement

MSVC: link runtime library

Closed this issue · 5 comments

CFLAGS: "-O$(if-then-else,$(eq,${BASEMENT_OPTIMIZE},0),d,${BASEMENT_OPTIMIZE})$(if-then-else,${BASEMENT_DEBUG}, -Zi,) -W3"
CXXFLAGS: "-O$(if-then-else,$(eq,${BASEMENT_OPTIMIZE},0),d,${BASEMENT_OPTIMIZE})$(if-then-else,${BASEMENT_DEBUG}, -Zi,) -W3"

for windows with msvc it is necessary to handle the runtime-library to get multiple modules together:

The allowed values are:

MultiThreaded: Compile with -MT or equivalent flag(s) to use a multi-threaded statically-linked runtime library.
MultiThreadedDLL: Compile with -MD or equivalent flag(s) to use a multi-threaded dynamically-linked runtime library.
MultiThreadedDebug: Compile with -MTd or equivalent flag(s) to use a multi-threaded statically-linked runtime library.
MultiThreadedDebugDLL: Compile with -MDd or equivalent flag(s) to use a multi-threaded dynamically-linked runtime library.

I guess, we should do something like that:

diff --git a/recipes/devel/win/vs2019-toolchain.yaml b/recipes/devel/win/vs2019-toolchain.yaml
index 227cbeb..2410849 100644
--- a/recipes/devel/win/vs2019-toolchain.yaml
+++ b/recipes/devel/win/vs2019-toolchain.yaml
@@ -25,8 +25,8 @@ provideTools:
             CXX: "cl"

             CPPFLAGS: ""
-            CFLAGS: "-O$(if-then-else,$(eq,${BASEMENT_OPTIMIZE},0),d,${BASEMENT_OPTIMIZE})$(if-then-else,${BASEMENT_DEBUG}, -Zi,) -W3"
-            CXXFLAGS: "-O$(if-then-else,$(eq,${BASEMENT_OPTIMIZE},0),d,${BASEMENT_OPTIMIZE})$(if-then-else,${BASEMENT_DEBUG}, -Zi,) -W3"
+            CFLAGS: "-O$(if-then-else,$(eq,${BASEMENT_OPTIMIZE},0),d,${BASEMENT_OPTIMIZE})$(if-then-else,${BASEMENT_DEBUG}, -Zi,) -MD$(if-then-else,${BASEMENT_DEBUG},d,) -W3"
+            CXXFLAGS: "-O$(if-then-else,$(eq,${BASEMENT_OPTIMIZE},0),d,${BASEMENT_OPTIMIZE})$(if-then-else,${BASEMENT_DEBUG}, -Zi,) -MD$(if-then-else,${BASEMENT_DEBUG},d,) -W3"
             LDFLAGS: ""

 multiPackage:

So we define MD as default, this is most commonly the default AFAIK and add the d if it is debug build:

If this variable is not set then the MSVC_RUNTIME_LIBRARY target property will not be set automatically. If that property is not set then CMake uses the default value MultiThreaded$<$CONFIG:Debug:Debug>DLL to select a MSVC runtime library.
https://cmake.org/cmake/help/latest/variable/CMAKE_MSVC_RUNTIME_LIBRARY.html?highlight=msvc_runtime

Because of this, also the classes/cmake.yaml has to be adapted. Our CONFIG is named Bob, so always MultiThreadedDLL is the result.

diff --git a/classes/cmake.yaml b/classes/cmake.yaml
index 5d27033..b0ca6fc 100644
--- a/classes/cmake.yaml
+++ b/classes/cmake.yaml
@@ -1,7 +1,7 @@
 inherit: [cpackage, ninja, install]

 buildToolsWeak: [cmake]
-buildVars: [AUTOCONF_HOST, CC, CXX, BASEMENT_LIBS]
+buildVars: [AUTOCONF_HOST, CC, CXX, BASEMENT_LIBS, BASEMENT_DEBUG]
 buildScript: |
     # Make sure CMake finds other stuff by its own logic too
     CMAKE_FIND_ROOT_PATH=
@@ -79,6 +79,12 @@ buildScript: |
             ;;
     esac

+    if [[ "${BASEMENT_DEBUG:-0}" != "0" ]] ; then
+        CMAKE_MSVC_RUNTIME_LIBRARY="MultiThreadedDebugDLL"
+    else
+        CMAKE_MSVC_RUNTIME_LIBRARY="MultiThreadedDLL"
+    fi
+
     # usage: cmakeBuild [-m <ninja_target>] [-o <ninja_options>]
     #                   [-n] [-i <install_component>]
     #                   <source-path> [-DCMAKE_...]
@@ -123,13 +129,14 @@ buildScript: |
             ${CMAKE_TOOLCHAIN_FILE:+-DCMAKE_TOOLCHAIN_FILE="$CMAKE_TOOLCHAIN_FILE"} \
             -DCMAKE_FIND_ROOT_PATH="$CMAKE_FIND_ROOT_PATH" \
             -DCMAKE_BUILD_TYPE=Bob \
+            -DCMAKE_MSVC_RUNTIME_LIBRARY=$CMAKE_MSVC_RUNTIME_LIBRARY \
             -DCMAKE_INSTALL_PREFIX="$CMAKE_INSTALL_PREFIX" \
             -DCMAKE_INSTALL_SYSCONFDIR="$CMAKE_INSTALL_SYSCONFDIR" \
             -DBUILD_SHARED_LIBS=$BUILD_SHARED_LIBS \
             "${@:2}"

btw: e.g. boost has the following switches:

  • link: static, shared
  • runtime-link: static, shared
  • variant: debug, release --> for link and runtime-link

If these flags are necessary then we should add them. I'm a bit confused why a change to the cmake class is necessary. The "Bob" config is used to make sure that CMake does not add any flags on its own but use the ones supplied in CFLAGS. Does that not work for the -MD flags?

Does that not work for the -MD flags?

Yep, answer is already in the first post:

If this variable is not set then the MSVC_RUNTIME_LIBRARY target property will not be set automatically. If that property is not set then CMake uses the default value MultiThreaded$<$CONFIG:Debug:Debug>DLL to select a MSVC runtime library.
https://cmake.org/cmake/help/latest/variable/CMAKE_MSVC_RUNTIME_LIBRARY.html?highlight=msvc_runtime

i do have a feeling... that we should use -MT as default. the runtime library stuff, i guess will installed by vs installer. so it will be impossible to execute the stuff without "developer"-environment?!
bad idea.. MD is the better solution. MT isn't default, and restricted in some combinations for some libraries (e.g. boost), e.g. MT (static runtime library) + shared library

Yes, MD seems more appropriate. Regarding the CMake magic: wouldn't setting CMAKE_MSVC_RUNTIME_LIBRARY to an empty string be sufficient? That should stop CMake from adding any additional flags and our CXXFLAGS could take precedence...

Yes, MD seems more appropriate. Regarding the CMake magic: wouldn't setting CMAKE_MSVC_RUNTIME_LIBRARY to an empty string be sufficient? That should stop CMake from adding any additional flags and our CXXFLAGS could take precedence...

indeed. hopefully that can do the job:

The value may also be the empty string ("") in which case no runtime library selection flag will be added explicitly by CMake. Note that with Visual Studio Generators the native build system may choose to add its own default runtime library selection flag.
https://cmake.org/cmake/help/git-stage/variable/CMAKE_MSVC_RUNTIME_LIBRARY.html