Start using C++17
[WebKit-https.git] / Source / cmake / WebKitCompilerFlags.cmake
1 # Prepends flags to CMAKE_C_FLAGS if supported by the C compiler. Almost all
2 # flags should be prepended to allow the user to override them.
3 macro(WEBKIT_PREPEND_GLOBAL_C_FLAGS)
4     foreach (_flag ${ARGN})
5         check_c_compiler_flag("${_flag}" C_COMPILER_SUPPORTS_${_flag})
6         if (C_COMPILER_SUPPORTS_${_flag})
7             set(CMAKE_C_FLAGS "${_flag} ${CMAKE_C_FLAGS}")
8         endif ()
9     endforeach ()
10 endmacro()
11
12 # Appends flags to CMAKE_C_FLAGS if supported by the C compiler. This macro
13 # should be used sparingly. Only append flags if the user must not be allowed to
14 # override them.
15 macro(WEBKIT_APPEND_GLOBAL_C_FLAGS)
16     foreach (_flag ${ARGN})
17         check_c_compiler_flag("${_flag}" C_COMPILER_SUPPORTS_${_flag})
18         if (C_COMPILER_SUPPORTS_${_flag})
19             set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_flag}")
20         endif ()
21     endforeach ()
22 endmacro()
23
24 # Prepends flags to CMAKE_CXX_FLAGS if supported by the C++ compiler. Almost all
25 # flags should be prepended to allow the user to override them.
26 macro(WEBKIT_PREPEND_GLOBAL_CXX_FLAGS)
27     foreach (_flag ${ARGN})
28         check_cxx_compiler_flag("${_flag}" CXX_COMPILER_SUPPORTS_${_flag})
29         if (CXX_COMPILER_SUPPORTS_${_flag})
30             set(CMAKE_CXX_FLAGS "${_flag} ${CMAKE_CXX_FLAGS}")
31         endif ()
32     endforeach ()
33 endmacro()
34
35 # Appends flags to CMAKE_CXX_FLAGS if supported by the C++ compiler. This macro
36 # should be used sparingly. Only append flags if the user must not be allowed to
37 # override them.
38 macro(WEBKIT_APPEND_GLOBAL_CXX_FLAGS)
39     foreach (_flag ${ARGN})
40         check_cxx_compiler_flag("${_flag}" CXX_COMPILER_SUPPORTS_${_flag})
41         if (CXX_COMPILER_SUPPORTS_${_flag})
42             set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${_flag}")
43         endif ()
44     endforeach ()
45 endmacro()
46
47 # Prepends flags to CMAKE_C_FLAGS and CMAKE_CXX_FLAGS if supported by the C
48 # or C++ compiler, respectively. Almost all flags should be prepended to allow
49 # the user to override them.
50 macro(WEBKIT_PREPEND_GLOBAL_COMPILER_FLAGS)
51     WEBKIT_PREPEND_GLOBAL_C_FLAGS(${ARGN})
52     WEBKIT_PREPEND_GLOBAL_CXX_FLAGS(${ARGN})
53 endmacro()
54
55 # Appends flags to CMAKE_C_FLAGS and CMAKE_CXX_FLAGS if supported by the C or
56 # C++ compiler, respectively. This macro should be used sparingly. Only append
57 # flags if the user must not be allowed to override them.
58 macro(WEBKIT_APPEND_GLOBAL_COMPILER_FLAGS)
59     WEBKIT_APPEND_GLOBAL_C_FLAGS(${ARGN})
60     WEBKIT_APPEND_GLOBAL_CXX_FLAGS(${ARGN})
61 endmacro()
62
63 # Appends flags to COMPILE_FLAGS of _target if supported by the C compiler.
64 # Note that it is simply not possible to pass different C and C++ flags, unless
65 # we drop support for the Visual Studio backend and use the COMPILE_LANGUAGE
66 # generator expression. This is a very serious limitation.
67 macro(WEBKIT_ADD_TARGET_C_FLAGS _target)
68     foreach (_flag ${ARGN})
69         check_c_compiler_flag("${_flag}" C_COMPILER_SUPPORTS_${_flag})
70         if (C_COMPILER_SUPPORTS_${_flag})
71             target_compile_options(${_target} PRIVATE ${_flag})
72         endif ()
73     endforeach ()
74 endmacro()
75
76 # Appends flags to COMPILE_FLAGS of _target if supported by the C++ compiler.
77 # Note that it is simply not possible to pass different C and C++ flags, unless
78 # we drop support for the Visual Studio backend and use the COMPILE_LANGUAGE
79 # generator expression. This is a very serious limitation.
80 macro(WEBKIT_ADD_TARGET_CXX_FLAGS _target)
81     foreach (_flag ${ARGN})
82         check_cxx_compiler_flag("${_flag}" CXX_COMPILER_SUPPORTS_${_flag})
83         if (CXX_COMPILER_SUPPORTS_${_flag})
84             target_compile_options(${_target} PRIVATE ${_flag})
85         endif ()
86     endforeach ()
87 endmacro()
88
89
90 if (COMPILER_IS_GCC_OR_CLANG)
91     WEBKIT_APPEND_GLOBAL_COMPILER_FLAGS(-fno-strict-aliasing)
92
93     # clang-cl.exe impersonates cl.exe so some clang arguments like -fno-rtti are
94     # represented using cl.exe's options and should not be passed as flags, so
95     # we do not add -fno-rtti or -fno-exceptions for clang-cl
96     if (COMPILER_IS_CLANG_CL)
97         # FIXME: These warnings should be addressed
98         WEBKIT_PREPEND_GLOBAL_COMPILER_FLAGS(-Wno-undef
99                                              -Wno-macro-redefined
100                                              -Wno-unknown-pragmas
101                                              -Wno-nonportable-include-path
102                                              -Wno-unknown-argument)
103     else ()
104         WEBKIT_APPEND_GLOBAL_COMPILER_FLAGS(-fno-exceptions)
105         WEBKIT_APPEND_GLOBAL_CXX_FLAGS(-fno-rtti)
106
107         check_cxx_compiler_flag("-std=c++17" CXX_COMPILER_SUPPORTS_CXX17)
108         if (CXX_COMPILER_SUPPORTS_CXX17)
109             WEBKIT_APPEND_GLOBAL_CXX_FLAGS(-std=c++17)
110         else ()
111             message(FATAL_ERROR "Compiler with C++17 support is required")
112         endif ()
113
114         if (WIN32)
115             WEBKIT_APPEND_GLOBAL_COMPILER_FLAGS(-mno-ms-bitfields)
116             WEBKIT_PREPEND_GLOBAL_COMPILER_FLAGS(-Wno-unknown-pragmas)
117             add_definitions(-D__USE_MINGW_ANSI_STDIO=1)
118         endif ()
119     endif ()
120
121     # Warnings to be enabled
122     WEBKIT_PREPEND_GLOBAL_COMPILER_FLAGS(-Wcast-align
123                                          -Wformat-security
124                                          -Wmissing-format-attribute
125                                          -Wpointer-arith
126                                          -Wundef
127                                          -Wwrite-strings)
128
129     # Warnings to be disabled
130     # FIXME: We should probably not be disabling -Wno-maybe-uninitialized?
131     WEBKIT_PREPEND_GLOBAL_COMPILER_FLAGS(-Qunused-arguments
132                                          -Wno-maybe-uninitialized
133                                          -Wno-noexcept-type
134                                          -Wno-parentheses-equality
135                                          -Wno-psabi)
136
137     # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80947
138     if (${CMAKE_CXX_COMPILER_VERSION} VERSION_LESS "8.0" AND NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang")
139         WEBKIT_PREPEND_GLOBAL_CXX_FLAGS(-Wno-attributes)
140     endif ()
141
142     # -Wexpansion-to-defined produces false positives with GCC but not Clang
143     # https://bugs.webkit.org/show_bug.cgi?id=167643#c13
144     if (CMAKE_COMPILER_IS_GNUCXX)
145         WEBKIT_PREPEND_GLOBAL_COMPILER_FLAGS(-Wno-expansion-to-defined)
146     endif ()
147 endif ()
148
149 if (COMPILER_IS_GCC_OR_CLANG AND NOT MSVC)
150     # Don't give -Wall to clang-cl because clang-cl treats /Wall and -Wall as -Weverything.
151     # -Wall and -Wextra should be specified before -Wno-* for Clang.
152     WEBKIT_PREPEND_GLOBAL_COMPILER_FLAGS(-Wall -Wextra)
153 endif ()
154
155 # Ninja tricks compilers into turning off color support.
156 if (CMAKE_GENERATOR STREQUAL "Ninja")
157     WEBKIT_PREPEND_GLOBAL_COMPILER_FLAGS(-fcolor-diagnostics
158                                          -fdiagnostics-color=always)
159 endif ()
160
161
162 string(TOLOWER ${CMAKE_HOST_SYSTEM_PROCESSOR} LOWERCASE_CMAKE_HOST_SYSTEM_PROCESSOR)
163 if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND NOT "${LOWERCASE_CMAKE_HOST_SYSTEM_PROCESSOR}" MATCHES "x86_64")
164     # To avoid out of memory when building with debug option in 32bit system.
165     # See https://bugs.webkit.org/show_bug.cgi?id=77327
166     set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "-Wl,--no-keep-memory ${CMAKE_SHARED_LINKER_FLAGS_DEBUG}")
167 endif ()
168
169 if (COMPILER_IS_GCC_OR_CLANG)
170     # Careful: this needs to be above where ENABLED_COMPILER_SANITIZERS is set.
171     # Also, it's not possible to use the normal prepend/append macros for
172     # -fsanitize=* flags, because check_cxx_compiler_flag will report it's
173     # unsupported, because it causes the build to fail if not used when linking.
174     if (ENABLE_SANITIZERS)
175         if (MSVC AND WTF_CPU_X86_64)
176             find_library(CLANG_ASAN_LIBRARY clang_rt.asan_dynamic_runtime_thunk-x86_64 ${CLANG_LIB_PATH})
177             find_library(CLANG_ASAN_RT_LIBRARY clang_rt.asan_dynamic-x86_64 PATHS ${CLANG_LIB_PATH})
178             set(SANITIZER_LINK_FLAGS "\"${CLANG_ASAN_LIBRARY}\" \"${CLANG_ASAN_RT_LIBRARY}\"")
179         else ()
180             set(SANITIZER_LINK_FLAGS "-lpthread")
181         endif ()
182
183         foreach (SANITIZER ${ENABLE_SANITIZERS})
184             if (${SANITIZER} MATCHES "address")
185                 WEBKIT_PREPEND_GLOBAL_COMPILER_FLAGS("-fno-omit-frame-pointer -fno-optimize-sibling-calls")
186                 set(SANITIZER_COMPILER_FLAGS "-fsanitize=address ${SANITIZER_COMPILER_FLAGS}")
187                 set(SANITIZER_LINK_FLAGS "-fsanitize=address ${SANITIZER_LINK_FLAGS}")
188
189             elseif (${SANITIZER} MATCHES "undefined")
190                 WEBKIT_PREPEND_GLOBAL_COMPILER_FLAGS("-fno-omit-frame-pointer -fno-optimize-sibling-calls")
191                 # -fsanitize=vptr is incompatible with -fno-rtti
192                 set(SANITIZER_COMPILER_FLAGS "-fsanitize=undefined -frtti ${SANITIZER_COMPILER_FLAGS}")
193                 set(SANITIZER_LINK_FLAGS "-fsanitize=undefined ${SANITIZER_LINK_FLAGS}")
194
195             elseif (${SANITIZER} MATCHES "thread" AND NOT MSVC)
196                 set(SANITIZER_COMPILER_FLAGS "-fsanitize=thread ${SANITIZER_COMPILER_FLAGS}")
197                 set(SANITIZER_LINK_FLAGS "-fsanitize=thread ${SANITIZER_LINK_FLAGS}")
198
199             elseif (${SANITIZER} MATCHES "memory" AND COMPILER_IS_CLANG AND NOT MSVC)
200                 set(SANITIZER_COMPILER_FLAGS "-fsanitize=memory ${SANITIZER_COMPILER_FLAGS}")
201                 set(SANITIZER_LINK_FLAGS "-fsanitize=memory ${SANITIZER_LINK_FLAGS}")
202
203             elseif (${SANITIZER} MATCHES "leak" AND NOT MSVC)
204                 set(SANITIZER_COMPILER_FLAGS "-fsanitize=leak ${SANITIZER_COMPILER_FLAGS}")
205                 set(SANITIZER_LINK_FLAGS "-fsanitize=leak ${SANITIZER_LINK_FLAGS}")
206
207             else ()
208                 message(FATAL_ERROR "Unsupported sanitizer: ${SANITIZER}")
209             endif ()
210         endforeach ()
211
212         set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SANITIZER_COMPILER_FLAGS}")
213         set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SANITIZER_COMPILER_FLAGS}")
214         set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${SANITIZER_LINK_FLAGS}")
215         set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${SANITIZER_LINK_FLAGS}")
216         set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${SANITIZER_LINK_FLAGS}")
217     endif ()
218 endif ()
219
220 if (NOT MSVC)
221     string(REGEX MATCHALL "-fsanitize=[^ ]*" ENABLED_COMPILER_SANITIZERS ${CMAKE_CXX_FLAGS})
222 endif ()
223
224 if (UNIX AND NOT APPLE AND NOT ENABLED_COMPILER_SANITIZERS)
225     set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--no-undefined ${CMAKE_SHARED_LINKER_FLAGS}")
226 endif ()
227
228
229 # CODE_GENERATOR_PREPROCESSOR_WITH_LINEMARKERS only matters with GCC >= 4.7.0.  Since this
230 # version, -P does not output empty lines, which currently breaks make_names.pl in
231 # WebCore. Investigating whether make_names.pl should be changed instead is left as an exercise to
232 # the reader.
233 if (MSVC)
234     set(CODE_GENERATOR_PREPROCESSOR_ARGUMENTS "/nologo /EP /TP")
235     set(CODE_GENERATOR_PREPROCESSOR_WITH_LINEMARKERS_ARGUMENTS ${CODE_GENERATOR_PREPROCESSOR_ARGUMENTS})
236 else ()
237     set(CODE_GENERATOR_PREPROCESSOR_ARGUMENTS "-E -P -x c++")
238     set(CODE_GENERATOR_PREPROCESSOR_WITH_LINEMARKERS_ARGUMENTS "-E -x c++")
239 endif ()
240
241 set(CODE_GENERATOR_PREPROCESSOR "\"${CMAKE_CXX_COMPILER}\" ${CODE_GENERATOR_PREPROCESSOR_ARGUMENTS}")
242 set(CODE_GENERATOR_PREPROCESSOR_WITH_LINEMARKERS "\"${CMAKE_CXX_COMPILER}\" ${CODE_GENERATOR_PREPROCESSOR_WITH_LINEMARKERS_ARGUMENTS}")
243
244
245 # Ensure that the default include system directories are added to the list of CMake implicit includes.
246 # This workarounds an issue that happens when using GCC 6 and using system includes (-isystem).
247 # For more details check: https://bugs.webkit.org/show_bug.cgi?id=161697
248 macro(DETERMINE_GCC_SYSTEM_INCLUDE_DIRS _lang _compiler _flags _result)
249     file(WRITE "${CMAKE_BINARY_DIR}/CMakeFiles/dummy" "\n")
250     separate_arguments(_buildFlags UNIX_COMMAND "${_flags}")
251     execute_process(COMMAND ${_compiler} ${_buildFlags} -v -E -x ${_lang} -dD dummy
252                     WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/CMakeFiles OUTPUT_QUIET
253                     ERROR_VARIABLE _gccOutput)
254     file(REMOVE "${CMAKE_BINARY_DIR}/CMakeFiles/dummy")
255     if ("${_gccOutput}" MATCHES "> search starts here[^\n]+\n *(.+) *\n *End of (search) list")
256         set(${_result} ${CMAKE_MATCH_1})
257         string(REPLACE "\n" " " ${_result} "${${_result}}")
258         separate_arguments(${_result})
259     endif ()
260 endmacro()
261
262 if (COMPILER_IS_GCC_OR_CLANG)
263    DETERMINE_GCC_SYSTEM_INCLUDE_DIRS("c" "${CMAKE_C_COMPILER}" "${CMAKE_C_FLAGS}" SYSTEM_INCLUDE_DIRS)
264    set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES ${CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES} ${SYSTEM_INCLUDE_DIRS})
265    DETERMINE_GCC_SYSTEM_INCLUDE_DIRS("c++" "${CMAKE_CXX_COMPILER}" "${CMAKE_CXX_FLAGS}" SYSTEM_INCLUDE_DIRS)
266    set(CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES} ${SYSTEM_INCLUDE_DIRS})
267 endif ()
268
269 if (COMPILER_IS_GCC_OR_CLANG)
270     set(ATOMIC_TEST_SOURCE "
271         #include <atomic>
272         int main() { std::atomic<int64_t> i(0); i++; return 0; }
273     ")
274     check_cxx_source_compiles("${ATOMIC_TEST_SOURCE}" ATOMIC_INT64_IS_BUILTIN)
275     if (NOT ATOMIC_INT64_IS_BUILTIN)
276         set(CMAKE_REQUIRED_LIBRARIES atomic)
277         check_cxx_source_compiles("${ATOMIC_TEST_SOURCE}" ATOMIC_INT64_REQUIRES_LIBATOMIC)
278         unset(CMAKE_REQUIRED_LIBRARIES)
279     endif ()
280 endif ()