Fix a couple of issues with the CMake script
[folly.git] / CMake / FollyCompiler.cmake
1 # Some additional configuration options.\r
2 option(MSVC_ENABLE_ALL_WARNINGS "If enabled, pass /Wall to the compiler." ON)\r
3 option(MSVC_ENABLE_DEBUG_INLINING "If enabled, enable inlining in the debug configuration. This allows /Zc:inline to be far more effective." OFF)\r
4 option(MSVC_ENABLE_FAST_LINK "If enabled, pass /DEBUG:FASTLINK to the linker. This makes linking faster, but the gtest integration for Visual Studio can't currently handle the .pdbs generated." OFF)\r
5 option(MSVC_ENABLE_LTCG "If enabled, use Link Time Code Generation for Release builds." OFF)\r
6 option(MSVC_ENABLE_PARALLEL_BUILD "If enabled, build multiple source files in parallel." ON)\r
7 option(MSVC_ENABLE_STATIC_ANALYSIS "If enabled, do more complex static analysis and generate warnings appropriately." OFF)\r
8 option(MSVC_USE_STATIC_RUNTIME "If enabled, build against the static, rather than the dynamic, runtime." OFF)\r
9 \r
10 # Alas, option() doesn't support string values.\r
11 set(MSVC_FAVORED_ARCHITECTURE "blend" CACHE STRING "One of 'blend', 'AMD64', 'INTEL64', or 'ATOM'. This tells the compiler to generate code optimized to run best on the specified architecture.")\r
12 # Validate, and then add the favored architecture.\r
13 if (NOT MSVC_FAVORED_ARCHITECTURE STREQUAL "blend" AND NOT MSVC_FAVORED_ARCHITECTURE STREQUAL "AMD64" AND NOT MSVC_FAVORED_ARCHITECTURE STREQUAL "INTEL64" AND NOT MSVC_FAVORED_ARCHITECTURE STREQUAL "ATOM")\r
14   message(FATAL_ERROR "MSVC_FAVORED_ARCHITECTURE must be set to one of exactly, 'blend', 'AMD64', 'INTEL64', or 'ATOM'! Got '${MSVC_FAVORED_ARCHITECTURE}' instead!")\r
15 endif()\r
16 \r
17 ############################################################\r
18 # We need to adjust a couple of the default option sets.\r
19 ############################################################\r
20 \r
21 # If the static runtime is requested, we have to\r
22 # overwrite some of CMake's defaults.\r
23 if (MSVC_USE_STATIC_RUNTIME)\r
24   foreach(flag_var\r
25       CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE\r
26       CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO\r
27       CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE\r
28       CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)\r
29     if (${flag_var} MATCHES "/MD")\r
30       string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")\r
31     endif()\r
32   endforeach()\r
33 endif()\r
34 \r
35 # In order for /Zc:inline, which speeds up the build significantly, to work\r
36 # we need to remove the /Ob0 parameter that CMake adds by default, because that\r
37 # would normally disable all inlining.\r
38 foreach(flag_var CMAKE_C_FLAGS_DEBUG CMAKE_CXX_FLAGS_DEBUG)\r
39   if (${flag_var} MATCHES "/Ob0")\r
40     string(REGEX REPLACE "/Ob0" "" ${flag_var} "${${flag_var}}")\r
41   endif()\r
42 endforeach()\r
43 \r
44 # Apply the option set for Folly to the specified target.\r
45 function(apply_folly_compile_options_to_target THETARGET)\r
46   # The general options passed:\r
47   target_compile_options(${THETARGET}\r
48     PUBLIC\r
49       #/std:c++latest # Build in C++17 mode\r
50       /EHa # Enable both SEH and C++ Exceptions.\r
51       /Zc:referenceBinding # Disallow temporaries from binding to non-const lvalue references.\r
52       /Zc:rvalueCast # Enforce the standard rules for explicit type conversion.\r
53       /Zc:implicitNoexcept # Enable implicit noexcept specifications where required, such as destructors.\r
54       /Zc:strictStrings # Don't allow conversion from a string literal to mutable characters.\r
55       /Zc:threadSafeInit # Enable thread-safe function-local statics initialization.\r
56       /Zc:throwingNew # Assume operator new throws on failure.\r
57 \r
58       # This is only supported by MSVC 2017\r
59       $<$<BOOL:${MSVC_IS_2017}>:/permissive-> # Be mean, don't allow bad non-standard stuff (C++/CLI, __declspec, etc. are all left intact).\r
60     PRIVATE\r
61       /bigobj # Support objects with > 65k sections. Needed due to templates.\r
62       /favor:${MSVC_FAVORED_ARCHITECTURE} # Architecture to prefer when generating code.\r
63       /Zc:inline # Have the compiler eliminate unreferenced COMDAT functions and data before emitting the object file.\r
64 \r
65       $<$<BOOL:${MSVC_ENABLE_ALL_WARNINGS}>:/Wall> # Enable all warnings if requested.\r
66       $<$<BOOL:${MSVC_ENABLE_PARALLEL_BUILD}>:/MP> # Enable multi-processor compilation if requested.\r
67       $<$<BOOL:${MSVC_ENABLE_STATIC_ANALYSIS}>:/analyze> # Enable static analysis if requested.\r
68 \r
69       # Debug builds\r
70       $<$<CONFIG:DEBUG>:\r
71         /Gy- # Disable function level linking.\r
72         /GF- # Disable string pooling.\r
73 \r
74         $<$<BOOL:${MSVC_ENABLE_DEBUG_INLINING}>:/Ob2> # Add /Ob2 if allowing inlining in debug mode.\r
75       >\r
76 \r
77       # Non-debug builds\r
78       $<$<NOT:$<CONFIG:DEBUG>>:\r
79         /GF # Enable string pooling. (this is enabled by default by the optimization level, but we enable it here for clarity)\r
80         /Gw # Optimize global data. (-fdata-sections)\r
81         /Gy # Enable function level linking. (-ffunction-sections)\r
82         /Qpar # Enable parallel code generation.\r
83         /Oi # Enable intrinsic functions.\r
84         /Ot # Favor fast code.\r
85 \r
86         $<$<BOOL:${MSVC_ENABLE_LTCG}>:/GL> # Enable link time code generation.\r
87       >\r
88   )\r
89 \r
90   target_compile_options(${THETARGET}\r
91     PUBLIC\r
92       /wd4191 # 'type cast' unsafe conversion of function pointers\r
93       /wd4291 # no matching operator delete found\r
94       /wd4309 # '=' truncation of constant value\r
95       /wd4310 # cast truncates constant value\r
96       /wd4366 # result of unary '&' operator may be unaligned\r
97       /wd4587 # behavior change; constructor no longer implicitly called\r
98       /wd4592 # symbol will be dynamically initialized (implementation limitation)\r
99       /wd4723 # potential divide by 0\r
100       /wd4724 # potential mod by 0\r
101       /wd4868 # compiler may not enforce left-to-right evaluation order\r
102       /wd4996 # user deprecated\r
103 \r
104       # The warnings that are disabled:\r
105       /wd4068 # Unknown pragma.\r
106       /wd4091 # 'typedef' ignored on left of '' when no variable is declared.\r
107       /wd4146 # Unary minus applied to unsigned type, result still unsigned.\r
108       /wd4800 # Values being forced to bool, this happens many places, and is a "performance warning".\r
109 \r
110       # NOTE: glog/logging.h:1116 change to `size_t pcount() const { return size_t(pptr() - pbase()); }`\r
111       # NOTE: gmock/gmock-spec-builders.h:1177 change to `*static_cast<const Action<F>*>(untyped_actions_[size_t(count - 1)]) :`\r
112       # NOTE: gmock/gmock-spec-builders.h:1749 change to `const size_t count = untyped_expectations_.size();`\r
113       # NOTE: gmock/gmock-spec-builders.h:1754 change to `for (size_t i = 0; i < count; i++) {`\r
114       # NOTE: gtest/gtest-printers.h:173 change to `const internal::BiggestInt kBigInt = internal::BiggestInt(value);`\r
115       # NOTE: gtest/internal/gtest-internal.h:890 add `GTEST_DISABLE_MSC_WARNINGS_PUSH_(4365)`\r
116       # NOTE: gtest/internal/gtest-internal.h:894 ass `GTEST_DISABLE_MSC_WARNINGS_POP_()`\r
117       # NOTE: boost/crc.hpp:578 change to `{ return static_cast<unsigned char>(x ^ rem); }`\r
118       # NOTE: boost/regex/v4/match_results.hpp:126 change to `return m_subs[size_type(sub)].length();`\r
119       # NOTE: boost/regex/v4/match_results.hpp:226 change to `return m_subs[size_type(sub)];`\r
120       # NOTE: boost/date_time/adjust_functors.hpp:67 change to `origDayOfMonth_ = short(ymd.day);`\r
121       # NOTE: boost/date_time/adjust_functors.hpp:75 change to `wrap_int2 wi(short(ymd.month));`\r
122       # NOTE: boost/date_time/adjust_functors.hpp:82 change to `day_type resultingEndOfMonthDay(cal_type::end_of_month_day(static_cast<unsigned short>(year), static_cast<unsigned short>(wi.as_int())));`\r
123       # NOTE: boost/date_time/adjust_functors.hpp:85 change to `return date_type(static_cast<unsigned short>(year), static_cast<unsigned short>(wi.as_int()), resultingEndOfMonthDay) - d;`\r
124       # NOTE: boost/date_time/adjust_functors.hpp:87 change to `day_type dayOfMonth = static_cast<unsigned short>(origDayOfMonth_);`\r
125       # NOTE: boost/date_time/adjust_functors.hpp:91 change to `return date_type(static_cast<unsigned short>(year), static_cast<unsigned short>(wi.as_int()), dayOfMonth) - d;`\r
126       # NOTE: boost/date_time/adjust_functors.hpp:98 change to `origDayOfMonth_ = short(ymd.day);`\r
127       # NOTE: boost/date_time/adjust_functors.hpp:106 change to `wrap_int2 wi(short(ymd.month));`\r
128       # NOTE: boost/date_time/adjust_functors.hpp:111 change to `day_type resultingEndOfMonthDay(cal_type::end_of_month_day(static_cast<unsigned short>(year), static_cast<unsigned short>(wi.as_int())));`\r
129       # NOTE: boost/date_time/adjust_functors.hpp:114 change to `return date_type(static_cast<unsigned short>(year), static_cast<unsigned short>(wi.as_int()), resultingEndOfMonthDay) - d;`\r
130       # NOTE: boost/date_time/adjust_functors.hpp:116 change to `day_type dayOfMonth = static_cast<unsigned short>(origDayOfMonth_);`\r
131       # NOTE: boost/date_time/adjust_functors.hpp:120 change to `return date_type(static_cast<unsigned short>(year), static_cast<unsigned short>(wi.as_int()), dayOfMonth) - d;`\r
132       # NOTE: boost/date_time/gregorian_calendar.ipp:81 change to `unsigned long  d = static_cast<unsigned long>(ymd.day + ((153*m + 2)/5) + 365*y + (y/4) - (y/100) + (y/400) - 32045);`\r
133       # NOTE: boost/date_time/gregorian/greg_date.hpp:122 change to `unsigned short eom_day =  gregorian_calendar::end_of_month_day(ymd.year, ymd.month);`\r
134       # NOTE: boost/thread/future.hpp:1050 change to `locks[std::ptrdiff_t(i)]=BOOST_THREAD_MAKE_RV_REF(boost::unique_lock<boost::mutex>(futures[i].future_->mutex));`\r
135       # NOTE: boost/thread/future.hpp:1063 change to `locks[std::ptrdiff_t(i)].unlock();`\r
136       # NOTE: boost/thread/win32/basic_recursive_mutex.hpp:47 change to `long const current_thread_id=long(win32::GetCurrentThreadId());`\r
137       # NOTE: boost/thread/win32/basic_recursive_mutex.hpp:53 change to `long const current_thread_id=long(win32::GetCurrentThreadId());`\r
138       # NOTE: boost/thread/win32/basic_recursive_mutex.hpp:64 change to `long const current_thread_id=long(win32::GetCurrentThreadId());`\r
139       # NOTE: boost/thread/win32/basic_recursive_mutex.hpp:78 change to `long const current_thread_id=long(win32::GetCurrentThreadId());`\r
140       # NOTE: boost/thread/win32/basic_recursive_mutex.hpp:84 change to `long const current_thread_id=long(win32::GetCurrentThreadId());`\r
141       # NOTE: boost/thread/win32/condition_variable.hpp:79 change to `detail::win32::ReleaseSemaphore(semaphore,long(count_to_release),0);`\r
142       # NOTE: boost/thread/win32/condition_variable.hpp:84 change to `release(unsigned(detail::interlocked_read_acquire(&waiters)));`\r
143       # NOTE: boost/algorithm/string/detail/classification.hpp:85 change to `std::size_t Size=std::size_t(::boost::distance(Range));`\r
144       /wd4018 # Signed/unsigned mismatch.\r
145       /wd4365 # Signed/unsigned mismatch.\r
146       /wd4388 # Signed/unsigned mismatch on relative comparison operator.\r
147       /wd4389 # Signed/unsigned mismatch on equality comparison operator.\r
148 \r
149       # TODO:\r
150       /wd4100 # Unreferenced formal parameter.\r
151       /wd4459 # Declaration of parameter hides global declaration.\r
152       /wd4505 # Unreferenced local function has been removed.\r
153       /wd4701 # Potentially uninitialized local variable used.\r
154       /wd4702 # Unreachable code.\r
155 \r
156       # These warnings are disabled because we've\r
157       # enabled all warnings. If all warnings are\r
158       # not enabled, we still need to disable them\r
159       # for consuming libs.\r
160       /wd4061 # Enum value not handled by a case in a switch on an enum. This isn't very helpful because it is produced even if a default statement is present.\r
161       /wd4127 # Conditional expression is constant.\r
162       /wd4200 # Non-standard extension, zero sized array.\r
163       /wd4201 # Non-standard extension used: nameless struct/union.\r
164       /wd4296 # '<' Expression is always false.\r
165       /wd4316 # Object allocated on the heap may not be aligned to 128.\r
166       /wd4324 # Structure was padded due to alignment specifier.\r
167       /wd4355 # 'this' used in base member initializer list.\r
168       /wd4371 # Layout of class may have changed due to fixes in packing.\r
169       /wd4435 # Object layout under /vd2 will change due to virtual base.\r
170       /wd4514 # Unreferenced inline function has been removed. (caused by /Zc:inline)\r
171       /wd4548 # Expression before comma has no effect. I wouldn't disable this normally, but malloc.h triggers this warning.\r
172       /wd4574 # ifdef'd macro was defined to 0.\r
173       /wd4582 # Constructor is not implicitly called.\r
174       /wd4583 # Destructor is not implicitly called.\r
175       /wd4619 # Invalid warning number used in #pragma warning.\r
176       /wd4623 # Default constructor was implicitly defined as deleted.\r
177       /wd4625 # Copy constructor was implicitly defined as deleted.\r
178       /wd4626 # Assignment operator was implicitly defined as deleted.\r
179       /wd4647 # Behavior change in __is_pod.\r
180       /wd4668 # Macro was not defined, replacing with 0.\r
181       /wd4706 # Assignment within conditional expression.\r
182       /wd4710 # Function was not inlined.\r
183       /wd4711 # Function was selected for automated inlining.\r
184       /wd4714 # Function marked as __forceinline not inlined.\r
185       /wd4820 # Padding added after data member.\r
186       /wd5026 # Move constructor was implicitly defined as deleted.\r
187       /wd5027 # Move assignment operator was implicitly defined as deleted.\r
188       /wd5031 # #pragma warning(pop): likely mismatch, popping warning state pushed in different file. This is needed because of how boost does things.\r
189 \r
190       # Warnings to treat as errors:\r
191       /we4099 # Mixed use of struct and class on same type names.\r
192       /we4129 # Unknown escape sequence. This is usually caused by incorrect escaping.\r
193       /we4566 # Character cannot be represented in current charset. This is remidied by prefixing string with "u8".\r
194 \r
195     PRIVATE\r
196       # Warnings disabled for /analyze\r
197       $<$<BOOL:${MSVC_ENABLE_STATIC_ANALYSIS}>:\r
198         /wd6001 # Using uninitialized memory. This is disabled because it is wrong 99% of the time.\r
199         /wd6011 # Dereferencing potentially NULL pointer.\r
200         /wd6031 # Return value ignored.\r
201         /wd6235 # (<non-zero constant> || <expression>) is always a non-zero constant.\r
202         /wd6237 # (<zero> && <expression>) is always zero. <expression> is never evaluated and may have side effects.\r
203         /wd6239 # (<non-zero constant> && <expression>) always evaluates to the result of <expression>.\r
204         /wd6240 # (<expression> && <non-zero constant>) always evaluates to the result of <expression>.\r
205         /wd6246 # Local declaration hides declaration of same name in outer scope.\r
206         /wd6248 # Setting a SECURITY_DESCRIPTOR's DACL to NULL will result in an unprotected object. This is done by one of the boost headers.\r
207         /wd6255 # _alloca indicates failure by raising a stack overflow exception.\r
208         /wd6262 # Function uses more than x bytes of stack space.\r
209         /wd6271 # Extra parameter passed to format function. The analysis pass doesn't recognize %j or %z, even though the runtime does.\r
210         /wd6285 # (<non-zero constant> || <non-zero constant>) is always true.\r
211         /wd6297 # 32-bit value is shifted then cast to 64-bits. The places this occurs never use more than 32 bits.\r
212         /wd6308 # Realloc might return null pointer: assigning null pointer to '<name>', which is passed as an argument to 'realloc', will cause the original memory to leak.\r
213         /wd6326 # Potential comparison of a constant with another constant.\r
214         /wd6330 # Unsigned/signed mismatch when passed as a parameter.\r
215         /wd6340 # Mismatch on sign when passed as format string value.\r
216         /wd6387 # '<value>' could be '0': This does not adhere to the specification for a function.\r
217         /wd28182 # Dereferencing NULL pointer. '<value>' contains the same NULL value as '<expression>'.\r
218         /wd28251 # Inconsistent annotation for function. This is because we only annotate the declaration and not the definition.\r
219         /wd28278 # Function appears with no prototype in scope.\r
220       >\r
221   )\r
222 \r
223   # And the extra defines:\r
224   target_compile_definitions(${THETARGET}\r
225     PUBLIC\r
226       _HAS_AUTO_PTR_ETC=1 # We're building in C++ 17 mode, but certain dependencies (Boost) still have dependencies on unary_function and binary_function, so we have to make sure not to remove them.\r
227       NOMINMAX # This is needed because, for some absurd reason, one of the windows headers tries to define "min" and "max" as macros, which messes up most uses of std::numeric_limits.\r
228       _CRT_NONSTDC_NO_WARNINGS # Don't deprecate posix names of functions.\r
229       _CRT_SECURE_NO_WARNINGS # Don't deprecate the non _s versions of various standard library functions, because safety is for chumps.\r
230       _SCL_SECURE_NO_WARNINGS # Don't deprecate the non _s versions of various standard library functions, because safety is for chumps.\r
231       _WINSOCK_DEPRECATED_NO_WARNINGS # Don't deprecate pieces of winsock\r
232       WIN32_LEAN_AND_MEAN # Don't include most of Windows.h\r
233       \r
234       _STL_EXTRA_DISABLED_WARNINGS=4365\ 4774\ 4775\ 4987\r
235   )\r
236 \r
237   # Ignore a warning about an object file not defining any symbols,\r
238   # these are known, and we don't care.\r
239   set_property(TARGET ${THETARGET} APPEND_STRING PROPERTY STATIC_LIBRARY_FLAGS " /ignore:4221")\r
240 \r
241   # The options to pass to the linker:\r
242   set_property(TARGET ${THETARGET} APPEND_STRING PROPERTY LINK_FLAGS_DEBUG " /INCREMENTAL") # Do incremental linking.\r
243   if (NOT $<TARGET_PROPERTY:${THETARGET},TYPE> STREQUAL "STATIC_LIBRARY")\r
244     set_property(TARGET ${THETARGET} APPEND_STRING PROPERTY LINK_FLAGS_DEBUG " /OPT:NOREF") # No unreferenced data elimination.\r
245     set_property(TARGET ${THETARGET} APPEND_STRING PROPERTY LINK_FLAGS_DEBUG " /OPT:NOICF") # No Identical COMDAT folding.\r
246 \r
247     set_property(TARGET ${THETARGET} APPEND_STRING PROPERTY LINK_FLAGS_RELEASE " /OPT:REF") # Remove unreferenced functions and data.\r
248     set_property(TARGET ${THETARGET} APPEND_STRING PROPERTY LINK_FLAGS_RELEASE " /OPT:ICF") # Identical COMDAT folding.\r
249   endif()\r
250 \r
251   if (MSVC_ENABLE_FAST_LINK)\r
252     set_property(TARGET ${THETARGET} APPEND_STRING PROPERTY LINK_FLAGS_DEBUG " /DEBUG:FASTLINK") # Generate a partial PDB file that simply references the original object and library files.\r
253   endif()\r
254 \r
255   # Add /GL to the compiler, and /LTCG to the linker\r
256   # if link time code generation is enabled.\r
257   if (MSVC_ENABLE_LTCG)\r
258     set_property(TARGET ${THETARGET} APPEND_STRING PROPERTY LINK_FLAGS_RELEASE " /LTCG")\r
259   endif()\r
260 endfunction()\r