cmake: set compiler flags for non-Windows platforms
authorAdam Simpkins <simpkins@fb.com>
Sat, 13 Jan 2018 00:02:58 +0000 (16:02 -0800)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Sat, 13 Jan 2018 00:07:43 +0000 (16:07 -0800)
Summary:
Update CMakeLists.txt to check the current platform, and to set compiler flags
correctly.  It now uses flags for Microsoft Visual Studio on Windows, and flags
for gcc or clang on all other platforms.  Previously it unconditionally used
MSVC flags.

Reviewed By: meyering

Differential Revision: D6710435

fbshipit-source-id: dbae3097bcadf1ee4a25879dd7770603387c0e4d

CMake/FollyCompiler.cmake [deleted file]
CMake/FollyCompilerMSVC.cmake [new file with mode: 0755]
CMake/FollyCompilerUnix.cmake [new file with mode: 0644]
CMakeLists.txt

diff --git a/CMake/FollyCompiler.cmake b/CMake/FollyCompiler.cmake
deleted file mode 100755 (executable)
index 3c80937..0000000
+++ /dev/null
@@ -1,285 +0,0 @@
-# Some additional configuration options.\r
-option(MSVC_ENABLE_ALL_WARNINGS "If enabled, pass /Wall to the compiler." ON)\r
-option(MSVC_ENABLE_CPP_LATEST "If enabled, pass /std:c++latest to the compiler" ON)\r
-option(MSVC_ENABLE_DEBUG_INLINING "If enabled, enable inlining in the debug configuration. This allows /Zc:inline to be far more effective." OFF)\r
-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
-option(MSVC_ENABLE_LEAN_AND_MEAN_WINDOWS "If enabled, define WIN32_LEAN_AND_MEAN to include a smaller subset of Windows.h" ON)\r
-option(MSVC_ENABLE_LTCG "If enabled, use Link Time Code Generation for Release builds." OFF)\r
-option(MSVC_ENABLE_PARALLEL_BUILD "If enabled, build multiple source files in parallel." ON)\r
-option(MSVC_ENABLE_STATIC_ANALYSIS "If enabled, do more complex static analysis and generate warnings appropriately." OFF)\r
-option(MSVC_USE_STATIC_RUNTIME "If enabled, build against the static, rather than the dynamic, runtime." OFF)\r
-\r
-# Alas, option() doesn't support string values.\r
-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
-# Add a pretty drop-down selector for these values when using the GUI.\r
-set_property(\r
-  CACHE MSVC_FAVORED_ARCHITECTURE\r
-  PROPERTY STRINGS\r
-    blend\r
-    AMD64\r
-    ATOM\r
-    INTEL64\r
-)\r
-# Validate, and then add the favored architecture.\r
-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
-  message(FATAL_ERROR "MSVC_FAVORED_ARCHITECTURE must be set to one of exactly, 'blend', 'AMD64', 'INTEL64', or 'ATOM'! Got '${MSVC_FAVORED_ARCHITECTURE}' instead!")\r
-endif()\r
-\r
-############################################################\r
-# We need to adjust a couple of the default option sets.\r
-############################################################\r
-\r
-# If the static runtime is requested, we have to\r
-# overwrite some of CMake's defaults.\r
-if (MSVC_USE_STATIC_RUNTIME)\r
-  foreach(flag_var\r
-      CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE\r
-      CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO\r
-      CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE\r
-      CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)\r
-    if (${flag_var} MATCHES "/MD")\r
-      string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")\r
-    endif()\r
-  endforeach()\r
-endif()\r
-\r
-# The Ninja generator doesn't de-dup the exception mode flag, so remove the\r
-# default flag so that MSVC doesn't warn about it on every single file.\r
-if ("${CMAKE_GENERATOR}" STREQUAL "Ninja")\r
-  foreach(flag_var\r
-      CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE\r
-      CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO\r
-      CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE\r
-      CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)\r
-    if (${flag_var} MATCHES "/EHsc")\r
-      string(REGEX REPLACE "/EHsc" "" ${flag_var} "${${flag_var}}")\r
-    endif()\r
-  endforeach()\r
-endif()\r
-\r
-# In order for /Zc:inline, which speeds up the build significantly, to work\r
-# we need to remove the /Ob0 parameter that CMake adds by default, because that\r
-# would normally disable all inlining.\r
-foreach(flag_var CMAKE_C_FLAGS_DEBUG CMAKE_CXX_FLAGS_DEBUG)\r
-  if (${flag_var} MATCHES "/Ob0")\r
-    string(REGEX REPLACE "/Ob0" "" ${flag_var} "${${flag_var}}")\r
-  endif()\r
-endforeach()\r
-\r
-# Apply the option set for Folly to the specified target.\r
-function(apply_folly_compile_options_to_target THETARGET)\r
-  # The general options passed:\r
-  target_compile_options(${THETARGET}\r
-    PUBLIC\r
-      /EHa # Enable both SEH and C++ Exceptions.\r
-      /GF # There are bugs with constexpr StringPiece when string pooling is disabled.\r
-      /Zc:referenceBinding # Disallow temporaries from binding to non-const lvalue references.\r
-      /Zc:rvalueCast # Enforce the standard rules for explicit type conversion.\r
-      /Zc:implicitNoexcept # Enable implicit noexcept specifications where required, such as destructors.\r
-      /Zc:strictStrings # Don't allow conversion from a string literal to mutable characters.\r
-      /Zc:threadSafeInit # Enable thread-safe function-local statics initialization.\r
-      /Zc:throwingNew # Assume operator new throws on failure.\r
-\r
-      $<$<BOOL:${MSVC_ENABLE_CPP_LATEST}>:/std:c++latest> # Build in C++ Latest mode if requested.\r
-\r
-      # This is only supported by MSVC 2017\r
-      $<$<BOOL:${MSVC_IS_2017}>:/permissive-> # Be mean, don't allow bad non-standard stuff (C++/CLI, __declspec, etc. are all left intact).\r
-    PRIVATE\r
-      /bigobj # Support objects with > 65k sections. Needed due to templates.\r
-      /favor:${MSVC_FAVORED_ARCHITECTURE} # Architecture to prefer when generating code.\r
-      /Zc:inline # Have the compiler eliminate unreferenced COMDAT functions and data before emitting the object file.\r
-\r
-      $<$<BOOL:${MSVC_ENABLE_ALL_WARNINGS}>:/Wall> # Enable all warnings if requested.\r
-      $<$<BOOL:${MSVC_ENABLE_PARALLEL_BUILD}>:/MP> # Enable multi-processor compilation if requested.\r
-      $<$<BOOL:${MSVC_ENABLE_STATIC_ANALYSIS}>:/analyze> # Enable static analysis if requested.\r
-\r
-      # Debug builds\r
-      $<$<CONFIG:DEBUG>:\r
-        /Gy- # Disable function level linking.\r
-\r
-        $<$<BOOL:${MSVC_ENABLE_DEBUG_INLINING}>:/Ob2> # Add /Ob2 if allowing inlining in debug mode.\r
-      >\r
-\r
-      # Non-debug builds\r
-      $<$<NOT:$<CONFIG:DEBUG>>:\r
-        /Gw # Optimize global data. (-fdata-sections)\r
-        /Gy # Enable function level linking. (-ffunction-sections)\r
-        /Qpar # Enable parallel code generation.\r
-        /Oi # Enable intrinsic functions.\r
-        /Ot # Favor fast code.\r
-\r
-        $<$<BOOL:${MSVC_ENABLE_LTCG}>:/GL> # Enable link time code generation.\r
-      >\r
-  )\r
-\r
-  target_compile_options(${THETARGET}\r
-    PUBLIC\r
-      /wd4191 # 'type cast' unsafe conversion of function pointers\r
-      /wd4291 # no matching operator delete found\r
-      /wd4309 # '=' truncation of constant value\r
-      /wd4310 # cast truncates constant value\r
-      /wd4366 # result of unary '&' operator may be unaligned\r
-      /wd4587 # behavior change; constructor no longer implicitly called\r
-      /wd4592 # symbol will be dynamically initialized (implementation limitation)\r
-      /wd4628 # digraphs not supported with -Ze\r
-      /wd4723 # potential divide by 0\r
-      /wd4724 # potential mod by 0\r
-      /wd4868 # compiler may not enforce left-to-right evaluation order\r
-      /wd4996 # user deprecated\r
-\r
-      # The warnings that are disabled:\r
-      /wd4068 # Unknown pragma.\r
-      /wd4091 # 'typedef' ignored on left of '' when no variable is declared.\r
-      /wd4146 # Unary minus applied to unsigned type, result still unsigned.\r
-      /wd4800 # Values being forced to bool, this happens many places, and is a "performance warning".\r
-\r
-      # NOTE: glog/logging.h:1116 change to `size_t pcount() const { return size_t(pptr() - pbase()); }`\r
-      # NOTE: gmock/gmock-spec-builders.h:1177 change to `*static_cast<const Action<F>*>(untyped_actions_[size_t(count - 1)]) :`\r
-      # NOTE: gmock/gmock-spec-builders.h:1749 change to `const size_t count = untyped_expectations_.size();`\r
-      # NOTE: gmock/gmock-spec-builders.h:1754 change to `for (size_t i = 0; i < count; i++) {`\r
-      # NOTE: gtest/gtest-printers.h:173 change to `const internal::BiggestInt kBigInt = internal::BiggestInt(value);`\r
-      # NOTE: gtest/internal/gtest-internal.h:890 add `GTEST_DISABLE_MSC_WARNINGS_PUSH_(4365)`\r
-      # NOTE: gtest/internal/gtest-internal.h:894 ass `GTEST_DISABLE_MSC_WARNINGS_POP_()`\r
-      # NOTE: boost/crc.hpp:578 change to `{ return static_cast<unsigned char>(x ^ rem); }`\r
-      # NOTE: boost/regex/v4/match_results.hpp:126 change to `return m_subs[size_type(sub)].length();`\r
-      # NOTE: boost/regex/v4/match_results.hpp:226 change to `return m_subs[size_type(sub)];`\r
-      # NOTE: boost/date_time/adjust_functors.hpp:67 change to `origDayOfMonth_ = short(ymd.day);`\r
-      # NOTE: boost/date_time/adjust_functors.hpp:75 change to `wrap_int2 wi(short(ymd.month));`\r
-      # 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
-      # 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
-      # NOTE: boost/date_time/adjust_functors.hpp:87 change to `day_type dayOfMonth = static_cast<unsigned short>(origDayOfMonth_);`\r
-      # 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
-      # NOTE: boost/date_time/adjust_functors.hpp:98 change to `origDayOfMonth_ = short(ymd.day);`\r
-      # NOTE: boost/date_time/adjust_functors.hpp:106 change to `wrap_int2 wi(short(ymd.month));`\r
-      # 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
-      # 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
-      # NOTE: boost/date_time/adjust_functors.hpp:116 change to `day_type dayOfMonth = static_cast<unsigned short>(origDayOfMonth_);`\r
-      # 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
-      # 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
-      # 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
-      # 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
-      # NOTE: boost/thread/future.hpp:1063 change to `locks[std::ptrdiff_t(i)].unlock();`\r
-      # NOTE: boost/thread/win32/basic_recursive_mutex.hpp:47 change to `long const current_thread_id=long(win32::GetCurrentThreadId());`\r
-      # NOTE: boost/thread/win32/basic_recursive_mutex.hpp:53 change to `long const current_thread_id=long(win32::GetCurrentThreadId());`\r
-      # NOTE: boost/thread/win32/basic_recursive_mutex.hpp:64 change to `long const current_thread_id=long(win32::GetCurrentThreadId());`\r
-      # NOTE: boost/thread/win32/basic_recursive_mutex.hpp:78 change to `long const current_thread_id=long(win32::GetCurrentThreadId());`\r
-      # NOTE: boost/thread/win32/basic_recursive_mutex.hpp:84 change to `long const current_thread_id=long(win32::GetCurrentThreadId());`\r
-      # NOTE: boost/thread/win32/condition_variable.hpp:79 change to `detail::win32::ReleaseSemaphore(semaphore,long(count_to_release),0);`\r
-      # NOTE: boost/thread/win32/condition_variable.hpp:84 change to `release(unsigned(detail::interlocked_read_acquire(&waiters)));`\r
-      # NOTE: boost/algorithm/string/detail/classification.hpp:85 change to `std::size_t Size=std::size_t(::boost::distance(Range));`\r
-      /wd4018 # Signed/unsigned mismatch.\r
-      /wd4365 # Signed/unsigned mismatch.\r
-      /wd4388 # Signed/unsigned mismatch on relative comparison operator.\r
-      /wd4389 # Signed/unsigned mismatch on equality comparison operator.\r
-\r
-      # TODO:\r
-      /wd4100 # Unreferenced formal parameter.\r
-      /wd4459 # Declaration of parameter hides global declaration.\r
-      /wd4505 # Unreferenced local function has been removed.\r
-      /wd4701 # Potentially uninitialized local variable used.\r
-      /wd4702 # Unreachable code.\r
-\r
-      # These warnings are disabled because we've\r
-      # enabled all warnings. If all warnings are\r
-      # not enabled, we still need to disable them\r
-      # for consuming libs.\r
-      /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
-      /wd4127 # Conditional expression is constant.\r
-      /wd4200 # Non-standard extension, zero sized array.\r
-      /wd4201 # Non-standard extension used: nameless struct/union.\r
-      /wd4296 # '<' Expression is always false.\r
-      /wd4316 # Object allocated on the heap may not be aligned to 128.\r
-      /wd4324 # Structure was padded due to alignment specifier.\r
-      /wd4355 # 'this' used in base member initializer list.\r
-      /wd4371 # Layout of class may have changed due to fixes in packing.\r
-      /wd4435 # Object layout under /vd2 will change due to virtual base.\r
-      /wd4514 # Unreferenced inline function has been removed. (caused by /Zc:inline)\r
-      /wd4548 # Expression before comma has no effect. I wouldn't disable this normally, but malloc.h triggers this warning.\r
-      /wd4574 # ifdef'd macro was defined to 0.\r
-      /wd4582 # Constructor is not implicitly called.\r
-      /wd4583 # Destructor is not implicitly called.\r
-      /wd4619 # Invalid warning number used in #pragma warning.\r
-      /wd4623 # Default constructor was implicitly defined as deleted.\r
-      /wd4625 # Copy constructor was implicitly defined as deleted.\r
-      /wd4626 # Assignment operator was implicitly defined as deleted.\r
-      /wd4647 # Behavior change in __is_pod.\r
-      /wd4668 # Macro was not defined, replacing with 0.\r
-      /wd4706 # Assignment within conditional expression.\r
-      /wd4710 # Function was not inlined.\r
-      /wd4711 # Function was selected for automated inlining.\r
-      /wd4714 # Function marked as __forceinline not inlined.\r
-      /wd4820 # Padding added after data member.\r
-      /wd5026 # Move constructor was implicitly defined as deleted.\r
-      /wd5027 # Move assignment operator was implicitly defined as deleted.\r
-      /wd5031 # #pragma warning(pop): likely mismatch, popping warning state pushed in different file. This is needed because of how boost does things.\r
-\r
-      # Warnings to treat as errors:\r
-      /we4099 # Mixed use of struct and class on same type names.\r
-      /we4129 # Unknown escape sequence. This is usually caused by incorrect escaping.\r
-      /we4566 # Character cannot be represented in current charset. This is remidied by prefixing string with "u8".\r
-\r
-    PRIVATE\r
-      # Warnings disabled for /analyze\r
-      $<$<BOOL:${MSVC_ENABLE_STATIC_ANALYSIS}>:\r
-        /wd6001 # Using uninitialized memory. This is disabled because it is wrong 99% of the time.\r
-        /wd6011 # Dereferencing potentially NULL pointer.\r
-        /wd6031 # Return value ignored.\r
-        /wd6235 # (<non-zero constant> || <expression>) is always a non-zero constant.\r
-        /wd6237 # (<zero> && <expression>) is always zero. <expression> is never evaluated and may have side effects.\r
-        /wd6239 # (<non-zero constant> && <expression>) always evaluates to the result of <expression>.\r
-        /wd6240 # (<expression> && <non-zero constant>) always evaluates to the result of <expression>.\r
-        /wd6246 # Local declaration hides declaration of same name in outer scope.\r
-        /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
-        /wd6255 # _alloca indicates failure by raising a stack overflow exception.\r
-        /wd6262 # Function uses more than x bytes of stack space.\r
-        /wd6271 # Extra parameter passed to format function. The analysis pass doesn't recognize %j or %z, even though the runtime does.\r
-        /wd6285 # (<non-zero constant> || <non-zero constant>) is always true.\r
-        /wd6297 # 32-bit value is shifted then cast to 64-bits. The places this occurs never use more than 32 bits.\r
-        /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
-        /wd6326 # Potential comparison of a constant with another constant.\r
-        /wd6330 # Unsigned/signed mismatch when passed as a parameter.\r
-        /wd6340 # Mismatch on sign when passed as format string value.\r
-        /wd6387 # '<value>' could be '0': This does not adhere to the specification for a function.\r
-        /wd28182 # Dereferencing NULL pointer. '<value>' contains the same NULL value as '<expression>'.\r
-        /wd28251 # Inconsistent annotation for function. This is because we only annotate the declaration and not the definition.\r
-        /wd28278 # Function appears with no prototype in scope.\r
-      >\r
-  )\r
-\r
-  # And the extra defines:\r
-  target_compile_definitions(${THETARGET}\r
-    PUBLIC\r
-      _CRT_NONSTDC_NO_WARNINGS # Don't deprecate posix names of functions.\r
-      _CRT_SECURE_NO_WARNINGS # Don't deprecate the non _s versions of various standard library functions, because safety is for chumps.\r
-      _SCL_SECURE_NO_WARNINGS # Don't deprecate the non _s versions of various standard library functions, because safety is for chumps.\r
-      \r
-      _STL_EXTRA_DISABLED_WARNINGS=4774\ 4987\r
-\r
-      $<$<BOOL:${MSVC_ENABLE_CPP_LATEST}>:_HAS_AUTO_PTR_ETC=1> # We're building in C++ 17 or greater 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
-      $<$<BOOL:${MSVC_ENABLE_LEAN_AND_MEAN_WINDOWS}>:WIN32_LEAN_AND_MEAN> # Don't include most of Windows.h\r
-  )\r
-\r
-  # Ignore a warning about an object file not defining any symbols,\r
-  # these are known, and we don't care.\r
-  set_property(TARGET ${THETARGET} APPEND_STRING PROPERTY STATIC_LIBRARY_FLAGS " /ignore:4221")\r
-\r
-  # The options to pass to the linker:\r
-  set_property(TARGET ${THETARGET} APPEND_STRING PROPERTY LINK_FLAGS_DEBUG " /INCREMENTAL") # Do incremental linking.\r
-  if (NOT $<TARGET_PROPERTY:${THETARGET},TYPE> STREQUAL "STATIC_LIBRARY")\r
-    set_property(TARGET ${THETARGET} APPEND_STRING PROPERTY LINK_FLAGS_DEBUG " /OPT:NOREF") # No unreferenced data elimination.\r
-    set_property(TARGET ${THETARGET} APPEND_STRING PROPERTY LINK_FLAGS_DEBUG " /OPT:NOICF") # No Identical COMDAT folding.\r
-\r
-    set_property(TARGET ${THETARGET} APPEND_STRING PROPERTY LINK_FLAGS_RELEASE " /OPT:REF") # Remove unreferenced functions and data.\r
-    set_property(TARGET ${THETARGET} APPEND_STRING PROPERTY LINK_FLAGS_RELEASE " /OPT:ICF") # Identical COMDAT folding.\r
-  endif()\r
-\r
-  if (MSVC_ENABLE_FAST_LINK)\r
-    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
-  endif()\r
-\r
-  # Add /GL to the compiler, and /LTCG to the linker\r
-  # if link time code generation is enabled.\r
-  if (MSVC_ENABLE_LTCG)\r
-    set_property(TARGET ${THETARGET} APPEND_STRING PROPERTY LINK_FLAGS_RELEASE " /LTCG")\r
-  endif()\r
-endfunction()\r
diff --git a/CMake/FollyCompilerMSVC.cmake b/CMake/FollyCompilerMSVC.cmake
new file mode 100755 (executable)
index 0000000..3c80937
--- /dev/null
@@ -0,0 +1,285 @@
+# Some additional configuration options.\r
+option(MSVC_ENABLE_ALL_WARNINGS "If enabled, pass /Wall to the compiler." ON)\r
+option(MSVC_ENABLE_CPP_LATEST "If enabled, pass /std:c++latest to the compiler" ON)\r
+option(MSVC_ENABLE_DEBUG_INLINING "If enabled, enable inlining in the debug configuration. This allows /Zc:inline to be far more effective." OFF)\r
+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
+option(MSVC_ENABLE_LEAN_AND_MEAN_WINDOWS "If enabled, define WIN32_LEAN_AND_MEAN to include a smaller subset of Windows.h" ON)\r
+option(MSVC_ENABLE_LTCG "If enabled, use Link Time Code Generation for Release builds." OFF)\r
+option(MSVC_ENABLE_PARALLEL_BUILD "If enabled, build multiple source files in parallel." ON)\r
+option(MSVC_ENABLE_STATIC_ANALYSIS "If enabled, do more complex static analysis and generate warnings appropriately." OFF)\r
+option(MSVC_USE_STATIC_RUNTIME "If enabled, build against the static, rather than the dynamic, runtime." OFF)\r
+\r
+# Alas, option() doesn't support string values.\r
+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
+# Add a pretty drop-down selector for these values when using the GUI.\r
+set_property(\r
+  CACHE MSVC_FAVORED_ARCHITECTURE\r
+  PROPERTY STRINGS\r
+    blend\r
+    AMD64\r
+    ATOM\r
+    INTEL64\r
+)\r
+# Validate, and then add the favored architecture.\r
+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
+  message(FATAL_ERROR "MSVC_FAVORED_ARCHITECTURE must be set to one of exactly, 'blend', 'AMD64', 'INTEL64', or 'ATOM'! Got '${MSVC_FAVORED_ARCHITECTURE}' instead!")\r
+endif()\r
+\r
+############################################################\r
+# We need to adjust a couple of the default option sets.\r
+############################################################\r
+\r
+# If the static runtime is requested, we have to\r
+# overwrite some of CMake's defaults.\r
+if (MSVC_USE_STATIC_RUNTIME)\r
+  foreach(flag_var\r
+      CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE\r
+      CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO\r
+      CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE\r
+      CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)\r
+    if (${flag_var} MATCHES "/MD")\r
+      string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")\r
+    endif()\r
+  endforeach()\r
+endif()\r
+\r
+# The Ninja generator doesn't de-dup the exception mode flag, so remove the\r
+# default flag so that MSVC doesn't warn about it on every single file.\r
+if ("${CMAKE_GENERATOR}" STREQUAL "Ninja")\r
+  foreach(flag_var\r
+      CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE\r
+      CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO\r
+      CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE\r
+      CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)\r
+    if (${flag_var} MATCHES "/EHsc")\r
+      string(REGEX REPLACE "/EHsc" "" ${flag_var} "${${flag_var}}")\r
+    endif()\r
+  endforeach()\r
+endif()\r
+\r
+# In order for /Zc:inline, which speeds up the build significantly, to work\r
+# we need to remove the /Ob0 parameter that CMake adds by default, because that\r
+# would normally disable all inlining.\r
+foreach(flag_var CMAKE_C_FLAGS_DEBUG CMAKE_CXX_FLAGS_DEBUG)\r
+  if (${flag_var} MATCHES "/Ob0")\r
+    string(REGEX REPLACE "/Ob0" "" ${flag_var} "${${flag_var}}")\r
+  endif()\r
+endforeach()\r
+\r
+# Apply the option set for Folly to the specified target.\r
+function(apply_folly_compile_options_to_target THETARGET)\r
+  # The general options passed:\r
+  target_compile_options(${THETARGET}\r
+    PUBLIC\r
+      /EHa # Enable both SEH and C++ Exceptions.\r
+      /GF # There are bugs with constexpr StringPiece when string pooling is disabled.\r
+      /Zc:referenceBinding # Disallow temporaries from binding to non-const lvalue references.\r
+      /Zc:rvalueCast # Enforce the standard rules for explicit type conversion.\r
+      /Zc:implicitNoexcept # Enable implicit noexcept specifications where required, such as destructors.\r
+      /Zc:strictStrings # Don't allow conversion from a string literal to mutable characters.\r
+      /Zc:threadSafeInit # Enable thread-safe function-local statics initialization.\r
+      /Zc:throwingNew # Assume operator new throws on failure.\r
+\r
+      $<$<BOOL:${MSVC_ENABLE_CPP_LATEST}>:/std:c++latest> # Build in C++ Latest mode if requested.\r
+\r
+      # This is only supported by MSVC 2017\r
+      $<$<BOOL:${MSVC_IS_2017}>:/permissive-> # Be mean, don't allow bad non-standard stuff (C++/CLI, __declspec, etc. are all left intact).\r
+    PRIVATE\r
+      /bigobj # Support objects with > 65k sections. Needed due to templates.\r
+      /favor:${MSVC_FAVORED_ARCHITECTURE} # Architecture to prefer when generating code.\r
+      /Zc:inline # Have the compiler eliminate unreferenced COMDAT functions and data before emitting the object file.\r
+\r
+      $<$<BOOL:${MSVC_ENABLE_ALL_WARNINGS}>:/Wall> # Enable all warnings if requested.\r
+      $<$<BOOL:${MSVC_ENABLE_PARALLEL_BUILD}>:/MP> # Enable multi-processor compilation if requested.\r
+      $<$<BOOL:${MSVC_ENABLE_STATIC_ANALYSIS}>:/analyze> # Enable static analysis if requested.\r
+\r
+      # Debug builds\r
+      $<$<CONFIG:DEBUG>:\r
+        /Gy- # Disable function level linking.\r
+\r
+        $<$<BOOL:${MSVC_ENABLE_DEBUG_INLINING}>:/Ob2> # Add /Ob2 if allowing inlining in debug mode.\r
+      >\r
+\r
+      # Non-debug builds\r
+      $<$<NOT:$<CONFIG:DEBUG>>:\r
+        /Gw # Optimize global data. (-fdata-sections)\r
+        /Gy # Enable function level linking. (-ffunction-sections)\r
+        /Qpar # Enable parallel code generation.\r
+        /Oi # Enable intrinsic functions.\r
+        /Ot # Favor fast code.\r
+\r
+        $<$<BOOL:${MSVC_ENABLE_LTCG}>:/GL> # Enable link time code generation.\r
+      >\r
+  )\r
+\r
+  target_compile_options(${THETARGET}\r
+    PUBLIC\r
+      /wd4191 # 'type cast' unsafe conversion of function pointers\r
+      /wd4291 # no matching operator delete found\r
+      /wd4309 # '=' truncation of constant value\r
+      /wd4310 # cast truncates constant value\r
+      /wd4366 # result of unary '&' operator may be unaligned\r
+      /wd4587 # behavior change; constructor no longer implicitly called\r
+      /wd4592 # symbol will be dynamically initialized (implementation limitation)\r
+      /wd4628 # digraphs not supported with -Ze\r
+      /wd4723 # potential divide by 0\r
+      /wd4724 # potential mod by 0\r
+      /wd4868 # compiler may not enforce left-to-right evaluation order\r
+      /wd4996 # user deprecated\r
+\r
+      # The warnings that are disabled:\r
+      /wd4068 # Unknown pragma.\r
+      /wd4091 # 'typedef' ignored on left of '' when no variable is declared.\r
+      /wd4146 # Unary minus applied to unsigned type, result still unsigned.\r
+      /wd4800 # Values being forced to bool, this happens many places, and is a "performance warning".\r
+\r
+      # NOTE: glog/logging.h:1116 change to `size_t pcount() const { return size_t(pptr() - pbase()); }`\r
+      # NOTE: gmock/gmock-spec-builders.h:1177 change to `*static_cast<const Action<F>*>(untyped_actions_[size_t(count - 1)]) :`\r
+      # NOTE: gmock/gmock-spec-builders.h:1749 change to `const size_t count = untyped_expectations_.size();`\r
+      # NOTE: gmock/gmock-spec-builders.h:1754 change to `for (size_t i = 0; i < count; i++) {`\r
+      # NOTE: gtest/gtest-printers.h:173 change to `const internal::BiggestInt kBigInt = internal::BiggestInt(value);`\r
+      # NOTE: gtest/internal/gtest-internal.h:890 add `GTEST_DISABLE_MSC_WARNINGS_PUSH_(4365)`\r
+      # NOTE: gtest/internal/gtest-internal.h:894 ass `GTEST_DISABLE_MSC_WARNINGS_POP_()`\r
+      # NOTE: boost/crc.hpp:578 change to `{ return static_cast<unsigned char>(x ^ rem); }`\r
+      # NOTE: boost/regex/v4/match_results.hpp:126 change to `return m_subs[size_type(sub)].length();`\r
+      # NOTE: boost/regex/v4/match_results.hpp:226 change to `return m_subs[size_type(sub)];`\r
+      # NOTE: boost/date_time/adjust_functors.hpp:67 change to `origDayOfMonth_ = short(ymd.day);`\r
+      # NOTE: boost/date_time/adjust_functors.hpp:75 change to `wrap_int2 wi(short(ymd.month));`\r
+      # 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
+      # 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
+      # NOTE: boost/date_time/adjust_functors.hpp:87 change to `day_type dayOfMonth = static_cast<unsigned short>(origDayOfMonth_);`\r
+      # 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
+      # NOTE: boost/date_time/adjust_functors.hpp:98 change to `origDayOfMonth_ = short(ymd.day);`\r
+      # NOTE: boost/date_time/adjust_functors.hpp:106 change to `wrap_int2 wi(short(ymd.month));`\r
+      # 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
+      # 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
+      # NOTE: boost/date_time/adjust_functors.hpp:116 change to `day_type dayOfMonth = static_cast<unsigned short>(origDayOfMonth_);`\r
+      # 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
+      # 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
+      # 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
+      # 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
+      # NOTE: boost/thread/future.hpp:1063 change to `locks[std::ptrdiff_t(i)].unlock();`\r
+      # NOTE: boost/thread/win32/basic_recursive_mutex.hpp:47 change to `long const current_thread_id=long(win32::GetCurrentThreadId());`\r
+      # NOTE: boost/thread/win32/basic_recursive_mutex.hpp:53 change to `long const current_thread_id=long(win32::GetCurrentThreadId());`\r
+      # NOTE: boost/thread/win32/basic_recursive_mutex.hpp:64 change to `long const current_thread_id=long(win32::GetCurrentThreadId());`\r
+      # NOTE: boost/thread/win32/basic_recursive_mutex.hpp:78 change to `long const current_thread_id=long(win32::GetCurrentThreadId());`\r
+      # NOTE: boost/thread/win32/basic_recursive_mutex.hpp:84 change to `long const current_thread_id=long(win32::GetCurrentThreadId());`\r
+      # NOTE: boost/thread/win32/condition_variable.hpp:79 change to `detail::win32::ReleaseSemaphore(semaphore,long(count_to_release),0);`\r
+      # NOTE: boost/thread/win32/condition_variable.hpp:84 change to `release(unsigned(detail::interlocked_read_acquire(&waiters)));`\r
+      # NOTE: boost/algorithm/string/detail/classification.hpp:85 change to `std::size_t Size=std::size_t(::boost::distance(Range));`\r
+      /wd4018 # Signed/unsigned mismatch.\r
+      /wd4365 # Signed/unsigned mismatch.\r
+      /wd4388 # Signed/unsigned mismatch on relative comparison operator.\r
+      /wd4389 # Signed/unsigned mismatch on equality comparison operator.\r
+\r
+      # TODO:\r
+      /wd4100 # Unreferenced formal parameter.\r
+      /wd4459 # Declaration of parameter hides global declaration.\r
+      /wd4505 # Unreferenced local function has been removed.\r
+      /wd4701 # Potentially uninitialized local variable used.\r
+      /wd4702 # Unreachable code.\r
+\r
+      # These warnings are disabled because we've\r
+      # enabled all warnings. If all warnings are\r
+      # not enabled, we still need to disable them\r
+      # for consuming libs.\r
+      /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
+      /wd4127 # Conditional expression is constant.\r
+      /wd4200 # Non-standard extension, zero sized array.\r
+      /wd4201 # Non-standard extension used: nameless struct/union.\r
+      /wd4296 # '<' Expression is always false.\r
+      /wd4316 # Object allocated on the heap may not be aligned to 128.\r
+      /wd4324 # Structure was padded due to alignment specifier.\r
+      /wd4355 # 'this' used in base member initializer list.\r
+      /wd4371 # Layout of class may have changed due to fixes in packing.\r
+      /wd4435 # Object layout under /vd2 will change due to virtual base.\r
+      /wd4514 # Unreferenced inline function has been removed. (caused by /Zc:inline)\r
+      /wd4548 # Expression before comma has no effect. I wouldn't disable this normally, but malloc.h triggers this warning.\r
+      /wd4574 # ifdef'd macro was defined to 0.\r
+      /wd4582 # Constructor is not implicitly called.\r
+      /wd4583 # Destructor is not implicitly called.\r
+      /wd4619 # Invalid warning number used in #pragma warning.\r
+      /wd4623 # Default constructor was implicitly defined as deleted.\r
+      /wd4625 # Copy constructor was implicitly defined as deleted.\r
+      /wd4626 # Assignment operator was implicitly defined as deleted.\r
+      /wd4647 # Behavior change in __is_pod.\r
+      /wd4668 # Macro was not defined, replacing with 0.\r
+      /wd4706 # Assignment within conditional expression.\r
+      /wd4710 # Function was not inlined.\r
+      /wd4711 # Function was selected for automated inlining.\r
+      /wd4714 # Function marked as __forceinline not inlined.\r
+      /wd4820 # Padding added after data member.\r
+      /wd5026 # Move constructor was implicitly defined as deleted.\r
+      /wd5027 # Move assignment operator was implicitly defined as deleted.\r
+      /wd5031 # #pragma warning(pop): likely mismatch, popping warning state pushed in different file. This is needed because of how boost does things.\r
+\r
+      # Warnings to treat as errors:\r
+      /we4099 # Mixed use of struct and class on same type names.\r
+      /we4129 # Unknown escape sequence. This is usually caused by incorrect escaping.\r
+      /we4566 # Character cannot be represented in current charset. This is remidied by prefixing string with "u8".\r
+\r
+    PRIVATE\r
+      # Warnings disabled for /analyze\r
+      $<$<BOOL:${MSVC_ENABLE_STATIC_ANALYSIS}>:\r
+        /wd6001 # Using uninitialized memory. This is disabled because it is wrong 99% of the time.\r
+        /wd6011 # Dereferencing potentially NULL pointer.\r
+        /wd6031 # Return value ignored.\r
+        /wd6235 # (<non-zero constant> || <expression>) is always a non-zero constant.\r
+        /wd6237 # (<zero> && <expression>) is always zero. <expression> is never evaluated and may have side effects.\r
+        /wd6239 # (<non-zero constant> && <expression>) always evaluates to the result of <expression>.\r
+        /wd6240 # (<expression> && <non-zero constant>) always evaluates to the result of <expression>.\r
+        /wd6246 # Local declaration hides declaration of same name in outer scope.\r
+        /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
+        /wd6255 # _alloca indicates failure by raising a stack overflow exception.\r
+        /wd6262 # Function uses more than x bytes of stack space.\r
+        /wd6271 # Extra parameter passed to format function. The analysis pass doesn't recognize %j or %z, even though the runtime does.\r
+        /wd6285 # (<non-zero constant> || <non-zero constant>) is always true.\r
+        /wd6297 # 32-bit value is shifted then cast to 64-bits. The places this occurs never use more than 32 bits.\r
+        /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
+        /wd6326 # Potential comparison of a constant with another constant.\r
+        /wd6330 # Unsigned/signed mismatch when passed as a parameter.\r
+        /wd6340 # Mismatch on sign when passed as format string value.\r
+        /wd6387 # '<value>' could be '0': This does not adhere to the specification for a function.\r
+        /wd28182 # Dereferencing NULL pointer. '<value>' contains the same NULL value as '<expression>'.\r
+        /wd28251 # Inconsistent annotation for function. This is because we only annotate the declaration and not the definition.\r
+        /wd28278 # Function appears with no prototype in scope.\r
+      >\r
+  )\r
+\r
+  # And the extra defines:\r
+  target_compile_definitions(${THETARGET}\r
+    PUBLIC\r
+      _CRT_NONSTDC_NO_WARNINGS # Don't deprecate posix names of functions.\r
+      _CRT_SECURE_NO_WARNINGS # Don't deprecate the non _s versions of various standard library functions, because safety is for chumps.\r
+      _SCL_SECURE_NO_WARNINGS # Don't deprecate the non _s versions of various standard library functions, because safety is for chumps.\r
+      \r
+      _STL_EXTRA_DISABLED_WARNINGS=4774\ 4987\r
+\r
+      $<$<BOOL:${MSVC_ENABLE_CPP_LATEST}>:_HAS_AUTO_PTR_ETC=1> # We're building in C++ 17 or greater 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
+      $<$<BOOL:${MSVC_ENABLE_LEAN_AND_MEAN_WINDOWS}>:WIN32_LEAN_AND_MEAN> # Don't include most of Windows.h\r
+  )\r
+\r
+  # Ignore a warning about an object file not defining any symbols,\r
+  # these are known, and we don't care.\r
+  set_property(TARGET ${THETARGET} APPEND_STRING PROPERTY STATIC_LIBRARY_FLAGS " /ignore:4221")\r
+\r
+  # The options to pass to the linker:\r
+  set_property(TARGET ${THETARGET} APPEND_STRING PROPERTY LINK_FLAGS_DEBUG " /INCREMENTAL") # Do incremental linking.\r
+  if (NOT $<TARGET_PROPERTY:${THETARGET},TYPE> STREQUAL "STATIC_LIBRARY")\r
+    set_property(TARGET ${THETARGET} APPEND_STRING PROPERTY LINK_FLAGS_DEBUG " /OPT:NOREF") # No unreferenced data elimination.\r
+    set_property(TARGET ${THETARGET} APPEND_STRING PROPERTY LINK_FLAGS_DEBUG " /OPT:NOICF") # No Identical COMDAT folding.\r
+\r
+    set_property(TARGET ${THETARGET} APPEND_STRING PROPERTY LINK_FLAGS_RELEASE " /OPT:REF") # Remove unreferenced functions and data.\r
+    set_property(TARGET ${THETARGET} APPEND_STRING PROPERTY LINK_FLAGS_RELEASE " /OPT:ICF") # Identical COMDAT folding.\r
+  endif()\r
+\r
+  if (MSVC_ENABLE_FAST_LINK)\r
+    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
+  endif()\r
+\r
+  # Add /GL to the compiler, and /LTCG to the linker\r
+  # if link time code generation is enabled.\r
+  if (MSVC_ENABLE_LTCG)\r
+    set_property(TARGET ${THETARGET} APPEND_STRING PROPERTY LINK_FLAGS_RELEASE " /LTCG")\r
+  endif()\r
+endfunction()\r
diff --git a/CMake/FollyCompilerUnix.cmake b/CMake/FollyCompilerUnix.cmake
new file mode 100644 (file)
index 0000000..b922815
--- /dev/null
@@ -0,0 +1,29 @@
+set(CMAKE_CXX_FLAGS_COMMON -g -Wall -Wextra)
+set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_COMMON}")
+set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_COMMON} -O3")
+
+function(apply_folly_compile_options_to_target THETARGET)
+  target_compile_options(${THETARGET}
+    PUBLIC
+      -g
+      -std=gnu++14
+      -fopenmp
+      -finput-charset=UTF-8
+      -fsigned-char
+      -faligned-new
+      -Werror
+      -Wall
+      -Wno-deprecated
+      -Wdeprecated-declarations
+      -Wno-error=deprecated-declarations
+      -Wno-sign-compare
+      -Wno-unused
+      -Wunused-label
+      -Wunused-result
+      -Wnon-virtual-dtor
+      -Wno-noexcept-type
+    PRIVATE
+      -D_REENTRANT
+      -D_GNU_SOURCE
+  )
+endfunction()
index f144675..fe6b4a5 100755 (executable)
@@ -86,7 +86,11 @@ configure_file(
   ${CMAKE_CURRENT_BINARY_DIR}/folly/folly-config.h
 )
 
-include(FollyCompiler)
+if("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
+  include(FollyCompilerMSVC)
+else()
+  include(FollyCompilerUnix)
+endif()
 include(FollyFunctions)
 
 # Main folly library files
@@ -196,11 +200,21 @@ else()
 endif()
 
 
+if("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
+  set(FOLLY_LINK_LIBRARIES
+    ${FOLLY_LINK_LIBRARIES}
+    Iphlpapi.lib
+    Ws2_32.lib
+  )
+else()
+  set(FOLLY_LINK_LIBRARIES
+    ${FOLLY_LINK_LIBRARIES}
+    dl
+  )
+endif()
+
 set(FOLLY_LINK_LIBRARIES
   ${FOLLY_LINK_LIBRARIES}
-  Iphlpapi.lib
-  Ws2_32.lib
-
   ${FOLLY_SHINY_DEPENDENCIES}
 )