xref: /aosp_15_r20/external/webrtc/third_party/crc32c/src/CMakeLists.txt (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1# Copyright 2017 The CRC32C Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file. See the AUTHORS file for names of contributors.
4
5cmake_minimum_required(VERSION 3.1)
6project(Crc32c VERSION 1.1.0 LANGUAGES C CXX)
7
8# C standard can be overridden when this is used as a sub-project.
9if(NOT CMAKE_C_STANDARD)
10  # This project can use C11, but will gracefully decay down to C89.
11  set(CMAKE_C_STANDARD 11)
12  set(CMAKE_C_STANDARD_REQUIRED OFF)
13  set(CMAKE_C_EXTENSIONS OFF)
14endif(NOT CMAKE_C_STANDARD)
15
16# C++ standard can be overridden when this is used as a sub-project.
17if(NOT CMAKE_CXX_STANDARD)
18  # This project requires C++11.
19  set(CMAKE_CXX_STANDARD 11)
20  set(CMAKE_CXX_STANDARD_REQUIRED ON)
21  set(CMAKE_CXX_EXTENSIONS OFF)
22endif(NOT CMAKE_CXX_STANDARD)
23
24# https://github.com/izenecloud/cmake/blob/master/SetCompilerWarningAll.cmake
25if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
26  # Use the highest warning level for Visual Studio.
27  set(CMAKE_CXX_WARNING_LEVEL 4)
28  if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
29    string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
30  else(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
31    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
32  endif(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
33
34  # Disable C++ exceptions.
35  string(REGEX REPLACE "/EH[a-z]+" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
36  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHs-c-")
37  add_definitions(-D_HAS_EXCEPTIONS=0)
38
39  # Disable RTTI.
40  string(REGEX REPLACE "/GR" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
41  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GR-")
42else(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
43  # Use -Wall for clang and gcc.
44  if(NOT CMAKE_CXX_FLAGS MATCHES "-Wall")
45    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
46  endif(NOT CMAKE_CXX_FLAGS MATCHES "-Wall")
47
48  # Use -Wextra for clang and gcc.
49  if(NOT CMAKE_CXX_FLAGS MATCHES "-Wextra")
50    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra")
51  endif(NOT CMAKE_CXX_FLAGS MATCHES "-Wextra")
52
53  # Use -Werror for clang and gcc.
54  if(NOT CMAKE_CXX_FLAGS MATCHES "-Werror")
55    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
56  endif(NOT CMAKE_CXX_FLAGS MATCHES "-Werror")
57
58  # Disable C++ exceptions.
59  string(REGEX REPLACE "-fexceptions" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
60  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions")
61
62  # Disable RTTI.
63  string(REGEX REPLACE "-frtti" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
64  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
65endif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
66
67option(CRC32C_BUILD_TESTS "Build CRC32C's unit tests" ON)
68option(CRC32C_BUILD_BENCHMARKS "Build CRC32C's benchmarks" ON)
69option(CRC32C_USE_GLOG "Build CRC32C's tests with Google Logging" ON)
70option(CRC32C_INSTALL "Install CRC32C's header and library" ON)
71
72include(TestBigEndian)
73test_big_endian(BYTE_ORDER_BIG_ENDIAN)
74
75include(CheckCXXCompilerFlag)
76# Used by glog.
77check_cxx_compiler_flag(-Wno-deprecated CRC32C_HAVE_NO_DEPRECATED)
78# Used by glog.
79check_cxx_compiler_flag(-Wno-sign-compare CRC32C_HAVE_NO_SIGN_COMPARE)
80# Used by glog.
81check_cxx_compiler_flag(-Wno-unused-parameter CRC32C_HAVE_NO_UNUSED_PARAMETER)
82# Used by googletest.
83check_cxx_compiler_flag(-Wno-missing-field-initializers
84                        CRC32C_HAVE_NO_MISSING_FIELD_INITIALIZERS)
85
86# Check for __builtin_prefetch support in the compiler.
87include(CheckCXXSourceCompiles)
88check_cxx_source_compiles("
89int main() {
90  char data = 0;
91  const char* address = &data;
92  __builtin_prefetch(address, 0, 0);
93  return 0;
94}
95"  HAVE_BUILTIN_PREFETCH)
96
97# Check for _mm_prefetch support in the compiler.
98include(CheckCXXSourceCompiles)
99check_cxx_source_compiles("
100#if defined(_MSC_VER)
101#include <intrin.h>
102#else  // !defined(_MSC_VER)
103#include <xmmintrin.h>
104#endif  // defined(_MSC_VER)
105
106int main() {
107  char data = 0;
108  const char* address = &data;
109  _mm_prefetch(address, _MM_HINT_NTA);
110  return 0;
111}
112"  HAVE_MM_PREFETCH)
113
114# Check for SSE4.2 support in the compiler.
115set(OLD_CMAKE_REQURED_FLAGS ${CMAKE_REQUIRED_FLAGS})
116if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
117  set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} /arch:AVX")
118else(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
119  set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -msse4.2")
120endif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
121check_cxx_source_compiles("
122#if defined(_MSC_VER)
123#include <intrin.h>
124#else  // !defined(_MSC_VER)
125#include <cpuid.h>
126#include <nmmintrin.h>
127#endif  // defined(_MSC_VER)
128
129int main() {
130  _mm_crc32_u8(0, 0); _mm_crc32_u32(0, 0);
131#if defined(_M_X64) || defined(__x86_64__)
132   _mm_crc32_u64(0, 0);
133#endif // defined(_M_X64) || defined(__x86_64__)
134  return 0;
135}
136"  HAVE_SSE42)
137set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQURED_FLAGS})
138
139# Check for ARMv8 w/ CRC and CRYPTO extensions support in the compiler.
140set(OLD_CMAKE_REQURED_FLAGS ${CMAKE_REQUIRED_FLAGS})
141if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
142  # TODO(pwnall): Insert correct flag when VS gets ARM CRC32C support.
143  set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} /arch:NOTYET")
144else(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
145  set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -march=armv8-a+crc+crypto")
146endif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
147check_cxx_source_compiles("
148#include <arm_acle.h>
149#include <arm_neon.h>
150
151int main() {
152  __crc32cb(0, 0); __crc32ch(0, 0); __crc32cw(0, 0); __crc32cd(0, 0);
153  vmull_p64(0, 0);
154  return 0;
155}
156" HAVE_ARM64_CRC32C)
157set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQURED_FLAGS})
158
159# Check for strong getauxval() support in the system headers.
160check_cxx_source_compiles("
161#include <arm_acle.h>
162#include <arm_neon.h>
163#include <sys/auxv.h>
164
165int main() {
166  getauxval(AT_HWCAP);
167  return 0;
168}
169" HAVE_STRONG_GETAUXVAL)
170
171# Check for weak getauxval() support in the compiler.
172check_cxx_source_compiles("
173unsigned long getauxval(unsigned long type) __attribute__((weak));
174#define AT_HWCAP 16
175
176int main() {
177  getauxval(AT_HWCAP);
178  return 0;
179}
180" HAVE_WEAK_GETAUXVAL)
181
182if(CRC32C_USE_GLOG)
183  # glog requires this setting to avoid using dynamic_cast.
184  set(DISABLE_RTTI ON CACHE BOOL "" FORCE)
185
186  # glog's test targets trigger deprecation warnings, and compiling them burns
187  # CPU cycles on the CI.
188  set(BUILD_TESTING_SAVED "${BUILD_TESTING}")
189  set(BUILD_TESTING OFF CACHE BOOL "" FORCE)
190  add_subdirectory("third_party/glog" EXCLUDE_FROM_ALL)
191  set(BUILD_TESTING "${BUILD_TESTING_SAVED}" CACHE BOOL "" FORCE)
192
193  # glog triggers deprecation warnings on OSX.
194  # https://github.com/google/glog/issues/185
195  if(CRC32C_HAVE_NO_DEPRECATED)
196    set_property(TARGET glog APPEND PROPERTY COMPILE_OPTIONS -Wno-deprecated)
197  endif(CRC32C_HAVE_NO_DEPRECATED)
198
199  # glog triggers sign comparison warnings on gcc.
200  if(CRC32C_HAVE_NO_SIGN_COMPARE)
201    set_property(TARGET glog APPEND PROPERTY COMPILE_OPTIONS -Wno-sign-compare)
202  endif(CRC32C_HAVE_NO_SIGN_COMPARE)
203
204  # glog triggers unused parameter warnings on clang.
205  if(CRC32C_HAVE_NO_UNUSED_PARAMETER)
206    set_property(TARGET glog
207                 APPEND PROPERTY COMPILE_OPTIONS -Wno-unused-parameter)
208  endif(CRC32C_HAVE_NO_UNUSED_PARAMETER)
209
210  set(CRC32C_TESTS_BUILT_WITH_GLOG 1)
211endif(CRC32C_USE_GLOG)
212
213configure_file(
214  "src/crc32c_config.h.in"
215  "${PROJECT_BINARY_DIR}/include/crc32c/crc32c_config.h"
216)
217
218include_directories("${PROJECT_BINARY_DIR}/include")
219
220# ARM64 CRC32C code is built separately, so we don't accidentally compile
221# unsupported instructions into code that gets run without ARM32 support.
222add_library(crc32c_arm64 OBJECT "")
223target_sources(crc32c_arm64
224  PRIVATE
225    "${PROJECT_BINARY_DIR}/include/crc32c/crc32c_config.h"
226    "src/crc32c_arm64.cc"
227    "src/crc32c_arm64.h"
228)
229if(HAVE_ARM64_CRC32C)
230  if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
231    # TODO(pwnall): Insert correct flag when VS gets ARM64 CRC32C support.
232    target_compile_options(crc32c_arm64 PRIVATE "/arch:NOTYET")
233  else(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
234    target_compile_options(crc32c_arm64 PRIVATE "-march=armv8-a+crc+crypto")
235  endif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
236endif(HAVE_ARM64_CRC32C)
237
238# CMake only enables PIC by default in SHARED and MODULE targets.
239if(BUILD_SHARED_LIBS)
240  set_property(TARGET crc32c_arm64 PROPERTY POSITION_INDEPENDENT_CODE TRUE)
241endif(BUILD_SHARED_LIBS)
242
243# SSE4.2 code is built separately, so we don't accidentally compile unsupported
244# instructions into code that gets run without SSE4.2 support.
245add_library(crc32c_sse42 OBJECT "")
246target_sources(crc32c_sse42
247  PRIVATE
248    "${PROJECT_BINARY_DIR}/include/crc32c/crc32c_config.h"
249    "src/crc32c_sse42.cc"
250    "src/crc32c_sse42.h"
251)
252if(HAVE_SSE42)
253  if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
254    target_compile_options(crc32c_sse42 PRIVATE "/arch:AVX")
255  else(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
256    target_compile_options(crc32c_sse42 PRIVATE "-msse4.2")
257  endif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
258endif(HAVE_SSE42)
259
260# CMake only enables PIC by default in SHARED and MODULE targets.
261if(BUILD_SHARED_LIBS)
262  set_property(TARGET crc32c_sse42 PROPERTY POSITION_INDEPENDENT_CODE TRUE)
263endif(BUILD_SHARED_LIBS)
264
265# Must be included before CMAKE_INSTALL_INCLUDEDIR is used.
266include(GNUInstallDirs)
267
268add_library(crc32c ""
269  # TODO(pwnall): Move the TARGET_OBJECTS generator expressions to the PRIVATE
270  # section of target_sources when cmake_minimum_required becomes 3.9 or above.
271  $<TARGET_OBJECTS:crc32c_arm64>
272  $<TARGET_OBJECTS:crc32c_sse42>
273)
274target_sources(crc32c
275  PRIVATE
276    "${PROJECT_BINARY_DIR}/include/crc32c/crc32c_config.h"
277    "src/crc32c_arm64.h"
278    "src/crc32c_arm64_check.h"
279    "src/crc32c_internal.h"
280    "src/crc32c_portable.cc"
281    "src/crc32c_prefetch.h"
282    "src/crc32c_read_le.h"
283    "src/crc32c_round_up.h"
284    "src/crc32c_sse42.h"
285    "src/crc32c_sse42_check.h"
286    "src/crc32c.cc"
287
288  # Only CMake 3.3+ supports PUBLIC sources in targets exported by "install".
289  $<$<VERSION_GREATER:CMAKE_VERSION,3.2>:PUBLIC>
290    "include/crc32c/crc32c.h"
291)
292
293target_include_directories(crc32c
294  PUBLIC
295    $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
296    $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
297)
298
299set_target_properties(crc32c
300  PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR})
301
302# Warnings as errors in Visual Studio for this project's targets.
303if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
304  set_property(TARGET crc32c APPEND PROPERTY COMPILE_OPTIONS "/WX")
305  set_property(TARGET crc32c_arm64 APPEND PROPERTY COMPILE_OPTIONS "/WX")
306  set_property(TARGET crc32c_sse42 APPEND PROPERTY COMPILE_OPTIONS "/WX")
307endif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
308
309if(CRC32C_BUILD_TESTS)
310  enable_testing()
311
312  # Prevent overriding the parent project's compiler/linker settings on Windows.
313  set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
314  set(install_gtest OFF)
315  set(install_gmock OFF)
316
317  # This project is tested using GoogleTest.
318  add_subdirectory("third_party/googletest")
319
320  # GoogleTest triggers a missing field initializers warning.
321  if(CRC32C_HAVE_NO_MISSING_FIELD_INITIALIZERS)
322    set_property(TARGET gtest
323        APPEND PROPERTY COMPILE_OPTIONS -Wno-missing-field-initializers)
324    set_property(TARGET gmock
325        APPEND PROPERTY COMPILE_OPTIONS -Wno-missing-field-initializers)
326  endif(CRC32C_HAVE_NO_MISSING_FIELD_INITIALIZERS)
327
328  add_executable(crc32c_tests "")
329  target_sources(crc32c_tests
330    PRIVATE
331      "${PROJECT_BINARY_DIR}/include/crc32c/crc32c_config.h"
332      "src/crc32c_arm64_unittest.cc"
333      "src/crc32c_extend_unittests.h"
334      "src/crc32c_portable_unittest.cc"
335      "src/crc32c_prefetch_unittest.cc"
336      "src/crc32c_read_le_unittest.cc"
337      "src/crc32c_round_up_unittest.cc"
338      "src/crc32c_sse42_unittest.cc"
339      "src/crc32c_unittest.cc"
340      "src/crc32c_test_main.cc"
341  )
342  target_link_libraries(crc32c_tests crc32c gtest)
343
344  # Warnings as errors in Visual Studio for this project's targets.
345  if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
346    set_property(TARGET crc32c_tests APPEND PROPERTY COMPILE_OPTIONS "/WX")
347  endif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
348
349  if(CRC32C_USE_GLOG)
350    target_link_libraries(crc32c_tests glog)
351  endif(CRC32C_USE_GLOG)
352
353  add_test(NAME crc32c_tests COMMAND crc32c_tests)
354
355  add_executable(crc32c_capi_tests "")
356  target_sources(crc32c_capi_tests
357    PRIVATE
358      "src/crc32c_capi_unittest.c"
359  )
360  target_link_libraries(crc32c_capi_tests crc32c)
361
362  # Warnings as errors in Visual Studio for this project's targets.
363  if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
364    set_property(TARGET crc32c_capi_tests APPEND PROPERTY COMPILE_OPTIONS "/WX")
365  endif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
366
367  add_test(NAME crc32c_capi_tests COMMAND crc32c_capi_tests)
368endif(CRC32C_BUILD_TESTS)
369
370if(CRC32C_BUILD_BENCHMARKS)
371  add_executable(crc32c_bench "")
372  target_sources(crc32c_bench
373    PRIVATE
374      "${PROJECT_BINARY_DIR}/include/crc32c/crc32c_config.h"
375      "src/crc32c_benchmark.cc"
376  )
377  target_link_libraries(crc32c_bench crc32c)
378
379  # This project uses Google benchmark for benchmarking.
380  set(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "" FORCE)
381  set(BENCHMARK_ENABLE_EXCEPTIONS OFF CACHE BOOL "" FORCE)
382  add_subdirectory("third_party/benchmark")
383  target_link_libraries(crc32c_bench benchmark)
384
385  if(CRC32C_USE_GLOG)
386    target_link_libraries(crc32c_bench glog)
387  endif(CRC32C_USE_GLOG)
388
389  # Warnings as errors in Visual Studio for this project's targets.
390  if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
391    set_property(TARGET crc32c_bench APPEND PROPERTY COMPILE_OPTIONS "/WX")
392  endif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
393endif(CRC32C_BUILD_BENCHMARKS)
394
395if(CRC32C_INSTALL)
396  install(TARGETS crc32c
397    EXPORT Crc32cTargets
398    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
399    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
400    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
401  )
402  install(
403    FILES
404      "include/crc32c/crc32c.h"
405    DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/crc32c"
406  )
407
408  include(CMakePackageConfigHelpers)
409  configure_package_config_file(
410    "${PROJECT_NAME}Config.cmake.in"
411    "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
412    INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
413  )
414  write_basic_package_version_file(
415    "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
416    COMPATIBILITY SameMajorVersion
417  )
418  install(
419    EXPORT Crc32cTargets
420    NAMESPACE Crc32c::
421    DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
422  )
423  install(
424    FILES
425      "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
426      "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
427    DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
428  )
429endif(CRC32C_INSTALL)
430