# Copyright 2019 Google Inc. All Rights Reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. cmake_minimum_required(VERSION 3.1) project(Snappy VERSION 1.1.10 LANGUAGES C CXX) # C++ standard can be overridden when this is used as a sub-project. if(NOT CMAKE_CXX_STANDARD) # This project requires C++11. set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) endif(NOT CMAKE_CXX_STANDARD) # https://github.com/izenecloud/cmake/blob/master/SetCompilerWarningAll.cmake if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") # Use the highest warning level for Visual Studio. set(CMAKE_CXX_WARNING_LEVEL 4) if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]") string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") else(CMAKE_CXX_FLAGS MATCHES "/W[0-4]") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4") endif(CMAKE_CXX_FLAGS MATCHES "/W[0-4]") # Disable C++ exceptions. string(REGEX REPLACE "/EH[a-z]+" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHs-c-") add_definitions(-D_HAS_EXCEPTIONS=0) # Disable RTTI. string(REGEX REPLACE "/GR" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GR-") else(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") # Use -Wall for clang and gcc. if(NOT CMAKE_CXX_FLAGS MATCHES "-Wall") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") endif(NOT CMAKE_CXX_FLAGS MATCHES "-Wall") # Use -Wextra for clang and gcc. if(NOT CMAKE_CXX_FLAGS MATCHES "-Wextra") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra") endif(NOT CMAKE_CXX_FLAGS MATCHES "-Wextra") # Use -Werror for clang only. if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") if(NOT CMAKE_CXX_FLAGS MATCHES "-Werror") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror") endif(NOT CMAKE_CXX_FLAGS MATCHES "-Werror") endif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") # Disable sign comparison warnings. Matches upcoming Bazel setup. if(NOT CMAKE_CXX_FLAGS MATCHES "-Wno-sign-compare") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-sign-compare") endif(NOT CMAKE_CXX_FLAGS MATCHES "-Wno-sign-compare") # Disable C++ exceptions. string(REGEX REPLACE "-fexceptions" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions") # Disable RTTI. string(REGEX REPLACE "-frtti" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti") endif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") # BUILD_SHARED_LIBS is a standard CMake variable, but we declare it here to make # it prominent in the GUI. option(BUILD_SHARED_LIBS "Build shared libraries(DLLs)." OFF) option(SNAPPY_BUILD_TESTS "Build Snappy's own tests." ON) option(SNAPPY_BUILD_BENCHMARKS "Build Snappy's benchmarks" ON) option(SNAPPY_FUZZING_BUILD "Build Snappy for fuzzing." OFF) option(SNAPPY_REQUIRE_AVX "Target processors with AVX support." OFF) option(SNAPPY_REQUIRE_AVX2 "Target processors with AVX2 support." OFF) option(SNAPPY_INSTALL "Install Snappy's header and library" ON) include(TestBigEndian) test_big_endian(SNAPPY_IS_BIG_ENDIAN) include(CheckIncludeFile) check_include_file("sys/mman.h" HAVE_SYS_MMAN_H) check_include_file("sys/resource.h" HAVE_SYS_RESOURCE_H) check_include_file("sys/time.h" HAVE_SYS_TIME_H) check_include_file("sys/uio.h" HAVE_SYS_UIO_H) check_include_file("unistd.h" HAVE_UNISTD_H) check_include_file("windows.h" HAVE_WINDOWS_H) include(CheckLibraryExists) check_library_exists(z zlibVersion "" HAVE_LIBZ) check_library_exists(lzo2 lzo1x_1_15_compress "" HAVE_LIBLZO2) check_library_exists(lz4 LZ4_compress_default "" HAVE_LIBLZ4) include(CheckCXXCompilerFlag) CHECK_CXX_COMPILER_FLAG("/arch:AVX" HAVE_VISUAL_STUDIO_ARCH_AVX) CHECK_CXX_COMPILER_FLAG("/arch:AVX2" HAVE_VISUAL_STUDIO_ARCH_AVX2) CHECK_CXX_COMPILER_FLAG("-mavx" HAVE_CLANG_MAVX) CHECK_CXX_COMPILER_FLAG("-mbmi2" HAVE_CLANG_MBMI2) if(SNAPPY_REQUIRE_AVX2) if(HAVE_VISUAL_STUDIO_ARCH_AVX2) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:AVX2") endif(HAVE_VISUAL_STUDIO_ARCH_AVX2) if(HAVE_CLANG_MAVX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx") endif(HAVE_CLANG_MAVX) if(HAVE_CLANG_MBMI2) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mbmi2") endif(HAVE_CLANG_MBMI2) elseif (SNAPPY_REQUIRE_AVX) if(HAVE_VISUAL_STUDIO_ARCH_AVX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:AVX") endif(HAVE_VISUAL_STUDIO_ARCH_AVX) if(HAVE_CLANG_MAVX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx") endif(HAVE_CLANG_MAVX) endif(SNAPPY_REQUIRE_AVX2) # Used by googletest. check_cxx_compiler_flag(-Wno-missing-field-initializers SNAPPY_HAVE_NO_MISSING_FIELD_INITIALIZERS) check_cxx_compiler_flag(-Wno-implicit-int-float-conversion SNAPPY_HAVE_NO_IMPLICIT_INT_FLOAT_CONVERSION) include(CheckCXXSourceCompiles) check_cxx_source_compiles(" int main() { return __builtin_expect(0, 1); }" HAVE_BUILTIN_EXPECT) check_cxx_source_compiles(" int main() { return __builtin_ctzll(0); }" HAVE_BUILTIN_CTZ) check_cxx_source_compiles(" int main() { __builtin_prefetch(0, 0, 3); return 0; }" HAVE_BUILTIN_PREFETCH) check_cxx_source_compiles(" __attribute__((always_inline)) int zero() { return 0; } int main() { return zero(); }" HAVE_ATTRIBUTE_ALWAYS_INLINE) check_cxx_source_compiles(" #include int main() { const __m128i *src = 0; __m128i dest; const __m128i shuffle_mask = _mm_load_si128(src); const __m128i pattern = _mm_shuffle_epi8(_mm_loadl_epi64(src), shuffle_mask); _mm_storeu_si128(&dest, pattern); return 0; }" SNAPPY_HAVE_SSSE3) check_cxx_source_compiles(" #include int main() { return _mm_crc32_u32(0, 1); }" SNAPPY_HAVE_X86_CRC32) check_cxx_source_compiles(" #include #include int main() { return __crc32cw(0, 1); }" SNAPPY_HAVE_NEON_CRC32) check_cxx_source_compiles(" #include int main() { return _bzhi_u32(0, 1); }" SNAPPY_HAVE_BMI2) check_cxx_source_compiles(" #include int main() { uint8_t val = 3, dup[8]; uint8x16_t v = vld1q_dup_u8(&val); vst1q_u8(dup, v); return 0; }" SNAPPY_HAVE_NEON) include(CheckSymbolExists) check_symbol_exists("mmap" "sys/mman.h" HAVE_FUNC_MMAP) check_symbol_exists("sysconf" "unistd.h" HAVE_FUNC_SYSCONF) configure_file( "cmake/config.h.in" "${PROJECT_BINARY_DIR}/config.h" ) # We don't want to define HAVE_ macros in public headers. Instead, we use # CMake's variable substitution with 0/1 variables, which will be seen by the # preprocessor as constants. set(HAVE_SYS_UIO_H_01 ${HAVE_SYS_UIO_H}) if(NOT HAVE_SYS_UIO_H_01) set(HAVE_SYS_UIO_H_01 0) endif(NOT HAVE_SYS_UIO_H_01) if (SNAPPY_FUZZING_BUILD) if (NOT "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") message(WARNING "Fuzzing builds are only supported with Clang") endif (NOT "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") if(NOT CMAKE_CXX_FLAGS MATCHES "-fsanitize=address") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") endif(NOT CMAKE_CXX_FLAGS MATCHES "-fsanitize=address") if(NOT CMAKE_CXX_FLAGS MATCHES "-fsanitize=fuzzer-no-link") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=fuzzer-no-link") endif(NOT CMAKE_CXX_FLAGS MATCHES "-fsanitize=fuzzer-no-link") endif (SNAPPY_FUZZING_BUILD) configure_file( "snappy-stubs-public.h.in" "${PROJECT_BINARY_DIR}/snappy-stubs-public.h") add_library(snappy "") target_sources(snappy PRIVATE "snappy-internal.h" "snappy-stubs-internal.h" "snappy-c.cc" "snappy-sinksource.cc" "snappy-stubs-internal.cc" "snappy.cc" "${PROJECT_BINARY_DIR}/config.h" # Only CMake 3.3+ supports PUBLIC sources in targets exported by "install". $<$:PUBLIC> $ $ $ $ $ $ $ $ ) target_include_directories(snappy PUBLIC $ $ $ ) set_target_properties(snappy PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR}) target_compile_definitions(snappy PRIVATE -DHAVE_CONFIG_H) if(BUILD_SHARED_LIBS) set_target_properties(snappy PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON) endif(BUILD_SHARED_LIBS) if(SNAPPY_BUILD_TESTS OR SNAPPY_BUILD_BENCHMARKS) add_library(snappy_test_support "") target_sources(snappy_test_support PRIVATE "snappy-test.cc" "snappy-test.h" "snappy_test_data.cc" "snappy_test_data.h" "${PROJECT_BINARY_DIR}/config.h" ) # Test files include snappy-test.h, HAVE_CONFIG_H must be defined. target_compile_definitions(snappy_test_support PUBLIC -DHAVE_CONFIG_H) target_link_libraries(snappy_test_support snappy) if(HAVE_LIBZ) target_link_libraries(snappy_test_support z) endif(HAVE_LIBZ) if(HAVE_LIBLZO2) target_link_libraries(snappy_test_support lzo2) endif(HAVE_LIBLZO2) if(HAVE_LIBLZ4) target_link_libraries(snappy_test_support lz4) endif(HAVE_LIBLZ4) target_include_directories(snappy_test_support BEFORE PUBLIC "${PROJECT_SOURCE_DIR}" ) endif(SNAPPY_BUILD_TESTS OR SNAPPY_BUILD_BENCHMARKS) if(SNAPPY_BUILD_TESTS) enable_testing() # Prevent overriding the parent project's compiler/linker settings on Windows. set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) set(install_gtest OFF) set(install_gmock OFF) set(build_gmock ON) # This project is tested using GoogleTest. add_subdirectory("third_party/googletest") # GoogleTest triggers a missing field initializers warning. if(SNAPPY_HAVE_NO_MISSING_FIELD_INITIALIZERS) set_property(TARGET gtest APPEND PROPERTY COMPILE_OPTIONS -Wno-missing-field-initializers) set_property(TARGET gmock APPEND PROPERTY COMPILE_OPTIONS -Wno-missing-field-initializers) endif(SNAPPY_HAVE_NO_MISSING_FIELD_INITIALIZERS) if(SNAPPY_HAVE_NO_IMPLICIT_INT_FLOAT_CONVERSION) set_property(TARGET gtest APPEND PROPERTY COMPILE_OPTIONS -Wno-implicit-int-float-conversion) endif(SNAPPY_HAVE_NO_IMPLICIT_INT_FLOAT_CONVERSION) add_executable(snappy_unittest "") target_sources(snappy_unittest PRIVATE "snappy_unittest.cc" ) target_link_libraries(snappy_unittest snappy_test_support gmock_main gtest) add_test( NAME snappy_unittest WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}" COMMAND "${PROJECT_BINARY_DIR}/snappy_unittest") add_executable(snappy_test_tool "") target_sources(snappy_test_tool PRIVATE "snappy_test_tool.cc" ) target_link_libraries(snappy_test_tool snappy_test_support) endif(SNAPPY_BUILD_TESTS) if(SNAPPY_BUILD_BENCHMARKS) add_executable(snappy_benchmark "") target_sources(snappy_benchmark PRIVATE "snappy_benchmark.cc" ) target_link_libraries(snappy_benchmark snappy_test_support benchmark_main) # This project uses Google benchmark for benchmarking. set(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "" FORCE) set(BENCHMARK_ENABLE_EXCEPTIONS OFF CACHE BOOL "" FORCE) add_subdirectory("third_party/benchmark") endif(SNAPPY_BUILD_BENCHMARKS) if(SNAPPY_FUZZING_BUILD) add_executable(snappy_compress_fuzzer "") target_sources(snappy_compress_fuzzer PRIVATE "snappy_compress_fuzzer.cc" ) target_link_libraries(snappy_compress_fuzzer snappy) set_target_properties(snappy_compress_fuzzer PROPERTIES LINK_FLAGS "-fsanitize=fuzzer" ) add_executable(snappy_uncompress_fuzzer "") target_sources(snappy_uncompress_fuzzer PRIVATE "snappy_uncompress_fuzzer.cc" ) target_link_libraries(snappy_uncompress_fuzzer snappy) set_target_properties(snappy_uncompress_fuzzer PROPERTIES LINK_FLAGS "-fsanitize=fuzzer" ) endif(SNAPPY_FUZZING_BUILD) # Must be included before CMAKE_INSTALL_INCLUDEDIR is used. include(GNUInstallDirs) if(SNAPPY_INSTALL) install(TARGETS snappy EXPORT SnappyTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) install( FILES "snappy-c.h" "snappy-sinksource.h" "snappy.h" "${PROJECT_BINARY_DIR}/snappy-stubs-public.h" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" ) include(CMakePackageConfigHelpers) configure_package_config_file( "cmake/${PROJECT_NAME}Config.cmake.in" "${PROJECT_BINARY_DIR}/cmake/${PROJECT_NAME}Config.cmake" INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" ) write_basic_package_version_file( "${PROJECT_BINARY_DIR}/cmake/${PROJECT_NAME}ConfigVersion.cmake" COMPATIBILITY SameMajorVersion ) install( EXPORT SnappyTargets NAMESPACE Snappy:: DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" ) install( FILES "${PROJECT_BINARY_DIR}/cmake/${PROJECT_NAME}Config.cmake" "${PROJECT_BINARY_DIR}/cmake/${PROJECT_NAME}ConfigVersion.cmake" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" ) endif(SNAPPY_INSTALL)