Skip to content

Commit d386c27

Browse files
authored
perf: cache flags for compiler, hardening, sanitizer (#135)
Signed-off-by: l.feng <43399351+msclock@users.noreply.github.com>
1 parent 511f6fa commit d386c27

4 files changed

Lines changed: 231 additions & 169 deletions

File tree

cmake/Common.cmake

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ function(check_flags_available return_var flags)
7878
set(FLAGS_BACKUP ${CMAKE_REQUIRED_FLAGS})
7979

8080
# Set QUIET flag to suppress output during compilation check
81-
set(CMAKE_REQUIRED_QUIET TRUE)
81+
set(CMAKE_REQUIRED_QUIET ON)
8282

8383
# Set the flags to be checked for availability
8484
set(CMAKE_REQUIRED_FLAGS "${flags}")
@@ -88,10 +88,11 @@ function(check_flags_available return_var flags)
8888
"int main() { return 0; }"
8989
is_available
9090
FAIL_REGEX
91-
D9002
92-
"unused-command-line-argument"
93-
"invalid argument"
94-
"unknown-warning-option") # linker error
91+
[[D9002]]
92+
[[unused-command-line-argument]]
93+
[[invalid argument]]
94+
[[unknown argument]]
95+
[[unknown-warning-option]])
9596

9697
# Store the result of flag availability check in the specified variable
9798
set(${return_var}

cmake/build/CompilerFlags.cmake

Lines changed: 75 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -104,63 +104,79 @@ message(
104104
COMPILER_FLAGS_SKIP_TARGETS_REGEXES: List of regexes to skip targets. Default is empty."
105105
)
106106

107-
if(MSVC)
108-
set(_warnings_cxx_temp ${COMPILER_FLAGS_WARNINGS_MSVC})
109-
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES
110-
".*Clang")
111-
set(_warnings_cxx_temp ${COMPILER_FLAGS_WARNINGS_GNU})
112-
else()
113-
message(
114-
AUTHOR_WARNING
115-
"No compiler warnings set for CXX compiler: '${CMAKE_CXX_COMPILER_ID}'")
116-
endif()
117-
118-
message(VERBOSE "Check Compiler Warnings CXX: ${_warnings_cxx_temp}")
119-
120-
foreach(_warn ${_warnings_cxx_temp})
121-
check_and_append_flag(FLAGS "${_warn}" TARGETS compiler_warnings_cxx)
122-
endforeach()
123-
124-
unset(_warnings_cxx_temp)
107+
string(
108+
SHA256
109+
_compiler_flags_hash
110+
"${COMPILER_FLAGS_WARNINGS_MSVC}#${COMPILER_FLAGS_WARNINGS_GNU}#${COMPILER_FLAGS_WARNINGS_CUDA}#${CMAKE_COMPILE_WARNING_AS_ERROR}"
111+
)
112+
if(NOT DEFINED CACHE{__COMPILER_FLAGS_HASH} OR NOT __COMPILER_FLAGS_HASH
113+
STREQUAL _compiler_flags_hash)
114+
set(__COMPILER_FLAGS_HASH
115+
"${_compiler_flags_hash}"
116+
CACHE INTERNAL "Hash of compiler flags options")
117+
set(__COMPILER_WARNINGS_C "")
118+
set(__COMPILER_WARNINGS_CXX "")
119+
set(__COMPILER_WARNINGS_CUDA "")
125120

126-
if(CMAKE_COMPILE_WARNING_AS_ERROR)
127121
if(MSVC)
128-
check_and_append_flag(FLAGS "/WX" TARGETS compiler_warnings_cxx)
122+
set(_warnings_cxx_temp ${COMPILER_FLAGS_WARNINGS_MSVC})
129123
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES
130124
".*Clang")
131-
check_and_append_flag(FLAGS "-Werror" TARGETS compiler_warnings_cxx)
125+
set(_warnings_cxx_temp ${COMPILER_FLAGS_WARNINGS_GNU})
132126
else()
133127
message(
134128
AUTHOR_WARNING
135-
"No compiler warnings as errors set for CXX compiler: '${CMAKE_CXX_COMPILER_ID}'"
136-
)
129+
"No compiler warnings set for CXX compiler: '${CMAKE_CXX_COMPILER_ID}'")
137130
endif()
131+
132+
message(VERBOSE "Check Compiler Warnings CXX: ${_warnings_cxx_temp}")
133+
134+
foreach(_warn ${_warnings_cxx_temp})
135+
check_and_append_flag(FLAGS "${_warn}" TARGETS __COMPILER_WARNINGS_CXX)
136+
endforeach()
137+
138+
unset(_warnings_cxx_temp)
139+
140+
if(CMAKE_COMPILE_WARNING_AS_ERROR)
141+
if(MSVC)
142+
check_and_append_flag(FLAGS "/WX" TARGETS __COMPILER_WARNINGS_CXX)
143+
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID
144+
MATCHES ".*Clang")
145+
check_and_append_flag(FLAGS "-Werror" TARGETS __COMPILER_WARNINGS_CXX)
146+
else()
147+
message(
148+
AUTHOR_WARNING
149+
"No compiler warnings as errors set for CXX compiler: '${CMAKE_CXX_COMPILER_ID}'"
150+
)
151+
endif()
152+
endif()
153+
154+
# use the same warning flags for C
155+
set(__COMPILER_WARNINGS_C "${__COMPILER_WARNINGS_CXX}")
156+
157+
foreach(_warn ${COMPILER_FLAGS_WARNINGS_CUDA})
158+
check_and_append_flag(FLAGS "${_warn}" TARGETS __COMPILER_WARNINGS_CUDA)
159+
endforeach()
160+
161+
flags_to_list(__COMPILER_WARNINGS_C "${__COMPILER_WARNINGS_C}")
162+
flags_to_list(__COMPILER_WARNINGS_CXX "${__COMPILER_WARNINGS_CXX}")
163+
flags_to_list(__COMPILER_WARNINGS_CUDA "${__COMPILER_WARNINGS_CUDA}")
164+
set(__COMPILER_WARNINGS_C
165+
"${__COMPILER_WARNINGS_C}"
166+
CACHE INTERNAL "compiler warnings flags for C")
167+
set(__COMPILER_WARNINGS_CXX
168+
"${__COMPILER_WARNINGS_CXX}"
169+
CACHE INTERNAL "compiler warnings flags for CXX")
170+
set(__COMPILER_WARNINGS_CUDA
171+
"${__COMPILER_WARNINGS_CUDA}"
172+
CACHE INTERNAL "compiler warnings flags for CUDA")
138173
endif()
139174

140-
# use the same warning flags for C
141-
set(compiler_warnings_c "${compiler_warnings_cxx}")
142-
143-
foreach(_warn ${COMPILER_FLAGS_WARNINGS_CUDA})
144-
check_and_append_flag(FLAGS "${_warn}" TARGETS compiler_warnings_cuda)
145-
endforeach()
146-
147-
flags_to_list(compiler_warnings_c "${compiler_warnings_c}")
148-
flags_to_list(compiler_warnings_cxx "${compiler_warnings_cxx}")
149-
flags_to_list(compiler_warnings_cuda "${compiler_warnings_cuda}")
150-
message(STATUS "Compiler final warnings for C: ${compiler_warnings_c}")
151-
message(STATUS "Compiler final warnings for CXX: ${compiler_warnings_cxx}")
152-
message(STATUS "Compiler final warnings for CUDA: ${compiler_warnings_cuda}")
153-
154-
add_custom_target(compiler_flags_warnings)
155-
set_target_properties(compiler_flags_warnings
156-
PROPERTIES _c "${compiler_warnings_c}")
157-
set_target_properties(compiler_flags_warnings
158-
PROPERTIES _cxx "${compiler_warnings_cxx}")
159-
set_target_properties(compiler_flags_warnings
160-
PROPERTIES _cuda "${compiler_warnings_cuda}")
161-
unset(compiler_warnings_c)
162-
unset(compiler_warnings_cxx)
163-
unset(compiler_warnings_cuda)
175+
message(STATUS "Compiler final warnings for C: $CACHE{__COMPILER_WARNINGS_C}")
176+
message(
177+
STATUS "Compiler final warnings for CXX: $CACHE{__COMPILER_WARNINGS_CXX}")
178+
message(
179+
STATUS "Compiler final warnings for CUDA: $CACHE{__COMPILER_WARNINGS_CUDA}")
164180

165181
#[[
166182
Function to apply compiler warnings to a target.
@@ -184,9 +200,18 @@ function(warn_target target)
184200
endforeach()
185201
endif()
186202

187-
get_target_property(_c compiler_flags_warnings _c)
188-
get_target_property(_cxx compiler_flags_warnings _cxx)
189-
get_target_property(_cuda compiler_flags_warnings _cuda)
203+
if(NOT DEFINED CACHE{__COMPILER_WARNINGS_C}
204+
OR NOT DEFINED CACHE{__COMPILER_WARNINGS_CXX}
205+
OR NOT DEFINED CACHE{__COMPILER_WARNINGS_CUDA})
206+
message(
207+
FATAL_ERROR
208+
"Compiler warnings not set. Please call 'include(${CMAKE_CURRENT_LIST_DIR}/CompilerFlags.cmake)'"
209+
)
210+
endif()
211+
212+
set(_c $CACHE{__COMPILER_WARNINGS_C})
213+
set(_cxx $CACHE{__COMPILER_WARNINGS_CXX})
214+
set(_cuda $CACHE{__COMPILER_WARNINGS_CUDA})
190215

191216
if(arg_INCLUDE_FLAGS)
192217
message(VERBOSE

cmake/build/Hardening.cmake

Lines changed: 65 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -96,65 +96,76 @@ if(NOT USE_HARDENING)
9696
message(STATUS "Hardening disabled by USE_HARDENING evaluates to false")
9797
endif()
9898

99-
# Create a custom target to hold the hardening flags
99+
string(SHA256 _hardening_flags_hash
100+
"${USE_HARDENING_FLAGS}#${USE_HARDENING_LINKS}")
101+
if(NOT DEFINED CACHE{__HARDENING_FLAGS_HASH} OR NOT __HARDENING_FLAGS_HASH
102+
STREQUAL _hardening_flags_hash)
103+
set(__HARDENING_FLAGS_HASH
104+
"${_hardening_flags_hash}"
105+
CACHE INTERNAL "Hash of hardening flags options")
106+
set(__HARDENING_FLAGS "")
107+
set(__HARDENING_LINKS "")
100108

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

103-
foreach(_harden ${USE_HARDENING_FLAGS})
104-
check_and_append_flag(FLAGS ${_harden} TARGETS hardening_flags)
105-
endforeach()
111+
message(VERBOSE "Check Hardening flags: ${USE_HARDENING_FLAGS}")
106112

107-
flags_to_list(hardening_flags "${hardening_flags}")
113+
foreach(_harden ${USE_HARDENING_FLAGS})
114+
check_and_append_flag(FLAGS ${_harden} TARGETS __HARDENING_FLAGS)
115+
endforeach()
108116

109-
message(VERBOSE "Check Hardening links: ${USE_HARDENING_LINKS}")
117+
flags_to_list(__HARDENING_FLAGS "${__HARDENING_FLAGS}")
110118

111-
foreach(_harden ${USE_HARDENING_LINKS})
112-
flags_to_list(_harden_list "${_harden}")
119+
message(VERBOSE "Check Hardening links: ${USE_HARDENING_LINKS}")
113120

114-
if(hardening_flags MATCHES "${_harden_list}")
115-
list(APPEND hardening_links ${_harden})
116-
endif()
117-
endforeach()
118-
119-
# Enable minimal runtime undefined but not not propagete globally, see
120-
# https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html#minimal-runtime
121-
if(hardening_flags MATCHES "-fsanitize=undefined;-fsanitize-minimal-runtime")
122-
message(VERBOSE
123-
"Try to enabling minimal runtime undefined behavior sanitizer")
124-
check_and_append_flag(FLAGS "-fno-sanitize-recover=undefined" TARGETS
125-
no_sanitize_recover_ub)
126-
flags_to_list(no_sanitize_recover_ub "${no_sanitize_recover_ub}")
127-
list(APPEND hardening_flags ${no_sanitize_recover_ub})
128-
list(APPEND hardening_links ${no_sanitize_recover_ub})
129-
endif()
121+
foreach(_harden ${USE_HARDENING_LINKS})
122+
flags_to_list(_harden_list "${_harden}")
130123

131-
flags_to_list(hardening_links "${hardening_links}")
124+
if(__HARDENING_FLAGS MATCHES "${_harden_list}")
125+
list(APPEND __HARDENING_LINKS ${_harden})
126+
endif()
127+
endforeach()
132128

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

137-
if(_san
138-
AND _san MATCHES "-fsanitize=address"
139-
AND hardening_flags MATCHES "-fsanitize-minimal-runtime")
140-
message(
141-
WARNING "Try to disable usan minimal runtime due to conflict with asan")
142-
list(REMOVE_ITEM hardening_flags "-fsanitize=undefined"
143-
"-fsanitize-minimal-runtime" "-fno-sanitize-recover=undefined")
144-
list(REMOVE_ITEM hardening_links "-fsanitize=undefined"
145-
"-fsanitize-minimal-runtime" "-fno-sanitize-recover=undefined")
142+
flags_to_list(__HARDENING_LINKS "${__HARDENING_LINKS}")
143+
144+
# Handle the conflics between hardening ubsan and asan
145+
if(TARGET sanitizer_flags)
146+
get_target_property(_san sanitizer_flags _san)
147+
148+
if(_san
149+
AND _san MATCHES "-fsanitize=address"
150+
AND __HARDENING_FLAGS MATCHES "-fsanitize-minimal-runtime")
151+
message(
152+
WARNING "Try to disable usan minimal runtime due to conflict with asan")
153+
list(REMOVE_ITEM __HARDENING_FLAGS "-fsanitize=undefined"
154+
"-fsanitize-minimal-runtime" "-fno-sanitize-recover=undefined")
155+
list(REMOVE_ITEM __HARDENING_LINKS "-fsanitize=undefined"
156+
"-fsanitize-minimal-runtime" "-fno-sanitize-recover=undefined")
157+
endif()
146158
endif()
159+
set(__HARDENING_FLAGS
160+
"${__HARDENING_FLAGS}"
161+
CACHE INTERNAL "Hardening flags")
162+
set(__HARDENING_LINKS
163+
"${__HARDENING_LINKS}"
164+
CACHE INTERNAL "Hardening links")
147165
endif()
148166

149-
message(STATUS "Hardening final flags: ${hardening_flags}")
150-
message(STATUS "Hardening final links: ${hardening_links}")
151-
152-
add_custom_target(hardening_flags)
153-
set_target_properties(hardening_flags PROPERTIES _flags "${hardening_flags}")
154-
set_target_properties(hardening_flags PROPERTIES _links "${hardening_links}")
155-
156-
unset(hardening_flags)
157-
unset(hardening_links)
167+
message(STATUS "Hardening final flags: $CACHE{__HARDENING_FLAGS}")
168+
message(STATUS "Hardening final links: $CACHE{__HARDENING_LINKS}")
158169

159170
function(harden_target target)
160171
set(_opts)
@@ -196,8 +207,13 @@ function(harden_target target)
196207
endif()
197208
endif()
198209

199-
get_target_property(_flags hardening_flags _flags)
200-
get_target_property(_links hardening_flags _links)
210+
if(NOT DEFINED CACHE{__HARDENING_FLAGS} OR NOT DEFINED
211+
CACHE{__HARDENING_LINKS})
212+
message(FATAL_ERROR "Hardening flags not defined")
213+
endif()
214+
215+
set(_flags $CACHE{__HARDENING_FLAGS})
216+
set(_links $CACHE{__HARDENING_LINKS})
201217

202218
set(FLAGS ${_flags} ${target_flags})
203219
set(LINKS ${_links} ${target_flags})

0 commit comments

Comments
 (0)