MantisBT - CMake
View Issue Details
0009445CMakeCMakepublic2009-08-21 23:272016-06-10 14:30
Taras 
Bill Hoffman 
normalfeatureN/A
closedmoved 
CMake-2-6 
 
0009445: Ability to select static runtime when use generator for MSVC
I couldn`t find out how to select static runtime for libraries when generate MSVC solution.
Google give only one usefull link related to problem,
http://www.cmake.org/pipermail/cmake/2008-September/023877.html [^]
But seems it is some kind of hack.
Could you add this? I think it can be another one property or even another one parameter in add_library, add_test, etc
No tags attached.
has duplicate 0011093closed David Cole [VS] Support static run-time 
Issue History
2009-08-21 23:27TarasNew Issue
2009-08-21 23:28TarasNote Added: 0017175
2009-08-22 16:35Philip LowmanNote Added: 0017176
2009-08-22 20:05TarasNote Added: 0017177
2009-08-22 20:25TarasNote Added: 0017178
2009-08-22 21:04TarasNote Added: 0017179
2009-08-22 21:07TarasNote Edited: 0017179
2009-08-29 21:16Philip LowmanNote Added: 0017233
2009-08-29 21:19Philip LowmanNote Edited: 0017233
2009-09-11 17:29Bill HoffmanStatusnew => assigned
2009-09-11 17:29Bill HoffmanAssigned To => Bill Hoffman
2009-09-11 17:29Bill HoffmanNote Added: 0017389
2009-09-19 23:22TarasNote Added: 0017654
2009-10-07 01:10Philip LowmanNote Added: 0018004
2011-01-11 16:02MaddesNote Added: 0024597
2011-01-11 16:03MaddesNote Edited: 0024597bug_revision_view_page.php?bugnote_id=24597#r110
2011-01-11 16:04MaddesNote Edited: 0024597bug_revision_view_page.php?bugnote_id=24597#r111
2011-01-15 14:10MaddesNote Edited: 0024597bug_revision_view_page.php?bugnote_id=24597#r125
2011-01-15 14:14MaddesNote Edited: 0024597bug_revision_view_page.php?bugnote_id=24597#r126
2011-01-15 17:10MaddesNote Edited: 0024597bug_revision_view_page.php?bugnote_id=24597#r127
2011-01-16 09:35MaddesNote Edited: 0024597bug_revision_view_page.php?bugnote_id=24597#r133
2011-02-03 18:33David ColeRelationship addedhas duplicate 0011093
2015-12-03 13:36Mikhail TitovNote Added: 0039950
2015-12-03 13:41Mikhail TitovNote Edited: 0039950bug_revision_view_page.php?bugnote_id=39950#r1965
2016-06-10 14:27Kitware RobotNote Added: 0041588
2016-06-10 14:27Kitware RobotStatusassigned => resolved
2016-06-10 14:27Kitware RobotResolutionopen => moved
2016-06-10 14:30Kitware RobotStatusresolved => closed

Notes
(0017175)
Taras   
2009-08-21 23:28   
Or at least provide some examples or better documentation on how to workaround this
(0017176)
Philip Lowman   
2009-08-22 16:35   
The default compilation flags for CMake generated projects (at least as of MSVC 2005) are /MD. I'm assuming you want /MT which is the multithreaded static runtime flag.

Here are a two options to change this:

1. Use the code snippit that you linked to to replace any "/MD" entries in the compilation flags with "/MT". Assuming you would want these compilation flags to affect all targets, you would want to do this before declaring any add_executable() or add_library() targets and before recursing into any subdirectories with add_subdirectory().

foreach(flag_var
        CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
        CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
    if(${flag_var} MATCHES "/MD")
        string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
    endif(${flag_var} MATCHES "/MD")
endforeach(flag_var)

2. Manually change the CMAKE_CXX_FLAGS_* CMake cache variables by showing Advanced variables in the cache editor.

Obviously the first option is probably better if this is a permanent thing. It could also be made configurable if this is needed.

if(MSVC)
   option(BUILD_WITH_STATIC_RUNTIME "Build the libraries with /MT" ON)
   if(BUILD_WITH_STATIC_RUNTIME)
      # do REGEX REPLACE code
   endif()
endif()

I don't think adding a flag to add_library() or add_executable() would be good for this as it would conflict with what people already do which is change the compilation flags.

I have added this answer to the FAQ

http://www.vtk.org/Wiki/CMake_FAQ#How_can_I_build_my_MSVC_application_with_a_static_runtime.3F [^]
(0017177)
Taras   
2009-08-22 20:05   
Thanks a lot. But seems it is not what I am exaclty need.
Is it possible to declare simulationiously two variants of library: one with static runtime and the second with dynamic? I tried

FUNCTION(enable_static_runtime)
    FOREACH(flag_var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
            CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
        STRING(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
    ENDFOREACH(flag_var)
ENDFUNCTION(enable_static_runtime)

FUNCTION(disable_static_runtime)
    FOREACH(flag_var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
            CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
        STRING(REGEX REPLACE "/MT" "/MD" ${flag_var} "${${flag_var}}")
    ENDFOREACH(flag_var)
ENDFUNCTION(disable_static_runtime)

# declare static library with dynamic runtime
ADD_LIBRARY(drwcurl_s STATIC ${libcurl_src})
SET(CURL_s_LIBRARIES ${drwcurl_s_location} PARENT_SCOPE)
SET(CURL_s_DEFINITIONS -DCURL_STATICLIB PARENT_SCOPE)

# declare also static library with static runtime for msvc
IF(MSVC)
    enable_static_runtime()
    ADD_LIBRARY(mycurl_s_c STATIC ${libcurl_src})
    disable_static_runtime()
    SET(CURL_s_c_LIBRARIES ${mycurl_s_c_location} PARENT_SCOPE)
    SET(CURL_s_c_DEFINITIONS -DCURL_STATICLIB PARENT_SCOPE)
ENDIF(MSVC)

But this doesn`t work properly. How can I change CXX flags only for target?
(0017178)
Taras   
2009-08-22 20:25   
Hm, what about workaround idea to manually remove /MD or /MDd flags from CMAKE_CXX_FLAGS_* and add them only as additional target compile flags after any ADD_LIBRARY, ADD_EXECUTABLE and others.
(0017179)
Taras   
2009-08-22 21:04   
(edited on: 2009-08-22 21:07)
The previous doesn`t work at all.
I placed
FUNCTION(enable_static_runtime)
    FOREACH(flag_var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
            CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
        STRING(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
    ENDFOREACH(flag_var)
    MESSAGE("Static runtime enabled")
    MESSAGE("CMAKE_CXX_FLAGS_DEBUG="${CMAKE_CXX_FLAGS_DEBUG})
# tried this too but it wasnt helpfull
# SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}" CACHE STRING)
ENDFUNCTION(enable_static_runtime)

enable_static_runtime()

in my topmost CMakeLists.txt

I got in console
Static runtime enabled
CMAKE_CXX_FLAGS_DEBUG=/D_DEBUG /MTd /Zi /Ob0 /Od /RTC1

But still had in cache
//Flags used by the compiler during debug builds.
CMAKE_CXX_FLAGS_DEBUG:STRING=/D_DEBUG /MDd /Zi /Ob0 /Od /RTC1

and in project properties Multi-threaded debug DLL runtime

How can I really change CMAKE_CXX_FLAGS_DEBUG variable?
So
http://www.vtk.org/Wiki/CMake_FAQ#How_can_I_build_my_MSVC_application_with_a_static_runtime.3F [^]
is inapplicable

(0017233)
Philip Lowman   
2009-08-29 21:16   
(edited on: 2009-08-29 21:19)
There are 4 choices I am aware of.

1. Create a local variable called CMAKE_CXX_FLAGS_<FOO> which overrides the cache variable. This is what I suggested in the FAQ and it should work fine in terms of the actual generated makefiles/project files except whatever is in the CACHE would have to be ignored.

One problem with your code above is you are using a function() without setting the new variables to the PARENT_SCOPE. Replace your code with a MACRO and things should kinda work better except you'll soon discover (as I did) that CMAKE_CXX_FLAGS_<FOO> appears to be a per-directory level thing. You can't change the flags in the middle of a directory and have targets affected. :(

2. Manually modify the cache after an initial configure to contain the flags you want (not good).

3. Use the FORCE option to set() to exactly set compile flags into the cache on every configure. This has the effect of if the user changes a variable in the cache editor and configures again it will reset back to the way it was.

4. (the most promising)
Change the initial seeding values for CMAKE_CXX_FLAGS_<FOO>_INIT by using a CMAKE_USER_MAKE_RULES_OVERRIDE and/or CMAKE_USER_MAKE_RULES_OVERRIDE_CXX file. To do this you would create a .cmake file that defines the flags you want, then set the override variable to the path of that file prior to calling project().

E.g.:

set(CMAKE_USER_MAKE_RULES_OVERRIDE
    ${CMAKE_CURRENT_SOURCE_DIR}/c_flag_overrides.cmake)
set(CMAKE_USER_MAKE_RULES_OVERRIDE_CXX
    ${CMAKE_CURRENT_SOURCE_DIR}/cxx_flag_overrides.cmake)
project(Bar)


I think I like option 4 a lot better if the /MT is going to be a permanent change across all targets (very likely considering what this flag does).

It's important to note though that owing to how option 4 works you won't be able to undo it after it's run once. That is to say, setting the _INIT variables only works on the initial configure.

(0017389)
Bill Hoffman   
2009-09-11 17:29   
Yes, rule override should be used for this.
(0017654)
Taras   
2009-09-19 23:22   
Hi,
I tried CMAKE_USER_MAKE_RULES_OVERRIDE as you advised, and it works fine. But I was unable to solve my initial problem.
I trying to migrate a huge crossplatform project in our company from own ugly build system to cmake. There are a few libs that must be build in 3 variants on windows:
shared with shared runtime, static with shared runtime and static with static runtime

I used CMAKE_USER_MAKE_RULES_OVERRIDE together with redefining INIT variables and almost solved this, but now the last problem is that I cannot specify <per target> and <per configuration> compile flags. COMPILE_FLAGS target property is not expanded to different configurations.

There is a feature request
http://www.vtk.org/Bug/view.php?id=6493, [^] seems it is what I am really need.

Please close this ticket
(0018004)
Philip Lowman   
2009-10-07 01:10   
I've updated the FAQ with an example of rule override. This bug can probably be closed.

http://www.vtk.org/Wiki/CMake_FAQ#How_can_I_build_my_MSVC_application_with_a_static_runtime.3F [^]
(0024597)
Maddes   
2011-01-11 16:02   
(edited on: 2011-01-16 09:35)
I use the following code that works well for me, at least in a clean build directory. Still I would like to have this handled inside CMake.

if(POLICY CMP0012)
    cmake_policy(SET CMP0012 NEW)
endif()

...

# Compilation options
# see http://www.cmake.org/cmake/help/cmake2.6docs.html#variable:BUILD_SHARED_LIBS [^]
# http://www.cmake.org/cmake/help/cmake2.6docs.html#command:add_library [^]
option(BUILD_SHARED_LIBS "Build Shared Libraries" OFF)
# see http://msdn.microsoft.com/en-us/library/aa278396(v=VS.60).aspx [^]
# http://msdn.microsoft.com/en-us/library/2kzt1wy3(v=VS.71).aspx [^]
option(MSVC_SHARED_RT "MSVC: Build with shared runtime libs (/MD)" ON)
option(MSVC_STHREADED_RT "MSVC: Build with single-threaded static runtime libs (/ML until VS .NET 2003)" OFF)

...

###
### General compilation settings
###
if(${BUILD_SHARED_LIBS})
    set(LABEL_SUFFIX "shared")
else()
    set(LABEL_SUFFIX "static")
endif()

if(${MSVC})
    ### General stuff
    # a) Change MSVC runtime library settings (/MD[d], /MT[d], /ML[d] (single-threaded until VS 2003))
    # plus set lib suffix for later use and project label accordingly
    # see http://msdn.microsoft.com/en-us/library/aa278396(v=VS.60).aspx [^]
    # http://msdn.microsoft.com/en-us/library/2kzt1wy3(v=VS.71).aspx [^]
    set(LIB_RT_SUFFIX "md") # CMake defaults to /MD for MSVC
    set(LIB_RT_OPTION "/MD")
    #
    if(NOT ${MSVC_SHARED_RT}) # User wants to have static runtime libraries (/MT, /ML)
        if(${MSVC_STHREADED_RT}) # User wants to have old single-threaded static runtime libraries
            set(LIB_RT_SUFFIX "ml")
            set(LIB_RT_OPTION "/ML")
            if(NOT ${MSVC_VERSION} LESS 1400)
                message(FATAL_ERROR "Single-threaded static runtime libraries (/ML) only available until VS .NET 2003 (7.1).")
            endif()
        else()
            set(LIB_RT_SUFFIX "mt")
            set(LIB_RT_OPTION "/MT")
        endif()

        # correct linker options
        foreach(flag_var CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
            foreach(config_name "" DEBUG RELEASE MINSIZEREL RELWITHDEBINFO)
                set(var_name "${flag_var}")
                if(NOT "${config_name}" STREQUAL "")
                    set(var_name "${var_name}_${config_name}")
                endif()
                string(REPLACE "/MD" "${LIB_RT_OPTION}" ${var_name} "${${var_name}}")
            endforeach()
        endforeach()
    endif()
    #
    set(LABEL_SUFFIX "${LABEL_SUFFIX} ${LIB_RT_OPTION}")

    # b) Change prefix for static libraries
    set(CMAKE_STATIC_LIBRARY_PREFIX "lib") # to distinguish static libraries from DLL import libs

    # c) Correct suffixes for static libraries
    if(NOT ${BUILD_SHARED_LIBS})
        ### General stuff
        set(LIB_TARGET_SUFFIX "${LIB_SUFFIX}${LIB_RT_SUFFIX}")

        ### Project stuff
        # correct external library names
        set(YAML_CPP_LIB "${CMAKE_STATIC_LIBRARY_PREFIX}${YAML_CPP_LIB}${LIB_RT_SUFFIX}")
        set(YAML_CPP_LIB_DBG "${YAML_CPP_LIB}d")
    endif()
endif()

...

add_library(pinproc
...
)

set_target_properties(pinproc PROPERTIES
    PROJECT_LABEL "pinproc ${LABEL_SUFFIX}"
...
)

if(${MSVC})
    if(NOT ${BUILD_SHARED_LIBS})
        # correct library names
        set_target_properties(pinproc PROPERTIES
            DEBUG_POSTFIX "${LIB_TARGET_SUFFIX}d"
            RELEASE_POSTFIX "${LIB_TARGET_SUFFIX}"
            MINSIZEREL_POSTFIX "${LIB_TARGET_SUFFIX}"
            RELWITHDEBINFO_POSTFIX "${LIB_TARGET_SUFFIX}"
        )
    endif()
endif()

(0039950)
Mikhail Titov   
2015-12-03 13:36   
(edited on: 2015-12-03 13:41)
I believe this is still an issue. Workarounds are fine for our own projects, but if I use ExternalProject (zlib is a good example), the only option left is to patch it. That just looks ugly and a PITA (https://cmake.org/pipermail/cmake/2014-January/056769.html [^]) :(

(0041588)
Kitware Robot   
2016-06-10 14:27   
Resolving issue as `moved`.

This issue tracker is no longer used. Further discussion of this issue may take place in the current CMake Issues page linked in the banner at the top of this page.