blob: 6eef485c2f45654742f657302f75ac299a248ac1 [file] [log] [blame]
James Kuszmaul48dd4c82021-10-27 20:04:08 -07001# Copyright 2019 Google Inc. All Rights Reserved.
2#
3# Redistribution and use in source and binary forms, with or without
4# modification, are permitted provided that the following conditions are
5# met:
6#
7# * Redistributions of source code must retain the above copyright
8# notice, this list of conditions and the following disclaimer.
9# * Redistributions in binary form must reproduce the above
10# copyright notice, this list of conditions and the following disclaimer
11# in the documentation and/or other materials provided with the
12# distribution.
13# * Neither the name of Google Inc. nor the names of its
14# contributors may be used to endorse or promote products derived from
15# this software without specific prior written permission.
16#
17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29cmake_minimum_required(VERSION 3.1)
30project(Snappy VERSION 1.1.9 LANGUAGES C CXX)
31
32# C++ standard can be overridden when this is used as a sub-project.
33if(NOT CMAKE_CXX_STANDARD)
34 # This project requires C++11.
35 set(CMAKE_CXX_STANDARD 11)
36 set(CMAKE_CXX_STANDARD_REQUIRED ON)
37 set(CMAKE_CXX_EXTENSIONS OFF)
38endif(NOT CMAKE_CXX_STANDARD)
39
40# https://github.com/izenecloud/cmake/blob/master/SetCompilerWarningAll.cmake
41if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
42 # Use the highest warning level for Visual Studio.
43 set(CMAKE_CXX_WARNING_LEVEL 4)
44 if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
45 string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
46 else(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
47 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
48 endif(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
49
50 # Disable C++ exceptions.
51 string(REGEX REPLACE "/EH[a-z]+" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
52 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHs-c-")
53 add_definitions(-D_HAS_EXCEPTIONS=0)
54
55 # Disable RTTI.
56 string(REGEX REPLACE "/GR" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
57 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GR-")
58else(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
59 # Use -Wall for clang and gcc.
60 if(NOT CMAKE_CXX_FLAGS MATCHES "-Wall")
61 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
62 endif(NOT CMAKE_CXX_FLAGS MATCHES "-Wall")
63
64 # Use -Wextra for clang and gcc.
65 if(NOT CMAKE_CXX_FLAGS MATCHES "-Wextra")
66 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra")
67 endif(NOT CMAKE_CXX_FLAGS MATCHES "-Wextra")
68
69 # Use -Werror for clang only.
70 if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
71 if(NOT CMAKE_CXX_FLAGS MATCHES "-Werror")
72 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
73 endif(NOT CMAKE_CXX_FLAGS MATCHES "-Werror")
74 endif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
75
76 # Disable C++ exceptions.
77 string(REGEX REPLACE "-fexceptions" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
78 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions")
79
80 # Disable RTTI.
81 string(REGEX REPLACE "-frtti" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
82 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
83endif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
84
85# BUILD_SHARED_LIBS is a standard CMake variable, but we declare it here to make
86# it prominent in the GUI.
87option(BUILD_SHARED_LIBS "Build shared libraries(DLLs)." OFF)
88
89option(SNAPPY_BUILD_TESTS "Build Snappy's own tests." ON)
90
91option(SNAPPY_BUILD_BENCHMARKS "Build Snappy's benchmarks" ON)
92
93option(SNAPPY_FUZZING_BUILD "Build Snappy for fuzzing." OFF)
94
95option(SNAPPY_REQUIRE_AVX "Target processors with AVX support." OFF)
96
97option(SNAPPY_REQUIRE_AVX2 "Target processors with AVX2 support." OFF)
98
99option(SNAPPY_INSTALL "Install Snappy's header and library" ON)
100
101include(TestBigEndian)
102test_big_endian(SNAPPY_IS_BIG_ENDIAN)
103
104include(CheckIncludeFile)
105check_include_file("sys/mman.h" HAVE_SYS_MMAN_H)
106check_include_file("sys/resource.h" HAVE_SYS_RESOURCE_H)
107check_include_file("sys/time.h" HAVE_SYS_TIME_H)
108check_include_file("sys/uio.h" HAVE_SYS_UIO_H)
109check_include_file("unistd.h" HAVE_UNISTD_H)
110check_include_file("windows.h" HAVE_WINDOWS_H)
111
112include(CheckLibraryExists)
113check_library_exists(z zlibVersion "" HAVE_LIBZ)
114check_library_exists(lzo2 lzo1x_1_15_compress "" HAVE_LIBLZO2)
115check_library_exists(lz4 LZ4_compress_default "" HAVE_LIBLZ4)
116
117include(CheckCXXCompilerFlag)
118CHECK_CXX_COMPILER_FLAG("/arch:AVX" HAVE_VISUAL_STUDIO_ARCH_AVX)
119CHECK_CXX_COMPILER_FLAG("/arch:AVX2" HAVE_VISUAL_STUDIO_ARCH_AVX2)
120CHECK_CXX_COMPILER_FLAG("-mavx" HAVE_CLANG_MAVX)
121CHECK_CXX_COMPILER_FLAG("-mbmi2" HAVE_CLANG_MBMI2)
122if(SNAPPY_REQUIRE_AVX2)
123 if(HAVE_VISUAL_STUDIO_ARCH_AVX2)
124 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:AVX2")
125 endif(HAVE_VISUAL_STUDIO_ARCH_AVX2)
126 if(HAVE_CLANG_MAVX)
127 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx")
128 endif(HAVE_CLANG_MAVX)
129 if(HAVE_CLANG_MBMI2)
130 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mbmi2")
131 endif(HAVE_CLANG_MBMI2)
132elseif (SNAPPY_REQUIRE_AVX)
133 if(HAVE_VISUAL_STUDIO_ARCH_AVX)
134 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:AVX")
135 endif(HAVE_VISUAL_STUDIO_ARCH_AVX)
136 if(HAVE_CLANG_MAVX)
137 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx")
138 endif(HAVE_CLANG_MAVX)
139endif(SNAPPY_REQUIRE_AVX2)
140
141# Used by googletest.
142check_cxx_compiler_flag(-Wno-missing-field-initializers
143 SNAPPY_HAVE_NO_MISSING_FIELD_INITIALIZERS)
144
145include(CheckCXXSourceCompiles)
146check_cxx_source_compiles("
147int main() {
148 return __builtin_expect(0, 1);
149}" HAVE_BUILTIN_EXPECT)
150
151check_cxx_source_compiles("
152int main() {
153 return __builtin_ctzll(0);
154}" HAVE_BUILTIN_CTZ)
155
156check_cxx_source_compiles("
157__attribute__((always_inline)) int zero() { return 0; }
158
159int main() {
160 return zero();
161}" HAVE_ATTRIBUTE_ALWAYS_INLINE)
162
163check_cxx_source_compiles("
164#include <tmmintrin.h>
165
166int main() {
167 const __m128i *src = 0;
168 __m128i dest;
169 const __m128i shuffle_mask = _mm_load_si128(src);
170 const __m128i pattern = _mm_shuffle_epi8(_mm_loadl_epi64(src), shuffle_mask);
171 _mm_storeu_si128(&dest, pattern);
172 return 0;
173}" SNAPPY_HAVE_SSSE3)
174
175check_cxx_source_compiles("
176#include <immintrin.h>
177int main() {
178 return _bzhi_u32(0, 1);
179}" SNAPPY_HAVE_BMI2)
180
181check_cxx_source_compiles("
182#include <arm_neon.h>
183int main() {
184 uint8_t val = 3, dup[8];
185 uint8x16_t v = vld1q_dup_u8(&val);
186 vst1q_u8(dup, v);
187 return 0;
188}" SNAPPY_HAVE_NEON)
189
190include(CheckSymbolExists)
191check_symbol_exists("mmap" "sys/mman.h" HAVE_FUNC_MMAP)
192check_symbol_exists("sysconf" "unistd.h" HAVE_FUNC_SYSCONF)
193
194configure_file(
195 "cmake/config.h.in"
196 "${PROJECT_BINARY_DIR}/config.h"
197)
198
199# We don't want to define HAVE_ macros in public headers. Instead, we use
200# CMake's variable substitution with 0/1 variables, which will be seen by the
201# preprocessor as constants.
202set(HAVE_SYS_UIO_H_01 ${HAVE_SYS_UIO_H})
203if(NOT HAVE_SYS_UIO_H_01)
204 set(HAVE_SYS_UIO_H_01 0)
205endif(NOT HAVE_SYS_UIO_H_01)
206
207if (SNAPPY_FUZZING_BUILD)
208 if (NOT "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
209 message(WARNING "Fuzzing builds are only supported with Clang")
210 endif (NOT "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
211
212 if(NOT CMAKE_CXX_FLAGS MATCHES "-fsanitize=address")
213 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
214 endif(NOT CMAKE_CXX_FLAGS MATCHES "-fsanitize=address")
215
216 if(NOT CMAKE_CXX_FLAGS MATCHES "-fsanitize=fuzzer-no-link")
217 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=fuzzer-no-link")
218 endif(NOT CMAKE_CXX_FLAGS MATCHES "-fsanitize=fuzzer-no-link")
219endif (SNAPPY_FUZZING_BUILD)
220
221configure_file(
222 "snappy-stubs-public.h.in"
223 "${PROJECT_BINARY_DIR}/snappy-stubs-public.h")
224
225add_library(snappy "")
226target_sources(snappy
227 PRIVATE
228 "snappy-internal.h"
229 "snappy-stubs-internal.h"
230 "snappy-c.cc"
231 "snappy-sinksource.cc"
232 "snappy-stubs-internal.cc"
233 "snappy.cc"
234 "${PROJECT_BINARY_DIR}/config.h"
235
236 # Only CMake 3.3+ supports PUBLIC sources in targets exported by "install".
237 $<$<VERSION_GREATER:CMAKE_VERSION,3.2>:PUBLIC>
238 $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/snappy-c.h>
239 $<INSTALL_INTERFACE:include/snappy-c.h>
240 $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/snappy-sinksource.h>
241 $<INSTALL_INTERFACE:include/snappy-sinksource.h>
242 $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/snappy.h>
243 $<INSTALL_INTERFACE:include/snappy.h>
244 $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/snappy-stubs-public.h>
245 $<INSTALL_INTERFACE:include/snappy-stubs-public.h>
246)
247target_include_directories(snappy
248 PUBLIC
249 $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}>
250 $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
251 $<INSTALL_INTERFACE:include>
252)
253set_target_properties(snappy
254 PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR})
255
256target_compile_definitions(snappy PRIVATE -DHAVE_CONFIG_H)
257if(BUILD_SHARED_LIBS)
258 set_target_properties(snappy PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON)
259endif(BUILD_SHARED_LIBS)
260
261if(SNAPPY_BUILD_TESTS OR SNAPPY_BUILD_BENCHMARKS)
262 add_library(snappy_test_support "")
263 target_sources(snappy_test_support
264 PRIVATE
265 "snappy-test.cc"
266 "snappy-test.h"
267 "snappy_test_data.cc"
268 "snappy_test_data.h"
269 "${PROJECT_BINARY_DIR}/config.h"
270 )
271
272 # Test files include snappy-test.h, HAVE_CONFIG_H must be defined.
273 target_compile_definitions(snappy_test_support PUBLIC -DHAVE_CONFIG_H)
274
275 target_link_libraries(snappy_test_support snappy)
276
277 if(HAVE_LIBZ)
278 target_link_libraries(snappy_test_support z)
279 endif(HAVE_LIBZ)
280 if(HAVE_LIBLZO2)
281 target_link_libraries(snappy_test_support lzo2)
282 endif(HAVE_LIBLZO2)
283 if(HAVE_LIBLZ4)
284 target_link_libraries(snappy_test_support lz4)
285 endif(HAVE_LIBLZ4)
286
287 target_include_directories(snappy_test_support
288 BEFORE PUBLIC
289 "${PROJECT_SOURCE_DIR}"
290 )
291endif(SNAPPY_BUILD_TESTS OR SNAPPY_BUILD_BENCHMARKS)
292
293if(SNAPPY_BUILD_TESTS)
294 enable_testing()
295
296 # Prevent overriding the parent project's compiler/linker settings on Windows.
297 set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
298 set(install_gtest OFF)
299 set(install_gmock OFF)
300 set(build_gmock ON)
301
302 # This project is tested using GoogleTest.
303 add_subdirectory("third_party/googletest")
304
305 # GoogleTest triggers a missing field initializers warning.
306 if(SNAPPY_HAVE_NO_MISSING_FIELD_INITIALIZERS)
307 set_property(TARGET gtest
308 APPEND PROPERTY COMPILE_OPTIONS -Wno-missing-field-initializers)
309 set_property(TARGET gmock
310 APPEND PROPERTY COMPILE_OPTIONS -Wno-missing-field-initializers)
311 endif(SNAPPY_HAVE_NO_MISSING_FIELD_INITIALIZERS)
312
313 add_executable(snappy_unittest "")
314 target_sources(snappy_unittest
315 PRIVATE
316 "snappy_unittest.cc"
317 )
318 target_link_libraries(snappy_unittest snappy_test_support gmock_main gtest)
319
320 add_test(
321 NAME snappy_unittest
322 WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
323 COMMAND "${PROJECT_BINARY_DIR}/snappy_unittest")
324
325 add_executable(snappy_test_tool "")
326 target_sources(snappy_test_tool
327 PRIVATE
328 "snappy_test_tool.cc"
329 )
330 target_link_libraries(snappy_test_tool snappy_test_support)
331endif(SNAPPY_BUILD_TESTS)
332
333if(SNAPPY_BUILD_BENCHMARKS)
334 add_executable(snappy_benchmark "")
335 target_sources(snappy_benchmark
336 PRIVATE
337 "snappy_benchmark.cc"
338 )
339 target_link_libraries(snappy_benchmark snappy_test_support benchmark_main)
340
341 # This project uses Google benchmark for benchmarking.
342 set(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "" FORCE)
343 set(BENCHMARK_ENABLE_EXCEPTIONS OFF CACHE BOOL "" FORCE)
344 add_subdirectory("third_party/benchmark")
345endif(SNAPPY_BUILD_BENCHMARKS)
346
347if(SNAPPY_FUZZING_BUILD)
348 add_executable(snappy_compress_fuzzer "")
349 target_sources(snappy_compress_fuzzer
350 PRIVATE "snappy_compress_fuzzer.cc"
351 )
352 target_link_libraries(snappy_compress_fuzzer snappy)
353 set_target_properties(snappy_compress_fuzzer
354 PROPERTIES LINK_FLAGS "-fsanitize=fuzzer"
355 )
356
357 add_executable(snappy_uncompress_fuzzer "")
358 target_sources(snappy_uncompress_fuzzer
359 PRIVATE "snappy_uncompress_fuzzer.cc"
360 )
361 target_link_libraries(snappy_uncompress_fuzzer snappy)
362 set_target_properties(snappy_uncompress_fuzzer
363 PROPERTIES LINK_FLAGS "-fsanitize=fuzzer"
364 )
365endif(SNAPPY_FUZZING_BUILD)
366
367# Must be included before CMAKE_INSTALL_INCLUDEDIR is used.
368include(GNUInstallDirs)
369
370if(SNAPPY_INSTALL)
371 install(TARGETS snappy
372 EXPORT SnappyTargets
373 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
374 LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
375 ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
376 )
377 install(
378 FILES
379 "snappy-c.h"
380 "snappy-sinksource.h"
381 "snappy.h"
382 "${PROJECT_BINARY_DIR}/snappy-stubs-public.h"
383 DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
384 )
385
386 include(CMakePackageConfigHelpers)
387 configure_package_config_file(
388 "cmake/${PROJECT_NAME}Config.cmake.in"
389 "${PROJECT_BINARY_DIR}/cmake/${PROJECT_NAME}Config.cmake"
390 INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
391 )
392 write_basic_package_version_file(
393 "${PROJECT_BINARY_DIR}/cmake/${PROJECT_NAME}ConfigVersion.cmake"
394 COMPATIBILITY SameMajorVersion
395 )
396 install(
397 EXPORT SnappyTargets
398 NAMESPACE Snappy::
399 DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
400 )
401 install(
402 FILES
403 "${PROJECT_BINARY_DIR}/cmake/${PROJECT_NAME}Config.cmake"
404 "${PROJECT_BINARY_DIR}/cmake/${PROJECT_NAME}ConfigVersion.cmake"
405 DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
406 )
407endif(SNAPPY_INSTALL)