CMakeLists.txt raw

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