diff --git a/cmake/modules/AddCompilerFlags.cmake b/cmake/modules/AddCompilerFlags.cmake index 7896df6a9e..6d14410dc0 100644 --- a/cmake/modules/AddCompilerFlags.cmake +++ b/cmake/modules/AddCompilerFlags.cmake @@ -1,159 +1,162 @@ # Allow to easily add flags for C and C++ include(CheckCXXCompilerFlag) include(CheckCCompilerFlag) include(SanitizeHelper) function(check_compiler_flag RESULT LANGUAGE FLAG) sanitize_c_cxx_definition("have_${LANGUAGE}_" ${FLAG} TEST_NAME) if("${LANGUAGE}" STREQUAL "C") CHECK_C_COMPILER_FLAG(${FLAG} ${TEST_NAME}) elseif("${LANGUAGE}" STREQUAL "CXX") CHECK_CXX_COMPILER_FLAG(${FLAG} ${TEST_NAME}) else() message(FATAL_ERROR "check_compiler_flag LANGUAGE should be C or CXX") endif() set(${RESULT} ${${TEST_NAME}} PARENT_SCOPE) endfunction() function(add_compiler_flags_to_var TARGET LANGUAGE) foreach(f ${ARGN}) # If the flag is already set, avoid duplicating it string(FIND "${${TARGET}}" "${f}" FLAG_POSITION) if(${FLAG_POSITION} LESS 0) check_compiler_flag(FLAG_IS_SUPPORTED ${LANGUAGE} ${f}) if(${FLAG_IS_SUPPORTED}) string(APPEND ${TARGET} " ${f}") endif() endif() endforeach() set(${TARGET} ${${TARGET}} PARENT_SCOPE) endfunction() function(add_compiler_flags_for_language LANGUAGE) foreach(f ${ARGN}) check_compiler_flag(FLAG_IS_SUPPORTED ${LANGUAGE} ${f}) if(${FLAG_IS_SUPPORTED}) add_compile_options($<$:${f}>) endif() endforeach() endfunction() macro(add_c_compiler_flags) add_compiler_flags_for_language(C ${ARGN}) endmacro() macro(add_cxx_compiler_flags) add_compiler_flags_for_language(CXX ${ARGN}) endmacro() macro(add_compiler_flags) add_c_compiler_flags(${ARGN}) add_cxx_compiler_flags(${ARGN}) endmacro() macro(remove_compiler_flags_from_var TARGET) foreach(f ${ARGN}) string(REGEX REPLACE "${f}( |$)" "" ${TARGET} "${${TARGET}}") endforeach() endmacro() function(remove_c_compiler_flags) remove_compiler_flags_from_var(CMAKE_C_FLAGS ${ARGN}) set(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} PARENT_SCOPE) if(NOT "${CMAKE_BUILD_TYPE}" STREQUAL "") string(TOUPPER "CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE}" BUILD_TYPE_FLAGS) remove_compiler_flags_from_var(${BUILD_TYPE_FLAGS} ${ARGN}) set(${BUILD_TYPE_FLAGS} ${${BUILD_TYPE_FLAGS}} PARENT_SCOPE) endif() endfunction() function(remove_cxx_compiler_flags) remove_compiler_flags_from_var(CMAKE_CXX_FLAGS ${ARGN}) set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} PARENT_SCOPE) if(NOT "${CMAKE_BUILD_TYPE}" STREQUAL "") string(TOUPPER "CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE}" BUILD_TYPE_FLAGS) remove_compiler_flags_from_var(${BUILD_TYPE_FLAGS} ${ARGN}) set(${BUILD_TYPE_FLAGS} ${${BUILD_TYPE_FLAGS}} PARENT_SCOPE) endif() endfunction() macro(remove_compiler_flags) remove_c_compiler_flags(${ARGN}) remove_cxx_compiler_flags(${ARGN}) endmacro() function(add_compile_options_to_configuration_for_language CONFIGURATION LANGUAGE) foreach(f ${ARGN}) check_compiler_flag(FLAG_IS_SUPPORTED ${LANGUAGE} ${f}) if(${FLAG_IS_SUPPORTED}) add_compile_options($<$,$>:${f}>) endif() endforeach() endfunction() macro(add_c_compile_options_to_configuration CONFIGURATION) add_compile_options_to_configuration_for_language(${CONFIGURATION} C ${ARGN}) endmacro() macro(add_cxx_compile_options_to_configuration CONFIGURATION) add_compile_options_to_configuration_for_language(${CONFIGURATION} CXX ${ARGN}) endmacro() macro(add_compile_options_to_configuration CONFIGURATION) add_c_compile_options_to_configuration(${CONFIGURATION} ${ARGN}) add_cxx_compile_options_to_configuration(${CONFIGURATION} ${ARGN}) endmacro() function(add_compile_definitions_to_configuration CONFIGURATION) foreach(f ${ARGN}) add_compile_definitions($<$:${f}>) endforeach() endfunction() # Note that CMake does not provide any facility to check that a linker flag is # supported by the compiler. # However since CMake 3.2 introduced the CMP0056 policy, the # CMAKE_EXE_LINKER_FLAGS variable is used by the try_compile function, so there # is a workaround that allow for testing the linker flags. -function(add_linker_flags) - foreach(f ${ARGN}) - sanitize_c_cxx_definition("have_linker_" ${f} FLAG_IS_SUPPORTED) +function(check_linker_flag RESULT FLAG) + # Some linkers (e.g.: Clang) will issue a -Wunused-command-line-argument + # warning when an unknown linker flag is set. + # Using -Werror will promote these warnings to errors so + # CHECK_CXX_COMPILER_FLAG() will return false, preventing the flag from + # being set. + add_compiler_flags_to_var( + CMAKE_REQUIRED_FLAGS + CXX + "-Werror=unused-command-line-argument" + ) + + # Save the current linker flags + set(SAVE_CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS}) + + # If the flag is already set, avoid duplicating it + string(FIND "${CMAKE_EXE_LINKER_FLAGS}" "${FLAG}" FLAG_POSITION) + if(${FLAG_POSITION} LESS 0) + string(APPEND CMAKE_EXE_LINKER_FLAGS " ${FLAG}") + endif() - # Some linkers (e.g.: Clang) will issue a -Wunused-command-line-argument - # warning when an unknown linker flag is set. - # Using -Werror will promote these warnings to errors so - # CHECK_CXX_COMPILER_FLAG() will return false, preventing the flag from - # being set. - add_compiler_flags_to_var( - CMAKE_REQUIRED_FLAGS - CXX - "-Werror=unused-command-line-argument" - ) + # CHECK_CXX_COMPILER_FLAG calls CHECK_CXX_SOURCE_COMPILES which in turn + # calls try_compile, so it will check our flag + CHECK_CXX_COMPILER_FLAG("" ${RESULT}) - # Save the current linker flags - set(SAVE_CMAKE_EXE_LINKERFLAGS ${CMAKE_EXE_LINKER_FLAGS}) + # Restore CMAKE_EXE_LINKER_FLAGS + set(CMAKE_EXE_LINKER_FLAGS ${SAVE_CMAKE_EXE_LINKER_FLAGS}) - # If the flag is already set, avoid duplicating it - string(FIND "${CMAKE_EXE_LINKER_FLAGS}" "${f}" FLAG_POSITION) - if(${FLAG_POSITION} LESS 0) - string(APPEND CMAKE_EXE_LINKER_FLAGS " ${f}") - endif() + set(${RESULT} ${${RESULT}} PARENT_SCOPE) +endfunction() - # CHECK_CXX_COMPILER_FLAG calls CHECK_CXX_SOURCE_COMPILES which in turn - # calls try_compile, so it will check our flag - CHECK_CXX_COMPILER_FLAG("" ${FLAG_IS_SUPPORTED}) +function(add_linker_flags) + foreach(f ${ARGN}) + sanitize_c_cxx_definition("have_linker_" ${f} FLAG_IS_SUPPORTED) - # Unset the -Werror=unused-command-line-argument flag if it is set. - remove_compiler_flags_from_var( - CMAKE_REQUIRED_FLAGS - "-Werror=unused-command-line-argument" - ) + check_linker_flag(${FLAG_IS_SUPPORTED} ${f}) - # If the flag is not supported restore CMAKE_EXE_LINKER_FLAGS - if(NOT ${FLAG_IS_SUPPORTED}) - set(CMAKE_EXE_LINKER_FLAGS ${SAVE_CMAKE_EXE_LINKERFLAGS}) + # If the flag is supported, add it to CMAKE_EXE_LINKER_FLAGS + if(${FLAG_IS_SUPPORTED}) + string(APPEND CMAKE_EXE_LINKER_FLAGS " ${f}") endif() endforeach() set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} PARENT_SCOPE) endfunction()