blob: a301d87ff75c71099e7cc8e2b90aa7bc7651cca9 [file] [log] [blame]
# The MIT License (MIT)
#
# Copyright (c) 2015 Microsoft Corporation
#
# -=- Robust Distributed System Nucleus (rDSN) -=-
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# Helper function to add preprocesor definition of FILE_BASENAME
# to pass the filename without directory path for debugging use.
#
# Note that in header files this is not consistent with
# __FILE__ and __LINE__ since FILE_BASENAME will be the
# compilation unit source file name (.c/.cpp).
#
# Example:
#
# define_file_basename_for_sources(my_target)
#
# Will add -DFILE_BASENAME="filename" for each source file depended on
# by my_target, where filename is the name of the file.
#
function(define_file_basename_for_sources targetname)
get_target_property(source_files "${targetname}" SOURCES)
foreach(sourcefile ${source_files})
# Add the FILE_BASENAME=filename compile definition to the list.
get_filename_component(basename "${sourcefile}" NAME)
# Set the updated compile definitions on the source file.
set_property(
SOURCE "${sourcefile}" APPEND
PROPERTY COMPILE_DEFINITIONS "__FILENAME__=\"${basename}\"")
endforeach()
endfunction()
# Install this target into ${CMAKE_INSTALL_PREFIX}/lib
function(dsn_install_library)
install(TARGETS ${MY_PROJ_NAME} DESTINATION "lib")
endfunction()
# Install this target into ${CMAKE_INSTALL_PREFIX}/bin/${PROJ_NAME}
function(dsn_install_executable)
set(MY_PROJ_TYPE "EXECUTABLE")
set(INSTALL_DIR "bin/${MY_PROJ_NAME}")
install(TARGETS ${MY_PROJ_NAME} DESTINATION "${INSTALL_DIR}")
# install the extra files together with the executable
if(NOT (MY_BINPLACES STREQUAL ""))
foreach(BF ${MY_BINPLACES})
install(FILES ${BF} DESTINATION "${INSTALL_DIR}")
endforeach()
endif()
endfunction()
function(ms_add_project PROJ_TYPE PROJ_NAME PROJ_SRC PROJ_LIBS PROJ_BINPLACES)
if(NOT((PROJ_TYPE STREQUAL "STATIC") OR (PROJ_TYPE STREQUAL "SHARED") OR
(PROJ_TYPE STREQUAL "EXECUTABLE") OR (PROJ_TYPE STREQUAL "OBJECT")))
message(FATAL_ERROR "Invalid project type.")
endif()
if(PROJ_SRC STREQUAL "")
message(FATAL_ERROR "No source files.")
endif()
if((PROJ_TYPE STREQUAL "STATIC") OR (PROJ_TYPE STREQUAL "OBJECT"))
add_library(${PROJ_NAME} ${PROJ_TYPE} ${PROJ_SRC})
elseif(PROJ_TYPE STREQUAL "SHARED")
add_library(${PROJ_NAME} ${PROJ_TYPE} ${PROJ_SRC})
elseif(PROJ_TYPE STREQUAL "EXECUTABLE")
add_executable(${PROJ_NAME} ${PROJ_SRC})
endif()
if((PROJ_TYPE STREQUAL "SHARED") OR (PROJ_TYPE STREQUAL "EXECUTABLE"))
if(PROJ_TYPE STREQUAL "SHARED")
set(LINK_MODE PRIVATE)
else()
set(LINK_MODE PUBLIC)
endif()
target_link_libraries(${PROJ_NAME} "${LINK_MODE}" ${PROJ_LIBS})
endif()
endfunction(ms_add_project)
# Parameters:
# - MY_PROJ_TYPE
# - MY_PROJ_NAME
# - MY_SRC_SEARCH_MODE
# Search mode for source files under current project directory
# "GLOB_RECURSE" for recursive search
# "GLOB" for non-recursive search
# - MY_PROJ_SRC
# - MY_PROJ_LIBS
# - MY_BINPLACES
# Extra files that will be installed
# - MY_BOOST_LIBS
function(dsn_add_project)
if((NOT DEFINED MY_PROJ_TYPE) OR (MY_PROJ_TYPE STREQUAL ""))
message(FATAL_ERROR "MY_PROJ_TYPE is empty.")
endif()
if((NOT DEFINED MY_PROJ_NAME) OR (MY_PROJ_NAME STREQUAL ""))
message(FATAL_ERROR "MY_PROJ_NAME is empty.")
endif()
if(NOT DEFINED MY_SRC_SEARCH_MODE)
set(MY_SRC_SEARCH_MODE "GLOB")
endif()
# find source files from current directory
if(NOT DEFINED MY_PROJ_SRC)
set(MY_PROJ_SRC "")
endif()
set(TEMP_SRC "")
# We restrict the file suffix to keep our codes consistent.
file(${MY_SRC_SEARCH_MODE} TEMP_SRC
"${CMAKE_CURRENT_SOURCE_DIR}/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/*.c"
)
set(MY_PROJ_SRC ${TEMP_SRC} ${MY_PROJ_SRC})
if(NOT DEFINED MY_PROJ_LIBS)
set(MY_PROJ_LIBS "")
endif()
if(NOT DEFINED MY_BINPLACES)
set(MY_BINPLACES "")
endif()
if(NOT DEFINED MY_BOOST_LIBS)
set(MY_BOOST_LIBS "")
endif()
if((MY_PROJ_TYPE STREQUAL "SHARED") OR (MY_PROJ_TYPE STREQUAL "EXECUTABLE"))
set(MY_PROJ_LIBS ${MY_PROJ_LIBS} ${DEFAULT_THIRDPARTY_LIBS} ${MY_BOOST_LIBS} ${DSN_SYSTEM_LIBS})
endif()
ms_add_project("${MY_PROJ_TYPE}" "${MY_PROJ_NAME}" "${MY_PROJ_SRC}" "${MY_PROJ_LIBS}" "${MY_BINPLACES}")
define_file_basename_for_sources(${MY_PROJ_NAME})
endfunction(dsn_add_project)
function(dsn_add_static_library)
set(MY_PROJ_TYPE "STATIC")
dsn_add_project()
dsn_install_library()
endfunction(dsn_add_static_library)
function(dsn_add_shared_library)
set(MY_PROJ_TYPE "SHARED")
dsn_add_project()
dsn_install_library()
endfunction(dsn_add_shared_library)
function(dsn_add_executable)
set(MY_PROJ_TYPE "EXECUTABLE")
dsn_add_project()
endfunction(dsn_add_executable)
function(dsn_add_object)
set(MY_PROJ_TYPE "OBJECT")
dsn_add_project()
endfunction(dsn_add_object)
function(dsn_add_test)
if(${BUILD_TEST})
add_definitions(-DGTEST_HAS_TR1_TUPLE=0 -DGTEST_USE_OWN_TR1_TUPLE=0)
set(MY_EXECUTABLE_IS_TEST TRUE)
dsn_add_executable()
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
execute_process(COMMAND ln -sf ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_BINARY_DIR}/bin/${MY_PROJ_NAME})
# copy the extra files together with the executable
if(NOT (MY_BINPLACES STREQUAL ""))
foreach(BF ${MY_BINPLACES})
FILE(COPY ${BF} DESTINATION "${CMAKE_BINARY_DIR}/bin/${MY_PROJ_NAME}")
endforeach()
endif()
endif()
endfunction()
function(dsn_setup_compiler_flags)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
add_definitions(-DDSN_BUILD_TYPE=Debug)
add_definitions(-g)
else()
add_definitions(-g)
add_definitions(-O2)
add_definitions(-DDSN_BUILD_TYPE=Release)
endif()
cmake_host_system_information(RESULT BUILD_HOSTNAME QUERY HOSTNAME)
add_definitions(-DDSN_BUILD_HOSTNAME=${BUILD_HOSTNAME})
# We want access to the PRI* print format macros.
add_definitions(-D__STDC_FORMAT_MACROS)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y" CACHE STRING "" FORCE)
# -Wall: Enable all warnings.
add_compile_options(-Wall)
add_compile_options(-Werror)
# -Wno-sign-compare: suppress warnings for comparison between signed and unsigned integers
add_compile_options(-Wno-sign-compare)
add_compile_options(-Wno-strict-aliasing)
add_compile_options(-Wuninitialized)
add_compile_options(-Wno-unused-result)
add_compile_options(-Wno-unused-variable)
add_compile_options(-Wno-deprecated-declarations)
add_compile_options(-Wno-inconsistent-missing-override)
add_compile_options(-Wno-attributes)
# -fno-omit-frame-pointer
# use frame pointers to allow simple stack frame walking for backtraces.
# This has a small perf hit but worth it for the ability to profile in production
add_compile_options( -fno-omit-frame-pointer)
# -Wno-deprecated-register
# kbr5.h uses the legacy 'register' keyword.
add_compile_options(-Wno-deprecated-register)
# -Wno-implicit-float-conversion
# Poco/Dynamic/VarHolder.h uses 'unsigned long' to 'float' conversion
add_compile_options(-Wno-implicit-float-conversion)
find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
if ("${COMPILER_FAMILY}" STREQUAL "clang")
add_compile_options(-Qunused-arguments)
endif()
message(STATUS "use ccache to speed up compilation")
endif(CCACHE_FOUND)
# add sanitizer check
if(DEFINED SANITIZER)
if(NOT (("${COMPILER_FAMILY}" STREQUAL "clang") OR
("${COMPILER_FAMILY}" STREQUAL "gcc" AND "${COMPILER_VERSION}" VERSION_GREATER "5.4.0")))
message(SEND_ERROR "Cannot use sanitizer without clang or gcc >= 5.4.0")
endif()
message(STATUS "Running cmake with sanitizer=${SANITIZER}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=${SANITIZER}" CACHE STRING "" FORCE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=${SANITIZER}" CACHE STRING "" FORCE)
endif()
set(CMAKE_EXE_LINKER_FLAGS
"${CMAKE_EXE_LINKER_FLAGS} -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free"
CACHE
STRING
""
FORCE)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free"
CACHE
STRING
""
FORCE)
endfunction(dsn_setup_compiler_flags)
# find necessary system libs
function(dsn_setup_system_libs)
find_package(Threads REQUIRED)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS ON)
message(STATUS "FIND_LIBRARY_USE_LIB64_PATHS = ON")
endif()
set(DSN_SYSTEM_LIBS "")
if (NOT APPLE)
find_package(RT REQUIRED)
set(DSN_SYSTEM_LIBS ${DSN_SYSTEM_LIBS} ${RT_LIBRARIES})
endif()
find_package(DL REQUIRED)
set(DSN_SYSTEM_LIBS ${DSN_SYSTEM_LIBS} ${DL_LIBRARIES})
# for md5 calculation
find_package(OpenSSL REQUIRED)
set(DSN_SYSTEM_LIBS ${DSN_SYSTEM_LIBS} ${OPENSSL_CRYPTO_LIBRARY})
if (NOT APPLE)
if(ENABLE_GPERF)
set(DSN_SYSTEM_LIBS ${DSN_SYSTEM_LIBS} tcmalloc_and_profiler)
add_definitions(-DDSN_ENABLE_GPERF)
endif()
endif()
if(USE_JEMALLOC)
find_package(Jemalloc REQUIRED)
# also use cpu profiler provided by gperftools
set(DSN_SYSTEM_LIBS ${DSN_SYSTEM_LIBS} JeMalloc::JeMalloc profiler)
add_definitions(-DDSN_USE_JEMALLOC)
endif()
set(DSN_SYSTEM_LIBS
${DSN_SYSTEM_LIBS}
${CMAKE_THREAD_LIBS_INIT} # the thread library found by FindThreads
CACHE STRING "rDSN system libs" FORCE
)
endfunction(dsn_setup_system_libs)
function(dsn_setup_include_path)#TODO(huangwei5): remove this
include_directories(${THIRDPARTY_INSTALL_DIR}/include)
endfunction(dsn_setup_include_path)
function(dsn_setup_thirdparty_libs)
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_STATIC_RUNTIME OFF)
set(BOOST_ROOT ${THIRDPARTY_INSTALL_DIR})
set(Boost_NO_SYSTEM_PATHS ON)
set(Boost_NO_BOOST_CMAKE ON)
set(CMAKE_PREFIX_PATH ${THIRDPARTY_INSTALL_DIR};${CMAKE_PREFIX_PATH})
message(STATUS "CMAKE_PREFIX_PATH = ${CMAKE_PREFIX_PATH}")
find_package(Boost COMPONENTS system filesystem regex REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})
find_library(THRIFT_LIB NAMES libthrift.a PATHS ${THIRDPARTY_INSTALL_DIR}/lib NO_DEFAULT_PATH)
if(NOT THRIFT_LIB)
message(FATAL_ERROR "thrift library not found in ${THIRDPARTY_INSTALL_DIR}/lib")
endif()
find_package(fmt REQUIRED)
set(DEFAULT_THIRDPARTY_LIBS ${THRIFT_LIB} fmt::fmt CACHE STRING "default thirdparty libs" FORCE)
# rocksdb
file(GLOB ROCKSDB_DEPENDS_MODULE_PATH ${THIRDPARTY_ROOT}/build/Source/rocksdb/cmake/modules)
if(NOT ROCKSDB_DEPENDS_MODULE_PATH)
message(WARNING "Cannot find RocksDB depends cmake modules path, might not find snappy, zstd, lz4")
endif()
list(APPEND CMAKE_MODULE_PATH "${ROCKSDB_DEPENDS_MODULE_PATH}")
find_package(snappy)
find_package(zstd)
find_package(lz4)
if(USE_JEMALLOC)
find_package(Jemalloc REQUIRED)
endif()
find_package(RocksDB REQUIRED)
# libhdfs
find_package(JNI REQUIRED)
message (STATUS "JAVA_JVM_LIBRARY=${JAVA_JVM_LIBRARY}")
link_libraries(${JAVA_JVM_LIBRARY})
link_directories(${THIRDPARTY_INSTALL_DIR}/lib)
if (NOT APPLE)
link_directories(${THIRDPARTY_INSTALL_DIR}/lib64)
endif()
if (APPLE)
include_directories(SYSTEM ${MACOS_OPENSSL_ROOT_DIR}/include)
link_directories(${MACOS_OPENSSL_ROOT_DIR}/lib)
message (STATUS "MACOS_OPENSSL_ROOT_DIR: ${MACOS_OPENSSL_ROOT_DIR}")
endif()
endfunction(dsn_setup_thirdparty_libs)
function(dsn_common_setup)
if(NOT (UNIX))
message(FATAL_ERROR "Only Unix are supported.")
endif()
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
message(FATAL_ERROR "In-source builds are not allowed.")
endif()
find_program(CCACHE "ccache")
if(CCACHE)
set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE})
set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE})
message(STATUS "CCACHE: ${CCACHE}")
set(ENV{CCACHE_COMPRESS} "true")
set(ENV{CCACHE_COMPRESSLEVEL} "6")
set(ENV{CCACHE_MAXSIZE} "1024M")
endif(CCACHE)
if(NOT DEFINED DSN_BUILD_RUNTIME)
set(DSN_BUILD_RUNTIME FALSE)
endif()
set(BUILD_SHARED_LIBS OFF)
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++1y" COMPILER_SUPPORTS_CXX1Y)
if(NOT ${COMPILER_SUPPORTS_CXX1Y})
message(FATAL_ERROR "You need a compiler with C++1y support.")
endif()
dsn_setup_system_libs()
dsn_setup_compiler_flags()
dsn_setup_include_path()
dsn_setup_thirdparty_libs()
include(ThriftUtils)
endfunction(dsn_common_setup)