## ## Copyright 2020-2021 Leonid Yuriev ## and other libmdbx authors: please see AUTHORS file. ## All rights reserved. ## ## Redistribution and use in source and binary forms, with or without ## modification, are permitted only as authorized by the OpenLDAP ## Public License. ## ## A copy of this license is available in the file LICENSE in the ## top-level directory of the distribution or, alternatively, at ## . ## ## ## libmdbx = { Revised and extended descendant of Symas LMDB. } ## Please see README.md at https://github.com/erthink/libmdbx ## ## Libmdbx is superior to LMDB in terms of features and reliability, ## not inferior in performance. libmdbx works on Linux, FreeBSD, MacOS X ## and other systems compliant with POSIX.1-2008, but also support Windows ## as a complementary platform. ## ## The next version is under active non-public development and will be ## released as MithrilDB and libmithrildb for libraries & packages. ## Admittedly mythical Mithril is resembling silver but being stronger and ## lighter than steel. Therefore MithrilDB is rightly relevant name. ## ## MithrilDB will be radically different from libmdbx by the new database ## format and API based on C++17, as well as the Apache 2.0 License. ## The goal of this revolution is to provide a clearer and robust API, ## add more features and new valuable properties of database. ## ## The Future will (be) Positive. Всё будет хорошо. ## cmake_minimum_required(VERSION 3.11) cmake_policy(PUSH) cmake_policy(VERSION 3.8.2) if(NOT CMAKE_VERSION VERSION_LESS 3.15) cmake_policy(SET CMP0091 NEW) endif() if(NOT CMAKE_VERSION VERSION_LESS 3.13) cmake_policy(SET CMP0077 NEW) endif() if(NOT CMAKE_VERSION VERSION_LESS 3.12) cmake_policy(SET CMP0075 NEW) endif() if(NOT CMAKE_VERSION VERSION_LESS 3.9) cmake_policy(SET CMP0069 NEW) include(CheckIPOSupported) check_ipo_supported(RESULT CMAKE_INTERPROCEDURAL_OPTIMIZATION_AVAILABLE) else() set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_AVAILABLE FALSE) endif() if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git" AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt" AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/core.c" AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/alloy.c" AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/config.h.in" AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/version.c.in" AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/man1" AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/mdbx_chk.c" AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/mdbx.c++") set(MDBX_AMALGAMATED_SOURCE FALSE) find_program(GIT git) if(NOT GIT) message(SEND_ERROR "Git command-line tool not found") endif() set(MDBX_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src") elseif(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/mdbx.c" AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/mdbx.c++" AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/config.h.in" AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/man1" AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/mdbx_chk.c") set(MDBX_AMALGAMATED_SOURCE TRUE) set(MDBX_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}") else() message(FATAL_ERROR "Please use libmdbx as a git-submodule or the amalgamated source code") endif() if(DEFINED PROJECT_NAME) set(SUBPROJECT ON) set(NOT_SUBPROJECT OFF) if(NOT MDBX_AMALGAMATED_SOURCE AND NOT DEFINED BUILD_TESTING) set(BUILD_TESTING OFF) endif() enable_language(C) else() set(SUBPROJECT OFF) set(NOT_SUBPROJECT ON) project(libmdbx C) if(NOT MDBX_AMALGAMATED_SOURCE AND NOT DEFINED BUILD_TESTING) set(BUILD_TESTING ON) endif() endif() if(MDBX_AMALGAMATED_SOURCE AND DEFINED MDBX_ENABLE_TESTS AND MDBX_ENABLE_TESTS) message(WARNING "MDBX_ENABLE_TESTS=${MDBX_ENABLE_TESTS}: But amalgamated source code don't includes tests.") set(MDBX_ENABLE_TESTS OFF) endif() # Try to find a C++ compiler unless sure that this is unnecessary. if (NOT CMAKE_CXX_COMPILER_LOADED) include(CheckLanguage) if(NOT DEFINED MDBX_BUILD_CXX OR MDBX_BUILD_CXX OR (NOT MDBX_AMALGAMATED_SOURCE AND (NOT DEFINED MDBX_ENABLE_TESTS OR MDBX_ENABLE_TESTS))) check_language(CXX) if(CMAKE_CXX_COMPILER) enable_language(CXX) endif() endif() else() enable_language(CXX) endif() if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE MinSizeRel CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE) endif() if(NOT_SUBPROJECT AND (CMAKE_CROSSCOMPILING OR IOS)) set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) endif() if(NOT "$ENV{TEAMCITY_PROCESS_FLOW_ID}" STREQUAL "") set(CI TEAMCITY) message(STATUS "TeamCity CI") elseif(NOT "$ENV{TRAVIS}" STREQUAL "") set(CI TRAVIS) message(STATUS "Travis CI") elseif(NOT "$ENV{CIRCLECI}" STREQUAL "") set(CI CIRCLE) message(STATUS "Circle CI") elseif(NOT "$ENV{APPVEYOR}" STREQUAL "") set(CI APPVEYOR) message(STATUS "AppVeyor CI") elseif(NOT "$ENV{CI}" STREQUAL "") set(CI "$ENV{CI}") message(STATUS "Other CI (${CI})") else() message(STATUS "Assume No any CI environment") unset(CI) endif() # output all mdbx-related targets in single directory if(NOT DEFINED MDBX_OUTPUT_DIR) set(MDBX_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}) endif() set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${MDBX_OUTPUT_DIR}) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${MDBX_OUTPUT_DIR}) set(CMAKE_PDB_OUTPUT_DIRECTORY ${MDBX_OUTPUT_DIR}) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${MDBX_OUTPUT_DIR}) include(CheckFunctionExists) include(FindPackageMessage) include(GNUInstallDirs) if(CMAKE_C_COMPILER_ID STREQUAL "MSVC" AND MSVC_VERSION LESS 1900) message(SEND_ERROR "MSVC compiler ${MSVC_VERSION} is too old for building MDBX." " At least 'Microsoft Visual Studio 2015' is required.") endif() # Set default build type to Release. This is to ease a User's life. if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE) endif() string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_UPPERCASE) set(CMAKE_THREAD_PREFER_PTHREAD TRUE) set(THREADS_PREFER_PTHREAD_FLAG TRUE) find_package(Threads REQUIRED) include(cmake/utils.cmake) include(cmake/compiler.cmake) include(cmake/profile.cmake) # Workaround for `-pthread` toolchain/cmake bug if(NOT APPLE AND NOT MSVC AND CMAKE_USE_PTHREADS_INIT AND NOT CMAKE_THREAD_LIBS_INIT AND (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG)) check_compiler_flag("-pthread" CC_HAS_PTHREAD) if(CC_HAS_PTHREAD AND NOT CMAKE_EXE_LINKER_FLAGS MATCHES "-pthread") message(STATUS "Force add -pthread for linker flags to avoid troubles") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pthread") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -pthread") set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -pthread") endif() endif() CHECK_FUNCTION_EXISTS(pow NOT_NEED_LIBM) if(NOT_NEED_LIBM) set(LIB_MATH "") else() set(CMAKE_REQUIRED_LIBRARIES m) CHECK_FUNCTION_EXISTS(pow HAVE_LIBM) if(HAVE_LIBM) set(LIB_MATH m) else() message(FATAL_ERROR "No libm found for math support") endif() endif() if(SUBPROJECT) if(NOT DEFINED BUILD_SHARED_LIBS) option(BUILD_SHARED_LIBS "Build shared libraries (DLLs)" OFF) endif() if(NOT DEFINED CMAKE_POSITION_INDEPENDENT_CODE) option(CMAKE_POSITION_INDEPENDENT_CODE "Generate position independent (PIC)" ON) endif() else() option(BUILD_SHARED_LIBS "Build shared libraries (DLLs)" ON) option(CMAKE_POSITION_INDEPENDENT_CODE "Generate position independent (PIC)" ON) if (CC_HAS_ARCH_NATIVE) option(BUILD_FOR_NATIVE_CPU "Generate code for the compiling machine CPU" OFF) endif() if(CMAKE_CONFIGURATION_TYPES OR NOT CMAKE_BUILD_TYPE_UPPERCASE STREQUAL "DEBUG") set(INTERPROCEDURAL_OPTIMIZATION_DEFAULT ON) else() set(INTERPROCEDURAL_OPTIMIZATION_DEFAULT OFF) endif() if(CMAKE_INTERPROCEDURAL_OPTIMIZATION_AVAILABLE OR GCC_LTO_AVAILABLE OR MSVC_LTO_AVAILABLE OR CLANG_LTO_AVAILABLE) option(INTERPROCEDURAL_OPTIMIZATION "Enable interprocedural/LTO optimization" ${INTERPROCEDURAL_OPTIMIZATION_DEFAULT}) endif() if(INTERPROCEDURAL_OPTIMIZATION) if(GCC_LTO_AVAILABLE) set(LTO_ENABLED TRUE) set(CMAKE_AR ${CMAKE_GCC_AR} CACHE PATH "Path to ar program with LTO-plugin" FORCE) set(CMAKE_NM ${CMAKE_GCC_NM} CACHE PATH "Path to nm program with LTO-plugin" FORCE) set(CMAKE_RANLIB ${CMAKE_GCC_RANLIB} CACHE PATH "Path to ranlib program with LTO-plugin" FORCE) message(STATUS "MDBX indulge Link-Time Optimization by GCC") elseif(CLANG_LTO_AVAILABLE) set(LTO_ENABLED TRUE) set(CMAKE_AR ${CMAKE_CLANG_AR} CACHE PATH "Path to ar program with LTO-plugin" FORCE) set(CMAKE_NM ${CMAKE_CLANG_NM} CACHE PATH "Path to nm program with LTO-plugin" FORCE) set(CMAKE_RANLIB ${CMAKE_CLANG_RANLIB} CACHE PATH "Path to ranlib program with LTO-plugin" FORCE) message(STATUS "MDBX indulge Link-Time Optimization by CLANG") elseif(MSVC_LTO_AVAILABLE) set(LTO_ENABLED TRUE) message(STATUS "MDBX indulge Link-Time Optimization by MSVC") elseif(CMAKE_INTERPROCEDURAL_OPTIMIZATION_AVAILABLE) message(STATUS "MDBX indulge Interprocedural Optimization by CMake") set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) set(LTO_ENABLED TRUE) else() message(WARNING "Unable to engage interprocedural/LTO optimization.") endif() else() set(CMAKE_INTERPROCEDURAL_OPTIMIZATION FALSE) set(LTO_ENABLED FALSE) endif() if(NOT MDBX_AMALGAMATED_SOURCE) find_program(VALGRIND valgrind) if(VALGRIND) # LY: cmake is ugly and nasty. # - therefore memcheck-options should be defined before including ctest; # - otherwise ctest may ignore it. set(MEMORYCHECK_SUPPRESSIONS_FILE "${CMAKE_CURRENT_SOURCE_DIR}/test/valgrind_suppress.txt" CACHE FILEPATH "Suppressions file for Valgrind" FORCE) set(MEMORYCHECK_COMMAND_OPTIONS "--trace-children=yes --leak-check=full --track-origins=yes --error-exitcode=42 --error-markers=@ --errors-for-leak-kinds=definite --fair-sched=yes --suppressions=${MEMORYCHECK_SUPPRESSIONS_FILE}" CACHE STRING "Valgrind options" FORCE) set(VALGRIND_COMMAND_OPTIONS "${MEMORYCHECK_COMMAND_OPTIONS}" CACHE STRING "Valgrind options" FORCE) endif() # Enable 'make tags' target. find_program(CTAGS ctags) if(CTAGS) add_custom_target(tags COMMAND ${CTAGS} -R -f tags WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) add_custom_target(ctags DEPENDS tags) endif(CTAGS) if(UNIX) find_program(CLANG_FORMAT NAMES clang-format-12 clang-format-11 clang-format-10 clang-format) if(CLANG_FORMAT) execute_process(COMMAND ${CLANG_FORMAT} "--version" OUTPUT_VARIABLE clang_format_version_info) string(REGEX MATCH "version ([0-9]+)\\.([0-9]+)\\.([0-9]+)(.*)?" clang_format_version_info CLANG_FORMAT_VERSION) if(clang_format_version_info AND NOT CLANG_FORMAT_VERSION VERSION_LESS 10.0) # Enable 'make reformat' target. add_custom_target(reformat VERBATIM COMMAND git ls-files | grep -E \\.\(c|cxx|cc|cpp|h|hxx|hpp\)\(\\.in\)?\$ | xargs ${CLANG_FORMAT} -i --style=file WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) endif() endif() endif() if(NOT "${PROJECT_BINARY_DIR}" STREQUAL "${PROJECT_SOURCE_DIR}") add_custom_target(distclean) add_custom_command(TARGET distclean COMMAND ${CMAKE_COMMAND} -E remove_directory "${PROJECT_BINARY_DIR}" COMMENT "Removing the build directory and its content") elseif(IS_DIRECTORY .git AND GIT) add_custom_target(distclean) add_custom_command(TARGET distclean WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMAND ${GIT} submodule foreach --recursive git clean -f -X -d COMMAND ${GIT} clean -f -X -d COMMENT "Removing all build files from the source directory") endif() endif(NOT MDBX_AMALGAMATED_SOURCE) setup_compile_flags() endif(SUBPROJECT) list(FIND CMAKE_C_COMPILE_FEATURES c_std_11 HAS_C11) list(FIND CMAKE_CXX_COMPILE_FEATURES cxx_std_11 HAS_CXX11) list(FIND CMAKE_CXX_COMPILE_FEATURES cxx_std_14 HAS_CXX14) list(FIND CMAKE_CXX_COMPILE_FEATURES cxx_std_17 HAS_CXX17) list(FIND CMAKE_CXX_COMPILE_FEATURES cxx_std_20 HAS_CXX20) if(NOT DEFINED MDBX_CXX_STANDARD) if(DEFINED CMAKE_CXX_STANDARD) set(MDBX_CXX_STANDARD ${CMAKE_CXX_STANDARD}) elseif(NOT HAS_CXX20 LESS 0) set(MDBX_CXX_STANDARD 20) elseif(NOT HAS_CXX17 LESS 0) set(MDBX_CXX_STANDARD 17) elseif(NOT HAS_CXX14 LESS 0) set(MDBX_CXX_STANDARD 14) elseif(NOT HAS_CXX11 LESS 0) set(MDBX_CXX_STANDARD 11) else() set(MDBX_CXX_STANDARD 98) endif() endif() if(NOT DEFINED MDBX_C_STANDARD) # MSVC >= 19.28 (Microsoft Visual Studio 16.8) is mad! # It unable process Windows SDK headers in the C11 mode! if(HAS_C11 LESS 0 OR (MSVC AND MSVC_VERSION GREATER 1927)) set(MDBX_C_STANDARD 99) else() set(MDBX_C_STANDARD 11) endif() endif() if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows" AND EXISTS "${MDBX_SOURCE_DIR}/ntdll.def") if(MSVC) if(NOT MSVC_LIB_EXE) # Find lib.exe get_filename_component(CL_NAME ${CMAKE_C_COMPILER} NAME) string(REPLACE cl.exe lib.exe MSVC_LIB_EXE "${CL_NAME}") find_program(MSVC_LIB_EXE ${MSVC_LIB_EXE}) endif() if(MSVC_LIB_EXE) message(STATUS "Found MSVC's lib tool: ${MSVC_LIB_EXE}") set(MDBX_NTDLL_EXTRA_IMPLIB "${CMAKE_CURRENT_BINARY_DIR}/mdbx_ntdll_extra.lib") add_custom_command(OUTPUT "${MDBX_NTDLL_EXTRA_IMPLIB}" COMMENT "Create extra-import-library for ntdll.dll" MAIN_DEPENDENCY "${MDBX_SOURCE_DIR}/ntdll.def" COMMAND ${MSVC_LIB_EXE} /def:"${MDBX_SOURCE_DIR}/ntdll.def" /out:"${MDBX_NTDLL_EXTRA_IMPLIB}" ${INITIAL_CMAKE_STATIC_LINKER_FLAGS}) else() message(WARNING "MSVC's lib tool not found") endif() elseif(MINGW OR MINGW64) if(NOT DLLTOOL) # Find dlltool get_filename_component(GCC_NAME ${CMAKE_C_COMPILER} NAME) string(REPLACE gcc dlltool DLLTOOL_NAME "${GCC_NAME}") find_program(DLLTOOL NAMES ${DLLTOOL_NAME}) endif() if(DLLTOOL) message(STATUS "Found dlltool: ${DLLTOOL}") set(MDBX_NTDLL_EXTRA_IMPLIB "${CMAKE_CURRENT_BINARY_DIR}/mdbx_ntdll_extra.a") add_custom_command(OUTPUT "${MDBX_NTDLL_EXTRA_IMPLIB}" COMMENT "Create extra-import-library for ntdll.dll" MAIN_DEPENDENCY "${MDBX_SOURCE_DIR}/ntdll.def" COMMAND ${DLLTOOL} -d "${MDBX_SOURCE_DIR}/ntdll.def" -l "${MDBX_NTDLL_EXTRA_IMPLIB}") else() message(WARNING "dlltool not found") endif() endif() if(MDBX_NTDLL_EXTRA_IMPLIB) # LY: Sometimes CMake requires a nightmarish magic for simple things. # 1) create a target out of the library compilation result add_custom_target(ntdll_extra_target DEPENDS "${MDBX_NTDLL_EXTRA_IMPLIB}") # 2) create an library target out of the library compilation result add_library(ntdll_extra STATIC IMPORTED GLOBAL) add_dependencies(ntdll_extra ntdll_extra_target) # 3) specify where the library is (and where to find the headers) set_target_properties(ntdll_extra PROPERTIES IMPORTED_LOCATION "${MDBX_NTDLL_EXTRA_IMPLIB}") endif() endif() ################################################################################ ################################################################################ # # #### ##### ##### # #### # # #### # # # # # # # # # ## # # # # # # # # # # # # # # #### # # # ##### # # # # # # # # # # # # # # # # # ## # # # #### # # # #### # # #### # set(MDBX_BUILD_OPTIONS ENABLE_ASAN MDBX_USE_VALGRIND ENABLE_GPROF ENABLE_GCOV) macro(add_mdbx_option NAME DESCRIPTION DEFAULT) list(APPEND MDBX_BUILD_OPTIONS ${NAME}) if(NOT ${DEFAULT} STREQUAL "AUTO") option(${NAME} "${DESCRIPTION}" ${DEFAULT}) elseif(NOT DEFINED ${NAME}) set(${NAME}_AUTO ON) endif() endmacro() if(IOS) set(MDBX_BUILD_TOOLS_DEFAULT OFF) if(NOT_SUBPROJECT) cmake_policy(SET CMP0006 OLD) set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO") endif() else() set(MDBX_BUILD_TOOLS_DEFAULT ON) endif() add_mdbx_option(MDBX_INSTALL_STATIC "Build and install libmdbx for static linking" OFF) add_mdbx_option(MDBX_BUILD_SHARED_LIBRARY "Build libmdbx as shared library (DLL)" ${BUILD_SHARED_LIBS}) add_mdbx_option(MDBX_BUILD_TOOLS "Build MDBX tools (mdbx_chk/stat/dump/load/copy)" ${MDBX_BUILD_TOOLS_DEFAULT}) CMAKE_DEPENDENT_OPTION(MDBX_INSTALL_MANPAGES "Install man-pages for MDBX tools (mdbx_chk/stat/dump/load/copy)" ON MDBX_BUILD_TOOLS OFF) add_mdbx_option(MDBX_TXN_CHECKOWNER "Checking transaction matches the calling thread inside libmdbx's API" ON) add_mdbx_option(MDBX_ENV_CHECKPID "Paranoid checking PID inside libmdbx's API" AUTO) mark_as_advanced(MDBX_ENV_CHECKPID) if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") add_mdbx_option(MDBX_DISABLE_GNU_SOURCE "Don't use GNU/Linux libc extensions" OFF) mark_as_advanced(MDBX_DISABLE_GNU_SOURCE) endif() if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" OR IOS) add_mdbx_option(MDBX_OSX_SPEED_INSTEADOF_DURABILITY "Disable use fcntl(F_FULLFSYNC) in favor of speed" OFF) mark_as_advanced(MDBX_OSX_SPEED_INSTEADOF_DURABILITY) endif() if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") if(MDBX_NTDLL_EXTRA_IMPLIB) add_mdbx_option(MDBX_AVOID_CRT "Avoid dependence from MSVC CRT and use ntdll.dll instead" OFF) endif() add_mdbx_option(MDBX_CONFIG_MANUAL_TLS_CALLBACK "Provide mdbx_dll_handler() for manual initialization" OFF) mark_as_advanced(MDBX_CONFIG_MANUAL_TLS_CALLBACK) else() add_mdbx_option(MDBX_USE_OFDLOCKS "Use Open file description locks (aka OFD locks, non-POSIX)" AUTO) mark_as_advanced(MDBX_USE_OFDLOCKS) endif() add_mdbx_option(MDBX_LOCKING "Locking method (Win32=-1, SysV=5, POSIX=1988, POSIX=2001, POSIX=2008, Futexes=1995)" AUTO) mark_as_advanced(MDBX_LOCKING) add_mdbx_option(MDBX_TRUST_RTC "Does a system have battery-backed Real-Time Clock or just a fake" AUTO) mark_as_advanced(MDBX_TRUST_RTC) option(MDBX_FORCE_ASSERTIONS "Force enable assertion checking" OFF) if(NOT MDBX_AMALGAMATED_SOURCE) add_mdbx_option(MDBX_ALLOY_BUILD "Build MDBX library through single/alloyed object file" ON) endif() if((MDBX_BUILD_TOOLS OR MDBX_ENABLE_TESTS) AND MDBX_BUILD_SHARED_LIBRARY) add_mdbx_option(MDBX_LINK_TOOLS_NONSTATIC "Link MDBX tools with non-static libmdbx" OFF) else() unset(MDBX_LINK_TOOLS_NONSTATIC CACHE) endif() if(CMAKE_CXX_COMPILER_LOADED AND MDBX_CXX_STANDARD GREATER_EQUAL 11 AND MDBX_CXX_STANDARD LESS 83) if(NOT MDBX_AMALGAMATED_SOURCE) option(MDBX_ENABLE_TESTS "Build MDBX tests" ${BUILD_TESTING}) endif() if(NOT MDBX_AVOID_CRT AND NOT (CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8) AND NOT (CMAKE_COMPILER_IS_CLANG AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4) AND NOT (MSVC AND MSVC_VERSION LESS 1900)) option(MDBX_BUILD_CXX "Build C++ portion" ON) else() set(MDBX_BUILD_CXX FALSE) endif() else() set(MDBX_BUILD_CXX FALSE) set(MDBX_ENABLE_TESTS FALSE) endif() ################################################################################ ################################################################################ if(MDBX_BUILD_CXX AND NOT CMAKE_CXX_COMPILER_LOADED) message(FATAL_ERROR "MDBX_BUILD_CXX=${MDBX_BUILD_CXX}: The C++ compiler is required to build the C++API.") endif() # Get version fetch_version(MDBX "${CMAKE_CURRENT_SOURCE_DIR}" FALSE) message(STATUS "libmdbx version is ${MDBX_VERSION}") # sources list set(LIBMDBX_PUBLIC_HEADERS mdbx.h) set(LIBMDBX_SOURCES mdbx.h "${CMAKE_CURRENT_BINARY_DIR}/config.h") if(MDBX_AMALGAMATED_SOURCE) list(APPEND LIBMDBX_SOURCES mdbx.c) else() # generate version file configure_file("${MDBX_SOURCE_DIR}/version.c.in" "${CMAKE_CURRENT_BINARY_DIR}/version.c" ESCAPE_QUOTES) file(SHA256 "${CMAKE_CURRENT_BINARY_DIR}/version.c" MDBX_SOURCERY_DIGEST) string(MAKE_C_IDENTIFIER "${MDBX_GIT_DESCRIBE}" MDBX_SOURCERY_SUFFIX) set(MDBX_BUILD_SOURCERY "${MDBX_SOURCERY_DIGEST}_${MDBX_SOURCERY_SUFFIX}") if(MDBX_ALLOY_BUILD) list(APPEND LIBMDBX_SOURCES "${MDBX_SOURCE_DIR}/alloy.c") include_directories("${MDBX_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}") else() list(APPEND LIBMDBX_SOURCES "${CMAKE_CURRENT_BINARY_DIR}/version.c" "${MDBX_SOURCE_DIR}/options.h" "${MDBX_SOURCE_DIR}/defs.h" "${MDBX_SOURCE_DIR}/internals.h" "${MDBX_SOURCE_DIR}/osal.h" "${MDBX_SOURCE_DIR}/core.c" "${MDBX_SOURCE_DIR}/osal.c" "${MDBX_SOURCE_DIR}/lck-posix.c" "${MDBX_SOURCE_DIR}/lck-windows.c") include_directories("${MDBX_SOURCE_DIR}") endif() endif(MDBX_AMALGAMATED_SOURCE) if(MDBX_BUILD_CXX) message(STATUS "Use C${MDBX_C_STANDARD} and C++${MDBX_CXX_STANDARD} for libmdbx") list(APPEND LIBMDBX_PUBLIC_HEADERS mdbx.h++) list(APPEND LIBMDBX_SOURCES "${MDBX_SOURCE_DIR}/mdbx.c++" mdbx.h++) else() message(STATUS "Use C${MDBX_C_STANDARD} for libmdbx but C++ portion is disabled") endif() macro(target_setup_options TARGET) if(DEFINED INTERPROCEDURAL_OPTIMIZATION) set_target_properties(${TARGET} PROPERTIES INTERPROCEDURAL_OPTIMIZATION $) endif() set_target_properties(${TARGET} PROPERTIES C_STANDARD ${MDBX_C_STANDARD} C_STANDARD_REQUIRED ON) if(MDBX_BUILD_CXX) set_target_properties(${TARGET} PROPERTIES CXX_STANDARD ${MDBX_CXX_STANDARD} CXX_STANDARD_REQUIRED ON) endif() if(CC_HAS_FASTMATH) target_compile_options(${TARGET} PRIVATE "-ffast-math") endif() if(CC_HAS_VISIBILITY) target_compile_options(${TARGET} PRIVATE "-fvisibility=hidden") endif() if(BUILD_FOR_NATIVE_CPU AND CC_HAS_ARCH_NATIVE) target_compile_options(${TARGET} PUBLIC "-march=native") endif() endmacro() macro(libmdbx_setup_libs TARGET MODE) target_link_libraries(${TARGET} ${MODE} Threads::Threads) if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") target_link_libraries(${TARGET} ${MODE} ntdll.lib) if(MDBX_NTDLL_EXTRA_IMPLIB AND MDBX_AVOID_CRT) target_link_libraries(${TARGET} ${MODE} ntdll_extra) endif() elseif(${CMAKE_SYSTEM_NAME} STREQUAL "SunOS" OR ${CMAKE_SYSTEM_NAME} STREQUAL "Solaris") target_link_libraries(${TARGET} ${MODE} kstat) elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Android") target_link_libraries(${TARGET} ${MODE} log) endif() if(LIBCXX_FILESYSTEM AND MDBX_BUILD_CXX) target_link_libraries(${TARGET} ${MODE} ${LIBCXX_FILESYSTEM}) endif() endmacro() # build static library if(MDBX_INSTALL_STATIC) add_library(mdbx-static STATIC ${LIBMDBX_SOURCES}) else() add_library(mdbx-static STATIC EXCLUDE_FROM_ALL ${LIBMDBX_SOURCES}) endif() set_target_properties(mdbx-static PROPERTIES PUBLIC_HEADER "${LIBMDBX_PUBLIC_HEADERS}") target_compile_definitions(mdbx-static PRIVATE MDBX_BUILD_SHARED_LIBRARY=0) target_setup_options(mdbx-static) libmdbx_setup_libs(mdbx-static INTERFACE) if(MDBX_BUILD_SHARED_LIBRARY) set_target_properties(mdbx-static PROPERTIES OUTPUT_NAME mdbx-static) else() set_target_properties(mdbx-static PROPERTIES OUTPUT_NAME mdbx) endif() ################################################################################ # build shared library if(MDBX_BUILD_SHARED_LIBRARY) add_library(mdbx SHARED ${LIBMDBX_SOURCES}) set_target_properties(mdbx PROPERTIES PUBLIC_HEADER "${LIBMDBX_PUBLIC_HEADERS}") target_compile_definitions(mdbx PRIVATE LIBMDBX_EXPORTS MDBX_BUILD_SHARED_LIBRARY=1 INTERFACE LIBMDBX_IMPORTS) target_setup_options(mdbx) libmdbx_setup_libs(mdbx PRIVATE) if(MSVC) if(MDBX_NTDLL_EXTRA_IMPLIB AND MDBX_AVOID_CRT) set_property(TARGET mdbx PROPERTY LINKER_FLAGS "/NODEFAULTLIB") else() set_property(TARGET mdbx PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL") endif() endif() if(CC_HAS_VISIBILITY AND (LTO_ENABLED OR INTERPROCEDURAL_OPTIMIZATION)) set_target_properties(mdbx PROPERTIES LINK_FLAGS "-fvisibility=hidden") endif() list(APPEND MDBX_BUILD_FLAGS ${CMAKE_SHARED_LINKER_FLAGS}) endif() if(MDBX_BUILD_SHARED_LIBRARY AND MDBX_LINK_TOOLS_NONSTATIC) set(TOOL_MDBX_LIB mdbx) # use, i.e. don't skip the full RPATH for the build tree set(CMAKE_SKIP_BUILD_RPATH FALSE) # when building, don't use the install RPATH already (but later on when installing) set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) # add the automatically determined parts of the RPATH # which point to directories outside the build tree to the install RPATH set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) # the RPATH to be used when installing, but only if it's not a system directory list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir) if(isSystemDir EQUAL -1) if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") set(CMAKE_INSTALL_RPATH "@executable_path/../lib") else() set(CMAKE_INSTALL_RPATH "\$ORIGIN/../lib") endif() endif() else() set(TOOL_MDBX_LIB mdbx-static) endif() # build mdbx-tools if(MDBX_BUILD_TOOLS) if(NOT MDBX_AMALGAMATED_SOURCE AND ${CMAKE_SYSTEM_NAME} STREQUAL "Windows") set(WINGETOPT_SRC ${MDBX_SOURCE_DIR}/wingetopt.c ${MDBX_SOURCE_DIR}/wingetopt.h) else() set(WINGETOPT_SRC "") endif() foreach(TOOL mdbx_chk mdbx_copy mdbx_stat mdbx_dump mdbx_load) add_executable(${TOOL} mdbx.h ${MDBX_SOURCE_DIR}/${TOOL}.c ${WINGETOPT_SRC}) if(MDBX_C_STANDARD) set_target_properties(${TOOL} PROPERTIES C_STANDARD ${MDBX_C_STANDARD} C_STANDARD_REQUIRED ON) endif() target_setup_options(${TOOL}) target_link_libraries(${TOOL} ${TOOL_MDBX_LIB}) endforeach() if(LIB_MATH) target_link_libraries(mdbx_chk ${LIB_MATH}) target_link_libraries(mdbx_stat ${LIB_MATH}) endif() endif() ################################################################################ # mdbx-shared-lib installation if(NOT DEFINED MDBX_DLL_INSTALL_DESTINATION) if(WIN32) set(MDBX_DLL_INSTALL_DESTINATION bin) else() set(MDBX_DLL_INSTALL_DESTINATION lib) endif() endif() if(MDBX_BUILD_SHARED_LIBRARY) if(CMAKE_VERSION VERSION_LESS 3.12) install(TARGETS mdbx EXPORT libmdbx LIBRARY DESTINATION ${MDBX_DLL_INSTALL_DESTINATION} COMPONENT runtime OBJECTS DESTINATION lib COMPONENT devel ARCHIVE DESTINATION lib COMPONENT devel PUBLIC_HEADER DESTINATION include COMPONENT devel INCLUDES DESTINATION include COMPONENT devel) else() install(TARGETS mdbx EXPORT libmdbx LIBRARY DESTINATION ${MDBX_DLL_INSTALL_DESTINATION} COMPONENT runtime NAMELINK_COMPONENT devel OBJECTS DESTINATION lib COMPONENT devel ARCHIVE DESTINATION lib COMPONENT devel PUBLIC_HEADER DESTINATION include COMPONENT devel INCLUDES DESTINATION include COMPONENT devel) endif() endif(MDBX_BUILD_SHARED_LIBRARY) # mdbx-tools installation if(MDBX_BUILD_TOOLS) if(NOT DEFINED MDBX_TOOLS_INSTALL_DESTINATION) set(MDBX_TOOLS_INSTALL_DESTINATION bin) endif() install( TARGETS mdbx_chk mdbx_stat mdbx_copy mdbx_dump mdbx_load RUNTIME DESTINATION ${MDBX_TOOLS_INSTALL_DESTINATION} COMPONENT runtime) if(MDBX_INSTALL_MANPAGES) if(NOT DEFINED MDBX_MAN_INSTALL_DESTINATION) set(MDBX_MAN_INSTALL_DESTINATION man/man1) endif() install( FILES "${MDBX_SOURCE_DIR}/man1/mdbx_chk.1" "${MDBX_SOURCE_DIR}/man1/mdbx_stat.1" "${MDBX_SOURCE_DIR}/man1/mdbx_copy.1" "${MDBX_SOURCE_DIR}/man1/mdbx_dump.1" "${MDBX_SOURCE_DIR}/man1/mdbx_load.1" DESTINATION ${MDBX_MAN_INSTALL_DESTINATION} COMPONENT doc) endif() endif(MDBX_BUILD_TOOLS) # mdbx-static-lib installation if(MDBX_INSTALL_STATIC) if(CMAKE_VERSION VERSION_LESS 3.12) install(TARGETS mdbx-static EXPORT libmdbx LIBRARY DESTINATION lib COMPONENT devel OBJECTS DESTINATION lib COMPONENT devel ARCHIVE DESTINATION lib COMPONENT devel PUBLIC_HEADER DESTINATION include COMPONENT devel INCLUDES DESTINATION include COMPONENT devel) else() install(TARGETS mdbx-static EXPORT libmdbx LIBRARY DESTINATION lib COMPONENT devel NAMELINK_COMPONENT devel OBJECTS DESTINATION lib COMPONENT devel ARCHIVE DESTINATION lib COMPONENT devel PUBLIC_HEADER DESTINATION include COMPONENT devel INCLUDES DESTINATION include COMPONENT devel) endif() endif(MDBX_INSTALL_STATIC) ################################################################################ # collect options & build info string(TIMESTAMP MDBX_BUILD_TIMESTAMP UTC) set(MDBX_BUILD_FLAGS ${CMAKE_C_FLAGS}) if(MDBX_BUILD_CXX) set(MDBX_BUILD_FLAGS ${CMAKE_CXX_FLAGS}) endif() # append cmake's build-type flags and defines if(NOT CMAKE_CONFIGURATION_TYPES) list(APPEND MDBX_BUILD_FLAGS ${CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE_UPPERCASE}}) if(MDBX_BUILD_CXX) list(APPEND MDBX_BUILD_FLAGS ${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE_UPPERCASE}}) endif() endif() # choice target to fetch definitions and options if(MDBX_BUILD_SHARED_LIBRARY) set(target4fetch mdbx) else() set(target4fetch mdbx-static) endif() # get definitions get_target_property(defs_list ${target4fetch} COMPILE_DEFINITIONS) if(defs_list) list(APPEND MDBX_BUILD_FLAGS ${defs_list}) endif() # get target compile options get_target_property(options_list ${target4fetch} COMPILE_OPTIONS) if(options_list) list(APPEND MDBX_BUILD_FLAGS ${options_list}) endif() list(REMOVE_DUPLICATES MDBX_BUILD_FLAGS) string(REPLACE ";" " " MDBX_BUILD_FLAGS "${MDBX_BUILD_FLAGS}") if(CMAKE_CONFIGURATION_TYPES) # add dynamic part via per-configuration define message(STATUS "MDBX Compile Flags: ${MDBX_BUILD_FLAGS} ") add_definitions(-DMDBX_BUILD_FLAGS_CONFIG="$<$:${CMAKE_C_FLAGS_DEBUG} ${CMAKE_C_DEFINES_DEBUG}>$<$:${CMAKE_C_FLAGS_RELEASE} ${CMAKE_C_DEFINES_RELEASE}>$<$:${CMAKE_C_FLAGS_RELWITHDEBINFO} ${CMAKE_C_DEFINES_RELWITHDEBINFO}>$<$:${CMAKE_C_FLAGS_MINSIZEREL} ${CMAKE_C_DEFINES_MINSIZEREL}>") else() message(STATUS "MDBX Compile Flags: ${MDBX_BUILD_FLAGS}") endif() # get compiler info execute_process(COMMAND sh -c "${CMAKE_C_COMPILER} --version | head -1" OUTPUT_VARIABLE MDBX_BUILD_COMPILER OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET RESULT_VARIABLE rc) if(rc OR NOT MDBX_BUILD_COMPILER) string(STRIP "${CMAKE_C_COMPILER_ID}-${CMAKE_C_COMPILER_VERSION}" MDBX_BUILD_COMPILER) endif() # make a build-target triplet if(CMAKE_C_COMPILER_TARGET) set(MDBX_BUILD_TARGET "${CMAKE_C_COMPILER_TARGET}") elseif(CMAKE_C_PLATFORM_ID AND NOT CMAKE_C_PLATFORM_ID STREQUAL CMAKE_SYSTEM_NAME) string(STRIP "${CMAKE_C_PLATFORM_ID}-${CMAKE_SYSTEM_NAME}" MDBX_BUILD_TARGET) elseif(CMAKE_LIBRARY_ARCHITECTURE) string(STRIP "${CMAKE_LIBRARY_ARCHITECTURE}-${CMAKE_SYSTEM_NAME}" MDBX_BUILD_TARGET) elseif(CMAKE_GENERATOR_PLATFORM AND NOT CMAKE_C_PLATFORM_ID STREQUAL CMAKE_SYSTEM_NAME) string(STRIP "${CMAKE_GENERATOR_PLATFORM}-${CMAKE_SYSTEM_NAME}" MDBX_BUILD_TARGET) elseif(CMAKE_SYSTEM_ARCH) string(STRIP "${CMAKE_SYSTEM_ARCH}-${CMAKE_SYSTEM_NAME}" MDBX_BUILD_TARGET) else() string(STRIP "${CMAKE_SYSTEM_PROCESSOR}-${CMAKE_SYSTEM_NAME}" MDBX_BUILD_TARGET) endif() # provide build-type if(CMAKE_CONFIGURATION_TYPES) # via per-configuration define add_definitions(-DMDBX_BUILD_TYPE="$") set(MDBX_BUILD_TYPE "") else() set(MDBX_BUILD_TYPE ${CMAKE_BUILD_TYPE}) endif() # options set(options VERSION C_COMPILER CXX_COMPILER MDBX_BUILD_TARGET MDBX_BUILD_TYPE) foreach(item IN LISTS options) if(DEFINED ${item}) set(value "${${item}}") elseif(DEFINED MDBX_${item}) set(item MDBX_${item}) set(value "${${item}}") elseif(DEFINED CMAKE_${item}) set(item CMAKE_${item}) set(value "${${item}}") else() set(value "undefined") endif() message(STATUS "${item}: ${value}") endforeach(item) # provide config.h for library build info configure_file("${MDBX_SOURCE_DIR}/config.h.in" "${CMAKE_CURRENT_BINARY_DIR}/config.h" ESCAPE_QUOTES) add_definitions(-DMDBX_CONFIG_H="${CMAKE_CURRENT_BINARY_DIR}/config.h") ################################################################################ if(NOT MDBX_AMALGAMATED_SOURCE AND MDBX_ENABLE_TESTS) if(NOT CMAKE_CXX_COMPILER_LOADED) message(FATAL_ERROR "MDBX_ENABLE_TESTS=${MDBX_ENABLE_TESTS}: The C++ compiler is required to build the tests.") endif() add_subdirectory(test) endif() ################################################################################ set(PACKAGE "libmdbx") set(CPACK_PACKAGE_VERSION_MAJOR ${MDBX_VERSION_MAJOR}) set(CPACK_PACKAGE_VERSION_MINOR ${MDBX_VERSION_MINOR}) set(CPACK_PACKAGE_VERSION_PATCH ${MDBX_VERSION_RELEASE}) set(CPACK_PACKAGE_VERSION_COMMIT ${MDBX_VERSION_REVISION}) set(PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}.${CPACK_PACKAGE_VERSION_COMMIT}") message(STATUS "libmdbx package version is ${PACKAGE_VERSION}") cmake_policy(POP)