1# The macro choose_msvc_crt() takes a list of possible 2# C runtimes to choose from, in the form of compiler flags, 3# to present to the user. (MTd for /MTd, etc) 4# 5# The macro is invoked at the end of the file. 6# 7# CMake already sets CRT flags in the CMAKE_CXX_FLAGS_* and 8# CMAKE_C_FLAGS_* variables by default. To let the user 9# override that for each build type: 10# 1. Detect which CRT is already selected, and reflect this in 11# LLVM_USE_CRT_* so the user can have a better idea of what 12# changes they're making. 13# 2. Replace the flags in both variables with the new flag via a regex. 14# 3. set() the variables back into the cache so the changes 15# are user-visible. 16 17### Helper macros: ### 18macro(make_crt_regex regex crts) 19 set(${regex} "") 20 foreach(crt ${${crts}}) 21 # Trying to match the beginning or end of the string with stuff 22 # like [ ^]+ didn't work, so use a bunch of parentheses instead. 23 set(${regex} "${${regex}}|(^| +)/${crt}($| +)") 24 endforeach(crt) 25 string(REGEX REPLACE "^\\|" "" ${regex} "${${regex}}") 26endmacro(make_crt_regex) 27 28macro(get_current_crt crt_current regex flagsvar) 29 # Find the selected-by-CMake CRT for each build type, if any. 30 # Strip off the leading slash and any whitespace. 31 string(REGEX MATCH "${${regex}}" ${crt_current} "${${flagsvar}}") 32 string(REPLACE "/" " " ${crt_current} "${${crt_current}}") 33 string(STRIP "${${crt_current}}" ${crt_current}) 34endmacro(get_current_crt) 35 36# Replaces or adds a flag to a variable. 37# Expects 'flag' to be padded with spaces. 38macro(set_flag_in_var flagsvar regex flag) 39 string(REGEX MATCH "${${regex}}" current_flag "${${flagsvar}}") 40 if("${current_flag}" STREQUAL "") 41 set(${flagsvar} "${${flagsvar}}${${flag}}") 42 else() 43 string(REGEX REPLACE "${${regex}}" "${${flag}}" ${flagsvar} "${${flagsvar}}") 44 endif() 45 string(STRIP "${${flagsvar}}" ${flagsvar}) 46 # Make sure this change gets reflected in the cache/gui. 47 # CMake requires the docstring parameter whenever set() touches the cache, 48 # so get the existing docstring and re-use that. 49 get_property(flagsvar_docs CACHE ${flagsvar} PROPERTY HELPSTRING) 50 set(${flagsvar} "${${flagsvar}}" CACHE STRING "${flagsvar_docs}" FORCE) 51endmacro(set_flag_in_var) 52 53 54macro(choose_msvc_crt MSVC_CRT) 55 if(LLVM_USE_CRT) 56 message(FATAL_ERROR 57 "LLVM_USE_CRT is deprecated. Use the CMAKE_BUILD_TYPE-specific 58variables (LLVM_USE_CRT_DEBUG, etc) instead.") 59 endif() 60 61 make_crt_regex(MSVC_CRT_REGEX ${MSVC_CRT}) 62 63 foreach(build_type ${CMAKE_CONFIGURATION_TYPES} ${CMAKE_BUILD_TYPE}) 64 string(TOUPPER "${build_type}" build) 65 if (NOT LLVM_USE_CRT_${build}) 66 get_current_crt(LLVM_USE_CRT_${build} 67 MSVC_CRT_REGEX 68 CMAKE_CXX_FLAGS_${build}) 69 set(LLVM_USE_CRT_${build} 70 "${LLVM_USE_CRT_${build}}" 71 CACHE STRING "Specify VC++ CRT to use for ${build_type} configurations." 72 FORCE) 73 set_property(CACHE LLVM_USE_CRT_${build} 74 PROPERTY STRINGS ;${${MSVC_CRT}}) 75 endif(NOT LLVM_USE_CRT_${build}) 76 endforeach(build_type) 77 78 foreach(build_type ${CMAKE_CONFIGURATION_TYPES} ${CMAKE_BUILD_TYPE}) 79 string(TOUPPER "${build_type}" build) 80 if ("${LLVM_USE_CRT_${build}}" STREQUAL "") 81 set(flag_string " ") 82 else() 83 set(flag_string " /${LLVM_USE_CRT_${build}} ") 84 list(FIND ${MSVC_CRT} ${LLVM_USE_CRT_${build}} idx) 85 if (idx LESS 0) 86 message(FATAL_ERROR 87 "Invalid value for LLVM_USE_CRT_${build}: ${LLVM_USE_CRT_${build}}. Valid options are one of: ${${MSVC_CRT}}") 88 endif (idx LESS 0) 89 message(STATUS "Using ${build_type} VC++ CRT: ${LLVM_USE_CRT_${build}}") 90 endif() 91 foreach(lang C CXX) 92 set_flag_in_var(CMAKE_${lang}_FLAGS_${build} MSVC_CRT_REGEX flag_string) 93 endforeach(lang) 94 endforeach(build_type) 95endmacro(choose_msvc_crt MSVC_CRT) 96 97 98# List of valid CRTs for MSVC 99set(MSVC_CRT 100 MD 101 MDd 102 MT 103 MTd) 104 105choose_msvc_crt(MSVC_CRT) 106 107