xref: /aosp_15_r20/external/leveldb/CMakeLists.txt (revision 9507f98c5f32dee4b5f9e4a38cd499f3ff5c4490)
1# Copyright 2017 The LevelDB 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.9)
6# Keep the version below in sync with the one in db.h
7project(leveldb VERSION 1.23.0 LANGUAGES C CXX)
8
9# C standard can be overridden when this is used as a sub-project.
10if(NOT CMAKE_C_STANDARD)
11  # This project can use C11, but will gracefully decay down to C89.
12  set(CMAKE_C_STANDARD 11)
13  set(CMAKE_C_STANDARD_REQUIRED OFF)
14  set(CMAKE_C_EXTENSIONS OFF)
15endif(NOT CMAKE_C_STANDARD)
16
17# C++ standard can be overridden when this is used as a sub-project.
18if(NOT CMAKE_CXX_STANDARD)
19  # This project requires C++11.
20  set(CMAKE_CXX_STANDARD 11)
21  set(CMAKE_CXX_STANDARD_REQUIRED ON)
22  set(CMAKE_CXX_EXTENSIONS OFF)
23endif(NOT CMAKE_CXX_STANDARD)
24
25if (WIN32)
26  set(LEVELDB_PLATFORM_NAME LEVELDB_PLATFORM_WINDOWS)
27  # TODO(cmumford): Make UNICODE configurable for Windows.
28  add_definitions(-D_UNICODE -DUNICODE)
29else (WIN32)
30  set(LEVELDB_PLATFORM_NAME LEVELDB_PLATFORM_POSIX)
31endif (WIN32)
32
33option(LEVELDB_BUILD_TESTS "Build LevelDB's unit tests" ON)
34option(LEVELDB_BUILD_BENCHMARKS "Build LevelDB's benchmarks" ON)
35option(LEVELDB_INSTALL "Install LevelDB's header and library" ON)
36
37include(CheckIncludeFile)
38check_include_file("unistd.h" HAVE_UNISTD_H)
39
40include(CheckLibraryExists)
41check_library_exists(crc32c crc32c_value "" HAVE_CRC32C)
42check_library_exists(snappy snappy_compress "" HAVE_SNAPPY)
43check_library_exists(tcmalloc malloc "" HAVE_TCMALLOC)
44
45include(CheckCXXSymbolExists)
46# Using check_cxx_symbol_exists() instead of check_c_symbol_exists() because
47# we're including the header from C++, and feature detection should use the same
48# compiler language that the project will use later. Principles aside, some
49# versions of do not expose fdatasync() in <unistd.h> in standard C mode
50# (-std=c11), but do expose the function in standard C++ mode (-std=c++11).
51check_cxx_symbol_exists(fdatasync "unistd.h" HAVE_FDATASYNC)
52check_cxx_symbol_exists(F_FULLFSYNC "fcntl.h" HAVE_FULLFSYNC)
53check_cxx_symbol_exists(O_CLOEXEC "fcntl.h" HAVE_O_CLOEXEC)
54
55if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
56  # Disable C++ exceptions.
57  string(REGEX REPLACE "/EH[a-z]+" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
58  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHs-c-")
59  add_definitions(-D_HAS_EXCEPTIONS=0)
60
61  # Disable RTTI.
62  string(REGEX REPLACE "/GR" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
63  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GR-")
64else(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
65  # Enable strict prototype warnings for C code in clang and gcc.
66  if(NOT CMAKE_C_FLAGS MATCHES "-Wstrict-prototypes")
67    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wstrict-prototypes")
68  endif(NOT CMAKE_C_FLAGS MATCHES "-Wstrict-prototypes")
69
70  # Disable C++ exceptions.
71  string(REGEX REPLACE "-fexceptions" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
72  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions")
73
74  # Disable RTTI.
75  string(REGEX REPLACE "-frtti" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
76  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
77endif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
78
79# Test whether -Wthread-safety is available. See
80# https://clang.llvm.org/docs/ThreadSafetyAnalysis.html
81include(CheckCXXCompilerFlag)
82check_cxx_compiler_flag(-Wthread-safety HAVE_CLANG_THREAD_SAFETY)
83
84# Used by googletest.
85check_cxx_compiler_flag(-Wno-missing-field-initializers
86                        LEVELDB_HAVE_NO_MISSING_FIELD_INITIALIZERS)
87
88include(CheckCXXSourceCompiles)
89
90# Test whether C++17 __has_include is available.
91check_cxx_source_compiles("
92#if defined(__has_include) &&  __has_include(<string>)
93#include <string>
94#endif
95int main() { std::string str; return 0; }
96" HAVE_CXX17_HAS_INCLUDE)
97
98set(LEVELDB_PUBLIC_INCLUDE_DIR "include/leveldb")
99set(LEVELDB_PORT_CONFIG_DIR "include/port")
100
101configure_file(
102  "port/port_config.h.in"
103  "${PROJECT_BINARY_DIR}/${LEVELDB_PORT_CONFIG_DIR}/port_config.h"
104)
105
106include_directories(
107  "${PROJECT_BINARY_DIR}/include"
108  "."
109)
110
111if(BUILD_SHARED_LIBS)
112  # Only export LEVELDB_EXPORT symbols from the shared library.
113  add_compile_options(-fvisibility=hidden)
114endif(BUILD_SHARED_LIBS)
115
116# Must be included before CMAKE_INSTALL_INCLUDEDIR is used.
117include(GNUInstallDirs)
118
119add_library(leveldb "")
120target_sources(leveldb
121  PRIVATE
122    "${PROJECT_BINARY_DIR}/${LEVELDB_PORT_CONFIG_DIR}/port_config.h"
123    "db/builder.cc"
124    "db/builder.h"
125    "db/c.cc"
126    "db/db_impl.cc"
127    "db/db_impl.h"
128    "db/db_iter.cc"
129    "db/db_iter.h"
130    "db/dbformat.cc"
131    "db/dbformat.h"
132    "db/dumpfile.cc"
133    "db/filename.cc"
134    "db/filename.h"
135    "db/log_format.h"
136    "db/log_reader.cc"
137    "db/log_reader.h"
138    "db/log_writer.cc"
139    "db/log_writer.h"
140    "db/memtable.cc"
141    "db/memtable.h"
142    "db/repair.cc"
143    "db/skiplist.h"
144    "db/snapshot.h"
145    "db/table_cache.cc"
146    "db/table_cache.h"
147    "db/version_edit.cc"
148    "db/version_edit.h"
149    "db/version_set.cc"
150    "db/version_set.h"
151    "db/write_batch_internal.h"
152    "db/write_batch.cc"
153    "port/port_stdcxx.h"
154    "port/port.h"
155    "port/thread_annotations.h"
156    "table/block_builder.cc"
157    "table/block_builder.h"
158    "table/block.cc"
159    "table/block.h"
160    "table/filter_block.cc"
161    "table/filter_block.h"
162    "table/format.cc"
163    "table/format.h"
164    "table/iterator_wrapper.h"
165    "table/iterator.cc"
166    "table/merger.cc"
167    "table/merger.h"
168    "table/table_builder.cc"
169    "table/table.cc"
170    "table/two_level_iterator.cc"
171    "table/two_level_iterator.h"
172    "util/arena.cc"
173    "util/arena.h"
174    "util/bloom.cc"
175    "util/cache.cc"
176    "util/coding.cc"
177    "util/coding.h"
178    "util/comparator.cc"
179    "util/crc32c.cc"
180    "util/crc32c.h"
181    "util/env.cc"
182    "util/filter_policy.cc"
183    "util/hash.cc"
184    "util/hash.h"
185    "util/logging.cc"
186    "util/logging.h"
187    "util/mutexlock.h"
188    "util/no_destructor.h"
189    "util/options.cc"
190    "util/random.h"
191    "util/status.cc"
192
193  # Only CMake 3.3+ supports PUBLIC sources in targets exported by "install".
194  $<$<VERSION_GREATER:CMAKE_VERSION,3.2>:PUBLIC>
195    "${LEVELDB_PUBLIC_INCLUDE_DIR}/c.h"
196    "${LEVELDB_PUBLIC_INCLUDE_DIR}/cache.h"
197    "${LEVELDB_PUBLIC_INCLUDE_DIR}/comparator.h"
198    "${LEVELDB_PUBLIC_INCLUDE_DIR}/db.h"
199    "${LEVELDB_PUBLIC_INCLUDE_DIR}/dumpfile.h"
200    "${LEVELDB_PUBLIC_INCLUDE_DIR}/env.h"
201    "${LEVELDB_PUBLIC_INCLUDE_DIR}/export.h"
202    "${LEVELDB_PUBLIC_INCLUDE_DIR}/filter_policy.h"
203    "${LEVELDB_PUBLIC_INCLUDE_DIR}/iterator.h"
204    "${LEVELDB_PUBLIC_INCLUDE_DIR}/options.h"
205    "${LEVELDB_PUBLIC_INCLUDE_DIR}/slice.h"
206    "${LEVELDB_PUBLIC_INCLUDE_DIR}/status.h"
207    "${LEVELDB_PUBLIC_INCLUDE_DIR}/table_builder.h"
208    "${LEVELDB_PUBLIC_INCLUDE_DIR}/table.h"
209    "${LEVELDB_PUBLIC_INCLUDE_DIR}/write_batch.h"
210)
211
212if (WIN32)
213  target_sources(leveldb
214    PRIVATE
215      "util/env_windows.cc"
216      "util/windows_logger.h"
217  )
218else (WIN32)
219  target_sources(leveldb
220    PRIVATE
221      "util/env_posix.cc"
222      "util/posix_logger.h"
223  )
224endif (WIN32)
225
226# MemEnv is not part of the interface and could be pulled to a separate library.
227target_sources(leveldb
228  PRIVATE
229    "helpers/memenv/memenv.cc"
230    "helpers/memenv/memenv.h"
231)
232
233target_include_directories(leveldb
234  PUBLIC
235    $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
236    $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
237)
238
239set_target_properties(leveldb
240  PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR})
241
242target_compile_definitions(leveldb
243  PRIVATE
244    # Used by include/export.h when building shared libraries.
245    LEVELDB_COMPILE_LIBRARY
246    # Used by port/port.h.
247    ${LEVELDB_PLATFORM_NAME}=1
248)
249if (NOT HAVE_CXX17_HAS_INCLUDE)
250  target_compile_definitions(leveldb
251    PRIVATE
252      LEVELDB_HAS_PORT_CONFIG_H=1
253  )
254endif(NOT HAVE_CXX17_HAS_INCLUDE)
255
256if(BUILD_SHARED_LIBS)
257  target_compile_definitions(leveldb
258    PUBLIC
259      # Used by include/export.h.
260      LEVELDB_SHARED_LIBRARY
261  )
262endif(BUILD_SHARED_LIBS)
263
264if(HAVE_CLANG_THREAD_SAFETY)
265  target_compile_options(leveldb
266    PUBLIC
267      -Werror -Wthread-safety)
268endif(HAVE_CLANG_THREAD_SAFETY)
269
270if(HAVE_CRC32C)
271  target_link_libraries(leveldb crc32c)
272endif(HAVE_CRC32C)
273if(HAVE_SNAPPY)
274  target_link_libraries(leveldb snappy)
275endif(HAVE_SNAPPY)
276if(HAVE_TCMALLOC)
277  target_link_libraries(leveldb tcmalloc)
278endif(HAVE_TCMALLOC)
279
280# Needed by port_stdcxx.h
281find_package(Threads REQUIRED)
282target_link_libraries(leveldb Threads::Threads)
283
284add_executable(leveldbutil
285  "db/leveldbutil.cc"
286)
287target_link_libraries(leveldbutil leveldb)
288
289if(LEVELDB_BUILD_TESTS)
290  enable_testing()
291
292  # Prevent overriding the parent project's compiler/linker settings on Windows.
293  set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
294  set(install_gtest OFF)
295  set(install_gmock OFF)
296  set(build_gmock ON)
297
298  # This project is tested using GoogleTest.
299  add_subdirectory("third_party/googletest")
300
301  # This project uses Google benchmark for benchmarking.
302  set(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "" FORCE)
303  set(BENCHMARK_ENABLE_EXCEPTIONS OFF CACHE BOOL "" FORCE)
304  add_subdirectory("third_party/benchmark")
305
306  # GoogleTest triggers a missing field initializers warning.
307  if(LEVELDB_HAVE_NO_MISSING_FIELD_INITIALIZERS)
308    set_property(TARGET gtest
309        APPEND PROPERTY COMPILE_OPTIONS -Wno-missing-field-initializers)
310    set_property(TARGET gmock
311        APPEND PROPERTY COMPILE_OPTIONS -Wno-missing-field-initializers)
312  endif(LEVELDB_HAVE_NO_MISSING_FIELD_INITIALIZERS)
313
314  function(leveldb_test test_file)
315    get_filename_component(test_target_name "${test_file}" NAME_WE)
316
317    add_executable("${test_target_name}" "")
318    target_sources("${test_target_name}"
319      PRIVATE
320        "${PROJECT_BINARY_DIR}/${LEVELDB_PORT_CONFIG_DIR}/port_config.h"
321        "util/testutil.cc"
322        "util/testutil.h"
323
324        "${test_file}"
325    )
326    target_link_libraries("${test_target_name}" leveldb gmock gtest benchmark)
327    target_compile_definitions("${test_target_name}"
328      PRIVATE
329        ${LEVELDB_PLATFORM_NAME}=1
330    )
331    if (NOT HAVE_CXX17_HAS_INCLUDE)
332      target_compile_definitions("${test_target_name}"
333        PRIVATE
334          LEVELDB_HAS_PORT_CONFIG_H=1
335      )
336    endif(NOT HAVE_CXX17_HAS_INCLUDE)
337
338    add_test(NAME "${test_target_name}" COMMAND "${test_target_name}")
339  endfunction(leveldb_test)
340
341  leveldb_test("db/c_test.c")
342  leveldb_test("db/fault_injection_test.cc")
343
344  leveldb_test("issues/issue178_test.cc")
345  leveldb_test("issues/issue200_test.cc")
346  leveldb_test("issues/issue320_test.cc")
347
348  leveldb_test("util/env_test.cc")
349  leveldb_test("util/status_test.cc")
350  leveldb_test("util/no_destructor_test.cc")
351
352  if(NOT BUILD_SHARED_LIBS)
353    leveldb_test("db/autocompact_test.cc")
354    leveldb_test("db/corruption_test.cc")
355    leveldb_test("db/db_test.cc")
356    leveldb_test("db/dbformat_test.cc")
357    leveldb_test("db/filename_test.cc")
358    leveldb_test("db/log_test.cc")
359    leveldb_test("db/recovery_test.cc")
360    leveldb_test("db/skiplist_test.cc")
361    leveldb_test("db/version_edit_test.cc")
362    leveldb_test("db/version_set_test.cc")
363    leveldb_test("db/write_batch_test.cc")
364
365    leveldb_test("helpers/memenv/memenv_test.cc")
366
367    leveldb_test("table/filter_block_test.cc")
368    leveldb_test("table/table_test.cc")
369
370    leveldb_test("util/arena_test.cc")
371    leveldb_test("util/bloom_test.cc")
372    leveldb_test("util/cache_test.cc")
373    leveldb_test("util/coding_test.cc")
374    leveldb_test("util/crc32c_test.cc")
375    leveldb_test("util/hash_test.cc")
376    leveldb_test("util/logging_test.cc")
377
378    # TODO(costan): This test also uses
379    #               "util/env_{posix|windows}_test_helper.h"
380    if (WIN32)
381      leveldb_test("util/env_windows_test.cc")
382    else (WIN32)
383      leveldb_test("util/env_posix_test.cc")
384    endif (WIN32)
385  endif(NOT BUILD_SHARED_LIBS)
386endif(LEVELDB_BUILD_TESTS)
387
388if(LEVELDB_BUILD_BENCHMARKS)
389  function(leveldb_benchmark bench_file)
390    get_filename_component(bench_target_name "${bench_file}" NAME_WE)
391
392    add_executable("${bench_target_name}" "")
393    target_sources("${bench_target_name}"
394      PRIVATE
395        "${PROJECT_BINARY_DIR}/${LEVELDB_PORT_CONFIG_DIR}/port_config.h"
396        "util/histogram.cc"
397        "util/histogram.h"
398        "util/testutil.cc"
399        "util/testutil.h"
400
401        "${bench_file}"
402    )
403    target_link_libraries("${bench_target_name}" leveldb gmock gtest)
404    target_compile_definitions("${bench_target_name}"
405      PRIVATE
406        ${LEVELDB_PLATFORM_NAME}=1
407    )
408    if (NOT HAVE_CXX17_HAS_INCLUDE)
409      target_compile_definitions("${bench_target_name}"
410        PRIVATE
411          LEVELDB_HAS_PORT_CONFIG_H=1
412      )
413    endif(NOT HAVE_CXX17_HAS_INCLUDE)
414  endfunction(leveldb_benchmark)
415
416  if(NOT BUILD_SHARED_LIBS)
417    leveldb_benchmark("benchmarks/db_bench.cc")
418  endif(NOT BUILD_SHARED_LIBS)
419
420  check_library_exists(sqlite3 sqlite3_open "" HAVE_SQLITE3)
421  if(HAVE_SQLITE3)
422    leveldb_benchmark("benchmarks/db_bench_sqlite3.cc")
423    target_link_libraries(db_bench_sqlite3 sqlite3)
424  endif(HAVE_SQLITE3)
425
426  # check_library_exists is insufficient here because the library names have
427  # different manglings when compiled with clang or gcc, at least when installed
428  # with Homebrew on Mac.
429  set(OLD_CMAKE_REQURED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
430  list(APPEND CMAKE_REQUIRED_LIBRARIES kyotocabinet)
431  check_cxx_source_compiles("
432#include <kcpolydb.h>
433
434int main() {
435  kyotocabinet::TreeDB* db = new kyotocabinet::TreeDB();
436  delete db;
437  return 0;
438}
439  "  HAVE_KYOTOCABINET)
440  set(CMAKE_REQUIRED_LIBRARIES ${OLD_CMAKE_REQURED_LIBRARIES})
441  if(HAVE_KYOTOCABINET)
442    leveldb_benchmark("benchmarks/db_bench_tree_db.cc")
443    target_link_libraries(db_bench_tree_db kyotocabinet)
444  endif(HAVE_KYOTOCABINET)
445endif(LEVELDB_BUILD_BENCHMARKS)
446
447if(LEVELDB_INSTALL)
448  install(TARGETS leveldb
449    EXPORT leveldbTargets
450    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
451    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
452    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
453  )
454  install(
455    FILES
456      "${LEVELDB_PUBLIC_INCLUDE_DIR}/c.h"
457      "${LEVELDB_PUBLIC_INCLUDE_DIR}/cache.h"
458      "${LEVELDB_PUBLIC_INCLUDE_DIR}/comparator.h"
459      "${LEVELDB_PUBLIC_INCLUDE_DIR}/db.h"
460      "${LEVELDB_PUBLIC_INCLUDE_DIR}/dumpfile.h"
461      "${LEVELDB_PUBLIC_INCLUDE_DIR}/env.h"
462      "${LEVELDB_PUBLIC_INCLUDE_DIR}/export.h"
463      "${LEVELDB_PUBLIC_INCLUDE_DIR}/filter_policy.h"
464      "${LEVELDB_PUBLIC_INCLUDE_DIR}/iterator.h"
465      "${LEVELDB_PUBLIC_INCLUDE_DIR}/options.h"
466      "${LEVELDB_PUBLIC_INCLUDE_DIR}/slice.h"
467      "${LEVELDB_PUBLIC_INCLUDE_DIR}/status.h"
468      "${LEVELDB_PUBLIC_INCLUDE_DIR}/table_builder.h"
469      "${LEVELDB_PUBLIC_INCLUDE_DIR}/table.h"
470      "${LEVELDB_PUBLIC_INCLUDE_DIR}/write_batch.h"
471    DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/leveldb"
472  )
473
474  include(CMakePackageConfigHelpers)
475  configure_package_config_file(
476    "cmake/${PROJECT_NAME}Config.cmake.in"
477    "${PROJECT_BINARY_DIR}/cmake/${PROJECT_NAME}Config.cmake"
478    INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
479  )
480  write_basic_package_version_file(
481    "${PROJECT_BINARY_DIR}/cmake/${PROJECT_NAME}ConfigVersion.cmake"
482    COMPATIBILITY SameMajorVersion
483  )
484  install(
485    EXPORT leveldbTargets
486    NAMESPACE leveldb::
487    DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
488  )
489  install(
490    FILES
491      "${PROJECT_BINARY_DIR}/cmake/${PROJECT_NAME}Config.cmake"
492      "${PROJECT_BINARY_DIR}/cmake/${PROJECT_NAME}ConfigVersion.cmake"
493    DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
494  )
495endif(LEVELDB_INSTALL)
496