1# Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
2#
3# This program is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation; version 2 of the License.
6#
7# This program is distributed in the hope that it will be useful,
8# but WITHOUT ANY WARRANTY; without even the implied warranty of
9# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10# GNU General Public License for more details.
11#
12# You should have received a copy of the GNU General Public License
13# along with this program; if not, write to the Free Software
14# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1335  USA
15
16# This file includes Windows specific hacks, mostly around compiler flags
17
18INCLUDE (CheckCSourceCompiles)
19INCLUDE (CheckCXXSourceCompiles)
20INCLUDE (CheckStructHasMember)
21INCLUDE (CheckLibraryExists)
22INCLUDE (CheckFunctionExists)
23INCLUDE (CheckCSourceRuns)
24INCLUDE (CheckSymbolExists)
25INCLUDE (CheckTypeSize)
26
27
28# avoid running system checks by using pre-cached check results
29# system checks are expensive on VS since every tiny program is to be compiled in
30# a VC solution.
31GET_FILENAME_COMPONENT(_SCRIPT_DIR ${CMAKE_CURRENT_LIST_FILE} PATH)
32INCLUDE(${_SCRIPT_DIR}/WindowsCache.cmake)
33
34
35# OS display name (version_compile_os etc).
36# Used by the test suite to ignore bugs on some platforms,
37IF(CMAKE_SIZEOF_VOID_P MATCHES 8)
38  SET(SYSTEM_TYPE "Win64")
39ELSE()
40  SET(SYSTEM_TYPE "Win32")
41ENDIF()
42
43# Intel compiler is almost Visual C++
44# (same compile flags etc). Set MSVC flag
45IF(CMAKE_C_COMPILER MATCHES "icl")
46 SET(MSVC TRUE)
47ENDIF()
48
49IF(MSVC  AND CMAKE_CXX_COMPILER_ID MATCHES Clang)
50 SET(CLANG_CL TRUE)
51ENDIF()
52
53ADD_DEFINITIONS(-D_WINDOWS -D__WIN__ -D_CRT_SECURE_NO_DEPRECATE)
54ADD_DEFINITIONS(-D_WIN32_WINNT=0x0A00)
55# We do not want the windows.h macros min/max
56ADD_DEFINITIONS(-DNOMINMAX)
57# Speed up build process excluding unused header files
58ADD_DEFINITIONS(-DWIN32_LEAN_AND_MEAN)
59
60# Adjust compiler and linker flags
61IF(MINGW AND CMAKE_SIZEOF_VOID_P EQUAL 4)
62   # mininal architecture flags, i486 enables GCC atomics
63  ADD_DEFINITIONS(-march=i486)
64ENDIF()
65
66MACRO(ENABLE_SANITIZERS)
67  IF(NOT  MSVC)
68    MESSAGE(FATAL_ERROR "clang-cl or MSVC necessary to enable asan/ubsan")
69  ENDIF()
70  # currently, asan is broken with static CRT.
71  IF(CLANG_CL AND NOT(MSVC_CRT_TYPE STREQUAL "/MD"))
72    SET(MSVC_CRT_TYPE "/MD" CACHE  INTERNAL "" FORCE)
73  ENDIF()
74  IF(CMAKE_SIZEOF_VOID_P EQUAL 4)
75    SET(ASAN_ARCH i386)
76  ELSE()
77    SET(ASAN_ARCH x86_64)
78  ENDIF()
79
80   # After installation, clang lib directory should be added to PATH
81  # (e.g C:/Program Files/LLVM/lib/clang/5.0.1/lib/windows)
82  SET(SANITIZER_LIBS)
83  SET(SANITIZER_LINK_LIBRARIES)
84  SET(SANITIZER_COMPILE_FLAGS)
85  IF(WITH_ASAN)
86    IF(CLANG_CL)
87      LIST(APPEND SANITIZER_LIBS
88        clang_rt.asan_dynamic-${ASAN_ARCH}.lib clang_rt.asan_dynamic_runtime_thunk-${ASAN_ARCH}.lib)
89    ENDIF()
90    STRING(APPEND SANITIZER_COMPILE_FLAGS " -fsanitize=address")
91  ENDIF()
92  IF(WITH_UBSAN)
93    STRING(APPEND SANITIZER_COMPILE_FLAGS " -fsanitize=undefined -fno-sanitize=alignment")
94  ENDIF()
95  FOREACH(lib ${SANITIZER_LIBS})
96    FIND_LIBRARY(${lib}_fullpath ${lib})
97    IF(NOT ${lib}_fullpath)
98      MESSAGE(FATAL_ERROR "Can't enable sanitizer : missing ${lib}")
99    ENDIF()
100    LIST(APPEND CMAKE_REQUIRED_LIBRARIES ${${lib}_fullpath})
101    STRING(APPEND CMAKE_C_STANDARD_LIBRARIES " \"${${lib}_fullpath}\" ")
102    STRING(APPEND CMAKE_CXX_STANDARD_LIBRARIES " \"${${lib}_fullpath}\" ")
103  ENDFOREACH()
104  STRING(APPEND CMAKE_C_FLAGS ${SANITIZER_COMPILE_FLAGS})
105  STRING(APPEND CMAKE_CXX_FLAGS ${SANITIZER_COMPILE_FLAGS})
106ENDMACRO()
107
108
109IF(MSVC)
110  IF(MSVC_VERSION LESS 1920)
111    MESSAGE(FATAL_ERROR "Visual Studio q2019 or later is required")
112  ENDIF()
113  # Disable mingw based pkg-config found in Strawberry perl
114  SET(PKG_CONFIG_EXECUTABLE 0 CACHE INTERNAL "")
115
116  SET(MSVC_CRT_TYPE /MT CACHE STRING
117    "Runtime library - specify runtime library for linking (/MT,/MTd,/MD,/MDd)"
118  )
119  SET(VALID_CRT_TYPES /MTd /MDd /MD /MT)
120  IF (NOT ";${VALID_CRT_TYPES};" MATCHES ";${MSVC_CRT_TYPE};")
121    MESSAGE(FATAL_ERROR "Invalid value ${MSVC_CRT_TYPE} for MSVC_CRT_TYPE, choose one of /MT,/MTd,/MD,/MDd ")
122  ENDIF()
123
124  IF(MSVC_CRT_TYPE MATCHES "/MD")
125   # Dynamic runtime (DLLs), need to install CRT libraries.
126   SET(CMAKE_INSTALL_SYSTEM_RUNTIME_COMPONENT VCCRT)
127   SET(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS TRUE)
128   IF(MSVC_CRT_TYPE STREQUAL "/MDd")
129     SET (CMAKE_INSTALL_DEBUG_LIBRARIES_ONLY TRUE)
130   ENDIF()
131   INCLUDE(InstallRequiredSystemLibraries)
132  ENDIF()
133
134  IF(WITH_ASAN AND (NOT CLANG_CL))
135    SET(DYNAMIC_UCRT_LINK_DEFAULT OFF)
136  ELSE()
137    SET(DYNAMIC_UCRT_LINK_DEFAULT ON)
138  ENDIF()
139
140  OPTION(DYNAMIC_UCRT_LINK "Link Universal CRT dynamically, if MSVC_CRT_TYPE=/MT" ${DYNAMIC_UCRT_LINK_DEFAULT})
141  SET(DYNAMIC_UCRT_LINKER_OPTION " /NODEFAULTLIB:libucrt.lib /DEFAULTLIB:ucrt.lib")
142
143  # Enable debug info also in Release build,
144  # and create PDB to be able to analyze crashes.
145  FOREACH(type EXE SHARED MODULE)
146   SET(CMAKE_${type}_LINKER_FLAGS_RELEASE
147     "${CMAKE_${type}_LINKER_FLAGS_RELEASE} /debug")
148   SET(CMAKE_${type}_LINKER_FLAGS_MINSIZEREL
149     "${CMAKE_${type}_LINKER_FLAGS_MINSIZEREL} /debug")
150  ENDFOREACH()
151
152  # Force runtime libraries
153  # Compile with /Zi to get debugging information
154
155  FOREACH(lang C CXX)
156    SET(CMAKE_${lang}_FLAGS_RELEASE "${CMAKE_${lang}_FLAGS_RELEASE} /Zi")
157  ENDFOREACH()
158  FOREACH(flag
159   CMAKE_C_FLAGS CMAKE_CXX_FLAGS
160   CMAKE_C_FLAGS_INIT CMAKE_CXX_FLAGS_INIT
161   CMAKE_C_FLAGS_RELEASE    CMAKE_C_FLAGS_RELWITHDEBINFO
162   CMAKE_C_FLAGS_DEBUG      CMAKE_C_FLAGS_DEBUG_INIT
163   CMAKE_CXX_FLAGS_RELEASE  CMAKE_CXX_FLAGS_RELWITHDEBINFO
164   CMAKE_CXX_FLAGS_DEBUG    CMAKE_CXX_FLAGS_DEBUG_INIT
165   CMAKE_C_FLAGS_MINSIZEREL  CMAKE_CXX_FLAGS_MINSIZEREL
166   )
167   STRING(REGEX REPLACE "/M[TD][d]?"  "${MSVC_CRT_TYPE}" "${flag}"  "${${flag}}" )
168   STRING(REPLACE "/ZI " "/Zi "  "${flag}"  "${${flag}}")
169   IF((NOT "${${flag}}" MATCHES "/Zi") AND (NOT "${${flag}}" MATCHES "/Z7"))
170    STRING(APPEND ${flag} " /Zi")
171   ENDIF()
172  ENDFOREACH()
173
174  IF(WITH_ASAN OR WITH_UBSAN)
175    # Workaround something Linux specific
176    SET(SECURITY_HARDENED 0 CACHE INTERNAL "" FORCE)
177    ENABLE_SANITIZERS()
178  ENDIF()
179
180  IF(CLANG_CL)
181     SET(CLANG_CL_FLAGS
182"-Wno-unknown-warning-option -Wno-unused-private-field \
183-Wno-unused-parameter -Wno-inconsistent-missing-override \
184-Wno-unused-command-line-argument -Wno-pointer-sign \
185-Wno-deprecated-register -Wno-missing-braces \
186-Wno-unused-function -Wno-unused-local-typedef -msse4.2 "
187    )
188    IF(CMAKE_SIZEOF_VOID_P MATCHES 8)
189      STRING(APPEND CLANG_CL_FLAGS "-mpclmul ")
190    ENDIF()
191    STRING(APPEND CMAKE_C_FLAGS " ${CLANG_CL_FLAGS} ${MSVC_CRT_TYPE}")
192    STRING(APPEND CMAKE_CXX_FLAGS " ${CLANG_CL_FLAGS}  ${MSVC_CRT_TYPE}")
193  ENDIF()
194
195  FOREACH(type EXE SHARED MODULE)
196   STRING(REGEX REPLACE "/STACK:([^ ]+)" "" CMAKE_${type}_LINKER_FLAGS "${CMAKE_${type}_LINKER_FLAGS}")
197   IF(WITH_ASAN)
198     SET(build_types RELWITHDEBINFO DEBUG)
199   ELSE()
200     SET(build_types RELWITHDEBINFO)
201   ENDIF()
202   FOREACH(btype ${build_types})
203     STRING(REGEX REPLACE "/INCREMENTAL:([^ ]+)" "/INCREMENTAL:NO" CMAKE_${type}_LINKER_FLAGS_${btype} "${CMAKE_${type}_LINKER_FLAGS_${btype}}")
204     STRING(REGEX REPLACE "/INCREMENTAL$" "/INCREMENTAL:NO" CMAKE_${type}_LINKER_FLAGS_${btype} "${CMAKE_${type}_LINKER_FLAGS_${btype}}")
205   ENDFOREACH()
206   IF(NOT CLANG_CL)
207     STRING(APPEND CMAKE_${type}_LINKER_FLAGS_RELWITHDEBINFO " /release /OPT:REF,ICF")
208   ENDIF()
209   IF(DYNAMIC_UCRT_LINK AND (MSVC_CRT_TYPE STREQUAL "/MT"))
210     FOREACH(config RELEASE RELWITHDEBINFO DEBUG MINSIZEREL)
211       STRING(APPEND CMAKE_${type}_LINKER_FLAGS_${config} ${DYNAMIC_UCRT_LINKER_OPTION})
212     ENDFOREACH()
213   ENDIF()
214  ENDFOREACH()
215
216
217  # Mark 32 bit executables large address aware so they can
218  # use > 2GB address space
219  IF(CMAKE_SIZEOF_VOID_P MATCHES 4)
220   STRING(APPEND CMAKE_EXE_LINKER_FLAGS " /LARGEADDRESSAWARE")
221  ENDIF()
222
223  # Speed up multiprocessor build
224  IF (NOT CLANG_CL)
225    STRING(APPEND CMAKE_C_FLAGS " /MP")
226    STRING(APPEND CMAKE_CXX_FLAGS " /MP")
227    STRING(APPEND CMAKE_C_FLAGS_RELWITHDEBINFO " /Gw")
228    STRING(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " /Gw")
229  ENDIF()
230
231  #TODO: update the code and remove the disabled warnings
232  STRING(APPEND CMAKE_C_FLAGS " /we4700 /we4311 /we4477 /we4302 /we4090")
233  STRING(APPEND CMAKE_CXX_FLAGS " /we4099 /we4700 /we4311 /we4477 /we4302 /we4090")
234  IF(MSVC_VERSION GREATER 1910  AND NOT CLANG_CL)
235    STRING(APPEND CMAKE_CXX_FLAGS " /permissive-")
236    STRING(APPEND CMAKE_C_FLAGS " /diagnostics:caret")
237    STRING(APPEND CMAKE_CXX_FLAGS " /diagnostics:caret")
238  ENDIF()
239  ADD_DEFINITIONS(-D_CRT_NONSTDC_NO_WARNINGS)
240  IF(MYSQL_MAINTAINER_MODE MATCHES "ERR")
241    STRING(APPEND CMAKE_C_FLAGS " /WX")
242    STRING(APPEND CMAKE_CXX_FLAGS " /WX")
243    FOREACH(type EXE SHARED MODULE)
244      FOREACH(cfg RELEASE DEBUG RELWITHDEBINFO)
245        SET(CMAKE_${type}_LINKER_FLAGS_${cfg} "${CMAKE_${type}_LINKER_FLAGS_${cfg}} /WX")
246      ENDFOREACH()
247    ENDFOREACH()
248  ENDIF()
249  IF(MSVC_VERSION LESS 1910)
250    # Noisy warning C4800: 'type': forcing value to bool 'true' or 'false' (performance warning),
251    # removed in VS2017
252    STRING(APPEND CMAKE_CXX_FLAGS " /wd4800")
253  ELSEIF (NOT CLANG_CL)
254    STRING(APPEND CMAKE_CXX_FLAGS " /d2OptimizeHugeFunctions")
255  ENDIF()
256ENDIF()
257
258# Always link with socket/synchronization libraries
259STRING(APPEND CMAKE_C_STANDARD_LIBRARIES " ws2_32.lib synchronization.lib")
260STRING(APPEND CMAKE_CXX_STANDARD_LIBRARIES " ws2_32.lib synchronization.lib")
261
262# System checks
263SET(SIGNAL_WITH_VIO_CLOSE 1) # Something that runtime team needs
264
265# IPv6 constants appeared in Vista SDK first. We need to define them in any case if they are
266# not in headers, to handle dual mode sockets correctly.
267CHECK_SYMBOL_EXISTS(IPPROTO_IPV6 "winsock2.h" HAVE_IPPROTO_IPV6)
268IF(NOT HAVE_IPPROTO_IPV6)
269  SET(HAVE_IPPROTO_IPV6 41)
270ENDIF()
271CHECK_SYMBOL_EXISTS(IPV6_V6ONLY  "winsock2.h;ws2ipdef.h" HAVE_IPV6_V6ONLY)
272IF(NOT HAVE_IPV6_V6ONLY)
273  SET(IPV6_V6ONLY 27)
274ENDIF()
275
276# Some standard functions exist there under different
277# names (e.g popen is _popen or strok_r is _strtok_s)
278# If a replacement function exists, HAVE_FUNCTION is
279# defined to 1. CMake variable <function_name> will also
280# be defined to the replacement name.
281# So for example, CHECK_FUNCTION_REPLACEMENT(popen _popen)
282# will define HAVE_POPEN to 1 and set variable named popen
283# to _popen. If the header template, one needs to have
284# cmakedefine popen @popen@ which will expand to
285# define popen _popen after CONFIGURE_FILE
286
287MACRO(CHECK_FUNCTION_REPLACEMENT function replacement)
288  STRING(TOUPPER ${function} function_upper)
289  CHECK_FUNCTION_EXISTS(${function} HAVE_${function_upper})
290  IF(NOT HAVE_${function_upper})
291    CHECK_FUNCTION_EXISTS(${replacement}  HAVE_${replacement})
292    IF(HAVE_${replacement})
293      SET(HAVE_${function_upper} 1 )
294      SET(${function} ${replacement})
295    ENDIF()
296  ENDIF()
297ENDMACRO()
298MACRO(CHECK_SYMBOL_REPLACEMENT symbol replacement header)
299  STRING(TOUPPER ${symbol} symbol_upper)
300  CHECK_SYMBOL_EXISTS(${symbol} ${header} HAVE_${symbol_upper})
301  IF(NOT HAVE_${symbol_upper})
302    CHECK_SYMBOL_EXISTS(${replacement} ${header} HAVE_${replacement})
303    IF(HAVE_${replacement})
304      SET(HAVE_${symbol_upper} 1)
305      SET(${symbol} ${replacement})
306    ENDIF()
307  ENDIF()
308ENDMACRO()
309
310CHECK_SYMBOL_REPLACEMENT(S_IROTH _S_IREAD sys/stat.h)
311CHECK_SYMBOL_REPLACEMENT(S_IFIFO _S_IFIFO sys/stat.h)
312CHECK_SYMBOL_REPLACEMENT(SIGQUIT SIGTERM signal.h)
313CHECK_SYMBOL_REPLACEMENT(SIGPIPE SIGINT signal.h)
314CHECK_FUNCTION_REPLACEMENT(popen _popen)
315CHECK_FUNCTION_REPLACEMENT(pclose _pclose)
316CHECK_FUNCTION_REPLACEMENT(access _access)
317CHECK_FUNCTION_REPLACEMENT(strcasecmp _stricmp)
318CHECK_FUNCTION_REPLACEMENT(strncasecmp _strnicmp)
319CHECK_SYMBOL_REPLACEMENT(snprintf _snprintf stdio.h)
320CHECK_FUNCTION_REPLACEMENT(strtok_r strtok_s)
321CHECK_FUNCTION_REPLACEMENT(strtoll _strtoi64)
322CHECK_FUNCTION_REPLACEMENT(strtoull _strtoui64)
323CHECK_FUNCTION_REPLACEMENT(vsnprintf _vsnprintf)
324CHECK_TYPE_SIZE(ssize_t SIZE_OF_SSIZE_T)
325IF(NOT HAVE_SIZE_OF_SSIZE_T)
326 SET(ssize_t SSIZE_T)
327ENDIF()
328
329SET(FN_NO_CASE_SENSE 1)
330SET(USE_SYMDIR 1)
331
332# Force static C runtime for targets in current directory
333# (useful to get rid of MFC dll's dependency, or in installer)
334MACRO(FORCE_STATIC_CRT)
335  FOREACH(flag
336    CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_RELWITHDEBINFO
337    CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_DEBUG_INIT
338    CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELWITHDEBINFO
339    CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_DEBUG_INIT
340    CMAKE_C_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_MINSIZEREL
341  )
342    STRING(REGEX REPLACE "/MD[d]?"  "/MT" "${flag}"  "${${flag}}" )
343    STRING(REPLACE "${DYNAMIC_UCRT_LINKER_OPTION}" "" "${flag}" "${${flag}}")
344  ENDFOREACH()
345ENDMACRO()
346