From 7e9117ad80bc5a5402d71a4e036e404f087adc68 Mon Sep 17 00:00:00 2001 From: Christopher Dykes Date: Wed, 12 Apr 2017 22:25:15 -0700 Subject: [PATCH] Add CMake build system Summary: This is for use on Windows only, and does not support Linux or OSX in the slightest. There are probably still a few hacks laying around in it, but it works, and that's good enough for now. Reviewed By: yfeldblum Differential Revision: D4873498 fbshipit-source-id: 5952a927037dc1d56c51e71d51ba506d2cd17357 --- CMake/FindDoubleConversion.cmake | 22 ++ CMake/FindGFlags.cmake | 23 ++ CMake/FindGMock.cmake | 23 ++ CMake/FindGlog.cmake | 23 ++ CMake/FindLibEvent.cmake | 37 +++ CMake/FindPThread.cmake | 27 ++ CMake/FollyCompiler.cmake | 258 +++++++++++++++ CMake/FollyFunctions.cmake | 281 +++++++++++++++++ CMake/folly-config.h.cmake | 42 +++ CMake/folly-deps.cmake | 18 ++ CMakeLists.txt | 525 +++++++++++++++++++++++++++++++ 11 files changed, 1279 insertions(+) create mode 100755 CMake/FindDoubleConversion.cmake create mode 100755 CMake/FindGFlags.cmake create mode 100755 CMake/FindGMock.cmake create mode 100755 CMake/FindGlog.cmake create mode 100755 CMake/FindLibEvent.cmake create mode 100755 CMake/FindPThread.cmake create mode 100755 CMake/FollyCompiler.cmake create mode 100755 CMake/FollyFunctions.cmake create mode 100755 CMake/folly-config.h.cmake create mode 100755 CMake/folly-deps.cmake create mode 100755 CMakeLists.txt diff --git a/CMake/FindDoubleConversion.cmake b/CMake/FindDoubleConversion.cmake new file mode 100755 index 00000000..0a967eb5 --- /dev/null +++ b/CMake/FindDoubleConversion.cmake @@ -0,0 +1,22 @@ +# Finds libdouble-conversion. +# +# This module defines: +# DOUBLE_CONVERSION_INCLUDE_DIR +# DOUBLE_CONVERSION_LIBRARY +# + +find_path(DOUBLE_CONVERSION_INCLUDE_DIR double-conversion/double-conversion.h) +find_library(DOUBLE_CONVERSION_LIBRARY NAMES double-conversion) + +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS( + DOUBLE_CONVERSION DEFAULT_MSG + DOUBLE_CONVERSION_LIBRARY DOUBLE_CONVERSION_INCLUDE_DIR) + +if (NOT DOUBLE_CONVERSION_FOUND) + message(STATUS "Using third-party bundled double-conversion") +else() + message(STATUS "Found double-conversion: ${DOUBLE_CONVERSION_LIBRARY}") +endif (NOT DOUBLE_CONVERSION_FOUND) + +mark_as_advanced(DOUBLE_CONVERSION_INCLUDE_DIR DOUBLE_CONVERSION_LIBRARY) diff --git a/CMake/FindGFlags.cmake b/CMake/FindGFlags.cmake new file mode 100755 index 00000000..167bdd4b --- /dev/null +++ b/CMake/FindGFlags.cmake @@ -0,0 +1,23 @@ +# +# Find libgflags +# +# LIBGFLAGS_INCLUDE_DIR - where to find gflags/gflags.h, etc. +# LIBGFLAGS_LIBRARY - List of libraries when using libgflags. +# LIBGFLAGS_FOUND - True if libgflags found. + + +IF (LIBGFLAGS_INCLUDE_DIR) + # Already in cache, be silent + SET(LIBGFLAGS_FIND_QUIETLY TRUE) +ENDIF () + +FIND_PATH(LIBGFLAGS_INCLUDE_DIR gflags/gflags.h) + +FIND_LIBRARY(LIBGFLAGS_LIBRARY gflags) + +# handle the QUIETLY and REQUIRED arguments and set LIBGFLAGS_FOUND to TRUE if +# all listed variables are TRUE +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBGFLAGS DEFAULT_MSG LIBGFLAGS_LIBRARY LIBFLAGS_INCLUDE_DIR) + +MARK_AS_ADVANCED(LIBGFLAGS_LIBRARY LIBGFLAGS_INCLUDE_DIR) diff --git a/CMake/FindGMock.cmake b/CMake/FindGMock.cmake new file mode 100755 index 00000000..d4f61525 --- /dev/null +++ b/CMake/FindGMock.cmake @@ -0,0 +1,23 @@ +# +# Find libgmock +# +# LIBGMOCK_INCLUDE_DIR - where to find gmock/gmock.h, etc. +# LIBGMOCK_LIBRARY - List of libraries when using libgmock. +# LIBGMOCK_FOUND - True if libgmock found. + + +IF (LIBGMOCK_INCLUDE_DIR) + # Already in cache, be silent + SET(LIBGMOCK_FIND_QUIETLY TRUE) +ENDIF () + +FIND_PATH(LIBGMOCK_INCLUDE_DIR gmock/gmock.h) + +FIND_LIBRARY(LIBGMOCK_LIBRARY gmock_main) + +# handle the QUIETLY and REQUIRED arguments and set LIBGMOCK_FOUND to TRUE if +# all listed variables are TRUE +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBGMOCK DEFAULT_MSG LIBGMOCK_LIBRARY LIBGMOCK_INCLUDE_DIR) + +MARK_AS_ADVANCED(LIBGMOCK_LIBRARY LIBGMOCK_INCLUDE_DIR) diff --git a/CMake/FindGlog.cmake b/CMake/FindGlog.cmake new file mode 100755 index 00000000..4338159a --- /dev/null +++ b/CMake/FindGlog.cmake @@ -0,0 +1,23 @@ +# +# Find libglog +# +# LIBGLOG_INCLUDE_DIR - where to find glog/logging.h, etc. +# LIBGLOG_LIBRARY - List of libraries when using libglog. +# LIBGLOG_FOUND - True if libglog found. + + +IF (LIBGLOG_INCLUDE_DIR) + # Already in cache, be silent + SET(LIBGLOG_FIND_QUIETLY TRUE) +ENDIF () + +FIND_PATH(LIBGLOG_INCLUDE_DIR glog/logging.h) + +FIND_LIBRARY(LIBGLOG_LIBRARY glog) + +# handle the QUIETLY and REQUIRED arguments and set LIBGLOG_FOUND to TRUE if +# all listed variables are TRUE +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBGLOG DEFAULT_MSG LIBGLOG_LIBRARY LIBGLOG_INCLUDE_DIR) + +MARK_AS_ADVANCED(LIBGLOG_LIBRARY LIBGLOG_INCLUDE_DIR) diff --git a/CMake/FindLibEvent.cmake b/CMake/FindLibEvent.cmake new file mode 100755 index 00000000..eca43a41 --- /dev/null +++ b/CMake/FindLibEvent.cmake @@ -0,0 +1,37 @@ +# - Find LibEvent (a cross event library) +# This module defines +# LIBEVENT_INCLUDE_DIR, where to find LibEvent headers +# LIBEVENT_LIB, LibEvent libraries +# LibEvent_FOUND, If false, do not try to use libevent + +set(LibEvent_EXTRA_PREFIXES /usr/local /opt/local "$ENV{HOME}") +foreach(prefix ${LibEvent_EXTRA_PREFIXES}) + list(APPEND LibEvent_INCLUDE_PATHS "${prefix}/include") + list(APPEND LibEvent_LIB_PATHS "${prefix}/lib") +endforeach() + +find_path(LIBEVENT_INCLUDE_DIR event.h PATHS ${LibEvent_INCLUDE_PATHS}) +find_library(LIBEVENT_LIB NAMES event PATHS ${LibEvent_LIB_PATHS}) + +if (LIBEVENT_LIB AND LIBEVENT_INCLUDE_DIR) + set(LibEvent_FOUND TRUE) + set(LIBEVENT_LIB ${LIBEVENT_LIB}) +else () + set(LibEvent_FOUND FALSE) +endif () + +if (LibEvent_FOUND) + if (NOT LibEvent_FIND_QUIETLY) + message(STATUS "Found libevent: ${LIBEVENT_LIB}") + endif () +else () + if (LibEvent_FIND_REQUIRED) + message(FATAL_ERROR "Could NOT find libevent.") + endif () + message(STATUS "libevent NOT found.") +endif () + +mark_as_advanced( + LIBEVENT_LIB + LIBEVENT_INCLUDE_DIR + ) diff --git a/CMake/FindPThread.cmake b/CMake/FindPThread.cmake new file mode 100755 index 00000000..4eda894e --- /dev/null +++ b/CMake/FindPThread.cmake @@ -0,0 +1,27 @@ +# - Try to find libpthread +# +# Once done this will define +# +# LIBPTHREAD_FOUND - system has libpthread +# LIBPTHREAD_INCLUDE_DIRS - the libpthread include directory +# LIBPTHREAD_LIBRARIES - Link these to use libpthread +# LIBPTHREAD_DEFINITIONS - Compiler switches required for using libpthread +# +# Redistribution and use is allowed according to the terms of the New +# BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. +# + + +if (LIBPTHREAD_LIBRARIES AND LIBPTHREAD_INCLUDE_DIRS) + set (LIBPTHREAD_FIND_QUIETLY TRUE) +endif (LIBPTHREAD_LIBRARIES AND LIBPTHREAD_INCLUDE_DIRS) + +find_path (LIBPTHREAD_INCLUDE_DIRS NAMES pthread.h) +find_library (LIBPTHREAD_LIBRARIES NAMES pthread) + +include (FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBPTHREAD DEFAULT_MSG + LIBPTHREAD_LIBRARIES LIBPTHREAD_INCLUDE_DIRS) + +mark_as_advanced(LIBPTHREAD_INCLUDE_DIRS LIBPTHREAD_LIBRARIES LIBPTHREAD_FOUND) diff --git a/CMake/FollyCompiler.cmake b/CMake/FollyCompiler.cmake new file mode 100755 index 00000000..e01f6569 --- /dev/null +++ b/CMake/FollyCompiler.cmake @@ -0,0 +1,258 @@ +# Some additional configuration options. +option(MSVC_ENABLE_ALL_WARNINGS "If enabled, pass /Wall to the compiler." ON) +option(MSVC_ENABLE_DEBUG_INLINING "If enabled, enable inlining in the debug configuration. This allows /Zc:inline to be far more effective." OFF) +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) +option(MSVC_ENABLE_LTCG "If enabled, use Link Time Code Generation for Release builds." OFF) +option(MSVC_ENABLE_PARALLEL_BUILD "If enabled, build multiple source files in parallel." ON) +option(MSVC_ENABLE_STATIC_ANALYSIS "If enabled, do more complex static analysis and generate warnings appropriately." OFF) +option(MSVC_USE_STATIC_RUNTIME "If enabled, build against the static, rather than the dynamic, runtime." OFF) + +# Alas, option() doesn't support string values. +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.") +# Validate, and then add the favored architecture. +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") + message(FATAL_ERROR "MSVC_FAVORED_ARCHITECTURE must be set to one of exactly, 'blend', 'AMD64', 'INTEL64', or 'ATOM'! Got '${MSVC_FAVORED_ARCHITECTURE}' instead!") +endif() + +############################################################ +# We need to adjust a couple of the default option sets. +############################################################ + +# If the static runtime is requested, we have to +# overwrite some of CMake's defaults. +if (MSVC_USE_STATIC_RUNTIME) + foreach(flag_var + CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE + CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO + CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE + CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) + if (${flag_var} MATCHES "/MD") + string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") + endif() + endforeach() +endif() + +# In order for /Zc:inline, which speeds up the build significantly, to work +# we need to remove the /Ob0 parameter that CMake adds by default, because that +# would normally disable all inlining. +foreach(flag_var CMAKE_C_FLAGS_DEBUG CMAKE_CXX_FLAGS_DEBUG) + if (${flag_var} MATCHES "/Ob0") + string(REGEX REPLACE "/Ob0" "" ${flag_var} "${${flag_var}}") + endif() +endforeach() + +# Apply the option set for Folly to the specified target. +function(apply_folly_compile_options_to_target THETARGET) + # The general options passed: + target_compile_options(${THETARGET} + PUBLIC + #/std:c++latest # Build in C++17 mode + /EHa # Enable both SEH and C++ Exceptions. + /Zc:referenceBinding # Disallow temporaries from binding to non-const lvalue references. + /Zc:rvalueCast # Enforce the standard rules for explicit type conversion. + /Zc:implicitNoexcept # Enable implicit noexcept specifications where required, such as destructors. + /Zc:strictStrings # Don't allow conversion from a string literal to mutable characters. + /Zc:threadSafeInit # Enable thread-safe function-local statics initialization. + /Zc:throwingNew # Assume operator new throws on failure. + /permissive- # Be mean, don't allow bad non-standard stuff (C++/CLI, __declspec, etc. are all left intact). + PRIVATE + /bigobj # Support objects with > 65k sections. Needed due to templates. + /favor:${MSVC_FAVORED_ARCHITECTURE} # Architecture to prefer when generating code. + /Zc:inline # Have the compiler eliminate unreferenced COMDAT functions and data before emitting the object file. + + $<$:/Wall> # Enable all warnings if requested. + $<$:/MP> # Enable multi-processor compilation if requested. + $<$:/analyze> # Enable static analysis if requested. + + # Debug builds + $<$: + /Gy- # Disable function level linking. + /GF- # Disable string pooling. + + $<$:/Ob2> # Add /Ob2 if allowing inlining in debug mode. + > + + # Non-debug builds + $<$>: + /GF # Enable string pooling. (this is enabled by default by the optimization level, but we enable it here for clarity) + /Gw # Optimize global data. (-fdata-sections) + /Gy # Enable function level linking. (-ffunction-sections) + /Qpar # Enable parallel code generation. + /Oi # Enable intrinsic functions. + /Ot # Favor fast code. + + $<$:/GL> # Enable link time code generation. + > + ) + + target_compile_options(${THETARGET} + PUBLIC + /wd4191 # 'type cast' unsafe conversion of function pointers + /wd4291 # no matching operator delete found + /wd4309 # '=' truncation of constant value + /wd4310 # cast truncates constant value + /wd4366 # result of unary '&' operator may be unaligned + /wd4587 # behavior change; constructor no longer implicitly called + /wd4592 # symbol will be dynamically initialized (implementation limitation) + /wd4723 # potential divide by 0 + /wd4724 # potential mod by 0 + /wd4868 # compiler may not enforce left-to-right evaluation order + /wd4996 # user deprecated + + # The warnings that are disabled: + /wd4068 # Unknown pragma. + /wd4091 # 'typedef' ignored on left of '' when no variable is declared. + /wd4146 # Unary minus applied to unsigned type, result still unsigned. + /wd4800 # Values being forced to bool, this happens many places, and is a "performance warning". + + # NOTE: glog/logging.h:1116 change to `size_t pcount() const { return size_t(pptr() - pbase()); }` + # NOTE: gmock/gmock-spec-builders.h:1177 change to `*static_cast*>(untyped_actions_[size_t(count - 1)]) :` + # NOTE: gmock/gmock-spec-builders.h:1749 change to `const size_t count = untyped_expectations_.size();` + # NOTE: gmock/gmock-spec-builders.h:1754 change to `for (size_t i = 0; i < count; i++) {` + # NOTE: gtest/gtest-printers.h:173 change to `const internal::BiggestInt kBigInt = internal::BiggestInt(value);` + # NOTE: gtest/internal/gtest-internal.h:890 add `GTEST_DISABLE_MSC_WARNINGS_PUSH_(4365)` + # NOTE: gtest/internal/gtest-internal.h:894 ass `GTEST_DISABLE_MSC_WARNINGS_POP_()` + # NOTE: boost/crc.hpp:578 change to `{ return static_cast(x ^ rem); }` + # NOTE: boost/regex/v4/match_results.hpp:126 change to `return m_subs[size_type(sub)].length();` + # NOTE: boost/regex/v4/match_results.hpp:226 change to `return m_subs[size_type(sub)];` + # NOTE: boost/date_time/adjust_functors.hpp:67 change to `origDayOfMonth_ = short(ymd.day);` + # NOTE: boost/date_time/adjust_functors.hpp:75 change to `wrap_int2 wi(short(ymd.month));` + # NOTE: boost/date_time/adjust_functors.hpp:82 change to `day_type resultingEndOfMonthDay(cal_type::end_of_month_day(static_cast(year), static_cast(wi.as_int())));` + # NOTE: boost/date_time/adjust_functors.hpp:85 change to `return date_type(static_cast(year), static_cast(wi.as_int()), resultingEndOfMonthDay) - d;` + # NOTE: boost/date_time/adjust_functors.hpp:87 change to `day_type dayOfMonth = static_cast(origDayOfMonth_);` + # NOTE: boost/date_time/adjust_functors.hpp:91 change to `return date_type(static_cast(year), static_cast(wi.as_int()), dayOfMonth) - d;` + # NOTE: boost/date_time/adjust_functors.hpp:98 change to `origDayOfMonth_ = short(ymd.day);` + # NOTE: boost/date_time/adjust_functors.hpp:106 change to `wrap_int2 wi(short(ymd.month));` + # NOTE: boost/date_time/adjust_functors.hpp:111 change to `day_type resultingEndOfMonthDay(cal_type::end_of_month_day(static_cast(year), static_cast(wi.as_int())));` + # NOTE: boost/date_time/adjust_functors.hpp:114 change to `return date_type(static_cast(year), static_cast(wi.as_int()), resultingEndOfMonthDay) - d;` + # NOTE: boost/date_time/adjust_functors.hpp:116 change to `day_type dayOfMonth = static_cast(origDayOfMonth_);` + # NOTE: boost/date_time/adjust_functors.hpp:120 change to `return date_type(static_cast(year), static_cast(wi.as_int()), dayOfMonth) - d;` + # NOTE: boost/date_time/gregorian_calendar.ipp:81 change to `unsigned long d = static_cast(ymd.day + ((153*m + 2)/5) + 365*y + (y/4) - (y/100) + (y/400) - 32045);` + # 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);` + # NOTE: boost/thread/future.hpp:1050 change to `locks[std::ptrdiff_t(i)]=BOOST_THREAD_MAKE_RV_REF(boost::unique_lock(futures[i].future_->mutex));` + # NOTE: boost/thread/future.hpp:1063 change to `locks[std::ptrdiff_t(i)].unlock();` + # NOTE: boost/thread/win32/basic_recursive_mutex.hpp:47 change to `long const current_thread_id=long(win32::GetCurrentThreadId());` + # NOTE: boost/thread/win32/basic_recursive_mutex.hpp:53 change to `long const current_thread_id=long(win32::GetCurrentThreadId());` + # NOTE: boost/thread/win32/basic_recursive_mutex.hpp:64 change to `long const current_thread_id=long(win32::GetCurrentThreadId());` + # NOTE: boost/thread/win32/basic_recursive_mutex.hpp:78 change to `long const current_thread_id=long(win32::GetCurrentThreadId());` + # NOTE: boost/thread/win32/basic_recursive_mutex.hpp:84 change to `long const current_thread_id=long(win32::GetCurrentThreadId());` + # NOTE: boost/thread/win32/condition_variable.hpp:79 change to `detail::win32::ReleaseSemaphore(semaphore,long(count_to_release),0);` + # NOTE: boost/thread/win32/condition_variable.hpp:84 change to `release(unsigned(detail::interlocked_read_acquire(&waiters)));` + # NOTE: boost/algorithm/string/detail/classification.hpp:85 change to `std::size_t Size=std::size_t(::boost::distance(Range));` + /wd4018 # Signed/unsigned mismatch. + /wd4365 # Signed/unsigned mismatch. + /wd4388 # Signed/unsigned mismatch on relative comparison operator. + /wd4389 # Signed/unsigned mismatch on equality comparison operator. + + # TODO: + /wd4100 # Unreferenced formal parameter. + /wd4459 # Declaration of parameter hides global declaration. + /wd4505 # Unreferenced local function has been removed. + /wd4701 # Potentially uninitialized local variable used. + /wd4702 # Unreachable code. + + # These warnings are disabled because we've + # enabled all warnings. If all warnings are + # not enabled, we still need to disable them + # for consuming libs. + /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. + /wd4127 # Conditional expression is constant. + /wd4200 # Non-standard extension, zero sized array. + /wd4201 # Non-standard extension used: nameless struct/union. + /wd4296 # '<' Expression is always false. + /wd4316 # Object allocated on the heap may not be aligned to 128. + /wd4324 # Structure was padded due to alignment specifier. + /wd4355 # 'this' used in base member initializer list. + /wd4371 # Layout of class may have changed due to fixes in packing. + /wd4435 # Object layout under /vd2 will change due to virtual base. + /wd4514 # Unreferenced inline function has been removed. (caused by /Zc:inline) + /wd4548 # Expression before comma has no effect. I wouldn't disable this normally, but malloc.h triggers this warning. + /wd4574 # ifdef'd macro was defined to 0. + /wd4582 # Constructor is not implicitly called. + /wd4583 # Destructor is not implicitly called. + /wd4619 # Invalid warning number used in #pragma warning. + /wd4623 # Default constructor was implicitly defined as deleted. + /wd4625 # Copy constructor was implicitly defined as deleted. + /wd4626 # Assignment operator was implicitly defined as deleted. + /wd4647 # Behavior change in __is_pod. + /wd4668 # Macro was not defined, replacing with 0. + /wd4706 # Assignment within conditional expression. + /wd4710 # Function was not inlined. + /wd4711 # Function was selected for automated inlining. + /wd4714 # Function marked as __forceinline not inlined. + /wd4820 # Padding added after data member. + /wd5026 # Move constructor was implicitly defined as deleted. + /wd5027 # Move assignment operator was implicitly defined as deleted. + /wd5031 # #pragma warning(pop): likely mismatch, popping warning state pushed in different file. This is needed because of how boost does things. + + # Warnings to treat as errors: + /we4099 # Mixed use of struct and class on same type names. + /we4129 # Unknown escape sequence. This is usually caused by incorrect escaping. + /we4566 # Character cannot be represented in current charset. This is remidied by prefixing string with "u8". + + PRIVATE + # Warnings disabled for /analyze + $<$: + /wd6001 # Using uninitialized memory. This is disabled because it is wrong 99% of the time. + /wd6011 # Dereferencing potentially NULL pointer. + /wd6031 # Return value ignored. + /wd6235 # ( || ) is always a non-zero constant. + /wd6237 # ( && ) is always zero. is never evaluated and may have side effects. + /wd6239 # ( && ) always evaluates to the result of . + /wd6240 # ( && ) always evaluates to the result of . + /wd6246 # Local declaration hides declaration of same name in outer scope. + /wd6248 # Setting a SECURITY_DESCRIPTOR's DACL to NULL will result in an unprotected object. This is done by one of the boost headers. + /wd6255 # _alloca indicates failure by raising a stack overflow exception. + /wd6262 # Function uses more than x bytes of stack space. + /wd6271 # Extra parameter passed to format function. The analysis pass doesn't recognize %j or %z, even though the runtime does. + /wd6285 # ( || ) is always true. + /wd6297 # 32-bit value is shifted then cast to 64-bits. The places this occurs never use more than 32 bits. + /wd6308 # Realloc might return null pointer: assigning null pointer to '', which is passed as an argument to 'realloc', will cause the original memory to leak. + /wd6326 # Potential comparison of a constant with another constant. + /wd6330 # Unsigned/signed mismatch when passed as a parameter. + /wd6340 # Mismatch on sign when passed as format string value. + /wd6387 # '' could be '0': This does not adhere to the specification for a function. + /wd28182 # Dereferencing NULL pointer. '' contains the same NULL value as ''. + /wd28251 # Inconsistent annotation for function. This is because we only annotate the declaration and not the definition. + /wd28278 # Function appears with no prototype in scope. + > + ) + + # And the extra defines: + target_compile_definitions(${THETARGET} + PUBLIC + _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. + 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. + _CRT_NONSTDC_NO_WARNINGS # Don't deprecate posix names of functions. + _CRT_SECURE_NO_WARNINGS # Don't deprecate the non _s versions of various standard library functions, because safety is for chumps. + _SCL_SECURE_NO_WARNINGS # Don't deprecate the non _s versions of various standard library functions, because safety is for chumps. + _WINSOCK_DEPRECATED_NO_WARNINGS # Don't deprecate pieces of winsock + WIN32_LEAN_AND_MEAN # Don't include most of Windows.h + + _STL_EXTRA_DISABLED_WARNINGS=4365\ 4774\ 4775\ 4987 + ) + + # Ignore a warning about an object file not defining any symbols, + # these are known, and we don't care. + set_property(TARGET ${THETARGET} APPEND_STRING PROPERTY STATIC_LIBRARY_FLAGS " /ignore:4221") + + # The options to pass to the linker: + set_property(TARGET ${THETARGET} APPEND_STRING PROPERTY LINK_FLAGS_DEBUG " /INCREMENTAL") # Do incremental linking. + if (NOT $ STREQUAL "STATIC_LIBRARY") + set_property(TARGET ${THETARGET} APPEND_STRING PROPERTY LINK_FLAGS_DEBUG " /OPT:NOREF") # No unreferenced data elimination. + set_property(TARGET ${THETARGET} APPEND_STRING PROPERTY LINK_FLAGS_DEBUG " /OPT:NOICF") # No Identical COMDAT folding. + + set_property(TARGET ${THETARGET} APPEND_STRING PROPERTY LINK_FLAGS_RELEASE " /OPT:REF") # Remove unreferenced functions and data. + set_property(TARGET ${THETARGET} APPEND_STRING PROPERTY LINK_FLAGS_RELEASE " /OPT:ICF") # Identical COMDAT folding. + endif() + + if (MSVC_ENABLE_FAST_LINK) + 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. + endif() + + # Add /GL to the compiler, and /LTCG to the linker + # if link time code generation is enabled. + if (MSVC_ENABLE_LTCG) + set_property(TARGET ${THETARGET} APPEND_STRING PROPERTY LINK_FLAGS_RELEASE " /LTCG") + endif() +endfunction() diff --git a/CMake/FollyFunctions.cmake b/CMake/FollyFunctions.cmake new file mode 100755 index 00000000..61992c62 --- /dev/null +++ b/CMake/FollyFunctions.cmake @@ -0,0 +1,281 @@ +function(auto_sources RETURN_VALUE PATTERN SOURCE_SUBDIRS) + if ("${SOURCE_SUBDIRS}" STREQUAL "RECURSE") + SET(PATH ".") + if (${ARGC} EQUAL 4) + list(GET ARGV 3 PATH) + endif () + endif() + + if ("${SOURCE_SUBDIRS}" STREQUAL "RECURSE") + unset(${RETURN_VALUE}) + file(GLOB SUBDIR_FILES "${PATH}/${PATTERN}") + list(APPEND ${RETURN_VALUE} ${SUBDIR_FILES}) + + file(GLOB subdirs RELATIVE ${PATH} ${PATH}/*) + + foreach(DIR ${subdirs}) + if (IS_DIRECTORY ${PATH}/${DIR}) + if (NOT "${DIR}" STREQUAL "CMakeFiles") + file(GLOB_RECURSE SUBDIR_FILES "${PATH}/${DIR}/${PATTERN}") + list(APPEND ${RETURN_VALUE} ${SUBDIR_FILES}) + endif() + endif() + endforeach() + else() + file(GLOB ${RETURN_VALUE} "${PATTERN}") + + foreach (PATH ${SOURCE_SUBDIRS}) + file(GLOB SUBDIR_FILES "${PATH}/${PATTERN}") + list(APPEND ${RETURN_VALUE} ${SUBDIR_FILES}) + endforeach() + endif () + + set(${RETURN_VALUE} ${${RETURN_VALUE}} PARENT_SCOPE) +endfunction(auto_sources) + +# Remove all files matching a set of patterns, and, +# optionally, not matching a second set of patterns, +# from a set of lists. +# +# Example: +# This will remove all files in the CPP_SOURCES list +# matching "/test/" or "Test.cpp$", but not matching +# "BobTest.cpp$". +# REMOVE_MATCHES_FROM_LISTS(CPP_SOURCES MATCHES "/test/" "Test.cpp$" IGNORE_MATCHES "BobTest.cpp$") +# +# Parameters: +# +# [...]: +# The names of the lists to remove matches from. +# +# [MATCHES ...]: +# The matches to remove from the lists. +# +# [IGNORE_MATCHES ...]: +# The matches not to remove, even if they match +# the main set of matches to remove. +function(REMOVE_MATCHES_FROM_LISTS) + set(LISTS_TO_SEARCH) + set(MATCHES_TO_REMOVE) + set(MATCHES_TO_IGNORE) + set(argumentState 0) + foreach (arg ${ARGN}) + if ("x${arg}" STREQUAL "xMATCHES") + set(argumentState 1) + elseif ("x${arg}" STREQUAL "xIGNORE_MATCHES") + set(argumentState 2) + elseif (argumentState EQUAL 0) + list(APPEND LISTS_TO_SEARCH ${arg}) + elseif (argumentState EQUAL 1) + list(APPEND MATCHES_TO_REMOVE ${arg}) + elseif (argumentState EQUAL 2) + list(APPEND MATCHES_TO_IGNORE ${arg}) + else() + message(FATAL_ERROR "Unknown argument state!") + endif() + endforeach() + + foreach (theList ${LISTS_TO_SEARCH}) + foreach (entry ${${theList}}) + foreach (match ${MATCHES_TO_REMOVE}) + if (${entry} MATCHES ${match}) + set(SHOULD_IGNORE OFF) + foreach (ign ${MATCHES_TO_IGNORE}) + if (${entry} MATCHES ${ign}) + set(SHOULD_IGNORE ON) + break() + endif() + endforeach() + + if (NOT SHOULD_IGNORE) + list(REMOVE_ITEM ${theList} ${entry}) + endif() + endif() + endforeach() + endforeach() + set(${theList} ${${theList}} PARENT_SCOPE) + endforeach() +endfunction() + +# Automatically create source_group directives for the sources passed in. +function(auto_source_group rootName rootDir) + file(TO_CMAKE_PATH "${rootDir}" rootDir) + string(LENGTH "${rootDir}" rootDirLength) + set(sourceGroups) + foreach (fil ${ARGN}) + file(TO_CMAKE_PATH "${fil}" filePath) + string(FIND "${filePath}" "/" rIdx REVERSE) + if (rIdx EQUAL -1) + message(FATAL_ERROR "Unable to locate the final forward slash in '${filePath}'!") + endif() + string(SUBSTRING "${filePath}" 0 ${rIdx} filePath) + + string(LENGTH "${filePath}" filePathLength) + string(FIND "${filePath}" "${rootDir}" rIdx) + if (rIdx EQUAL 0) + math(EXPR filePathLength "${filePathLength} - ${rootDirLength}") + string(SUBSTRING "${filePath}" ${rootDirLength} ${filePathLength} fileGroup) + + string(REPLACE "/" "\\" fileGroup "${fileGroup}") + set(fileGroup "\\${rootName}${fileGroup}") + + list(FIND sourceGroups "${fileGroup}" rIdx) + if (rIdx EQUAL -1) + list(APPEND sourceGroups "${fileGroup}") + source_group("${fileGroup}" REGULAR_EXPRESSION "${filePath}/[^/.]+.(cpp|h)$") + endif() + endif() + endforeach() +endfunction() + +# CMake is a pain and doesn't have an easy way to install only the files +# we actually included in our build :( +function(auto_install_files rootName rootDir) + file(TO_CMAKE_PATH "${rootDir}" rootDir) + string(LENGTH "${rootDir}" rootDirLength) + set(sourceGroups) + foreach (fil ${ARGN}) + file(TO_CMAKE_PATH "${fil}" filePath) + string(FIND "${filePath}" "/" rIdx REVERSE) + if (rIdx EQUAL -1) + message(FATAL_ERROR "Unable to locate the final forward slash in '${filePath}'!") + endif() + string(SUBSTRING "${filePath}" 0 ${rIdx} filePath) + + string(LENGTH "${filePath}" filePathLength) + string(FIND "${filePath}" "${rootDir}" rIdx) + if (rIdx EQUAL 0) + math(EXPR filePathLength "${filePathLength} - ${rootDirLength}") + string(SUBSTRING "${filePath}" ${rootDirLength} ${filePathLength} fileGroup) + install(FILES ${fil} DESTINATION include/${rootName}${fileGroup}) + endif() + endforeach() +endfunction() + +function(folly_define_tests) + set(directory_count 0) + set(test_count 0) + set(currentArg 0) + while (currentArg LESS ${ARGC}) + if ("x${ARGV${currentArg}}" STREQUAL "xDIRECTORY") + math(EXPR currentArg "${currentArg} + 1") + if (NOT currentArg LESS ${ARGC}) + message(FATAL_ERROR "Expected base directory!") + endif() + + set(cur_dir ${directory_count}) + math(EXPR directory_count "${directory_count} + 1") + set(directory_${cur_dir}_name "${ARGV${currentArg}}") + # We need a single list of sources to get source_group to work nicely. + set(directory_${cur_dir}_source_list) + + math(EXPR currentArg "${currentArg} + 1") + while (currentArg LESS ${ARGC}) + if ("x${ARGV${currentArg}}" STREQUAL "xDIRECTORY") + break() + elseif ("x${ARGV${currentArg}}" STREQUAL "xTEST") + math(EXPR currentArg "${currentArg} + 1") + if (NOT currentArg LESS ${ARGC}) + message(FATAL_ERROR "Expected test name!") + endif() + + set(cur_test ${test_count}) + math(EXPR test_count "${test_count} + 1") + set(test_${cur_test}_name "${ARGV${currentArg}}") + math(EXPR currentArg "${currentArg} + 1") + set(test_${cur_test}_directory ${cur_dir}) + set(test_${cur_test}_content_dir) + set(test_${cur_test}_headers) + set(test_${cur_test}_sources) + set(test_${cur_test}_tag "NONE") + + set(argumentState 0) + while (currentArg LESS ${ARGC}) + if ("x${ARGV${currentArg}}" STREQUAL "xHEADERS") + set(argumentState 1) + elseif ("x${ARGV${currentArg}}" STREQUAL "xSOURCES") + set(argumentState 2) + elseif ("x${ARGV${currentArg}}" STREQUAL "xCONTENT_DIR") + math(EXPR currentArg "${currentArg} + 1") + if (NOT currentArg LESS ${ARGC}) + message(FATAL_ERROR "Expected content directory name!") + endif() + set(test_${cur_test}_content_dir "${ARGV${currentArg}}") + elseif ("x${ARGV${currentArg}}" STREQUAL "xTEST" OR + "x${ARGV${currentArg}}" STREQUAL "xDIRECTORY") + break() + elseif (argumentState EQUAL 0) + if ("x${ARGV${currentArg}}" STREQUAL "xHANGING") + set(test_${cur_test}_tag "HANGING") + elseif ("x${ARGV${currentArg}}" STREQUAL "xSLOW") + set(test_${cur_test}_tag "SLOW") + else() + message(FATAL_ERROR "Unknown test tag '${ARGV${currentArg}}'!") + endif() + elseif (argumentState EQUAL 1) + list(APPEND test_${cur_test}_headers + "${FOLLY_DIR}/${directory_${cur_dir}_name}${ARGV${currentArg}}" + ) + elseif (argumentState EQUAL 2) + list(APPEND test_${cur_test}_sources + "${FOLLY_DIR}/${directory_${cur_dir}_name}${ARGV${currentArg}}" + ) + else() + message(FATAL_ERROR "Unknown argument state!") + endif() + math(EXPR currentArg "${currentArg} + 1") + endwhile() + + list(APPEND directory_${cur_dir}_source_list + ${test_${cur_test}_sources} ${test_${cur_test}_headers}) + else() + message(FATAL_ERROR "Unknown argument inside directory '${ARGV${currentArg}}'!") + endif() + endwhile() + else() + message(FATAL_ERROR "Unknown argument '${ARGV${currentArg}}'!") + endif() + endwhile() + + set(cur_dir 0) + while (cur_dir LESS directory_count) + source_group("" FILES ${directory_${cur_dir}_source_list}) + math(EXPR cur_dir "${cur_dir} + 1") + endwhile() + + set(cur_test 0) + while (cur_test LESS test_count) + if ("x${test_${cur_test}_tag}" STREQUAL "xNONE" OR + ("x${test_${cur_test}_tag}" STREQUAL "xSLOW" AND BUILD_SLOW_TESTS) OR + ("x${test_${cur_test}_tag}" STREQUAL "xHANGING" AND BUILD_HANGING_TESTS) + ) + set(cur_test_name ${test_${cur_test}_name}) + set(cur_dir_name ${directory_${test_${cur_test}_directory}_name}) + add_executable(${cur_test_name} + ${test_${cur_test}_headers} + ${test_${cur_test}_sources} + ) + if (NOT "x${test_${cur_test}_content_dir}" STREQUAL "x") + # Copy the content directory to the output directory tree so that + # tests can be run easily from Visual Studio without having to change + # the working directory for each test individually. + file( + COPY "${FOLLY_DIR}/${cur_dir_name}${test_${cur_test}_content_dir}" + DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/folly/${cur_dir_name}${test_${cur_test}_content_dir}" + ) + add_custom_command(TARGET ${cur_test_name} POST_BUILD COMMAND + ${CMAKE_COMMAND} ARGS -E copy_directory + "${FOLLY_DIR}/${cur_dir_name}${test_${cur_test}_content_dir}" + "$/folly/${cur_dir_name}${test_${cur_test}_content_dir}" + COMMENT "Copying test content for ${cur_test_name}" VERBATIM + ) + endif() + # Strip the tailing test directory name for the folder name. + string(REPLACE "test/" "" test_dir_name "${cur_dir_name}") + set_property(TARGET ${cur_test_name} PROPERTY FOLDER "Tests/${test_dir_name}") + target_link_libraries(${cur_test_name} PRIVATE folly_test_support) + apply_folly_compile_options_to_target(${cur_test_name}) + endif() + math(EXPR cur_test "${cur_test} + 1") + endwhile() +endfunction() diff --git a/CMake/folly-config.h.cmake b/CMake/folly-config.h.cmake new file mode 100755 index 00000000..e3c13960 --- /dev/null +++ b/CMake/folly-config.h.cmake @@ -0,0 +1,42 @@ +/* + * Copyright 2016 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#define FOLLY_HAVE_LIBGFLAGS 1 +#define FOLLY_UNUSUAL_GFLAGS_NAMESPACE 1 +#define FOLLY_GFLAGS_NAMESPACE google + +#define FOLLY_HAVE_IFUNC 0 +#define FOLLY_HAVE_MALLOC_H 1 +#define FOLLY_HAVE_MEMRCHR 0 +#define FOLLY_HAVE_PREADV 0 +#define FOLLY_HAVE_PTHREAD_SPINLOCK_T 1 +#define FOLLY_HAVE_PWRITEV 0 +#define FOLLY_HAVE_SCHED_H 1 +#define FOLLY_HAVE_STD__IS_TRIVIALLY_COPYABLE 1 +#define FOLLY_HAVE_STD_THIS_THREAD_SLEEP_FOR 1 +#define FOLLY_HAVE_UNALIGNED_ACCESS 1 +#define FOLLY_HAVE_VLA 0 +#define FOLLY_HAVE_WEAK_SYMBOLS 0 + +#define FOLLY_VERSION "${PACKAGE_VERSION}" + +//#define FOLLY_HAVE_LIBLZ4 1 +//#define FOLLY_HAVE_LIBLZMA 1 +//#define FOLLY_HAVE_LIBSNAPPY 1 +//#define FOLLY_HAVE_LIBZ 1 +//#define FOLLY_HAVE_LIBZSTD 1 diff --git a/CMake/folly-deps.cmake b/CMake/folly-deps.cmake new file mode 100755 index 00000000..8f972c5f --- /dev/null +++ b/CMake/folly-deps.cmake @@ -0,0 +1,18 @@ +find_package(Boost 1.55.0 MODULE + COMPONENTS + context + chrono + date_time + filesystem + program_options + regex + system + thread + REQUIRED +) +find_package(DoubleConversion MODULE REQUIRED) +find_package(GFlags MODULE REQUIRED) +find_package(GLog MODULE REQUIRED) +find_package(LibEvent MODULE REQUIRED) +find_package(OpenSSL MODULE REQUIRED) +find_package(PThread MODULE REQUIRED) diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100755 index 00000000..030d1c7b --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,525 @@ +cmake_minimum_required(VERSION 3.4.0 FATAL_ERROR) + +# Unfortunately, CMake doesn't easily provide us a way to merge static +# libraries, which is what we want to do to generate the main folly library, so +# we do a bit of a workaround here to inject a property into the generated +# project files that will only get enabled for the folly target. Ugly, but +# the alternatives are far, far worse. +if ("${CMAKE_GENERATOR}" MATCHES "Visual Studio 15( 2017)? Win64") + set(CMAKE_GENERATOR_TOOLSET "v141truev141") +elseif ("${CMAKE_GENERATOR}" STREQUAL "Visual Studio 14 2015 Win64") + set(CMAKE_GENERATOR_TOOLSET "v140truev140") +else() + message(FATAL_ERROR "This build script only supports building Folly on 64-bit Windows with Visual Studio 2015 or Visual Studio 2017.") +endif() + +# includes +set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake" ${CMAKE_MODULE_PATH}) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +# package information +set(PACKAGE_NAME "folly") +set(PACKAGE_VERSION "0.58.0-dev") +set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") +set(PACKAGE_TARNAME "${PACKAGE_NAME}-${PACKAGE_VERSION}") +set(PACKAGE_BUGREPORT "https://github.com/facebook/folly/issues") + +# 150+ tests in the root folder anyone? No? I didn't think so. +set_property(GLOBAL PROPERTY USE_FOLDERS ON) + +project(${PACKAGE_NAME} CXX) + +# Check architecture OS +if (NOT CMAKE_SIZEOF_VOID_P EQUAL 8) + message(FATAL_ERROR "Folly requires a 64bit OS") +endif() +if(NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "Windows") + message(FATAL_ERROR "You should only be using CMake to build Folly if you are on Windows!") +endif() + +set(FOLLY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/folly") + +# Generate a few tables and create the main config file. +find_package(PythonInterp REQUIRED) +add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/folly/build/EscapeTables.cpp + COMMAND ${PYTHON_EXECUTABLE} "${FOLLY_DIR}/build/generate_escape_tables.py" + DEPENDS ${FOLLY_DIR}/build/generate_escape_tables.py + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/folly/build/ + COMMENT "Generating the escape tables..." VERBATIM +) +add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/folly/build/FormatTables.cpp + COMMAND ${PYTHON_EXECUTABLE} "${FOLLY_DIR}/build/generate_format_tables.py" + DEPENDS ${FOLLY_DIR}/build/generate_format_tables.py + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/folly/build/ + COMMENT "Generating the format tables..." VERBATIM +) +add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/folly/build/GroupVarintTables.cpp" + COMMAND ${PYTHON_EXECUTABLE} "${FOLLY_DIR}/build/generate_varint_tables.py" + DEPENDS ${FOLLY_DIR}/build/generate_varint_tables.py + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/folly/build/ + COMMENT "Generating the group varint tables..." VERBATIM +) +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/CMake/folly-config.h.cmake + ${CMAKE_CURRENT_BINARY_DIR}/folly/folly-config.h +) + +include(FollyCompiler) +include(FollyFunctions) + +# Main folly library files +auto_sources(files "*.cpp" "RECURSE" "${FOLLY_DIR}") +auto_sources(hfiles "*.h" "RECURSE" "${FOLLY_DIR}") + +# No need for tests or benchmarks, and we can't build most experimental stuff. +REMOVE_MATCHES_FROM_LISTS(files hfiles + MATCHES + "/build/" + "/experimental/exception_tracer/" + "/experimental/hazptr/example/" + "/experimental/symbolizer/" + "/futures/exercises/" + "/test/" + "Benchmark.cpp$" + "Test.cpp$" + IGNORE_MATCHES + "/Benchmark.cpp$" +) +list(REMOVE_ITEM files + ${FOLLY_DIR}/Subprocess.cpp + ${FOLLY_DIR}/SingletonStackTrace.cpp + ${FOLLY_DIR}/experimental/JSONSchemaTester.cpp + ${FOLLY_DIR}/experimental/RCUUtils.cpp + ${FOLLY_DIR}/experimental/io/AsyncIO.cpp + ${FOLLY_DIR}/experimental/io/HugePageUtil.cpp + ${FOLLY_DIR}/futures/test/Benchmark.cpp +) +list(REMOVE_ITEM hfiles + ${FOLLY_DIR}/Fingerprint.h + ${FOLLY_DIR}/detail/SlowFingerprint.h + ${FOLLY_DIR}/detail/FingerprintPolynomial.h + ${FOLLY_DIR}/experimental/RCURefCount.h + ${FOLLY_DIR}/experimental/RCUUtils.h + ${FOLLY_DIR}/experimental/io/AsyncIO.h +) + +add_library(folly_base STATIC + ${files} ${hfiles} + ${CMAKE_CURRENT_BINARY_DIR}/folly/folly-config.h + ${CMAKE_CURRENT_BINARY_DIR}/folly/build/EscapeTables.cpp + ${CMAKE_CURRENT_BINARY_DIR}/folly/build/FormatTables.cpp + ${CMAKE_CURRENT_BINARY_DIR}/folly/build/GroupVarintTables.cpp +) +auto_source_group(folly ${FOLLY_DIR} ${files} ${hfiles}) +apply_folly_compile_options_to_target(folly_base) +target_include_directories(folly_base PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) +# Add the generated files to the correct source group. +source_group("folly" FILES ${CMAKE_CURRENT_BINARY_DIR}/folly/folly-config.h) +source_group("folly\\build" FILES + ${CMAKE_CURRENT_BINARY_DIR}/folly/build/EscapeTables.cpp + ${CMAKE_CURRENT_BINARY_DIR}/folly/build/FingerprintTables.cpp + ${CMAKE_CURRENT_BINARY_DIR}/folly/build/FormatTables.cpp + ${CMAKE_CURRENT_BINARY_DIR}/folly/build/GroupVarintTables.cpp +) + +include(folly-deps) # Find the required packages +target_include_directories(folly_base + PUBLIC + ${DOUBLE_CONVERSION_INCLUDE_DIR} + ${LIBGFLAGS_INCLUDE_DIR} + ${LIBGLOG_INCLUDE_DIR} + ${LIBEVENT_INCLUDE_DIR} + ${LIBPTHREAD_INCLUDE_DIRS} +) +target_link_libraries(folly_base + PUBLIC + Boost::chrono + Boost::context + Boost::date_time + Boost::filesystem + Boost::program_options + Boost::regex + Boost::system + ${DOUBLE_CONVERSION_LIBRARY} + ${LIBEVENT_LIB} + ${LIBGFLAGS_LIBRARY} + ${LIBGLOG_LIBRARY} + ${LIBPTHREAD_LIBRARIES} + OpenSSL::SSL + OpenSSL::Crypto + Ws2_32.lib +) + +# Now to generate the fingerprint tables +add_executable(GenerateFingerprintTables + ${FOLLY_DIR}/build/GenerateFingerprintTables.cpp +) +apply_folly_compile_options_to_target(GenerateFingerprintTables) +set_property(TARGET GenerateFingerprintTables PROPERTY FOLDER "Build") +target_link_libraries(GenerateFingerprintTables PRIVATE folly_base) +source_group("" FILES ${FOLLY_DIR}/build/GenerateFingerprintTables.cpp) + +# Compile the fingerprint tables. +add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/folly/build/FingerprintTables.cpp + COMMAND GenerateFingerprintTables + DEPENDS GenerateFingerprintTables + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/folly/build/ + COMMENT "Generating the fingerprint tables..." +) +add_library(folly_fingerprint STATIC + ${CMAKE_CURRENT_BINARY_DIR}/folly/build/FingerprintTables.cpp + ${FOLLY_DIR}/Fingerprint.h + ${FOLLY_DIR}/detail/SlowFingerprint.h + ${FOLLY_DIR}/detail/FingerprintPolynomial.h +) +apply_folly_compile_options_to_target(folly_fingerprint) +target_link_libraries(folly_fingerprint PRIVATE folly_base) + +# We want to generate a single library and target for folly, but we needed a +# two-stage compile for the fingerprint tables, so we create a phony source +# file that we modify whenever the base libraries change, causing folly to be +# re-linked, making things happy. +add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/folly_dep.cpp + COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/folly_dep.cpp + DEPENDS folly_base folly_fingerprint +) +add_library(folly ${CMAKE_CURRENT_BINARY_DIR}/folly_dep.cpp) +apply_folly_compile_options_to_target(folly) +source_group("" FILES ${CMAKE_CURRENT_BINARY_DIR}/folly_dep.cpp) + +# Rather than list the dependencies in two places, we apply them directly on +# the folly_base target and then copy them over to the folly target. +get_target_property(FOLLY_LINK_LIBRARIES folly_base INTERFACE_LINK_LIBRARIES) +target_link_libraries(folly PUBLIC ${FOLLY_LINK_LIBRARIES}) +target_include_directories(folly PUBLIC $) + +install(TARGETS folly + EXPORT folly + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib) +auto_install_files(folly ${FOLLY_DIR} + ${hfiles} + ${FOLLY_DIR}/Fingerprint.h + ${FOLLY_DIR}/detail/SlowFingerprint.h + ${FOLLY_DIR}/detail/FingerprintPolynomial.h +) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/folly/folly-config.h DESTINATION include/folly) +install( + EXPORT folly + DESTINATION share/folly + NAMESPACE Folly:: + FILE folly-targets.cmake +) + +# We need a wrapper config file to do the find_package calls to ensure +# that all our dependencies are available to link against. +file( + COPY ${CMAKE_CURRENT_SOURCE_DIR}/CMake/folly-deps.cmake + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/ +) +file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/folly-deps.cmake "\ninclude(folly-targets.cmake)\n") +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/folly-deps.cmake DESTINATION share/folly RENAME folly-config.cmake) + +option(BUILD_TESTS "If enabled, compile the tests." OFF) +option(BUILD_HANGING_TESTS "If enabled, compile tests that are known to hang." OFF) +option(BUILD_SLOW_TESTS "If enabled, compile tests that take a while to run in debug mode." OFF) +if (BUILD_TESTS) + find_package(GMock MODULE REQUIRED) + + add_library(folly_test_support + ${FOLLY_DIR}/test/DeterministicSchedule.cpp + ${FOLLY_DIR}/test/DeterministicSchedule.h + ${FOLLY_DIR}/test/SingletonTestStructs.cpp + ${FOLLY_DIR}/test/SocketAddressTestHelper.cpp + ${FOLLY_DIR}/test/SocketAddressTestHelper.h + ${FOLLY_DIR}/io/async/test/BlockingSocket.h + ${FOLLY_DIR}/io/async/test/MockAsyncServerSocket.h + ${FOLLY_DIR}/io/async/test/MockAsyncSocket.h + ${FOLLY_DIR}/io/async/test/MockAsyncSSLSocket.h + ${FOLLY_DIR}/io/async/test/MockAsyncTransport.h + ${FOLLY_DIR}/io/async/test/MockAsyncUDPSocket.h + ${FOLLY_DIR}/io/async/test/MockTimeoutManager.h + ${FOLLY_DIR}/io/async/test/ScopedBoundPort.cpp + ${FOLLY_DIR}/io/async/test/ScopedBoundPort.h + ${FOLLY_DIR}/io/async/test/SocketPair.cpp + ${FOLLY_DIR}/io/async/test/SocketPair.h + ${FOLLY_DIR}/io/async/test/TestSSLServer.cpp + ${FOLLY_DIR}/io/async/test/TestSSLServer.h + ${FOLLY_DIR}/io/async/test/TimeUtil.cpp + ${FOLLY_DIR}/io/async/test/TimeUtil.h + ${FOLLY_DIR}/io/async/test/UndelayedDestruction.h + ${FOLLY_DIR}/io/async/test/Util.h + ) + target_include_directories(folly_test_support + PUBLIC + ${LIBGMOCK_INCLUDE_DIR} + ) + target_link_libraries(folly_test_support + PUBLIC + Boost::thread + folly + ${LIBGMOCK_LIBRARY} + ) + apply_folly_compile_options_to_target(folly_test_support) + + folly_define_tests( + DIRECTORY experimental/test/ + TEST autotimer_test SOURCES AutoTimerTest.cpp + TEST bits_test_2 SOURCES BitsTest.cpp + TEST bitvector_test SOURCES BitVectorCodingTest.cpp + TEST dynamic_parser_test SOURCES DynamicParserTest.cpp + TEST eliasfano_test SOURCES EliasFanoCodingTest.cpp + TEST event_count_test SOURCES EventCountTest.cpp + TEST function_scheduler_test_2 SOURCES FunctionSchedulerTest.cpp + TEST future_dag_test SOURCES FutureDAGTest.cpp + TEST json_schema_test SOURCES JSONSchemaTest.cpp + TEST lock_free_ring_buffer_test SOURCES LockFreeRingBufferTest.cpp + #TEST nested_command_line_app_test SOURCES NestedCommandLineAppTest.cpp + #TEST program_options_test SOURCES ProgramOptionsTest.cpp + # Depends on liburcu + #TEST read_mostly_shared_ptr_test SOURCES ReadMostlySharedPtrTest.cpp + #TEST ref_count_test SOURCES RefCountTest.cpp + TEST stringkeyed_test SOURCES StringKeyedTest.cpp + TEST test_util_test SOURCES TestUtilTest.cpp + TEST tuple_ops_test SOURCES TupleOpsTest.cpp + + DIRECTORY experimental/io/test/ + # Depends on libaio + #TEST async_io_test SOURCES AsyncIOTest.cpp + TEST fs_util_test SOURCES FsUtilTest.cpp + + DIRECTORY fibers/test/ + TEST fibers_test SOURCES FibersTest.cpp + + DIRECTORY futures/test/ + TEST futures-test + HEADERS + ThenCompileTest.h + SOURCES + BarrierTest.cpp + CollectTest.cpp + ContextTest.cpp + CoreTest.cpp + EnsureTest.cpp + ExecutorTest.cpp + FSMTest.cpp + FilterTest.cpp + # MSVC SFINAE bug + #FutureTest.cpp + HeaderCompileTest.cpp + InterruptTest.cpp + MapTest.cpp + NonCopyableLambdaTest.cpp + PollTest.cpp + PromiseTest.cpp + ReduceTest.cpp + # MSVC SFINAE bug + #RetryingTest.cpp + SelfDestructTest.cpp + SharedPromiseTest.cpp + ThenCompileTest.cpp + ThenTest.cpp + TimekeeperTest.cpp + TimesTest.cpp + UnwrapTest.cpp + ViaTest.cpp + WaitTest.cpp + WhenTest.cpp + WhileDoTest.cpp + WillEqualTest.cpp + WindowTest.cpp + + DIRECTORY gen/test/ + # MSVC bug can't resolve initializer_list constructor properly + #TEST base_test SOURCES BaseTest.cpp + TEST combine_test SOURCES CombineTest.cpp + TEST parallel_map_test SOURCES ParallelMapTest.cpp + TEST parallel_test SOURCES ParallelTest.cpp + + DIRECTORY io/test/ + TEST compression_test SOURCES CompressionTest.cpp + TEST iobuf_test SOURCES IOBufTest.cpp + TEST iobuf_cursor_test SOURCES IOBufCursorTest.cpp + TEST iobuf_queue_test SOURCES IOBufQueueTest.cpp + TEST record_io_test SOURCES RecordIOTest.cpp + TEST ShutdownSocketSetTest HANGING + SOURCES ShutdownSocketSetTest.cpp + + DIRECTORY io/async/test/ + TEST async_test + CONTENT_DIR certs/ + HEADERS + AsyncSocketTest.h + AsyncSSLSocketTest.h + SOURCES + AsyncPipeTest.cpp + AsyncSocketExceptionTest.cpp + AsyncSocketTest.cpp + AsyncSocketTest2.cpp + AsyncSSLSocketTest.cpp + AsyncSSLSocketTest2.cpp + AsyncSSLSocketWriteTest.cpp + AsyncTransportTest.cpp + # This is disabled because it depends on things that don't exist + # on Windows. + #EventHandlerTest.cpp + TEST async_timeout_test SOURCES AsyncTimeoutTest.cpp + TEST AsyncUDPSocketTest SOURCES AsyncUDPSocketTest.cpp + TEST DelayedDestructionTest SOURCES DelayedDestructionTest.cpp + TEST DelayedDestructionBaseTest SOURCES DelayedDestructionBaseTest.cpp + TEST EventBaseTest SOURCES EventBaseTest.cpp + TEST EventBaseLocalTest SOURCES EventBaseLocalTest.cpp + TEST HHWheelTimerTest SOURCES HHWheelTimerTest.cpp + TEST HHWheelTimerSlowTests SLOW + SOURCES HHWheelTimerSlowTests.cpp + TEST NotificationQueueTest SOURCES NotificationQueueTest.cpp + TEST RequestContextTest SOURCES RequestContextTest.cpp + TEST ScopedEventBaseThreadTest SOURCES ScopedEventBaseThreadTest.cpp + TEST ssl_session_test SOURCES SSLSessionTest.cpp + TEST writechain_test SOURCES WriteChainAsyncTransportWrapperTest.cpp + + DIRECTORY io/async/ssl/test/ + TEST ssl_errors_test SOURCES SSLErrorsTest.cpp + + DIRECTORY portability/test/ + TEST constexpr_test SOURCES ConstexprTest.cpp + TEST libgen-test SOURCES LibgenTest.cpp + TEST time-test SOURCES TimeTest.cpp + + DIRECTORY ssl/test/ + TEST openssl_hash_test SOURCES OpenSSLHashTest.cpp + + DIRECTORY test/ + TEST ahm_int_stress_test SOURCES AHMIntStressTest.cpp + TEST apply_tuple_test SOURCES ApplyTupleTest.cpp + TEST arena_test SOURCES ArenaTest.cpp + TEST arena_smartptr_test SOURCES ArenaSmartPtrTest.cpp + TEST array_test SOURCES ArrayTest.cpp + TEST ascii_check_test SOURCES AsciiCaseInsensitiveTest.cpp + TEST atomic_bit_set_test SOURCES AtomicBitSetTest.cpp + TEST atomic_hash_array_test SOURCES AtomicHashArrayTest.cpp + TEST atomic_hash_map_test HANGING + SOURCES AtomicHashMapTest.cpp + TEST atomic_linked_list_test SOURCES AtomicLinkedListTest.cpp + TEST atomic_struct_test SOURCES AtomicStructTest.cpp + TEST atomic_unordered_map_test SOURCES AtomicUnorderedMapTest.cpp + TEST baton_test SOURCES BatonTest.cpp + TEST bit_iterator_test SOURCES BitIteratorTest.cpp + TEST bits_test SOURCES BitsTest.cpp + TEST cache_locality_test SOURCES CacheLocalityTest.cpp + TEST cacheline_padded_test SOURCES CachelinePaddedTest.cpp + TEST call_once_test SOURCES CallOnceTest.cpp + TEST checksum_test SOURCES ChecksumTest.cpp + TEST clock_gettime_wrappers_test SOURCES ClockGettimeWrappersTest.cpp + TEST concurrent_skip_list_test SOURCES ConcurrentSkipListTest.cpp + TEST container_traits_test SOURCES ContainerTraitsTest.cpp + TEST conv_test SOURCES ConvTest.cpp + TEST cpu_id_test SOURCES CpuIdTest.cpp + TEST demangle_test SOURCES DemangleTest.cpp + TEST deterministic_schedule_test SOURCES DeterministicScheduleTest.cpp + TEST discriminated_ptr_test SOURCES DiscriminatedPtrTest.cpp + TEST dynamic_test SOURCES DynamicTest.cpp + TEST dynamic_converter_test SOURCES DynamicConverterTest.cpp + TEST dynamic_other_test SOURCES DynamicOtherTest.cpp + TEST endian_test SOURCES EndianTest.cpp + TEST enumerate_test SOURCES EnumerateTest.cpp + TEST evicting_cache_map_test SOURCES EvictingCacheMapTest.cpp + TEST exception_test SOURCES ExceptionTest.cpp + TEST exception_wrapper_test SOURCES ExceptionWrapperTest.cpp + TEST expected_test SOURCES ExpectedTest.cpp + TEST fbvector_test SOURCES FBVectorTest.cpp + TEST file_test SOURCES FileTest.cpp + #TEST file_lock_test SOURCES FileLockTest.cpp + TEST file_util_test HANGING + SOURCES FileUtilTest.cpp + TEST fingerprint_test SOURCES FingerprintTest.cpp + TEST foreach_test SOURCES ForeachTest.cpp + TEST format_other_test SOURCES FormatOtherTest.cpp + TEST format_test SOURCES FormatTest.cpp + TEST function_scheduler_test SOURCES FunctionSchedulerTest.cpp + TEST function_test SOURCES FunctionTest.cpp + TEST function_ref_test SOURCES FunctionRefTest.cpp + TEST futex_test SOURCES FutexTest.cpp + TEST group_varint_test SOURCES GroupVarintTest.cpp + TEST group_varint_test_ssse3 SOURCES GroupVarintTest.cpp + TEST has_member_fn_traits_test SOURCES HasMemberFnTraitsTest.cpp + TEST hash_test SOURCES HashTest.cpp + TEST histogram_test SOURCES HistogramTest.cpp + TEST indestructible_test SOURCES IndestructibleTest.cpp + TEST indexed_mem_pool_test SOURCES IndexedMemPoolTest.cpp + # MSVC Preprocessor stringizing raw string literals bug + #TEST json_test SOURCES JsonTest.cpp + TEST json_other_test + CONTENT_DIR json_test_data/ + SOURCES + JsonOtherTest.cpp + TEST lazy_test SOURCES LazyTest.cpp + TEST lifosem_test SOURCES LifoSemTests.cpp + TEST lock_traits_test SOURCES LockTraitsTest.cpp + TEST locks_test SOURCES SmallLocksTest.cpp SpinLockTest.cpp + TEST logging_test SOURCES LoggingTest.cpp + TEST mallctl_helper_test SOURCES MallctlHelperTest.cpp + TEST math_test SOURCES MathTest.cpp + TEST map_util_test SOURCES MapUtilTest.cpp + TEST memcpy_test SOURCES MemcpyTest.cpp + TEST memory_idler_test SOURCES MemoryIdlerTest.cpp + TEST memory_mapping_test SOURCES MemoryMappingTest.cpp + TEST memory_test SOURCES MemoryTest.cpp + TEST merge SOURCES MergeTest.cpp + TEST move_wrapper_test SOURCES MoveWrapperTest.cpp + TEST mpmc_pipeline_test SOURCES MPMCPipelineTest.cpp + TEST mpmc_queue_test SLOW + SOURCES MPMCQueueTest.cpp + TEST network_address_test HANGING + SOURCES + IPAddressTest.cpp + MacAddressTest.cpp + SocketAddressTest.cpp + TEST optional_test SOURCES OptionalTest.cpp + TEST packed_sync_ptr_test HANGING + SOURCES PackedSyncPtrTest.cpp + TEST padded_test SOURCES PaddedTest.cpp + TEST partial_test SOURCES PartialTest.cpp + TEST portability_test SOURCES PortabilityTest.cpp + TEST producer_consumer_queue_test SLOW + SOURCES ProducerConsumerQueueTest.cpp + TEST r_w_spin_lock_test SOURCES RWSpinLockTest.cpp + TEST random_test SOURCES RandomTest.cpp + TEST range_test SOURCES RangeTest.cpp + TEST safe_assert_test SOURCES SafeAssertTest.cpp + TEST scope_guard_test SOURCES ScopeGuardTest.cpp + # Heavily dependent on drand and srand48 + #TEST shared_mutex_test SOURCES SharedMutexTest.cpp + TEST shell_test SOURCES ShellTest.cpp + TEST singleton_test SOURCES SingletonTest.cpp + TEST singleton_test_global SOURCES SingletonTestGlobal.cpp + TEST singleton_thread_local_test SOURCES SingletonThreadLocalTest.cpp + TEST singletonvault_c_test SOURCES SingletonVaultCTest.cpp + TEST small_vector_test SOURCES small_vector_test.cpp + TEST sorted_vector_types_test SOURCES sorted_vector_test.cpp + TEST sparse_byte_set_test SOURCES SparseByteSetTest.cpp + TEST spooky_hash_v1_test SOURCES SpookyHashV1Test.cpp + TEST spooky_hash_v2_test SOURCES SpookyHashV2Test.cpp + TEST string_test SOURCES StringTest.cpp + #TEST subprocess_test SOURCES SubprocessTest.cpp + TEST synchronized_test SOURCES SynchronizedTest.cpp + TEST thread_cached_arena_test SOURCES ThreadCachedArenaTest.cpp + TEST thread_cached_int_test SOURCES ThreadCachedIntTest.cpp + TEST thread_local_test SOURCES ThreadLocalTest.cpp + TEST thread_name_test SOURCES ThreadNameTest.cpp + TEST timeout_queue_test SOURCES TimeoutQueueTest.cpp + TEST timeseries_histogram_test SOURCES TimeseriesHistogramTest.cpp + TEST timeseries_test SOURCES TimeseriesTest.cpp + TEST token_bucket_test SOURCES TokenBucketTest.cpp + TEST traits_test SOURCES TraitsTest.cpp + TEST try_test SOURCES TryTest.cpp + TEST unit_test SOURCES UnitTest.cpp + TEST uri_test SOURCES UriTest.cpp + TEST varint_test SOURCES VarintTest.cpp + ) +endif() -- 2.34.1