Tarantool development patches archive
 help / color / mirror / Atom feed
* [tarantool-patches] [PATCH v3] Tarantool static build ability
@ 2018-08-28 20:06 Georgy Kirichenko
  2018-08-29  1:25 ` [tarantool-patches] " Alexander Turenko
  0 siblings, 1 reply; 3+ messages in thread
From: Georgy Kirichenko @ 2018-08-28 20:06 UTC (permalink / raw)
  To: tarantool-patches; +Cc: Georgy Kirichenko

A possibility to build tarantool with included library dependencies.
Use the flag -DBUILD_STATIC=ON to build statically against curl, readline,
ncurses, icu and z.
Use the flag -DOPENSSL_USE_STATIC_LIBS=ON to build with static
openssl

Changes:
  * Add FindOpenSSL.cmake because some distributions do not support the use of
  openssl static libraries.
  * Find libssl before curl because of build dependency.
  * Catch all bundled libraries API and export then it in case of static
  build.
  * Rename crc32 internal functions to avoid a name clash with linked libraries.

Notes:
  * Bundled libyaml is not properly exported, use the system one.
  * Dockerfile to build static with docker is included

Fixes #3445
---
Changes in v3:
  - ixed comments as per review by Alexander Turenko

Changes in v2:
  - Fixed comments as per review by Alexander Turenko

https://github.com/tarantool/tarantool/issues/3445
https://github.com/tarantool/tarantool/tree/g.kirichenko/static-build
 CMakeLists.txt           |  51 +++--
 Dockerfile.staticbuild   |  99 +++++++++
 cmake/BuildMisc.cmake    |  10 +
 cmake/FindCURL.cmake     |  16 +-
 cmake/FindICU.cmake      |  22 +-
 cmake/FindLibYAML.cmake  |   8 +-
 cmake/FindOpenSSL.cmake  | 465 +++++++++++++++++++++++++++++++++++++++
 cmake/FindReadline.cmake |  23 +-
 cmake/FindTermcap.cmake  |   8 +-
 cmake/FindZSTD.cmake     |   7 +-
 cmake/compiler.cmake     |  42 ++--
 extra/mkexports          |  14 +-
 src/CMakeLists.txt       |  53 ++++-
 third_party/crc32.c      |   6 +-
 third_party/crc32.h      |   6 +-
 15 files changed, 766 insertions(+), 64 deletions(-)
 create mode 100644 Dockerfile.staticbuild
 create mode 100644 cmake/FindOpenSSL.cmake

diff --git a/CMakeLists.txt b/CMakeLists.txt
index d0cae0f01..a1dfb10b0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -286,6 +286,31 @@ find_package_message(MODULE_LIBPATH "Lua package.cpath: ${MODULE_LIBPATH}"
 
 add_custom_target(build_bundled_libs)
 
+# Debian: missing zstd_static.h in libzstd-dev
+# Fedora: not found
+# => use bundled version by default
+
+option(ENABLE_BUNDLED_ZSTD "Enable building of the bundled zstd" ON)
+if (ENABLE_BUNDLED_ZSTD)
+    include(BuildZSTD)
+    zstd_build()
+    add_dependencies(build_bundled_libs zstd)
+else()
+    set(ZSTD_FIND_REQUIRED ON)
+    find_package(ZSTD)
+endif()
+
+#
+# OpenSSL
+#
+find_package(OpenSSL)
+if (OPENSSL_FOUND)
+    message(STATUS "OpenSSL ${OPENSSL_VERSION} found")
+    include_directories(${OPENSSL_INCLUDE_DIR})
+else()
+    message(FATAL_ERROR "Could NOT find OpenSSL development files (libssl-dev/openssl-devel package)")
+endif()
+
 #
 # Curl
 #
@@ -398,32 +423,6 @@ endif()
 # zstd
 #
 
-# Debian: missing zstd_static.h in libzstd-dev
-# Fedora: not found
-# => use bundled version by default
-
-option(ENABLE_BUNDLED_ZSTD "Enable building of the bundled zstd" ON)
-if (ENABLE_BUNDLED_ZSTD)
-    include(BuildZSTD)
-    zstd_build()
-    add_dependencies(build_bundled_libs zstd)
-else()
-    set(ZSTD_FIND_REQUIRED ON)
-    find_package(ZSTD)
-endif()
-
-#
-# OpenSSL
-#
-
-find_package(OpenSSL)
-if (OPENSSL_FOUND)
-    message(STATUS "OpenSSL ${OPENSSL_VERSION} found")
-    include_directories(${OPENSSL_INCLUDE_DIR})
-else()
-    message(FATAL_ERROR "Could NOT find OpenSSL development files (libssl-dev/openssl-devel package)")
-endif()
-
 #
 # Third-Party misc
 #
diff --git a/Dockerfile.staticbuild b/Dockerfile.staticbuild
new file mode 100644
index 000000000..3e814c8f8
--- /dev/null
+++ b/Dockerfile.staticbuild
@@ -0,0 +1,99 @@
+FROM centos:7
+
+RUN yum install -y epel-release
+RUN yum install -y yum install https://centos7.iuscommunity.org/ius-release.rpm
+
+RUN set -x \
+    && yum -y install \
+        libstdc++ \
+        libstdc++-static \
+        readline \
+        openssl \
+        lz4 \
+        binutils \
+        ncurses \
+        libgomp \
+        lua \
+        curl \
+        tar \
+        zip \
+        unzip \
+        libunwind \
+        libcurl \
+    && yum -y install \
+        perl \
+        gcc-c++ \
+        cmake \
+        lz4-devel \
+        binutils-devel \
+        lua-devel \
+        make \
+        git \
+        autoconf \
+        automake \
+        libtool \
+        wget
+
+RUN yum -y install ncurses-static readline-static zlib-static pcre-static glibc-static
+
+RUN set -x && \
+    cd / && \
+    curl -O -L https://www.openssl.org/source/openssl-1.1.0h.tar.gz && \
+    tar -xvf openssl-1.1.0h.tar.gz && \
+    cd openssl-1.1.0h && \
+    ./config no-shared && \
+    make && make install
+
+RUN set -x && \
+    cd / && \
+    git clone https://github.com/curl/curl.git && \
+    cd curl && \
+    git checkout curl-7_59_0 && \
+    ./buildconf && \
+    LIBS=" -lssl -lcrypto -ldl" ./configure --enable-static --enable-shared --with-ssl && \
+    make -j && make install
+
+RUN set -x && \
+    cd / && \
+    wget http://download.icu-project.org/files/icu4c/62.1/icu4c-62_1-src.tgz && \
+    tar -xvf icu4c-62_1-src.tgz && \
+    cd icu/source && \
+    ./configure --with-data-packaging=static --enable-static --enable-shared && \
+    make && make install
+
+RUN set -x && \
+    cd / && \
+    curl -O -L http://download.savannah.nongnu.org/releases/libunwind/libunwind-1.3-rc1.tar.gz && \
+    tar -xvf libunwind-1.3-rc1.tar.gz && \
+    cd libunwind-1.3-rc1 && \
+    ./configure --enable-static --disable-shared && \
+    make && make install
+
+RUN set -x && \
+    cd / && \
+    wget http://pyyaml.org/download/libyaml/yaml-0.2.1.tar.gz && \
+    tar -xvf yaml-0.2.1.tar.gz && \
+    cd /yaml-0.2.1 && \
+    ./configure --enable-static --enable-shared && \
+    make -j && make install
+
+COPY . /tarantool
+
+RUN set -x && \
+    cd tarantool && \
+    git submodule init && \
+    git submodule update
+
+RUN set -x \
+    && (cd /tarantool; \
+       cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo \
+             -DENABLE_BUNDLED_LIBYAML:BOOL=OFF \
+             -DENABLE_DIST:BOOL=ON \
+             -DBUILD_STATIC=ON \
+             -DOPENSSL_USE_STATIC_LIBS=ON \
+             .) \
+    && make -C /tarantool -j
+
+RUN cd /tarantool && make install
+
+ENTRYPOINT /bin/bash
diff --git a/cmake/BuildMisc.cmake b/cmake/BuildMisc.cmake
index 20ecb4f63..937c2f568 100644
--- a/cmake/BuildMisc.cmake
+++ b/cmake/BuildMisc.cmake
@@ -33,5 +33,15 @@ macro(libmisc_build)
 
     add_library(misc STATIC ${misc_src})
 
+    if (HAVE_OPENMP)
+        target_compile_options(misc PRIVATE "-fopenmp")
+        if(BUILD_STATIC)
+            set(GOMP_LIBRARY libgomp.a)
+        else()
+            set(GOMP_LIBRARY gomp)
+        endif()
+        target_link_libraries(misc pthread ${GOMP_LIBRARY})
+    endif()
+
     unset(misc_src)
 endmacro(libmisc_build)
diff --git a/cmake/FindCURL.cmake b/cmake/FindCURL.cmake
index dc7dc0735..ed9856c40 100644
--- a/cmake/FindCURL.cmake
+++ b/cmake/FindCURL.cmake
@@ -16,6 +16,14 @@
 #   CURL_FOUND          - True if curl found.
 #   CURL_VERSION_STRING - the version of curl found (since CMake 2.8.8)
 
+if(BUILD_STATIC)
+    set(CURL_LIB_NAME libcurl.a)
+    set(Z_LIB_NAME libz.a)
+else()
+    set(CURL_LIB_NAME curl)
+    set(Z_LIB_NAME z)
+endif()
+
 if(DEFINED CURL_ROOT)
     set(CURL_FIND_OPTS NO_CMAKE NO_CMAKE_SYSTEM_PATH)
     set(CURL_FIND_LIBRARY_HINTS "${CURL_ROOT}/lib")
@@ -36,7 +44,7 @@ mark_as_advanced(CURL_INCLUDE_DIR)
 
 # Look for the library (sorted from most current/relevant entry to least).
 find_library(CURL_LIBRARY NAMES
-    curl
+    ${CURL_LIB_NAME}
   # Windows MSVC prebuilts:
     curllib
     libcurl_imp
@@ -65,10 +73,14 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(CURL
                                   REQUIRED_VARS CURL_LIBRARY CURL_INCLUDE_DIR
                                   VERSION_VAR CURL_VERSION_STRING)
 
+find_library(Z_LIBRARY NAMES
+    ${Z_LIB_NAME}
+)
+
 if(CURL_FOUND)
   set(CURL_LIBRARIES ${CURL_LIBRARY})
   set(CURL_INCLUDE_DIRS ${CURL_INCLUDE_DIR})
-  set(CMAKE_REQUIRED_LIBRARIES ${CURL_LIBRARIES})
+  set(CMAKE_REQUIRED_LIBRARIES ${CURL_LIBRARIES} ${OPENSSL_LIBRARIES} ${Z_LIBRARY} pthread dl)
   set(CMAKE_REQUIRED_INCLUDES ${CURL_INCLUDE_DIRS})
   check_c_source_runs("
     #include <curl/curl.h>
diff --git a/cmake/FindICU.cmake b/cmake/FindICU.cmake
index ad8ce600d..26f0683f3 100644
--- a/cmake/FindICU.cmake
+++ b/cmake/FindICU.cmake
@@ -21,11 +21,27 @@ find_path(ICU_INCLUDE_DIR
     HINTS ${ICU_FIND_PATH_HINTS}
     ${ICU_FIND_OPTS}
 )
-find_library(ICU_LIBRARY_I18N NAMES icui18n
+
+if(BUILD_STATIC)
+    set(ICU_I18N_LIB_NAME libicui18n.a)
+    set(ICU_UC_LIB_NAME libicuuc.a)
+    set(ICU_DATA_LIB_NAME libicudata.a)
+else()
+    set(ICU_I18N_LIB_NAME icui18n)
+    set(ICU_UC_LIB_NAME icuuc)
+    set(ICU_DATA_LIB_NAME icudata)
+endif()
+
+find_library(ICU_LIBRARY_I18N NAMES ${ICU_I18N_LIB_NAME}
     HINTS ${ICU_FIND_LIBRARY_HINTS}
     ${ICU_FIND_OPTS}
 )
-find_library(ICU_LIBRARY_UC NAMES icuuc
+find_library(ICU_LIBRARY_UC NAMES ${ICU_UC_LIB_NAME}
+    HINTS ${ICU_FIND_LIBRARY_HINTS}
+    ${ICU_FIND_OPTS}
+)
+
+find_library(ICU_LIBRARY_DATA NAMES ${ICU_DATA_LIB_NAME}
     HINTS ${ICU_FIND_LIBRARY_HINTS}
     ${ICU_FIND_OPTS}
 )
@@ -34,7 +50,7 @@ include(FindPackageHandleStandardArgs)
 find_package_handle_standard_args(ICU
     REQUIRED_VARS ICU_INCLUDE_DIR ICU_LIBRARY_I18N ICU_LIBRARY_UC)
 set(ICU_INCLUDE_DIRS ${ICU_INCLUDE_DIR})
-set(ICU_LIBRARIES ${ICU_LIBRARY_I18N} ${ICU_LIBRARY_UC})
+set(ICU_LIBRARIES ${ICU_LIBRARY_I18N} ${ICU_LIBRARY_UC} ${ICU_LIBRARY_DATA})
 mark_as_advanced(ICU_INCLUDE_DIR ICU_INCLUDE_DIRS
         ICU_LIBRARY_I18N ICU_LIBRARY_UC ICU_LIBRARIES)
 
diff --git a/cmake/FindLibYAML.cmake b/cmake/FindLibYAML.cmake
index 8abe5f9f0..ade06e292 100644
--- a/cmake/FindLibYAML.cmake
+++ b/cmake/FindLibYAML.cmake
@@ -2,8 +2,14 @@ find_path(LIBYAML_INCLUDE_DIR
   NAMES yaml.h
 )
 
+if(BUILD_STATIC)
+    set(YAML_LIB_NAME libyaml.a)
+else()
+    set(YAML_LIB_NAME yaml)
+endif()
+
 find_library(LIBYAML_LIBRARY
-  NAMES yaml
+    NAMES ${YAML_LIB_NAME}
 )
 
 set(LIBYAML_INCLUDE_DIRS "${LIBYAML_INCLUDE_DIR}")
diff --git a/cmake/FindOpenSSL.cmake b/cmake/FindOpenSSL.cmake
new file mode 100644
index 000000000..f4579b465
--- /dev/null
+++ b/cmake/FindOpenSSL.cmake
@@ -0,0 +1,465 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#.rst:
+# FindOpenSSL
+# -----------
+#
+# Find the OpenSSL encryption library.
+#
+# Imported Targets
+# ^^^^^^^^^^^^^^^^
+#
+# This module defines the following :prop_tgt:`IMPORTED` targets:
+#
+# ``OpenSSL::SSL``
+#   The OpenSSL ``ssl`` library, if found.
+# ``OpenSSL::Crypto``
+#   The OpenSSL ``crypto`` library, if found.
+#
+# Result Variables
+# ^^^^^^^^^^^^^^^^
+#
+# This module will set the following variables in your project:
+#
+# ``OPENSSL_FOUND``
+#   System has the OpenSSL library.
+# ``OPENSSL_INCLUDE_DIR``
+#   The OpenSSL include directory.
+# ``OPENSSL_CRYPTO_LIBRARY``
+#   The OpenSSL crypto library.
+# ``OPENSSL_SSL_LIBRARY``
+#   The OpenSSL SSL library.
+# ``OPENSSL_LIBRARIES``
+#   All OpenSSL libraries.
+# ``OPENSSL_VERSION``
+#   This is set to ``$major.$minor.$revision$patch`` (e.g. ``0.9.8s``).
+#
+# Hints
+# ^^^^^
+#
+# Set ``OPENSSL_ROOT_DIR`` to the root directory of an OpenSSL installation.
+# Set ``OPENSSL_USE_STATIC_LIBS`` to ``TRUE`` to look for static libraries.
+# Set ``OPENSSL_MSVC_STATIC_RT`` set ``TRUE`` to choose the MT version of the lib.
+
+if (UNIX)
+  find_package(PkgConfig QUIET)
+  pkg_check_modules(_OPENSSL QUIET openssl)
+endif ()
+
+# Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES
+if(OPENSSL_USE_STATIC_LIBS)
+  set(_openssl_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
+  if(WIN32)
+    set(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
+  else()
+    set(CMAKE_FIND_LIBRARY_SUFFIXES .a )
+  endif()
+endif()
+
+if (WIN32)
+  # http://www.slproweb.com/products/Win32OpenSSL.html
+  set(_OPENSSL_ROOT_HINTS
+    ${OPENSSL_ROOT_DIR}
+    "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (32-bit)_is1;Inno Setup: App Path]"
+    "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (64-bit)_is1;Inno Setup: App Path]"
+    ENV OPENSSL_ROOT_DIR
+    )
+  file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" _programfiles)
+  set(_OPENSSL_ROOT_PATHS
+    "${_programfiles}/OpenSSL"
+    "${_programfiles}/OpenSSL-Win32"
+    "${_programfiles}/OpenSSL-Win64"
+    "C:/OpenSSL/"
+    "C:/OpenSSL-Win32/"
+    "C:/OpenSSL-Win64/"
+    )
+  unset(_programfiles)
+else ()
+  set(_OPENSSL_ROOT_HINTS
+    ${OPENSSL_ROOT_DIR}
+    ENV OPENSSL_ROOT_DIR
+    )
+endif ()
+
+set(_OPENSSL_ROOT_HINTS_AND_PATHS
+    HINTS ${_OPENSSL_ROOT_HINTS}
+    PATHS ${_OPENSSL_ROOT_PATHS}
+    )
+
+find_path(OPENSSL_INCLUDE_DIR
+  NAMES
+    openssl/ssl.h
+  ${_OPENSSL_ROOT_HINTS_AND_PATHS}
+  HINTS
+    ${_OPENSSL_INCLUDEDIR}
+  PATH_SUFFIXES
+    include
+)
+
+if(WIN32 AND NOT CYGWIN)
+  if(MSVC)
+    # /MD and /MDd are the standard values - if someone wants to use
+    # others, the libnames have to change here too
+    # use also ssl and ssleay32 in debug as fallback for openssl < 0.9.8b
+    # enable OPENSSL_MSVC_STATIC_RT to get the libs build /MT (Multithreaded no-DLL)
+    # In Visual C++ naming convention each of these four kinds of Windows libraries has it's standard suffix:
+    #   * MD for dynamic-release
+    #   * MDd for dynamic-debug
+    #   * MT for static-release
+    #   * MTd for static-debug
+
+    # Implementation details:
+    # We are using the libraries located in the VC subdir instead of the parent directory even though :
+    # libeay32MD.lib is identical to ../libeay32.lib, and
+    # ssleay32MD.lib is identical to ../ssleay32.lib
+    # enable OPENSSL_USE_STATIC_LIBS to use the static libs located in lib/VC/static
+
+    if (OPENSSL_MSVC_STATIC_RT)
+      set(_OPENSSL_MSVC_RT_MODE "MT")
+    else ()
+      set(_OPENSSL_MSVC_RT_MODE "MD")
+    endif ()
+
+    # Since OpenSSL 1.1, lib names are like libcrypto32MTd.lib and libssl32MTd.lib
+    if( "${CMAKE_SIZEOF_VOID_P}" STREQUAL "8" )
+        set(_OPENSSL_MSVC_ARCH_SUFFIX "64")
+    else()
+        set(_OPENSSL_MSVC_ARCH_SUFFIX "32")
+    endif()
+
+    if(OPENSSL_USE_STATIC_LIBS)
+      set(_OPENSSL_PATH_SUFFIXES
+        "lib/VC/static"
+        "VC/static"
+        "lib"
+        )
+    else()
+      set(_OPENSSL_PATH_SUFFIXES
+        "lib/VC"
+        "VC"
+        "lib"
+        )
+    endif ()
+
+    find_library(LIB_EAY_DEBUG
+      NAMES
+        libcrypto${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d
+        libcrypto${_OPENSSL_MSVC_RT_MODE}d
+        libcryptod
+        libeay32${_OPENSSL_MSVC_RT_MODE}d
+        libeay32d
+        cryptod
+      NAMES_PER_DIR
+      ${_OPENSSL_ROOT_HINTS_AND_PATHS}
+      PATH_SUFFIXES
+        ${_OPENSSL_PATH_SUFFIXES}
+    )
+
+    find_library(LIB_EAY_RELEASE
+      NAMES
+        libcrypto${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE}
+        libcrypto${_OPENSSL_MSVC_RT_MODE}
+        libcrypto
+        libeay32${_OPENSSL_MSVC_RT_MODE}
+        libeay32
+        crypto
+      NAMES_PER_DIR
+      ${_OPENSSL_ROOT_HINTS_AND_PATHS}
+      PATH_SUFFIXES
+        ${_OPENSSL_PATH_SUFFIXES}
+    )
+
+    find_library(SSL_EAY_DEBUG
+      NAMES
+        libssl${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d
+        libssl${_OPENSSL_MSVC_RT_MODE}d
+        libssld
+        ssleay32${_OPENSSL_MSVC_RT_MODE}d
+        ssleay32d
+        ssld
+      NAMES_PER_DIR
+      ${_OPENSSL_ROOT_HINTS_AND_PATHS}
+      PATH_SUFFIXES
+        ${_OPENSSL_PATH_SUFFIXES}
+    )
+
+    find_library(SSL_EAY_RELEASE
+      NAMES
+        libssl${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE}
+        libssl${_OPENSSL_MSVC_RT_MODE}
+        libssl
+        ssleay32${_OPENSSL_MSVC_RT_MODE}
+        ssleay32
+        ssl
+      NAMES_PER_DIR
+      ${_OPENSSL_ROOT_HINTS_AND_PATHS}
+      PATH_SUFFIXES
+        ${_OPENSSL_PATH_SUFFIXES}
+    )
+
+    set(LIB_EAY_LIBRARY_DEBUG "${LIB_EAY_DEBUG}")
+    set(LIB_EAY_LIBRARY_RELEASE "${LIB_EAY_RELEASE}")
+    set(SSL_EAY_LIBRARY_DEBUG "${SSL_EAY_DEBUG}")
+    set(SSL_EAY_LIBRARY_RELEASE "${SSL_EAY_RELEASE}")
+
+    include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
+    select_library_configurations(LIB_EAY)
+    select_library_configurations(SSL_EAY)
+
+    mark_as_advanced(LIB_EAY_LIBRARY_DEBUG LIB_EAY_LIBRARY_RELEASE
+                     SSL_EAY_LIBRARY_DEBUG SSL_EAY_LIBRARY_RELEASE)
+    set(OPENSSL_SSL_LIBRARY ${SSL_EAY_LIBRARY} )
+    set(OPENSSL_CRYPTO_LIBRARY ${LIB_EAY_LIBRARY} )
+  elseif(MINGW)
+    # same player, for MinGW
+    set(LIB_EAY_NAMES crypto libeay32)
+    set(SSL_EAY_NAMES ssl ssleay32)
+    find_library(LIB_EAY
+      NAMES
+        ${LIB_EAY_NAMES}
+      NAMES_PER_DIR
+      ${_OPENSSL_ROOT_HINTS_AND_PATHS}
+      PATH_SUFFIXES
+        "lib/MinGW"
+        "lib"
+    )
+
+    find_library(SSL_EAY
+      NAMES
+        ${SSL_EAY_NAMES}
+      NAMES_PER_DIR
+      ${_OPENSSL_ROOT_HINTS_AND_PATHS}
+      PATH_SUFFIXES
+        "lib/MinGW"
+        "lib"
+    )
+
+    mark_as_advanced(SSL_EAY LIB_EAY)
+    set(OPENSSL_SSL_LIBRARY ${SSL_EAY} )
+    set(OPENSSL_CRYPTO_LIBRARY ${LIB_EAY} )
+    unset(LIB_EAY_NAMES)
+    unset(SSL_EAY_NAMES)
+  else()
+    # Not sure what to pick for -say- intel, let's use the toplevel ones and hope someone report issues:
+    find_library(LIB_EAY
+      NAMES
+        libcrypto
+        libeay32
+      NAMES_PER_DIR
+      ${_OPENSSL_ROOT_HINTS_AND_PATHS}
+      HINTS
+        ${_OPENSSL_LIBDIR}
+      PATH_SUFFIXES
+        lib
+    )
+
+    find_library(SSL_EAY
+      NAMES
+        libssl
+        ssleay32
+      NAMES_PER_DIR
+      ${_OPENSSL_ROOT_HINTS_AND_PATHS}
+      HINTS
+        ${_OPENSSL_LIBDIR}
+      PATH_SUFFIXES
+        lib
+    )
+
+    mark_as_advanced(SSL_EAY LIB_EAY)
+    set(OPENSSL_SSL_LIBRARY ${SSL_EAY} )
+    set(OPENSSL_CRYPTO_LIBRARY ${LIB_EAY} )
+  endif()
+else()
+
+  find_library(OPENSSL_SSL_LIBRARY
+    NAMES
+      ssl
+      ssleay32
+      ssleay32MD
+    NAMES_PER_DIR
+    ${_OPENSSL_ROOT_HINTS_AND_PATHS}
+    HINTS
+      ${_OPENSSL_LIBDIR}
+    PATH_SUFFIXES
+      lib
+  )
+
+  find_library(OPENSSL_CRYPTO_LIBRARY
+    NAMES
+      crypto
+    NAMES_PER_DIR
+    ${_OPENSSL_ROOT_HINTS_AND_PATHS}
+    HINTS
+      ${_OPENSSL_LIBDIR}
+    PATH_SUFFIXES
+      lib
+  )
+
+  mark_as_advanced(OPENSSL_CRYPTO_LIBRARY OPENSSL_SSL_LIBRARY)
+
+  # compat defines
+  set(OPENSSL_SSL_LIBRARIES ${OPENSSL_SSL_LIBRARY})
+  set(OPENSSL_CRYPTO_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
+
+endif()
+
+function(from_hex HEX DEC)
+  string(TOUPPER "${HEX}" HEX)
+  set(_res 0)
+  string(LENGTH "${HEX}" _strlen)
+
+  while (_strlen GREATER 0)
+    math(EXPR _res "${_res} * 16")
+    string(SUBSTRING "${HEX}" 0 1 NIBBLE)
+    string(SUBSTRING "${HEX}" 1 -1 HEX)
+    if (NIBBLE STREQUAL "A")
+      math(EXPR _res "${_res} + 10")
+    elseif (NIBBLE STREQUAL "B")
+      math(EXPR _res "${_res} + 11")
+    elseif (NIBBLE STREQUAL "C")
+      math(EXPR _res "${_res} + 12")
+    elseif (NIBBLE STREQUAL "D")
+      math(EXPR _res "${_res} + 13")
+    elseif (NIBBLE STREQUAL "E")
+      math(EXPR _res "${_res} + 14")
+    elseif (NIBBLE STREQUAL "F")
+      math(EXPR _res "${_res} + 15")
+    else()
+      math(EXPR _res "${_res} + ${NIBBLE}")
+    endif()
+
+    string(LENGTH "${HEX}" _strlen)
+  endwhile()
+
+  set(${DEC} ${_res} PARENT_SCOPE)
+endfunction()
+
+if(OPENSSL_INCLUDE_DIR AND EXISTS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h")
+  file(STRINGS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h" openssl_version_str
+       REGEX "^#[\t ]*define[\t ]+OPENSSL_VERSION_NUMBER[\t ]+0x([0-9a-fA-F])+.*")
+
+  if(openssl_version_str)
+    # The version number is encoded as 0xMNNFFPPS: major minor fix patch status
+    # The status gives if this is a developer or prerelease and is ignored here.
+    # Major, minor, and fix directly translate into the version numbers shown in
+    # the string. The patch field translates to the single character suffix that
+    # indicates the bug fix state, which 00 -> nothing, 01 -> a, 02 -> b and so
+    # on.
+
+    string(REGEX REPLACE "^.*OPENSSL_VERSION_NUMBER[\t ]+0x([0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F]).*$"
+           "\\1;\\2;\\3;\\4;\\5" OPENSSL_VERSION_LIST "${openssl_version_str}")
+    list(GET OPENSSL_VERSION_LIST 0 OPENSSL_VERSION_MAJOR)
+    list(GET OPENSSL_VERSION_LIST 1 OPENSSL_VERSION_MINOR)
+    from_hex("${OPENSSL_VERSION_MINOR}" OPENSSL_VERSION_MINOR)
+    list(GET OPENSSL_VERSION_LIST 2 OPENSSL_VERSION_FIX)
+    from_hex("${OPENSSL_VERSION_FIX}" OPENSSL_VERSION_FIX)
+    list(GET OPENSSL_VERSION_LIST 3 OPENSSL_VERSION_PATCH)
+
+    if (NOT OPENSSL_VERSION_PATCH STREQUAL "00")
+      from_hex("${OPENSSL_VERSION_PATCH}" _tmp)
+      # 96 is the ASCII code of 'a' minus 1
+      math(EXPR OPENSSL_VERSION_PATCH_ASCII "${_tmp} + 96")
+      unset(_tmp)
+      # Once anyone knows how OpenSSL would call the patch versions beyond 'z'
+      # this should be updated to handle that, too. This has not happened yet
+      # so it is simply ignored here for now.
+      string(ASCII "${OPENSSL_VERSION_PATCH_ASCII}" OPENSSL_VERSION_PATCH_STRING)
+    endif ()
+
+    set(OPENSSL_VERSION "${OPENSSL_VERSION_MAJOR}.${OPENSSL_VERSION_MINOR}.${OPENSSL_VERSION_FIX}${OPENSSL_VERSION_PATCH_STRING}")
+  endif ()
+endif ()
+
+include(FindPackageHandleStandardArgs)
+
+set(OPENSSL_LIBRARIES ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY} )
+
+if (OPENSSL_VERSION)
+  find_package_handle_standard_args(OpenSSL
+    REQUIRED_VARS
+      #OPENSSL_SSL_LIBRARY # FIXME: require based on a component request?
+      OPENSSL_CRYPTO_LIBRARY
+      OPENSSL_INCLUDE_DIR
+    VERSION_VAR
+      OPENSSL_VERSION
+    FAIL_MESSAGE
+      "Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the system variable OPENSSL_ROOT_DIR"
+  )
+else ()
+  find_package_handle_standard_args(OpenSSL "Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the system variable OPENSSL_ROOT_DIR"
+    #OPENSSL_SSL_LIBRARY # FIXME: require based on a component request?
+    OPENSSL_CRYPTO_LIBRARY
+    OPENSSL_INCLUDE_DIR
+  )
+endif ()
+
+mark_as_advanced(OPENSSL_INCLUDE_DIR OPENSSL_LIBRARIES)
+
+if(OPENSSL_FOUND)
+  if(NOT TARGET OpenSSL::Crypto AND
+      (EXISTS "${OPENSSL_CRYPTO_LIBRARY}" OR
+        EXISTS "${LIB_EAY_LIBRARY_DEBUG}" OR
+        EXISTS "${LIB_EAY_LIBRARY_RELEASE}")
+      )
+    add_library(OpenSSL::Crypto UNKNOWN IMPORTED)
+    set_target_properties(OpenSSL::Crypto PROPERTIES
+      INTERFACE_INCLUDE_DIRECTORIES "${OPENSSL_INCLUDE_DIR}")
+    if(EXISTS "${OPENSSL_CRYPTO_LIBRARY}")
+      set_target_properties(OpenSSL::Crypto PROPERTIES
+        IMPORTED_LINK_INTERFACE_LANGUAGES "C"
+        IMPORTED_LOCATION "${OPENSSL_CRYPTO_LIBRARY}")
+    endif()
+    if(EXISTS "${LIB_EAY_LIBRARY_RELEASE}")
+      set_property(TARGET OpenSSL::Crypto APPEND PROPERTY
+        IMPORTED_CONFIGURATIONS RELEASE)
+      set_target_properties(OpenSSL::Crypto PROPERTIES
+        IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C"
+        IMPORTED_LOCATION_RELEASE "${LIB_EAY_LIBRARY_RELEASE}")
+    endif()
+    if(EXISTS "${LIB_EAY_LIBRARY_DEBUG}")
+      set_property(TARGET OpenSSL::Crypto APPEND PROPERTY
+        IMPORTED_CONFIGURATIONS DEBUG)
+      set_target_properties(OpenSSL::Crypto PROPERTIES
+        IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "C"
+        IMPORTED_LOCATION_DEBUG "${LIB_EAY_LIBRARY_DEBUG}")
+    endif()
+  endif()
+  if(NOT TARGET OpenSSL::SSL AND
+      (EXISTS "${OPENSSL_SSL_LIBRARY}" OR
+        EXISTS "${SSL_EAY_LIBRARY_DEBUG}" OR
+        EXISTS "${SSL_EAY_LIBRARY_RELEASE}")
+      )
+    add_library(OpenSSL::SSL UNKNOWN IMPORTED)
+    set_target_properties(OpenSSL::SSL PROPERTIES
+      INTERFACE_INCLUDE_DIRECTORIES "${OPENSSL_INCLUDE_DIR}")
+    if(EXISTS "${OPENSSL_SSL_LIBRARY}")
+      set_target_properties(OpenSSL::SSL PROPERTIES
+        IMPORTED_LINK_INTERFACE_LANGUAGES "C"
+        IMPORTED_LOCATION "${OPENSSL_SSL_LIBRARY}")
+    endif()
+    if(EXISTS "${SSL_EAY_LIBRARY_RELEASE}")
+      set_property(TARGET OpenSSL::SSL APPEND PROPERTY
+        IMPORTED_CONFIGURATIONS RELEASE)
+      set_target_properties(OpenSSL::SSL PROPERTIES
+        IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C"
+        IMPORTED_LOCATION_RELEASE "${SSL_EAY_LIBRARY_RELEASE}")
+    endif()
+    if(EXISTS "${SSL_EAY_LIBRARY_DEBUG}")
+      set_property(TARGET OpenSSL::SSL APPEND PROPERTY
+        IMPORTED_CONFIGURATIONS DEBUG)
+      set_target_properties(OpenSSL::SSL PROPERTIES
+        IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "C"
+        IMPORTED_LOCATION_DEBUG "${SSL_EAY_LIBRARY_DEBUG}")
+    endif()
+    if(TARGET OpenSSL::Crypto)
+      set_target_properties(OpenSSL::SSL PROPERTIES
+        INTERFACE_LINK_LIBRARIES OpenSSL::Crypto)
+    endif()
+  endif()
+endif()
+
+# Restore the original find library ordering
+if(OPENSSL_USE_STATIC_LIBS)
+  set(CMAKE_FIND_LIBRARY_SUFFIXES ${_openssl_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES})
+endif()
diff --git a/cmake/FindReadline.cmake b/cmake/FindReadline.cmake
index 681a6f5de..770c4e15f 100644
--- a/cmake/FindReadline.cmake
+++ b/cmake/FindReadline.cmake
@@ -6,22 +6,37 @@
 # READLINE_LIBRARIES
 #
 
+if(BUILD_STATIC)
+    find_library(CURSES_CURSES_LIBRARY NAMES libcurses.a)
+    find_library(CURSES_NCURSES_LIBRARY NAMES libncurses.a)
+    find_library(CURSES_FORM_LIBRARY NAMES libform.a)
+    find_library(CURSES_INFO_LIBRARY NAMES libtinfo.a)
+    if (NOT CURSES_INFO_LIBRARY)
+        set(CURSES_INFO_LIBRARY "")
+    endif()
+endif()
 find_package(Curses)
 if(NOT CURSES_FOUND)
     find_package(Termcap)
 endif()
 
+if(BUILD_STATIC)
+    set(READLINE_LIB_NAME libreadline.a)
+else()
+    set(READLINE_LIB_NAME readline)
+endif()
+
 if (DEFINED READLINE_ROOT)
   set(_FIND_OPTS NO_CMAKE NO_CMAKE_SYSTEM_PATH)
   find_library(READLINE_LIBRARY
-    NAMES readline
+	  NAMES ${READLINE_LIB_NAME}
     HINTS ${READLINE_ROOT}/lib
     ${_FIND_OPTS})
   find_path(READLINE_INCLUDE_DIR
     NAMES readline/readline.h
     HINTS ${READLINE_ROOT}/include ${_FIND_OPTS})
 else()
-  find_library(READLINE_LIBRARY NAMES readline)
+	find_library(READLINE_LIBRARY NAMES ${READLINE_LIB_NAME})
   find_path(READLINE_INCLUDE_DIR readline/readline.h)
 endif()
 
@@ -41,10 +56,10 @@ if(READLINE_FOUND)
       endif()
   endif()
   if(CURSES_FOUND)
-    set(READLINE_LIBRARIES ${READLINE_LIBRARIES} ${CURSES_LIBRARIES})
+    set(READLINE_LIBRARIES ${READLINE_LIBRARIES} ${CURSES_LIBRARIES} ${CURSES_INFO_LIBRARY})
     set(READLINE_INCLUDE_DIRS ${READLINE_INCLUDE_DIRS} ${CURSES_INCLUDE_DIRS})
   elseif(TERMCAP_FOUND)
-    set(READLINE_LIBRARIES ${READLINE_LIBRARIES} ${TERMCAP_LIBRARIES})
+    set(READLINE_LIBRARIES ${READLINE_LIBRARIES} ${TERMCAP_LIBRARIES} ${CURSES_INFO_LIBRARY})
     set(READLINE_INCLUDE_DIRS ${READLINE_INCLUDE_DIRS} ${TERMCAP_INCLUDE_DIRS})
   endif()
 endif(READLINE_FOUND)
diff --git a/cmake/FindTermcap.cmake b/cmake/FindTermcap.cmake
index efe0c48cf..fa88fe7b2 100644
--- a/cmake/FindTermcap.cmake
+++ b/cmake/FindTermcap.cmake
@@ -4,7 +4,13 @@
 # TERMCAP_LIBRARY
 # TERMCAP_INCLUDE_DIR
 
-FIND_LIBRARY(TERMCAP_LIBRARY NAMES termcap)
+if(BUILD_STATIC)
+    set(TERMCAP_STATIC libtermcap.a)
+else()
+    set(TERMCAP_STATIC termcap)
+endif()
+
+FIND_LIBRARY(TERMCAP_LIBRARY NAMES ${TERMCAP_STATIC})
 FIND_PATH(TERMCAP_INCLUDE_DIR NAMES termcap.h)
 
 include(FindPackageHandleStandardArgs)
diff --git a/cmake/FindZSTD.cmake b/cmake/FindZSTD.cmake
index 738de535d..b4421fbe6 100644
--- a/cmake/FindZSTD.cmake
+++ b/cmake/FindZSTD.cmake
@@ -2,8 +2,13 @@ find_path(ZSTD_INCLUDE_DIR
   NAMES zstd.h
 )
 
+if(BUILD_STATIC)
+    set(ZSTD_LIB_NAME libzstd.a)
+else()
+    set(ZSTD_LIB_NAME zstd)
+endif()
 find_library(ZSTD_LIBRARY
-  NAMES zstd
+    NAMES ${ZSTD_LIB_NAME}
 )
 
 set(ZSTD_INCLUDE_DIRS "${ZSTD_INCLUDE_DIR}")
diff --git a/cmake/compiler.cmake b/cmake/compiler.cmake
index 05d33ab48..33c0f6470 100644
--- a/cmake/compiler.cmake
+++ b/cmake/compiler.cmake
@@ -116,7 +116,12 @@ set (CMAKE_CXX_FLAGS_RELWITHDEBINFO
 unset(CC_DEBUG_OPT)
 
 check_include_file(libunwind.h HAVE_LIBUNWIND_H)
-find_library(UNWIND_LIBRARY PATH_SUFFIXES system NAMES unwind)
+if(BUILD_STATIC)
+    set(UNWIND_LIB_NAME libunwind.a)
+else()
+    set(UNWIND_LIB_NAME unwind)
+endif()
+find_library(UNWIND_LIBRARY PATH_SUFFIXES system NAMES ${UNWIND_LIB_NAME})
 
 set(ENABLE_BACKTRACE_DEFAULT OFF)
 if (UNWIND_LIBRARY AND HAVE_LIBUNWIND_H)
@@ -137,20 +142,36 @@ if (ENABLE_BACKTRACE)
     else()
         if (CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR
             CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64")
-            find_library(UNWIND_PLATFORM_LIBRARY PATH_SUFFIXES system
-                         NAMES "unwind-${CMAKE_SYSTEM_PROCESSOR}")
+            if(BUILD_STATIC)
+                set(UNWIND_PLATFORM_LIB_NAME "libunwind-${CMAKE_SYSTEM_PROCESSOR}.a")
+            else()
+                set(UNWIND_PLATFORM_LIB_NAME "unwind-${CMAKE_SYSTEM_PROCESSOR}")
+            endif()
         elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "i686")
-            find_library(UNWIND_PLATFORM_LIBRARY PATH_SUFFIXES system
-                         NAMES "unwind-x86")
+            if(BUILD_STATIC)
+                set(UNWIND_PLATFORM_LIB_NAME "libunwind-x86.a")
+            else()
+                set(UNWIND_PLATFORM_LIB_NAME "unwind-x86")
+            endif()
         elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "arm*")
-            find_library(UNWIND_PLATFORM_LIBRARY PATH_SUFFIXES system
-                         NAMES "unwind-arm")
+            if(BUILD_STATIC)
+                set(UNWIND_PLATFORM_LIB_NAME "libunwind-arm.a")
+            else()
+                set(UNWIND_PLATFORM_LIB_NAME "unwind-arm")
+            endif()
         endif()
-        set (UNWIND_LIBRARIES ${UNWIND_LIBRARY} ${UNWIND_PLATFORM_LIBRARY})
+        find_library(UNWIND_PLATFORM_LIBRARY PATH_SUFFIXES system
+            NAMES ${UNWIND_PLATFORM_LIB_NAME})
+        set(UNWIND_LIBRARIES ${UNWIND_PLATFORM_LIBRARY} ${UNWIND_LIBRARY})
     endif()
     find_package_message(UNWIND_LIBRARIES "Found unwind" "${UNWIND_LIBRARIES}")
 endif()
 
+if(BUILD_STATIC)
+    # Static linking for c++ routines
+    add_compile_flags("C;CXX" "-static-libgcc" "-static-libstdc++")
+endif()
+
 #
 # Set flags for all include files: those maintained by us and
 # coming from third parties.
@@ -259,11 +280,6 @@ macro(enable_tnt_compile_flags)
     endif()
 endmacro(enable_tnt_compile_flags)
 
-if (HAVE_OPENMP)
-    add_compile_flags("C;CXX" "-fopenmp")
-endif()
-
-
 if (CMAKE_COMPILER_IS_CLANG OR CMAKE_COMPILER_IS_GNUCC)
     set(HAVE_BUILTIN_CTZ 1)
     set(HAVE_BUILTIN_CTZLL 1)
diff --git a/extra/mkexports b/extra/mkexports
index 20b3454d4..145e5b8ce 100755
--- a/extra/mkexports
+++ b/extra/mkexports
@@ -2,6 +2,7 @@
 # $1 - in  file
 # $2 - out file
 # $3 - os
+# $4 - export templates
 if [ "x$3x" = xDarwinx ]; then
     # _func1
     # _func2
@@ -11,5 +12,16 @@ else
     #   func1;
     #   func2;
     # };
-    ( echo "{" && sed -e '/^\s*$/d;s/$/;/;' $1 && echo "};" ) > $2
+    echo "$4"
+    ( echo "{" && {
+      # combine static defined list of functions
+      cat $1 ;
+      # with list of exported functions of bundled libraries
+      for so in $4 ; do {
+        # exported names from shared object
+        nm -D $so ||
+        # or follow patch from shared object script
+        nm -D `cat $so | grep GROUP | awk '{print $3}'` ;
+      } | awk '{print $3}' ; done ;
+    } | sed '/^\s*$/d;s/$/;/;' && echo "};" ) > $2
 fi
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 2a952923e..e9b6458ef 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -107,18 +107,19 @@ endif ()
 
 add_library(core STATIC ${core_sources})
 target_link_libraries(core
-    salad small pthread
+    salad small
     ${LIBEV_LIBRARIES}
     ${LIBEIO_LIBRARIES}
     ${LIBCORO_LIBRARIES}
     ${MSGPUCK_LIBRARIES}
+    dl pthread
 )
 
 add_library(stat STATIC rmean.c latency.c histogram.c)
 target_link_libraries(stat core)
 
 if (ENABLE_BACKTRACE AND NOT TARGET_OS_DARWIN)
-	target_link_libraries(core gcc_s ${UNWIND_LIBRARIES})
+    target_link_libraries(core gcc_s ${UNWIND_LIBRARIES})
 endif()
 
 if (CC_HAS_WNO_IMPLICIT_FALLTHROUGH)
@@ -218,12 +219,18 @@ target_link_libraries(server core bit uri uuid ${ICU_LIBRARIES})
 set (reexport_libraries server core misc bitset csv
      ${LUAJIT_LIBRARIES} ${MSGPUCK_LIBRARIES} ${ICU_LIBRARIES})
 
+if(BUILD_STATIC)
+    set(Z_STATIC libz.a)
+endif()
+find_library(Z_LIBRARY NAMES ${Z_STATIC} z)
+
 set (common_libraries
     ${reexport_libraries}
     ${LIBYAML_LIBRARIES}
     ${READLINE_LIBRARIES}
-    ${OPENSSL_LIBRARIES}
     ${CURL_LIBRARIES}
+    ${OPENSSL_LIBRARIES}
+    ${Z_STATIC}
 )
 
 if (TARGET_OS_LINUX OR TARGET_OS_DEBIAN_FREEBSD)
@@ -248,6 +255,8 @@ endif()
 set (common_libraries ${common_libraries} ${LIBUUID_LIBRARIES})
 set (common_libraries ${common_libraries} PARENT_SCOPE)
 
+set (generic_libraries pthread dl)
+
 add_subdirectory(lib)
 add_subdirectory(box)
 
@@ -255,6 +264,33 @@ add_subdirectory(box)
 set(TARANTOOL_C_FLAGS ${CMAKE_C_FLAGS} PARENT_SCOPE)
 set(TARANTOOL_CXX_FLAGS ${CMAKE_CXX_FLAGS} PARENT_SCOPE)
 
+set(EXPORT_LIST)
+if(BUILD_STATIC)
+    # for each static library we should find a corresponding shared library to
+    # parse and reexport library api functions
+    foreach(libstatic
+            ${READLINE_LIBRARIES}
+            ${CURL_LIBRARIES}
+            ${OPENSSL_LIBRARIES}
+            ${ICU_LIBRARIES}
+            ${Z_STATIC}
+            ${LIBYAML_LIBRARIES})
+        if (${libstatic} MATCHES "lib[^/]+.a")
+            string(REGEX MATCH "lib[^/]+.a" libname ${libstatic})
+            string(REGEX REPLACE "\\.a$" "" libname ${libname})
+            string(REGEX REPLACE "^lib" "" libname ${libname})
+            find_library(SYMBOLS_LIB NAMES ${libname})
+            # add found library to export list
+            list(APPEND EXPORT_LIST ${SYMBOLS_LIB})
+            # set variable to allow rescan (CMake depended)
+            set(SYMBOLS_LIB "SYMBOLS_LIB-NOTFOUND")
+        else()
+            message(WARNING "${libstatic} should be a static")
+        endif()
+    endforeach(libstatic)
+    string(REPLACE ";" " " EXPORT_LIST "${EXPORT_LIST}")
+endif()
+
 # Exports syntax is toolchain-dependent, preprocessing is necessary
 set(exports_file ${CMAKE_BINARY_DIR}/extra/exports.${CMAKE_SYSTEM_NAME})
 add_custom_target(preprocess_exports
@@ -264,12 +300,14 @@ add_custom_command(
     DEPENDS ${CMAKE_SOURCE_DIR}/extra/exports
     COMMAND ${CMAKE_SOURCE_DIR}/extra/mkexports
             ${CMAKE_SOURCE_DIR}/extra/exports
-            ${exports_file} ${CMAKE_SYSTEM_NAME})
+            ${exports_file} ${CMAKE_SYSTEM_NAME}
+            ${EXPORT_LIST}
+)
 
 add_executable(
-	tarantool main.cc
-	${LIBUTIL_FREEBSD_SRC}/flopen.c
-	${LIBUTIL_FREEBSD_SRC}/pidfile.c)
+    tarantool main.cc
+    ${LIBUTIL_FREEBSD_SRC}/flopen.c
+    ${LIBUTIL_FREEBSD_SRC}/pidfile.c)
 
 add_dependencies(tarantool build_bundled_libs preprocess_exports)
 
@@ -295,6 +333,7 @@ if (TARGET_OS_DARWIN)
         LINK_FLAGS "-Wl,-exported_symbols_list,${exports_file}")
 else ()
     target_link_libraries(tarantool
+                          ${generic_libraries}
                           -Wl,--whole-archive box ${reexport_libraries}
                           salad -Wl,--no-whole-archive
                           ${common_libraries})
diff --git a/third_party/crc32.c b/third_party/crc32.c
index a271d07ec..16b8c4040 100644
--- a/third_party/crc32.c
+++ b/third_party/crc32.c
@@ -45,7 +45,7 @@
 #include <unistd.h>
 #include <stdint.h>
 
-uint32_t crc32_table[] = {
+static uint32_t crc32_table[] = {
 	0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
 	0xe963a535, 0x9e6495a3,	0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
 	0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
@@ -92,7 +92,7 @@ uint32_t crc32_table[] = {
 };
 
 uint32_t
-crc32(const void *buf, size_t size)
+tnt_crc32(const void *buf, size_t size)
 {
 	const uint8_t *p = buf;
 	uint32_t crc;
@@ -735,7 +735,7 @@ multitable_crc32c(uint32_t crc32c,
 }
 
 uint32_t
-crc32c(uint32_t crc32c,
+tnt_crc32c(uint32_t crc32c,
     const char *buffer,
     unsigned int length)
 {
diff --git a/third_party/crc32.h b/third_party/crc32.h
index 55c7072f3..8dc61d05d 100644
--- a/third_party/crc32.h
+++ b/third_party/crc32.h
@@ -3,7 +3,9 @@
 
 #include <stdint.h>
 
-uint32_t crc32(const void *buf, size_t size);
-uint32_t crc32c(uint32_t crc32c, const char *buffer, unsigned int length);
+#define crc32 tnt_crc32
+uint32_t tnt_crc32(const void *buf, size_t size);
+#define crc32c tnt_crc32c
+uint32_t tnt_crc32c(uint32_t crc32c, const char *buffer, unsigned int length);
 
 #endif
-- 
2.18.0

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [tarantool-patches] Re: [PATCH v3] Tarantool static build ability
  2018-08-28 20:06 [tarantool-patches] [PATCH v3] Tarantool static build ability Georgy Kirichenko
@ 2018-08-29  1:25 ` Alexander Turenko
  2018-08-29  6:07   ` Georgy Kirichenko
  0 siblings, 1 reply; 3+ messages in thread
From: Alexander Turenko @ 2018-08-29  1:25 UTC (permalink / raw)
  To: Georgy Kirichenko; +Cc: tarantool-patches

Hi, Georgy!

I have minor notes on the code and some experimenting results. Please,
especially consider attempt to use docker at end of the email.

I don't think I can add more value on the next review rounds, so,
please, proceed with the next reviewer (I guess Kirill Yu.) if the
process allows it.

WBR, Alexander Turenko.

---- Updates ----

From answers to comments to v2:

> * there is no possibility to use a new version of FindOpenSSL.cmake module
> because line 411 of the module:
> `include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)'
> requires for other file in our internal cmake directory.

Included cmake file has the same line at the line 374 (fixed in the our repo,
of cource, see the first review, where I show the diff).

I don't insist on including the last version and don't sure whether it would
better from, say, portability reasons. I'm okay with the version included now,
just was curious. Let's consider the question closed.

---- Inline comments ----

> --- a/cmake/BuildMisc.cmake
> +++ b/cmake/BuildMisc.cmake
> @@ -33,5 +33,15 @@ macro(libmisc_build)
>  
>      add_library(misc STATIC ${misc_src})
>  
> +    if (HAVE_OPENMP)
> +        target_compile_options(misc PRIVATE "-fopenmp")
> +        if(BUILD_STATIC)
> +            set(GOMP_LIBRARY libgomp.a)
> +        else()
> +            set(GOMP_LIBRARY gomp)
> +        endif()
> +        target_link_libraries(misc pthread ${GOMP_LIBRARY})
> +    endif()
> +
>      unset(misc_src)
>  endmacro(libmisc_build)

Are not pthread should follows gomp? nm reports undefined static symbols starts
with 'pthread_' in libgomp.a.

>  if(CURL_FOUND)
>    set(CURL_LIBRARIES ${CURL_LIBRARY})
>    set(CURL_INCLUDE_DIRS ${CURL_INCLUDE_DIR})
> -  set(CMAKE_REQUIRED_LIBRARIES ${CURL_LIBRARIES})
> +  set(CMAKE_REQUIRED_LIBRARIES ${CURL_LIBRARIES} ${OPENSSL_LIBRARIES} ${Z_LIBRARY} pthread dl)

libcurl.a can be linked with other libraries (nghttp2 at least) and we
possibly should take care of it to perform static build successfully on
different OSes. It is not important in context of the issue you work on,
but maybe will matter in the future. So I just note it here and don't
know whether we should do something later.

> diff --git a/cmake/FindReadline.cmake b/cmake/FindReadline.cmake
> index 681a6f5de..770c4e15f 100644
> --- a/cmake/FindReadline.cmake
> +++ b/cmake/FindReadline.cmake
> @@ -6,22 +6,37 @@
>  # READLINE_LIBRARIES
>  #
>  
> +if(BUILD_STATIC)
> +    find_library(CURSES_CURSES_LIBRARY NAMES libcurses.a)
> +    find_library(CURSES_NCURSES_LIBRARY NAMES libncurses.a)
> +    find_library(CURSES_FORM_LIBRARY NAMES libform.a)
> +    find_library(CURSES_INFO_LIBRARY NAMES libtinfo.a)
> +    if (NOT CURSES_INFO_LIBRARY)
> +        set(CURSES_INFO_LIBRARY "")
> +    endif()
> +endif()

CURSES_CURSES_LIBRARY is not used.
CURSES_NCURSES_LIBRARY is not used.
CURSES_FORM_LIBRARY is not used.

I don't get the point of this block (except placing libtinfo.a into deps if it
is present). Please, clarify it or remove the dead code.

> +if(BUILD_STATIC)
> +    # Static linking for c++ routines
> +    add_compile_flags("C;CXX" "-static-libgcc" "-static-libstdc++")
> +endif()
> +

Maybe it should also be under an option, because static linking with a
libc can make the resulting executable less portable (I guess because of
compatibility with new kernels). Security updates questiong is arisen
here too. I think most of user don't want it and it should be disable by
default.

Sorry, I miss this before.

> diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
> index 2a952923e..e9b6458ef 100644
> --- a/src/CMakeLists.txt
> +++ b/src/CMakeLists.txt
> @@ -107,18 +107,19 @@ endif ()
>  
>  add_library(core STATIC ${core_sources})
>  target_link_libraries(core
> -    salad small pthread
> +    salad small
>      ${LIBEV_LIBRARIES}
>      ${LIBEIO_LIBRARIES}
>      ${LIBCORO_LIBRARIES}
>      ${MSGPUCK_LIBRARIES}
> +    dl pthread
>  )
>  

You are use `generic_libraries` variable for pthread and dl below. Maybe
set the variable above and use it here too?

> +if(BUILD_STATIC)
> +    set(Z_STATIC libz.a)
> +endif()
> +find_library(Z_LIBRARY NAMES ${Z_STATIC} z)
> +

Note: Z_LIBRARY is not used below.

Do we want to add libz dependency *only* in case of static build? If so,
I think we should write it like so:

if(BUILD_STATIC)
    find_library(Z_LIBRARY_STATIC NAMES libz.a)
endif()

And use Z_LIBRARY_STATIC below instead of Z_STATIC.

If I understand it wrongly and we okay to add libz dependency in case of
dynamic build we can just use ${Z_LIBRARY} below, because we already set it in
cmake/FindCURL.cmake. It seems the case is similar to libgomp one, but we don't
avoid linking the dynamic version for gomp (however we could).

>  set (common_libraries
>      ${reexport_libraries}
>      ${LIBYAML_LIBRARIES}
>      ${READLINE_LIBRARIES}
> -    ${OPENSSL_LIBRARIES}
>      ${CURL_LIBRARIES}
> +    ${OPENSSL_LIBRARIES}
> +    ${Z_STATIC}
>  )
>  

This hunk cannot be applied automatically on top of the current 1.10,
because of adding ${ICONV_LIBRARIES} in dcac64af. Can you please rebase
on top of 1.10? The rest are applied successfully.

Note: nghttp2 is needed here too if libcurl.a needs it (see the comment
above). (No changes are required, just note.)

> +set(EXPORT_LIST)
> +if(BUILD_STATIC)
> +    # for each static library we should find a corresponding shared library to
> +    # parse and reexport library api functions
> +    foreach(libstatic
> +            ${READLINE_LIBRARIES}
> +            ${CURL_LIBRARIES}
> +            ${OPENSSL_LIBRARIES}
> +            ${ICU_LIBRARIES}
> +            ${Z_STATIC}

Note: don't forget to change Z_STATIC here to reflect changes above if
you'll do it.

> @@ -295,6 +333,7 @@ if (TARGET_OS_DARWIN)
>          LINK_FLAGS "-Wl,-exported_symbols_list,${exports_file}")
>  else ()
>      target_link_libraries(tarantool
> +                          ${generic_libraries}
>                            -Wl,--whole-archive box ${reexport_libraries}
>                            salad -Wl,--no-whole-archive
>                            ${common_libraries})

You have ${generic_libraries} added at end of core.a target, but here it is at
the start. I think generic libraries should follows others in general to
collect all needed symbols before resolving with the generic libraries.

If you place it at start to avoid link as static, don't afraid. It seems
that cmake correctly juggles with -Wl,-Bstatic and -Wl,-Bdynamic to get
static libs static and dynamic libs dynamic.

---- Experimenting (take 2) ----

Environment: Gentoo; /etc/portage/package.use/tarantool contains:

sys-libs/zlib static-libs
net-misc/curl static-libs
dev-libs/openssl static-libs
sys-libs/readline static-libs
sys-libs/ncurses static-libs
dev-libs/icu static-libs

net-misc/curl USE flags: http2 ipv6 ssl static-libs ABI_X86="64"
CURL_SSL="openssl" (the comment about nghttp2 is because of the http2
flag here).

Have added nghttp2 in two cmake files as noted above.

I'm able to build tarantool.

The following warnings I got on the configure stage:

CMake Warning at src/CMakeLists.txt:285 (message):
  /usr/lib64/libssl.so should be a static
  /usr/lib64/libcrypto.so should be a static
  yaml should be a static

The following warnings I got on the build stage:

nm: /usr/lib/libz.so: File format not recognized
nm: /usr/lib/libcurses.so: File format not recognized
nm: /usr/lib/libz.so: File format not recognized
(maybe missed some of them)

$ lddtree src/tarantool 
tarantool => src/tarantool (interpreter => /lib64/ld-linux-x86-64.so.2)
    libpthread.so.0 => /lib64/libpthread.so.0
    libdl.so.2 => /lib64/libdl.so.2
    libssl.so.1.0.0 => /usr/lib64/libssl.so.1.0.0
    libcrypto.so.1.0.0 => /usr/lib64/libcrypto.so.1.0.0
        libz.so.1 => /lib64/libz.so.1
    libnghttp2.so.14 => /usr/lib64/libnghttp2.so.14
    librt.so.1 => /lib64/librt.so.1
    libgcc_s.so.1 => /usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/libgcc_s.so.1
    libm.so.6 => /lib64/libm.so.6
    libc.so.6 => /lib64/libc.so.6
    ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2

The executable runs, the interactive session looks a bit strange (but
ok):

tarantool> require('strict')
tarantool> ---
- on: 'function: 0x40046128'
  off: 'function: 0x40046108'
...

Compare with mine system tarantool:

tarantool> require('strict')
---
- on: 'function: 0x412ff1b0'
  off: 'function: 0x412ff190'

Tried with -DOPENSSL_USE_STATIC_LIBS=ON.

At configure:

CMake Warning at src/CMakeLists.txt:286 (message):
  yaml should be a static

At build:

/usr/lib/libreadline.so /usr/lib/libcurses.so /usr/lib/libform.so /usr/lib/libcurl.so /usr/lib/libssl.so /usr/lib/libcrypto.so /usr/lib/libicui18n.so /usr/lib/libicuuc.so /usr/lib/libicudata.so /usr/lib/libz.so (some debug are forgotten?)
nm: /usr/lib/libz.so: File format not recognized
nm: /usr/lib/libreadline.so: File format not recognized
(maybe missed some of them)

$ lddtree src/tarantool 
tarantool => src/tarantool (interpreter => /lib64/ld-linux-x86-64.so.2)
    libpthread.so.0 => /lib64/libpthread.so.0
    libdl.so.2 => /lib64/libdl.so.2
    libnghttp2.so.14 => /usr/lib64/libnghttp2.so.14
    librt.so.1 => /lib64/librt.so.1
    libgcc_s.so.1 => /usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/libgcc_s.so.1
    libm.so.6 => /lib64/libm.so.6
    libc.so.6 => /lib64/libc.so.6
    ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2

Don't sure why libgcc_s is here, but I think it is okay.

Runs okay (the same as the previous one).

Dynamic build is okay too:

$ lddtree src/tarantool 
tarantool => src/tarantool (interpreter => /lib64/ld-linux-x86-64.so.2)
    libicui18n.so.60 => /usr/lib64/libicui18n.so.60
    libicuuc.so.60 => /usr/lib64/libicuuc.so.60
        libicudata.so.60 => /usr/lib64/libicudata.so.60
    libreadline.so.7 => /lib64/libreadline.so.7
    libncurses.so.6 => /lib64/libncurses.so.6
    libform.so.6 => /usr/lib64/libform.so.6
    libssl.so.1.0.0 => /usr/lib64/libssl.so.1.0.0
    libcrypto.so.1.0.0 => /usr/lib64/libcrypto.so.1.0.0
        libz.so.1 => /lib64/libz.so.1
    libcurl.so.4 => /usr/lib64/libcurl.so.4
        libnghttp2.so.14 => /usr/lib64/libnghttp2.so.14
    libdl.so.2 => /lib64/libdl.so.2
        ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2
    librt.so.1 => /lib64/librt.so.1
    libpthread.so.0 => /lib64/libpthread.so.0
    libgcc_s.so.1 => /usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/libgcc_s.so.1
    libunwind.so.8 => /usr/lib64/libunwind.so.8
    libunwind-x86_64.so.8 => /usr/lib64/libunwind-x86_64.so.8
    libstdc++.so.6 => /usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/libstdc++.so.6
    libm.so.6 => /lib64/libm.so.6
    libgomp.so.1 => /usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/libgomp.so.1
    libc.so.6 => /lib64/libc.so.6

Runs okay.

Trying docker:

$ docker build -t staticbuild -f Dockerfile.staticbuild .
$ docker run -it staticbuild
[root@62614d253850 /]# tarantool
PANIC: unprotected error in call to Lua API (builtin/crypto.lua:64: tarantool: undefined symbol: EVP_get_digestbyname)

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [tarantool-patches] Re: [PATCH v3] Tarantool static build ability
  2018-08-29  1:25 ` [tarantool-patches] " Alexander Turenko
@ 2018-08-29  6:07   ` Georgy Kirichenko
  0 siblings, 0 replies; 3+ messages in thread
From: Georgy Kirichenko @ 2018-08-29  6:07 UTC (permalink / raw)
  To: Alexander Turenko; +Cc: tarantool-patches

[-- Attachment #1: Type: text/plain, Size: 2093 bytes --]

On Wednesday, August 29, 2018 4:25:47 AM MSK Alexander Turenko wrote:
I sent fixed branch and a message.
Please look on my comments inline
> Hi, Georgy!
> 
> I have minor notes on the code and some experimenting results. Please,
> especially consider attempt to use docker at end of the email.
> 
> I don't think I can add more value on the next review rounds, so,
> please, proceed with the next reviewer (I guess Kirill Yu.) if the
> process allows it.
> 
> WBR, Alexander Turenko.
> 
> ---- Updates ----
> 
> Included cmake file has the same line at the line 374 (fixed in the our
> repo, of cource, see the first review, where I show the diff).
Fixed

> Are not pthread should follows gomp? nm reports undefined static symbols
> starts with 'pthread_' in libgomp.a.
Fixed

> libcurl.a can be linked with other libraries (nghttp2 at least) and we
> possibly should take care of it to perform static build successfully on
Fixed

> CURSES_CURSES_LIBRARY is not used.
> CURSES_NCURSES_LIBRARY is not used.
> CURSES_FORM_LIBRARY is not used.
> 
> I don't get the point of this block (except placing libtinfo.a into deps if
> it is present). Please, clarify it or remove the dead code.
This variables are used by FindCurses module internally. We could set it to 
the libraries we want and FindCurses wouldn't locate dynamic versions for that 
libraries while execution.

> 
> > +if(BUILD_STATIC)
> > +    # Static linking for c++ routines
> > +    add_compile_flags("C;CXX" "-static-libgcc" "-static-libstdc++")
> > +endif()
> > +
> 
Fixed we can't remove libgcc from dynamic dependencies

> You are use `generic_libraries` variable for pthread and dl below. Maybe
> set the variable above and use it here too?
Fixed

> Note: Z_LIBRARY is not used below.
Fixed, Z_LIBRARY is now OPENSSL_LIBRARIES member

> This hunk cannot be applied automatically on top of the current 1.10,
> because of adding ${ICONV_LIBRARIES} in dcac64af. Can you please rebase
> on top of 1.10? The rest are applied successfully.
Fixed

> You have ${generic_libraries} added at end of core.a target, but here it is
Fixed

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2018-08-29  6:07 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-08-28 20:06 [tarantool-patches] [PATCH v3] Tarantool static build ability Georgy Kirichenko
2018-08-29  1:25 ` [tarantool-patches] " Alexander Turenko
2018-08-29  6:07   ` Georgy Kirichenko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox