Fix MSVC compiler/linker flags.

Turn off ccache for vcpkg builds (this is only relevant to MSVC, where
ccache does not work yet.)

Throw an error if CMAKE_BUILD_TYPE is not valid or does not match case
exactly (to make comparisons simple.)

Add SetCompilerLinkerFlags.cmake lib with the functions:

add_compiler_flags()

For each flag passed in, add it to CMAKE_CXX_FLAGS and CMAKE_C_FLAGS if
not already present. Also clears all build-specific flag variables on
every call, if using this functions you must set build-specific flags
yourself.

add_linker_flags()

For each flag passed in, add it to
CMAKE_(EXE|SHARED|MODULE|STATIC)_LINKER_FLAGS if not already present.

Add remove_dupes() function to VbamFunctions.cmake from:

https://stackoverflow.com/a/41416298/262458

This is used to remove duplicate flags in SetCompilerLinkerFlags.cmake
described above.

Use the new functions to set compiler and linker flags for MSVC.

Signed-off-by: Rafael Kitover <rkitover@gmail.com>
This commit is contained in:
Rafael Kitover 2022-02-02 22:27:39 +00:00
parent 5ed544aad3
commit 7d454e054a
No known key found for this signature in database
GPG Key ID: 08AB596679D86240
3 changed files with 91 additions and 46 deletions

View File

@ -58,20 +58,16 @@ endif()
# Use ccache if available and not already enabled on the command line.
# This has to be done before the project() call.
if(NOT (CMAKE_CXX_COMPILER_LAUNCHER OR CMAKE_CXX_COMPILER MATCHES ccache))
if(NOT (VCPKG_TARGET_TRIPLET OR CMAKE_CXX_COMPILER_LAUNCHER OR CMAKE_CXX_COMPILER MATCHES ccache))
find_program(CCACHE_EXECUTABLE ccache)
if(CCACHE_EXECUTABLE)
message(STATUS "Enabling ccache")
if(CMAKE_VERSION VERSION_LESS 3.4.0)
# FIXME: This method currently breaks for native ccache on windows
# with the visual studio resource compiler.
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE_EXECUTABLE})
else()
set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE_EXECUTABLE} CACHE STRING "C compiler launcher" FORCE)
set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE_EXECUTABLE} CACHE STRING "C++ compiler launcher" FORCE)
set(CMAKE_ASM_NASM_COMPILER_LAUNCHER ${CCACHE_EXECUTABLE} CACHE STRING "nasm assembler launcher" FORCE)
endif()
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE_EXECUTABLE})
set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE_EXECUTABLE} CACHE STRING "C compiler launcher" FORCE)
set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE_EXECUTABLE} CACHE STRING "C++ compiler launcher" FORCE)
set(CMAKE_ASM_NASM_COMPILER_LAUNCHER ${CCACHE_EXECUTABLE} CACHE STRING "nasm assembler launcher" FORCE)
endif()
endif()
@ -85,6 +81,8 @@ endif()
if(CMAKE_BUILD_TYPE STREQUAL "")
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build Type" FORCE)
elseif(NOT CMAKE_BUILD_TYPE MATCHES "^(Release|Debug|RelWithDebInfo|MinSizeRel)$")
message(FATAL_ERROR "Invalid CMAKE_BUILD_TYPE: '${CMAKE_BUILD_TYPE}', must be one of: 'Release', 'Debug', 'RelWithDebInfo' or 'MinSizeRel'")
endif()
include(CTest)
@ -547,6 +545,8 @@ ProcessorCount(num_cpus)
option(UPSTREAM_RELEASE "do some optimizations and release automation tasks" OFF)
include(SetCompilerLinkerFlags)
if(CMAKE_C_COMPILER_ID STREQUAL Clang AND CMAKE_CXX_COMPILER_ID STREQUAL Clang)
include(LLVMToolchain)
endif()
@ -770,47 +770,38 @@ elseif(MSVC)
string(REGEX REPLACE "/[Ww][^ ]+" "" CMAKE_C_FLAGS ${CMAKE_C_FLAGS})
string(REGEX REPLACE "/[Ww][^ ]+" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
add_compile_options(/std:c++17 -D__STDC_LIMIT_MACROS /fp:fast /Oi)
if(CMAKE_BUILD_TYPE STREQUAL Debug)
add_compile_options(/W4)
else()
add_compile_options(/w)
if(X86_32)
add_compile_options(/Ot /Oy /Ob3 /GF /Gy)
else()
add_compile_options(/O2 /Ob3)
endif()
if(ENABLE_LTO)
add_compile_options(/GL)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /LTCG")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /LTCG")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /LTCG")
set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /LTCG")
endif()
endif()
add_compiler_flags(/std:c++17 -D__STDC_LIMIT_MACROS /fp:fast /Oi)
if(VBAM_STATIC)
string(REGEX REPLACE "/MDd?" "" CMAKE_C_FLAGS ${CMAKE_CXX_FLAGS})
string(REGEX REPLACE "/MDd?" "" CMAKE_C_FLAGS_MINSIZEREL ${CMAKE_CXX_FLAGS})
string(REGEX REPLACE "/MDd?" "" CMAKE_C_FLAGS_RELEASE ${CMAKE_CXX_FLAGS})
string(REGEX REPLACE "/MDd?" "" CMAKE_C_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS})
string(REGEX REPLACE "/MDd?" "" CMAKE_C_FLAGS_DEBUG ${CMAKE_CXX_FLAGS})
set(runtime "/MT")
else()
set(runtime "/MD")
endif()
string(REGEX REPLACE "/MDd?" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
string(REGEX REPLACE "/MDd?" "" CMAKE_CXX_FLAGS_MINSIZEREL ${CMAKE_CXX_FLAGS})
string(REGEX REPLACE "/MDd?" "" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS})
string(REGEX REPLACE "/MDd?" "" CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS})
string(REGEX REPLACE "/MDd?" "" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS})
if(CMAKE_BUILD_TYPE STREQUAL Debug)
set(runtime "${runtime}d")
if(CMAKE_BUILD_TYPE MATCHES "Debug|RelWithDebInfo")
add_compile_options(/MTd)
add_compiler_flags(${runtime} /W4 /Ob0 /Od /RTC1 /DDEBUG)
else()
add_compiler_flags(/w /DNDEBUG)
if(CMAKE_BUILD_TYPE STREQUAL Release)
if(X86_32)
add_compiler_flags(${runtime} /Ot /Oy /GF /Gy /Ob3)
else()
add_compiler_flags(${runtime} /O2 /Ob3)
endif()
elseif(CMAKE_BUILD_TYPE STREQUAL RelWithDebInfo)
add_compiler_flags(${runtime} /Zi /Ob1)
elseif(CMAKE_BUILD_TYPE STREQUAL MinSizeRel)
add_compiler_flags(${runtime} /O1 /Ob1)
else()
add_compile_options(/MT)
message(FATAL_ERROR "Unknown CMAKE_BUILD_TYPE: '${CMAKE_BUILD_TYPE}'")
endif()
if(ENABLE_LTO)
add_compiler_flags(/GL)
add_linker_flags(/LTCG)
endif()
endif()
endif()

View File

@ -0,0 +1,44 @@
include(VbamFunctions)
function(add_compiler_flags)
foreach(var RELEASE DEBUG RELWITHDEBINFO MINSIZEREL)
set("CMAKE_CXX_FLAGS_${var}" "" CACHE STRING "MUST BE UNSET" FORCE)
set("CMAKE_CXX_FLAGS_${var}" "" PARENT_SCOPE)
set("CMAKE_C_FLAGS_${var}" "" CACHE STRING "MUST BE UNSET" FORCE)
set("CMAKE_C_FLAGS_${var}" "" PARENT_SCOPE)
endforeach()
# Set C and CXX flags if not already set.
foreach(flag ${ARGV})
foreach(var CMAKE_CXX_FLAGS CMAKE_C_FLAGS)
# Remove any duplicates first.
remove_dupes("${${var}}" "${var}")
string(FIND "${${var}}" "${flag}" found)
if(found EQUAL -1)
set("${var}" "${${var}} ${flag}" CACHE STRING "Compiler Flags" FORCE)
set("${var}" "${${var}} ${flag}" PARENT_SCOPE)
endif()
endforeach()
endforeach()
endfunction()
function(add_linker_flags)
# Set linker flags if not already set.
foreach(flag ${ARGV})
foreach(var EXE SHARED MODULE STATIC)
set(var "CMAKE_${var}_LINKER_FLAGS")
# Remove any duplicates first.
remove_dupes("${${var}}" "${var}")
string(FIND "${${var}}" "${flag}" found)
if(found EQUAL -1)
set("${var}" "${${var}} ${flag}" CACHE STRING "Linker Flags" FORCE)
set("${var}" "${${var}} ${flag}" PARENT_SCOPE)
endif()
endforeach()
endforeach()
endfunction()

View File

@ -1,3 +1,13 @@
# From: https://stackoverflow.com/a/41416298/262458
function(REMOVE_DUPES ARG_STR OUTPUT)
set(ARG_LIST ${ARG_STR})
separate_arguments(ARG_LIST)
list(REMOVE_DUPLICATES ARG_LIST)
string (REGEX REPLACE "([^\\]|^);" "\\1 " _TMP_STR "${ARG_LIST}")
string (REGEX REPLACE "[\\](.)" "\\1" _TMP_STR "${_TMP_STR}") #fixes escaping
set (${OUTPUT} "${_TMP_STR}" PARENT_SCOPE)
endfunction()
# From: https://stackoverflow.com/a/7216542
function(JOIN VALUES GLUE OUTPUT)
string (REGEX REPLACE "([^\\]|^);" "\\1${GLUE}" _TMP_STR "${VALUES}")