Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions cmake/Common.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ function(check_flags_available return_var flags)
set(FLAGS_BACKUP ${CMAKE_REQUIRED_FLAGS})

# Set QUIET flag to suppress output during compilation check
set(CMAKE_REQUIRED_QUIET TRUE)
set(CMAKE_REQUIRED_QUIET ON)

# Set the flags to be checked for availability
set(CMAKE_REQUIRED_FLAGS "${flags}")
Expand All @@ -88,10 +88,11 @@ function(check_flags_available return_var flags)
"int main() { return 0; }"
is_available
FAIL_REGEX
D9002
"unused-command-line-argument"
"invalid argument"
"unknown-warning-option") # linker error
[[D9002]]
[[unused-command-line-argument]]
[[invalid argument]]
[[unknown argument]]
[[unknown-warning-option]])

# Store the result of flag availability check in the specified variable
set(${return_var}
Expand Down
125 changes: 75 additions & 50 deletions cmake/build/CompilerFlags.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -104,63 +104,79 @@ message(
COMPILER_FLAGS_SKIP_TARGETS_REGEXES: List of regexes to skip targets. Default is empty."
)

if(MSVC)
set(_warnings_cxx_temp ${COMPILER_FLAGS_WARNINGS_MSVC})
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES
".*Clang")
set(_warnings_cxx_temp ${COMPILER_FLAGS_WARNINGS_GNU})
else()
message(
AUTHOR_WARNING
"No compiler warnings set for CXX compiler: '${CMAKE_CXX_COMPILER_ID}'")
endif()

message(VERBOSE "Check Compiler Warnings CXX: ${_warnings_cxx_temp}")

foreach(_warn ${_warnings_cxx_temp})
check_and_append_flag(FLAGS "${_warn}" TARGETS compiler_warnings_cxx)
endforeach()

unset(_warnings_cxx_temp)
string(
SHA256
_compiler_flags_hash
"${COMPILER_FLAGS_WARNINGS_MSVC}#${COMPILER_FLAGS_WARNINGS_GNU}#${COMPILER_FLAGS_WARNINGS_CUDA}#${CMAKE_COMPILE_WARNING_AS_ERROR}"
)
if(NOT DEFINED CACHE{__COMPILER_FLAGS_HASH} OR NOT __COMPILER_FLAGS_HASH
STREQUAL _compiler_flags_hash)
set(__COMPILER_FLAGS_HASH
"${_compiler_flags_hash}"
CACHE INTERNAL "Hash of compiler flags options")
set(__COMPILER_WARNINGS_C "")
set(__COMPILER_WARNINGS_CXX "")
set(__COMPILER_WARNINGS_CUDA "")

if(CMAKE_COMPILE_WARNING_AS_ERROR)
if(MSVC)
check_and_append_flag(FLAGS "/WX" TARGETS compiler_warnings_cxx)
set(_warnings_cxx_temp ${COMPILER_FLAGS_WARNINGS_MSVC})
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES
".*Clang")
check_and_append_flag(FLAGS "-Werror" TARGETS compiler_warnings_cxx)
set(_warnings_cxx_temp ${COMPILER_FLAGS_WARNINGS_GNU})
else()
message(
AUTHOR_WARNING
"No compiler warnings as errors set for CXX compiler: '${CMAKE_CXX_COMPILER_ID}'"
)
"No compiler warnings set for CXX compiler: '${CMAKE_CXX_COMPILER_ID}'")
endif()

message(VERBOSE "Check Compiler Warnings CXX: ${_warnings_cxx_temp}")

foreach(_warn ${_warnings_cxx_temp})
check_and_append_flag(FLAGS "${_warn}" TARGETS __COMPILER_WARNINGS_CXX)
endforeach()

unset(_warnings_cxx_temp)

if(CMAKE_COMPILE_WARNING_AS_ERROR)
if(MSVC)
check_and_append_flag(FLAGS "/WX" TARGETS __COMPILER_WARNINGS_CXX)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID
MATCHES ".*Clang")
check_and_append_flag(FLAGS "-Werror" TARGETS __COMPILER_WARNINGS_CXX)
else()
message(
AUTHOR_WARNING
"No compiler warnings as errors set for CXX compiler: '${CMAKE_CXX_COMPILER_ID}'"
)
endif()
endif()

# use the same warning flags for C
set(__COMPILER_WARNINGS_C "${__COMPILER_WARNINGS_CXX}")

foreach(_warn ${COMPILER_FLAGS_WARNINGS_CUDA})
check_and_append_flag(FLAGS "${_warn}" TARGETS __COMPILER_WARNINGS_CUDA)
endforeach()

flags_to_list(__COMPILER_WARNINGS_C "${__COMPILER_WARNINGS_C}")
flags_to_list(__COMPILER_WARNINGS_CXX "${__COMPILER_WARNINGS_CXX}")
flags_to_list(__COMPILER_WARNINGS_CUDA "${__COMPILER_WARNINGS_CUDA}")
set(__COMPILER_WARNINGS_C
"${__COMPILER_WARNINGS_C}"
CACHE INTERNAL "compiler warnings flags for C")
set(__COMPILER_WARNINGS_CXX
"${__COMPILER_WARNINGS_CXX}"
CACHE INTERNAL "compiler warnings flags for CXX")
set(__COMPILER_WARNINGS_CUDA
"${__COMPILER_WARNINGS_CUDA}"
CACHE INTERNAL "compiler warnings flags for CUDA")
endif()

# use the same warning flags for C
set(compiler_warnings_c "${compiler_warnings_cxx}")

foreach(_warn ${COMPILER_FLAGS_WARNINGS_CUDA})
check_and_append_flag(FLAGS "${_warn}" TARGETS compiler_warnings_cuda)
endforeach()

flags_to_list(compiler_warnings_c "${compiler_warnings_c}")
flags_to_list(compiler_warnings_cxx "${compiler_warnings_cxx}")
flags_to_list(compiler_warnings_cuda "${compiler_warnings_cuda}")
message(STATUS "Compiler final warnings for C: ${compiler_warnings_c}")
message(STATUS "Compiler final warnings for CXX: ${compiler_warnings_cxx}")
message(STATUS "Compiler final warnings for CUDA: ${compiler_warnings_cuda}")

add_custom_target(compiler_flags_warnings)
set_target_properties(compiler_flags_warnings
PROPERTIES _c "${compiler_warnings_c}")
set_target_properties(compiler_flags_warnings
PROPERTIES _cxx "${compiler_warnings_cxx}")
set_target_properties(compiler_flags_warnings
PROPERTIES _cuda "${compiler_warnings_cuda}")
unset(compiler_warnings_c)
unset(compiler_warnings_cxx)
unset(compiler_warnings_cuda)
message(STATUS "Compiler final warnings for C: $CACHE{__COMPILER_WARNINGS_C}")
message(
STATUS "Compiler final warnings for CXX: $CACHE{__COMPILER_WARNINGS_CXX}")
message(
STATUS "Compiler final warnings for CUDA: $CACHE{__COMPILER_WARNINGS_CUDA}")

#[[
Function to apply compiler warnings to a target.
Expand All @@ -184,9 +200,18 @@ function(warn_target target)
endforeach()
endif()

get_target_property(_c compiler_flags_warnings _c)
get_target_property(_cxx compiler_flags_warnings _cxx)
get_target_property(_cuda compiler_flags_warnings _cuda)
if(NOT DEFINED CACHE{__COMPILER_WARNINGS_C}
OR NOT DEFINED CACHE{__COMPILER_WARNINGS_CXX}
OR NOT DEFINED CACHE{__COMPILER_WARNINGS_CUDA})
message(
FATAL_ERROR
"Compiler warnings not set. Please call 'include(${CMAKE_CURRENT_LIST_DIR}/CompilerFlags.cmake)'"
)
endif()

set(_c $CACHE{__COMPILER_WARNINGS_C})
set(_cxx $CACHE{__COMPILER_WARNINGS_CXX})
set(_cuda $CACHE{__COMPILER_WARNINGS_CUDA})

if(arg_INCLUDE_FLAGS)
message(VERBOSE
Expand Down
114 changes: 65 additions & 49 deletions cmake/build/Hardening.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -96,65 +96,76 @@ if(NOT USE_HARDENING)
message(STATUS "Hardening disabled by USE_HARDENING evaluates to false")
endif()

# Create a custom target to hold the hardening flags
string(SHA256 _hardening_flags_hash
"${USE_HARDENING_FLAGS}#${USE_HARDENING_LINKS}")
if(NOT DEFINED CACHE{__HARDENING_FLAGS_HASH} OR NOT __HARDENING_FLAGS_HASH
STREQUAL _hardening_flags_hash)
set(__HARDENING_FLAGS_HASH
"${_hardening_flags_hash}"
CACHE INTERNAL "Hash of hardening flags options")
set(__HARDENING_FLAGS "")
set(__HARDENING_LINKS "")

message(VERBOSE "Check Hardening flags: ${USE_HARDENING_FLAGS}")
# Create a custom target to hold the hardening flags

foreach(_harden ${USE_HARDENING_FLAGS})
check_and_append_flag(FLAGS ${_harden} TARGETS hardening_flags)
endforeach()
message(VERBOSE "Check Hardening flags: ${USE_HARDENING_FLAGS}")

flags_to_list(hardening_flags "${hardening_flags}")
foreach(_harden ${USE_HARDENING_FLAGS})
check_and_append_flag(FLAGS ${_harden} TARGETS __HARDENING_FLAGS)
endforeach()

message(VERBOSE "Check Hardening links: ${USE_HARDENING_LINKS}")
flags_to_list(__HARDENING_FLAGS "${__HARDENING_FLAGS}")

foreach(_harden ${USE_HARDENING_LINKS})
flags_to_list(_harden_list "${_harden}")
message(VERBOSE "Check Hardening links: ${USE_HARDENING_LINKS}")

if(hardening_flags MATCHES "${_harden_list}")
list(APPEND hardening_links ${_harden})
endif()
endforeach()

# Enable minimal runtime undefined but not not propagete globally, see
# https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html#minimal-runtime
if(hardening_flags MATCHES "-fsanitize=undefined;-fsanitize-minimal-runtime")
message(VERBOSE
"Try to enabling minimal runtime undefined behavior sanitizer")
check_and_append_flag(FLAGS "-fno-sanitize-recover=undefined" TARGETS
no_sanitize_recover_ub)
flags_to_list(no_sanitize_recover_ub "${no_sanitize_recover_ub}")
list(APPEND hardening_flags ${no_sanitize_recover_ub})
list(APPEND hardening_links ${no_sanitize_recover_ub})
endif()
foreach(_harden ${USE_HARDENING_LINKS})
flags_to_list(_harden_list "${_harden}")

flags_to_list(hardening_links "${hardening_links}")
if(__HARDENING_FLAGS MATCHES "${_harden_list}")
list(APPEND __HARDENING_LINKS ${_harden})
endif()
endforeach()

# Handle the conflics between hardening ubsan and asan
if(TARGET sanitizer_flags)
get_target_property(_san sanitizer_flags _san)
# Enable minimal runtime undefined but not not propagete globally, see
# https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html#minimal-runtime
if(__HARDENING_FLAGS MATCHES
"-fsanitize=undefined;-fsanitize-minimal-runtime")
message(VERBOSE
"Try to enabling minimal runtime undefined behavior sanitizer")
check_and_append_flag(FLAGS "-fno-sanitize-recover=undefined" TARGETS
no_sanitize_recover_ub)
flags_to_list(no_sanitize_recover_ub "${no_sanitize_recover_ub}")
list(APPEND __HARDENING_FLAGS ${no_sanitize_recover_ub})
list(APPEND __HARDENING_LINKS ${no_sanitize_recover_ub})
endif()

if(_san
AND _san MATCHES "-fsanitize=address"
AND hardening_flags MATCHES "-fsanitize-minimal-runtime")
message(
WARNING "Try to disable usan minimal runtime due to conflict with asan")
list(REMOVE_ITEM hardening_flags "-fsanitize=undefined"
"-fsanitize-minimal-runtime" "-fno-sanitize-recover=undefined")
list(REMOVE_ITEM hardening_links "-fsanitize=undefined"
"-fsanitize-minimal-runtime" "-fno-sanitize-recover=undefined")
flags_to_list(__HARDENING_LINKS "${__HARDENING_LINKS}")

# Handle the conflics between hardening ubsan and asan
if(TARGET sanitizer_flags)
get_target_property(_san sanitizer_flags _san)

if(_san
AND _san MATCHES "-fsanitize=address"
AND __HARDENING_FLAGS MATCHES "-fsanitize-minimal-runtime")
message(
WARNING "Try to disable usan minimal runtime due to conflict with asan")
list(REMOVE_ITEM __HARDENING_FLAGS "-fsanitize=undefined"
"-fsanitize-minimal-runtime" "-fno-sanitize-recover=undefined")
list(REMOVE_ITEM __HARDENING_LINKS "-fsanitize=undefined"
"-fsanitize-minimal-runtime" "-fno-sanitize-recover=undefined")
endif()
endif()
set(__HARDENING_FLAGS
"${__HARDENING_FLAGS}"
CACHE INTERNAL "Hardening flags")
set(__HARDENING_LINKS
"${__HARDENING_LINKS}"
CACHE INTERNAL "Hardening links")
endif()

message(STATUS "Hardening final flags: ${hardening_flags}")
message(STATUS "Hardening final links: ${hardening_links}")

add_custom_target(hardening_flags)
set_target_properties(hardening_flags PROPERTIES _flags "${hardening_flags}")
set_target_properties(hardening_flags PROPERTIES _links "${hardening_links}")

unset(hardening_flags)
unset(hardening_links)
message(STATUS "Hardening final flags: $CACHE{__HARDENING_FLAGS}")
message(STATUS "Hardening final links: $CACHE{__HARDENING_LINKS}")

function(harden_target target)
set(_opts)
Expand Down Expand Up @@ -196,8 +207,13 @@ function(harden_target target)
endif()
endif()

get_target_property(_flags hardening_flags _flags)
get_target_property(_links hardening_flags _links)
if(NOT DEFINED CACHE{__HARDENING_FLAGS} OR NOT DEFINED
CACHE{__HARDENING_LINKS})
message(FATAL_ERROR "Hardening flags not defined")
endif()

set(_flags $CACHE{__HARDENING_FLAGS})
set(_links $CACHE{__HARDENING_LINKS})

set(FLAGS ${_flags} ${target_flags})
set(LINKS ${_links} ${target_flags})
Expand Down
Loading
Loading