1# Copyright (C) 2020 The Khronos Group Inc. 2# 3# All rights reserved. 4# 5# Redistribution and use in source and binary forms, with or without 6# modification, are permitted provided that the following conditions 7# are met: 8# 9# Redistributions of source code must retain the above copyright 10# notice, this list of conditions and the following disclaimer. 11# 12# Redistributions in binary form must reproduce the above 13# copyright notice, this list of conditions and the following 14# disclaimer in the documentation and/or other materials provided 15# with the distribution. 16# 17# Neither the name of The Khronos Group Inc. nor the names of its 18# contributors may be used to endorse or promote products derived 19# from this software without specific prior written permission. 20# 21# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32# POSSIBILITY OF SUCH DAMAGE. 33 34# The macro choose_msvc_crt() takes a list of possible 35# C runtimes to choose from, in the form of compiler flags, 36# to present to the user. (MTd for /MTd, etc) 37# 38# The macro is invoked at the end of the file. 39# 40# CMake already sets CRT flags in the CMAKE_CXX_FLAGS_* and 41# CMAKE_C_FLAGS_* variables by default. To let the user 42# override that for each build type: 43# 1. Detect which CRT is already selected, and reflect this in 44# LLVM_USE_CRT_* so the user can have a better idea of what 45# changes they're making. 46# 2. Replace the flags in both variables with the new flag via a regex. 47# 3. set() the variables back into the cache so the changes 48# are user-visible. 49 50### Helper macros: ### 51macro(make_crt_regex regex crts) 52 set(${regex} "") 53 foreach(crt ${${crts}}) 54 # Trying to match the beginning or end of the string with stuff 55 # like [ ^]+ didn't work, so use a bunch of parentheses instead. 56 set(${regex} "${${regex}}|(^| +)/${crt}($| +)") 57 endforeach(crt) 58 string(REGEX REPLACE "^\\|" "" ${regex} "${${regex}}") 59endmacro(make_crt_regex) 60 61macro(get_current_crt crt_current regex flagsvar) 62 # Find the selected-by-CMake CRT for each build type, if any. 63 # Strip off the leading slash and any whitespace. 64 string(REGEX MATCH "${${regex}}" ${crt_current} "${${flagsvar}}") 65 string(REPLACE "/" " " ${crt_current} "${${crt_current}}") 66 string(STRIP "${${crt_current}}" ${crt_current}) 67endmacro(get_current_crt) 68 69# Replaces or adds a flag to a variable. 70# Expects 'flag' to be padded with spaces. 71macro(set_flag_in_var flagsvar regex flag) 72 string(REGEX MATCH "${${regex}}" current_flag "${${flagsvar}}") 73 if("${current_flag}" STREQUAL "") 74 set(${flagsvar} "${${flagsvar}}${${flag}}") 75 else() 76 string(REGEX REPLACE "${${regex}}" "${${flag}}" ${flagsvar} "${${flagsvar}}") 77 endif() 78 string(STRIP "${${flagsvar}}" ${flagsvar}) 79 # Make sure this change gets reflected in the cache/gui. 80 # CMake requires the docstring parameter whenever set() touches the cache, 81 # so get the existing docstring and re-use that. 82 get_property(flagsvar_docs CACHE ${flagsvar} PROPERTY HELPSTRING) 83 set(${flagsvar} "${${flagsvar}}" CACHE STRING "${flagsvar_docs}" FORCE) 84endmacro(set_flag_in_var) 85 86 87macro(choose_msvc_crt MSVC_CRT) 88 if(LLVM_USE_CRT) 89 message(FATAL_ERROR 90 "LLVM_USE_CRT is deprecated. Use the CMAKE_BUILD_TYPE-specific 91variables (LLVM_USE_CRT_DEBUG, etc) instead.") 92 endif() 93 94 make_crt_regex(MSVC_CRT_REGEX ${MSVC_CRT}) 95 96 foreach(build_type ${CMAKE_CONFIGURATION_TYPES} ${CMAKE_BUILD_TYPE}) 97 string(TOUPPER "${build_type}" build) 98 if (NOT LLVM_USE_CRT_${build}) 99 get_current_crt(LLVM_USE_CRT_${build} 100 MSVC_CRT_REGEX 101 CMAKE_CXX_FLAGS_${build}) 102 set(LLVM_USE_CRT_${build} 103 "${LLVM_USE_CRT_${build}}" 104 CACHE STRING "Specify VC++ CRT to use for ${build_type} configurations." 105 FORCE) 106 set_property(CACHE LLVM_USE_CRT_${build} 107 PROPERTY STRINGS ;${${MSVC_CRT}}) 108 endif(NOT LLVM_USE_CRT_${build}) 109 endforeach(build_type) 110 111 foreach(build_type ${CMAKE_CONFIGURATION_TYPES} ${CMAKE_BUILD_TYPE}) 112 string(TOUPPER "${build_type}" build) 113 if ("${LLVM_USE_CRT_${build}}" STREQUAL "") 114 set(flag_string " ") 115 else() 116 set(flag_string " /${LLVM_USE_CRT_${build}} ") 117 list(FIND ${MSVC_CRT} ${LLVM_USE_CRT_${build}} idx) 118 if (idx LESS 0) 119 message(FATAL_ERROR 120 "Invalid value for LLVM_USE_CRT_${build}: ${LLVM_USE_CRT_${build}}. Valid options are one of: ${${MSVC_CRT}}") 121 endif (idx LESS 0) 122 message(STATUS "Using ${build_type} VC++ CRT: ${LLVM_USE_CRT_${build}}") 123 endif() 124 foreach(lang C CXX) 125 set_flag_in_var(CMAKE_${lang}_FLAGS_${build} MSVC_CRT_REGEX flag_string) 126 endforeach(lang) 127 endforeach(build_type) 128endmacro(choose_msvc_crt MSVC_CRT) 129 130 131# List of valid CRTs for MSVC 132set(MSVC_CRT 133 MD 134 MDd 135 MT 136 MTd) 137 138choose_msvc_crt(MSVC_CRT) 139