forked from bitcoin/bitcoin
-
Notifications
You must be signed in to change notification settings - Fork 5
/
TryAppendCXXFlags.cmake
138 lines (111 loc) · 4.33 KB
/
TryAppendCXXFlags.cmake
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# Copyright (c) 2023-present The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or https://opensource.org/license/mit/.
include_guard(GLOBAL)
include(CheckCXXSourceCompiles)
#[=[
Add language-wide flags, which will be passed to all invocations of the compiler.
This includes invocations that drive compiling and those that drive linking.
Usage examples:
try_append_cxx_flags("-Wformat -Wformat-security" VAR warn_cxx_flags)
try_append_cxx_flags("-Wsuggest-override" VAR warn_cxx_flags
SOURCE "struct A { virtual void f(); }; struct B : A { void f() final; };"
)
try_append_cxx_flags("-fsanitize=${SANITIZERS}" TARGET core_interface
RESULT_VAR cxx_supports_sanitizers
)
if(NOT cxx_supports_sanitizers)
message(FATAL_ERROR "Compiler did not accept requested flags.")
endif()
try_append_cxx_flags("-Wunused-parameter" TARGET core_interface
IF_CHECK_PASSED "-Wno-unused-parameter"
)
try_append_cxx_flags("-Werror=return-type" TARGET core_interface
IF_CHECK_FAILED "-Wno-error=return-type"
SOURCE "#include <cassert>\nint f(){ assert(false); }"
)
In configuration output, this function prints a string by the following pattern:
-- Performing Test CXX_SUPPORTS_[flags]
-- Performing Test CXX_SUPPORTS_[flags] - Success
]=]
function(try_append_cxx_flags flags)
cmake_parse_arguments(PARSE_ARGV 1
TACXXF # prefix
"SKIP_LINK" # options
"TARGET;VAR;SOURCE;RESULT_VAR" # one_value_keywords
"IF_CHECK_PASSED;IF_CHECK_FAILED" # multi_value_keywords
)
set(flags_as_string "${flags}")
separate_arguments(flags)
string(MAKE_C_IDENTIFIER "${flags_as_string}" id_string)
string(TOUPPER "${id_string}" id_string)
set(source "int main() { return 0; }")
if(DEFINED TACXXF_SOURCE AND NOT TACXXF_SOURCE STREQUAL source)
set(source "${TACXXF_SOURCE}")
string(SHA256 source_hash "${source}")
string(SUBSTRING ${source_hash} 0 4 source_hash_head)
string(APPEND id_string _${source_hash_head})
endif()
# This avoids running a linker.
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
set(CMAKE_REQUIRED_FLAGS "${flags_as_string} ${working_compiler_werror_flag}")
set(compiler_result CXX_SUPPORTS_${id_string})
check_cxx_source_compiles("${source}" ${compiler_result})
if(${compiler_result})
if(DEFINED TACXXF_IF_CHECK_PASSED)
if(DEFINED TACXXF_TARGET)
target_compile_options(${TACXXF_TARGET} INTERFACE ${TACXXF_IF_CHECK_PASSED})
endif()
if(DEFINED TACXXF_VAR)
string(STRIP "${${TACXXF_VAR}} ${TACXXF_IF_CHECK_PASSED}" ${TACXXF_VAR})
endif()
else()
if(DEFINED TACXXF_TARGET)
target_compile_options(${TACXXF_TARGET} INTERFACE ${flags})
endif()
if(DEFINED TACXXF_VAR)
string(STRIP "${${TACXXF_VAR}} ${flags_as_string}" ${TACXXF_VAR})
endif()
endif()
elseif(DEFINED TACXXF_IF_CHECK_FAILED)
if(DEFINED TACXXF_TARGET)
target_compile_options(${TACXXF_TARGET} INTERFACE ${TACXXF_IF_CHECK_FAILED})
endif()
if(DEFINED TACXXF_VAR)
string(STRIP "${${TACXXF_VAR}} ${TACXXF_IF_CHECK_FAILED}" ${TACXXF_VAR})
endif()
endif()
if(DEFINED TACXXF_VAR)
set(${TACXXF_VAR} "${${TACXXF_VAR}}" PARENT_SCOPE)
endif()
if(DEFINED TACXXF_RESULT_VAR)
set(${TACXXF_RESULT_VAR} "${${compiler_result}}" PARENT_SCOPE)
endif()
if(NOT ${compiler_result} OR TACXXF_SKIP_LINK)
return()
endif()
# This forces running a linker.
set(CMAKE_TRY_COMPILE_TARGET_TYPE EXECUTABLE)
set(CMAKE_REQUIRED_FLAGS "${flags_as_string}")
set(CMAKE_REQUIRED_LINK_OPTIONS ${working_linker_werror_flag})
set(linker_result LINKER_SUPPORTS_${id_string})
check_cxx_source_compiles("${source}" ${linker_result})
if(${linker_result})
if(DEFINED TACXXF_IF_CHECK_PASSED)
if(DEFINED TACXXF_TARGET)
target_link_options(${TACXXF_TARGET} INTERFACE ${TACXXF_IF_CHECK_PASSED})
endif()
else()
if(DEFINED TACXXF_TARGET)
target_link_options(${TACXXF_TARGET} INTERFACE ${flags})
endif()
endif()
else()
message(WARNING "'${flags_as_string}' fail(s) to link.")
endif()
endfunction()
if(MSVC)
try_append_cxx_flags("/WX /options:strict" VAR working_compiler_werror_flag SKIP_LINK)
else()
try_append_cxx_flags("-Werror" VAR working_compiler_werror_flag SKIP_LINK)
endif()