master
cmake 155 lines 5.7 KB
Raw
1 # SPDX-License-Identifier: GPL-3.0-or-later
2 # Functions to simplify handling of extra compiler flags.
3
4 include(CheckCCompilerFlag)
5 include(CheckCXXCompilerFlag)
6 include(CMakePushCheckState)
7
8 # Conditionally add an extra compiler flag to C and C++ flags.
9 #
10 # If the language flags already match the `match` argument, skip this flag.
11 # Otherwise, check for support for `flag` and if support is found, add it to
12 # the compiler flags for the run. Also sets `result` to MATCHED/ADDED/UNSUPPORTED
13 # depending on whether the flag was added or not.
14 function(add_extra_compiler_flag match flag result)
15 cmake_push_check_state()
16 set(CMAKE_REQUIRED_FLAGS "-Werror")
17
18 string(MAKE_C_IDENTIFIER "${flag}" flag_name)
19
20 if(NOT ${CMAKE_C_FLAGS} MATCHES ${match})
21 check_c_compiler_flag("${flag}" HAVE_C_${flag_name})
22 else()
23 set(matched_c TRUE)
24 endif()
25
26 if(NOT ${CMAKE_CXX_FLAGS} MATCHES ${match})
27 check_cxx_compiler_flag("${flag}" HAVE_CXX_${flag_name})
28 else()
29 set(matched_cxx TRUE)
30 endif()
31 cmake_pop_check_state()
32
33 if(HAVE_C_${flag_name} AND HAVE_CXX_${flag_name})
34 add_compile_options("${flag}")
35 add_link_options("${flag}")
36 set(${result} ADDED PARENT_SCOPE)
37 elseif(matched_c OR matched_cxx)
38 set(${result} MATCHED PARENT_SCOPE)
39 else()
40 set(${result} UNSUPPORTED PARENT_SCOPE)
41 endif()
42 endfunction()
43
44 # Same as add_simple_extra_compiler_flag, but check for a second flag if the
45 # first one is unsupported.
46 function(add_double_extra_compiler_flag match flag1 flag2 result)
47 add_extra_compiler_flag("${match}" "${flag1}" flag1_success)
48
49 if(${flag1_success} STREQUAL UNSUPPORTED)
50 add_extra_compiler_flag("${match}" "${flag2}" flag2_success)
51 set(${result} "${flag2_success}" PARENT_SCOPE)
52 else()
53 set(${result} "${flag1_success}" PARENT_SCOPE)
54 endif()
55 endfunction()
56
57 # Add a required extra compiler flag to C and C++ flags.
58 #
59 # Similar logic to add_extra_compiler_flag, but ignores existing
60 # instances and throws an error if the flag is not supported.
61 function(add_required_compiler_flag flag)
62 cmake_push_check_state()
63 set(CMAKE_REQUIRED_FLAGS "-Werror")
64
65 string(MAKE_C_IDENTIFIER "${flag}" flag_name)
66
67 check_c_compiler_flag("${flag}" HAVE_C_${flag_name})
68 check_cxx_compiler_flag("${flag}" HAVE_CXX_${flag_name})
69 cmake_pop_check_state()
70
71 if(HAVE_C_${flag_name} AND HAVE_CXX_${flag_name})
72 add_compile_options("${flag}")
73 add_link_options("${flag}")
74 else()
75 message(FATAL_ERROR "${flag} support is required to build Netdata")
76 endif()
77 endfunction()
78
79 message(CHECK_START "Checking for known bad compiler flags")
80 string(REGEX MATCH "(-Ofast|-ffast-math)" BAD_FLAGS "${CMAKE_C_FLAGS}" "${CMAKE_CXX_FLAGS}")
81 if(BAD_FLAGS)
82 message(CHECK_FAIL "${BAD_FLAGS}")
83 message(FATAL_ERROR "Found known bad compiler flag '${BAD_FLAGS}'. This flag allows the compiler to violate the guarantees of the C/C++ standards in ways that are known to break Netdata (and many other things as well). Refusing to build with this compiler flag. Any issues opened about builds that circumvent this check and build with this flag anyway will be closed as invalid.")
84 else()
85 message(CHECK_PASS "none found")
86 endif()
87
88 if(CMAKE_BUILD_TYPE STREQUAL "Debug")
89 option(DISABLE_HARDENING "Disable adding extra compiler flags for hardening" TRUE)
90 option(USE_LTO "Attempt to use of LTO when building. Defaults to being enabled if supported for release builds." FALSE)
91 else()
92 option(DISABLE_HARDENING "Disable adding extra compiler flags for hardening" FALSE)
93 option(USE_LTO "Attempt to use of LTO when building. Defaults to being enabled if supported for release builds." TRUE)
94 endif()
95
96 option(ENABLE_ADDRESS_SANITIZER "Build with address sanitizer enabled" False)
97 mark_as_advanced(ENABLE_ADDRESS_SANITIZER)
98
99 if(ENABLE_ADDRESS_SANITIZER)
100 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address")
101 endif()
102
103 if(STATIC_BUILD)
104 add_required_compiler_flag("-static")
105
106 set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
107 endif()
108
109 if(USE_LTO)
110 if(OS_WINDOWS)
111 message(WARNING "LTO not supported on Windows, not checking for it")
112 else()
113 include(CheckIPOSupported)
114
115 message(CHECK_START "Checking for LTO support")
116 check_ipo_supported(RESULT HAVE_LTO)
117
118 if(HAVE_LTO)
119 message(CHECK_PASS "supported")
120 set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
121
122 if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
123 if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 10.0)
124 list(APPEND CMAKE_C_COMPILE_OPTIONS_IPO "-flto=auto")
125 list(APPEND CMAKE_CXX_COMPILE_OPTIONS_IPO "-flto=auto")
126 endif()
127 #elseif(CMAKE_C_COMPILER_ID STREQUAL "Clang")
128 #list(APPEND CMAKE_C_COMPILE_OPTIONS_IPO "-flto=thin")
129 #list(APPEND CMAKE_CXX_COMPILE_OPTIONS_IPO "-flto=thin")
130 endif()
131 else()
132 message(CHECK_FAIL "not supported")
133 endif()
134 endif()
135 else()
136 message(STATUS "Not checking for LTO support as it has been explicitly disabled")
137 endif()
138
139 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_C_FLAGS}")
140
141 add_required_compiler_flag("-fexceptions")
142
143 if(NOT ${DISABLE_HARDENING})
144 add_double_extra_compiler_flag("stack-protector" "-fstack-protector-strong" "-fstack-protector" HAVE_STACK_PROTECTOR)
145 add_double_extra_compiler_flag("_FORTIFY_SOURCE" "-D_FORTIFY_SOURCE=3" "-D_FORTIFY_SOURCE=2" HAVE_FORTIFY_SOURCE)
146 add_extra_compiler_flag("stack-clash-protection" "-fstack-clash-protection" HAVE_STACK_CLASH_PROTECTION)
147 add_extra_compiler_flag("-fcf-protection" "-fcf-protection=full" HAVE_CFI)
148 add_extra_compiler_flag("branch-protection" "-mbranch-protection=standard" HAVE_BRANCH_PROTECTION)
149 endif()
150
151 foreach(FLAG function-sections data-sections)
152 add_extra_compiler_flag("${FLAG}" "-f${FLAG}" HAVE_${FLAG})
153 endforeach()
154
155 add_extra_compiler_flag("-Wbuiltin-macro-redefined" "-Wno-builtin-macro-redefined" HAVE_MACRO)