cmake_minimum_required(VERSION 2.8) project(tarantool C CXX) set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) set(CMAKE_INCLUDE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_INCLUDE_PATH}) include(CheckLibraryExists) include(CheckIncludeFile) include(CheckCCompilerFlag) include(CheckSymbolExists) include(CheckCSourceRuns) include(CheckCXXSourceRuns) include(CheckCSourceCompiles) include(CheckCXXSourceCompiles) include(TestBigEndian) include(CheckFunctionExists) include(FindOptionalPackage) include(FindPackageMessage) find_program(ECHO echo) find_program(XSLTPROC xsltproc) find_program(XMLLINT xmllint) find_program(JING jing) find_program(LYNX lynx) find_program(CAT cat) find_program(GIT git) find_program(LD ld) find_program(CTAGS ctags) # Define PACKAGE macro in tarantool/config.h set (PACKAGE "Tarantool") # # Set default build type to Debug. This is to ease a developer's # life. Release binaries are built by BuildBot automatically anyway. # if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." FORCE) endif() # Define GNU standard installation directories include(GNUInstallDirs) include(cmake/utils.cmake) include(cmake/pod2man.cmake) # the order is significant: we need to know os and compiler to configure libs include(cmake/arch.cmake) include(cmake/os.cmake) include(cmake/compiler.cmake) include(cmake/simd.cmake) include(cmake/atomic.cmake) include(cmake/profile.cmake) include(cmake/FindSphinx.cmake) include(cmake/module.cmake) include(cmake/thread.cmake) option(ENABLE_VALGRIND "Enable integration with valgrind, a memory analyzing tool" OFF) check_symbol_exists(MAP_ANON sys/mman.h HAVE_MAP_ANON) check_symbol_exists(MAP_ANONYMOUS sys/mman.h HAVE_MAP_ANONYMOUS) check_include_file(sys/time.h HAVE_SYS_TIME_H) check_include_file(unwind.h HAVE_UNWIND_H) check_include_file(cpuid.h HAVE_CPUID_H) check_include_file(sys/prctl.h HAVE_PRCTL_H) check_symbol_exists(O_DSYNC fcntl.h HAVE_O_DSYNC) check_symbol_exists(fdatasync unistd.h HAVE_FDATASYNC) check_symbol_exists(pthread_yield pthread.h HAVE_PTHREAD_YIELD) check_symbol_exists(sched_yield sched.h HAVE_SCHED_YIELD) check_function_exists(memmem HAVE_MEMMEM) check_function_exists(memrchr HAVE_MEMRCHR) check_function_exists(sendfile HAVE_SENDFILE) if (HAVE_SENDFILE) if (TARGET_OS_LINUX) set(HAVE_SENDFILE_LINUX 1) else(HAVE_SENDFILE) set(HAVE_SENDFILE_BSD 1) endif() endif() check_function_exists(open_memstream HAVE_OPEN_MEMSTREAM) check_function_exists(fmemopen HAVE_FMEMOPEN) check_function_exists(funopen HAVE_FUNOPEN) check_function_exists(fopencookie HAVE_FOPENCOOKIE) check_function_exists(uuidgen HAVE_UUIDGEN) # # clock_gettime() is not defined on Mac OS X, # or own (slow) implementation is in third_party/clock_gettime.c # if (TARGET_OS_LINUX) check_library_exists(rt clock_gettime "" HAVE_CLOCK_GETTIME) else() check_function_exists(clock_gettime HAVE_CLOCK_GETTIME) endif() # Checks for libev include(CheckStructHasMember) check_struct_has_member("struct stat" "st_mtim" "sys/stat.h" HAVE_STRUCT_STAT_ST_MTIM) check_struct_has_member("struct stat" "st_mtimensec" "sys/stat.h" HAVE_STRUCT_STAT_ST_MTIMENSEC) # # Some versions of GNU libc define non-portable __libc_stack_end # which we use to determine the end (or beginning, actually) of # stack. Find whether or not it's present. check_library_exists("" __libc_stack_end "" HAVE_LIBC_STACK_END) check_function_exists(setproctitle HAVE_SETPROCTITLE) check_function_exists(setprogname HAVE_SETPROGNAME) check_function_exists(getprogname HAVE_GETPROGNAME) # # Enable 'make tags' target. # add_custom_target(tags COMMAND ${CTAGS} -R -f tags WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) add_custom_target(ctags DEPENDS tags) # # Get version # set (PACKAGE_VERSION "") set (TARANTOOL_VERSION "") # Try to get version from VERSION file set(VERSION_FILE_ORIG "${PROJECT_SOURCE_DIR}/VERSION") set(VERSION_FILE "${PROJECT_BINARY_DIR}/VERSION") if (EXISTS "${VERSION_FILE_ORIG}") file (STRINGS "${VERSION_FILE_ORIG}" TARANTOOL_VERSION) elseif (EXISTS "${VERSION_FILE}") file (STRINGS "${VERSION_FILE}" TARANTOOL_VERSION) endif() # Get git version only if source directory has .git repository, this # avoids git to search .git repository in parent # directories. # if (EXISTS "${CMAKE_SOURCE_DIR}/.git") execute_process (COMMAND ${GIT} describe --long HEAD OUTPUT_VARIABLE TARANTOOL_GIT_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) if (NOT ("${TARANTOOL_GIT_VERSION}" STREQUAL "${TARANTOOL_VERSION}")) set(TARANTOOL_VERSION "${TARANTOOL_GIT_VERSION}") file(WRITE ${VERSION_FILE} "${TARANTOOL_VERSION}\n") message(STATUS "Generating VERSION file") endif() endif() if (NOT TARANTOOL_VERSION) message (FATAL_ERROR "Unable to retrive version from git or ${VERSION_FILE} file.") endif() # # Split full version (git describe --long) to get components # string(REPLACE "-" "." TARANTOOL_VERSION_LIST ${TARANTOOL_VERSION}) string(REPLACE "." ";" TARANTOOL_VERSION_LIST ${TARANTOOL_VERSION_LIST}) LIST(GET TARANTOOL_VERSION_LIST 0 CPACK_PACKAGE_VERSION_MAJOR) LIST(GET TARANTOOL_VERSION_LIST 1 CPACK_PACKAGE_VERSION_MINOR) LIST(GET TARANTOOL_VERSION_LIST 2 CPACK_PACKAGE_VERSION_PATCH) LIST(GET TARANTOOL_VERSION_LIST 3 CPACK_PACKAGE_VERSION_COMMIT) set(PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}") set(PACKAGE_VERSION "${PACKAGE_VERSION}.${CPACK_PACKAGE_VERSION_MINOR}") set(PACKAGE_VERSION "${PACKAGE_VERSION}.${CPACK_PACKAGE_VERSION_PATCH}") set(PACKAGE_VERSION "${PACKAGE_VERSION}.${CPACK_PACKAGE_VERSION_COMMIT}") find_package_message(TARANTOOL_VERSION "Tarantool version is ${TARANTOOL_VERSION} (${PACKAGE_VERSION})" "${PACKAGE_VERSION}") # # Specify where to look for include files. # include_directories(${PROJECT_SOURCE_DIR}/src) include_directories(${PROJECT_BINARY_DIR}/src) include_directories(${PROJECT_SOURCE_DIR}/src/lib) include_directories(${PROJECT_SOURCE_DIR}/src/lib/small) include_directories(${PROJECT_SOURCE_DIR}) # # Specify Tarantool modules prefixes # set(MODULE_SUFFIX "tarantool") set(MODULE_LIBDIR "${CMAKE_INSTALL_LIBDIR}/${MODULE_SUFFIX}") set(MODULE_LUADIR "${CMAKE_INSTALL_DATADIR}/${MODULE_SUFFIX}") set(MODULE_INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}/${MODULE_SUFFIX}") set(MODULE_FULL_LIBDIR "${CMAKE_INSTALL_FULL_LIBDIR}/${MODULE_SUFFIX}") set(MODULE_FULL_LUADIR "${CMAKE_INSTALL_FULL_DATADIR}/${MODULE_SUFFIX}") set(MODULE_FULL_INCLUDEDIR "${CMAKE_INSTALL_FULL_INCLUDEDIR}/${MODULE_SUFFIX}") include(cmake/multilib.cmake) set(_datadirs) list(APPEND _datadirs "/usr/local/share") # LuaRocks list(APPEND _datadirs "${CMAKE_INSTALL_FULL_DATADIR}") # Install prefix if(NOT CMAKE_CROSSCOMPILING AND EXISTS "/etc/gentoo-release") # LuaRocks on Gentoo list(APPEND _datadirs "/usr/${MULTILIB}/lua/luarocks/share") endif() list(APPEND _datadirs "/usr/share") # System packages list(REMOVE_DUPLICATES _datadirs) set(MODULE_LUAPATH) foreach(dir "${MODULE_SUFFIX}" "lua/5.1") foreach(prefix IN LISTS _datadirs) list(APPEND MODULE_LUAPATH "${prefix}/${dir}/?.lua") list(APPEND MODULE_LUAPATH "${prefix}/${dir}/?/init.lua") endforeach() endforeach() set(_libdirs) list(APPEND _libdirs "/usr/local/${MULTILIB}") # LuaRocks list(APPEND _libdirs "${CMAKE_INSTALL_FULL_LIBDIR}") # Install prefix if(NOT CMAKE_CROSSCOMPILING AND EXISTS "/etc/debian_version") # gh-1085: LuaRocks on Debian uses lib instead of lib/x86_64-linux-gnu/ list(APPEND _libdirs "/usr/local/lib") # LuaRocks on Debian endif() if(NOT CMAKE_CROSSCOMPILING AND EXISTS "/etc/gentoo-release") # LuaRocks on Gentoo list(APPEND _libdirs "/usr/${MULTILIB}/lua/luarocks/lib") endif() list(APPEND _libdirs "/usr/${MULTILIB}") # System packages list(REMOVE_DUPLICATES _libdirs) set(MODULE_LIBPATH) foreach(dir "${MODULE_SUFFIX}" "lua/5.1") foreach(prefix IN LISTS _libdirs) list(APPEND MODULE_LIBPATH "${prefix}/${dir}/?${CMAKE_SHARED_MODULE_SUFFIX}") endforeach() endforeach() find_package_message(MODULE_LUAPATH "Lua package.path: ${MODULE_LUAPATH}" "${MODULE_LUAPATH}") find_package_message(MODULE_LIBPATH "Lua package.cpath: ${MODULE_LIBPATH}" "${MODULE_LIBPATH}") # # Now handle all configuration options. # option(ENABLE_DOC "Enable building of documentation" OFF) option(ENABLE_TRACE "Enable debug trace of tarantool_box execution to a file specified in TARANTOOL_TRACE environment variable" ON) option(ENABLE_BACKTRACE "Enable output of fiber backtrace information in 'show fiber' administrative command. Only works on x86 architectures, if compiled with gcc. If GNU binutils and binutils-dev libraries are installed, backtrace is output with resolved function (symbol) names. Otherwise only frame addresses are printed." ${CMAKE_COMPILER_IS_GNUCC}) set (HAVE_BFD False) if (ENABLE_BACKTRACE) if (NOT ${CMAKE_COMPILER_IS_GNUCC}) # We only know this option to work with gcc message (FATAL_ERROR "ENABLE_BACKTRACE option is set but the system is not x86 based (${CMAKE_SYSTEM_PROCESSOR}) or the compiler is not GNU GCC (${CMAKE_C_COMPILER}).") endif() # Use GNU bfd if present. check_library_exists (bfd bfd_init "" HAVE_BFD_LIB) check_library_exists (iberty cplus_demangle "" HAVE_IBERTY_LIB) set(CMAKE_REQUIRED_DEFINITIONS -DPACKAGE=${PACKAGE} -DPACKAGE_VERSION=${PACKAGE_VERSION}) check_include_file(bfd.h HAVE_BFD_H) set(CMAKE_REQUIRED_DEFINITIONS) if (HAVE_BFD_LIB AND HAVE_BFD_H AND HAVE_IBERTY_LIB) set (HAVE_BFD True) endif() endif() ## ## Third-Party libraries ## # # Since we *optionally* build bundled libs, a direct build # dependency between tarantool_box and libluajit/libobjc won't # work: add an empty custom target for this dependency instead. # If a bundled objc or luajit is built, it is added to the # dependency list of build_bundled_libs target. # add_custom_target(build_bundled_libs) # # ReadLine # set(Readline_FIND_REQUIRED ON) find_package(Readline) # # LuaJIT # # Patched. # set(ENABLE_BUNDLED_LUAJIT ON) include(luajit) # # LibEV # # Patched. # set(ENABLE_BUNDLED_LIBEV ON) include(BuildLibEV) libev_build() add_dependencies(build_bundled_libs ev) # # LibEIO # # Patched. # #option(ENABLE_BUNDLED_LIBEIO "Enable building of the bundled libeio" ON) set(ENABLE_BUNDLED_LIBEIO ON) if (ENABLE_BUNDLED_LIBEIO) include(BuildLibEIO) libeio_build() add_dependencies(build_bundled_libs eio) else() set(LIBEIO_FIND_REQUIRED ON) find_package(LibEIO) endif() # # LibCORO # # # Tarantool uses 'coro' (coroutines) library to implement # cooperative multi-tasking. Since coro.h is included # universally, define the underlying implementation switch # in the top level CMakeLists.txt, to ensure a consistent # header file layout across the entire project. # set(ENABLE_BUNDLED_LIBCORO ON) include(BuildLibCORO) libcoro_build() add_dependencies(build_bundled_libs coro) # # LibGOPT # include(BuildLibGOPT) libgopt_build() add_dependencies(build_bundled_libs gopt) # # MsgPuck # option(ENABLE_BUNDLED_MSGPUCK "Enable building of the bundled MsgPuck" ON) if (ENABLE_BUNDLED_MSGPUCK) add_library(msgpuck STATIC src/lib/msgpuck/msgpuck.c) set(MSGPUCK_LIBRARIES msgpuck) set(MSGPUCK_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/src/lib/msgpuck) find_package_message(MsgPuck "Using bundled MsgPuck" "${MSGPUCK_LIBRARIES}:${MSGPUCK_INCLUDE_DIRS}") else() set(MsgPuck_FIND_REQUIRED ON) find_package(MsgPuck) endif() # # LibYAML # option(ENABLE_BUNDLED_LIBYAML "Enable building of the bundled libyaml" ON) if (ENABLE_BUNDLED_LIBYAML) include(BuildLibYAML) libyaml_build() add_dependencies(build_bundled_libs yaml) else() set(LIBYAML_FIND_REQUIRED ON) find_package(LibYAML) endif() # # Third-Party misc # include(BuildMisc) libmisc_build() add_dependencies(build_bundled_libs misc) # # Sophia # include(BuildSophia) sophia_build() # cpack config. called package.cmake to avoid # conflicts with the global CPack.cmake (On MacOS X # file names are case-insensitive) # include (cmake/package.cmake) # # RPM build environment # CPACK is only used for .tar.gz package generation. # To build an RPM we need a source package, # so rpm.cmake depends on package.cmake. # include (cmake/rpm.cmake) add_subdirectory(src) add_subdirectory(extra) add_subdirectory(test) add_subdirectory(doc) # # tarantool info summary (used in server version output) # set(TARANTOOL_OPTIONS "-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}") set(TARANTOOL_OPTIONS "${TARANTOOL_OPTIONS} -DENABLE_TRACE=${ENABLE_TRACE} -DENABLE_BACKTRACE=${ENABLE_BACKTRACE}") set(TARANTOOL_BUILD "${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}-${CMAKE_BUILD_TYPE}") set(TARANTOOL_C_COMPILER ${CMAKE_C_COMPILER}) set(TARANTOOL_CXX_COMPILER ${CMAKE_CXX_COMPILER}) # # Output compile-time defines into config.h. Do it at the end # of the script to make sure all variables are set. # configure_file( "${PROJECT_SOURCE_DIR}/src/trivia/config.h.cmake" "${PROJECT_BINARY_DIR}/src/trivia/config.h" ) message (STATUS "") set(PREFIX ${CMAKE_INSTALL_PREFIX}) set(options VERSION BUILD C_COMPILER CXX_COMPILER C_FLAGS CXX_FLAGS PREFIX ENABLE_SSE2 ENABLE_AVX ENABLE_GCOV ENABLE_GPROF ENABLE_VALGRIND ENABLE_TRACE ENABLE_BACKTRACE ENABLE_DOC ENABLE_DIST ENABLE_BUNDLED_LIBYAML ENABLE_BUNDLED_MSGPUCK) foreach(option IN LISTS options) if (NOT DEFINED ${option}) set(value "${TARANTOOL_${option}}") else () set(value "${${option}}") endif () find_package_message("${option}" "${option}: ${value}" "${value}") endforeach(option) list_optional_packages() message (STATUS "")