diff --git a/cmake/BuildLibCURL.cmake b/cmake/BuildLibCURL.cmake
index 866b3c49e7565e8789ad06c7147291e260ccd8b8..dc1b407503df25e9c9b50ce6fdc29a79296fcd50 100644
--- a/cmake/BuildLibCURL.cmake
+++ b/cmake/BuildLibCURL.cmake
@@ -14,13 +14,23 @@ macro(curl_build)
         message(FATAL_ERROR "Unable to find zlib")
     endif()
 
-    # Set curl option to find OpenSSL library.
-    if ("${OPENSSL_ROOT_DIR}" STREQUAL "")
-        # Linux / FreeBSD.
-        set(LIBCURL_OPENSSL_OPT "--with-ssl")
-    else()
-        # Mac OS.
-        set(LIBCURL_OPENSSL_OPT "--with-ssl=${OPENSSL_ROOT_DIR}")
+    # Use the same OpenSSL library for libcurl as is used for
+    # tarantool itself.
+    get_filename_component(FOUND_OPENSSL_ROOT_DIR ${OPENSSL_INCLUDE_DIR} DIRECTORY)
+    set(LIBCURL_OPENSSL_OPT "--with-ssl=${FOUND_OPENSSL_ROOT_DIR}")
+
+    # Pass -isysroot=<SDK_PATH> option on Mac OS to a preprocessor
+    # and a C compiler to find header files installed with an SDK.
+    #
+    # The idea here is to don't pass all compiler/linker options
+    # that is set for tarantool, but only a subset that is
+    # necessary for choosen toolchain, and let curl's configure
+    # script set options that are appropriate for libcurl.
+    set(LIBCURL_CPPFLAGS "")
+    set(LIBCURL_CFLAGS "")
+    if (TARGET_OS_DARWIN AND NOT "${CMAKE_OSX_SYSROOT}" STREQUAL "")
+        set(LIBCURL_CPPFLAGS "${LIBCURL_CPPFLAGS} ${CMAKE_C_SYSROOT_FLAG} ${CMAKE_OSX_SYSROOT}")
+        set(LIBCURL_CFLAGS "${LIBCURL_CFLAGS} ${CMAKE_C_SYSROOT_FLAG} ${CMAKE_OSX_SYSROOT}")
     endif()
 
     include(ExternalProject)
@@ -35,6 +45,9 @@ macro(curl_build)
         CONFIGURE_COMMAND
             cd <SOURCE_DIR> && ./buildconf &&
             cd <BINARY_DIR> && <SOURCE_DIR>/configure
+                CC=${CMAKE_C_COMPILER}
+                CPPFLAGS=${LIBCURL_CPPFLAGS}
+                CFLAGS=${LIBCURL_CFLAGS}
                 --prefix <INSTALL_DIR>
                 --enable-static
                 --enable-shared
@@ -112,6 +125,9 @@ macro(curl_build)
         set(CURL_LIBRARIES ${CURL_LIBRARIES} rt)
     endif()
 
+    unset(LIBCURL_CPPFLAGS)
+    unset(LIBCURL_CFLAGS)
+    unset(FOUND_OPENSSL_ROOT_DIR)
     unset(LIBCURL_INSTALL_DIR)
     unset(LIBCURL_BINARY_DIR)
     unset(LIBCURL_SOURCE_DIR)
diff --git a/cmake/compiler.cmake b/cmake/compiler.cmake
index 887485c800fd651d482b8fb80aca30c6cf78a03e..c9ad2b09248fc1c71b16e8c44837c27e95176d8b 100644
--- a/cmake/compiler.cmake
+++ b/cmake/compiler.cmake
@@ -128,8 +128,10 @@ else()
 endif()
 find_library(UNWIND_LIBRARY PATH_SUFFIXES system NAMES ${UNWIND_LIB_NAME})
 
+# Disabled backtraces support on FreeBSD by default, because of
+# gh-4278.
 set(ENABLE_BACKTRACE_DEFAULT OFF)
-if (UNWIND_LIBRARY AND HAVE_LIBUNWIND_H)
+if (NOT TARGET_OS_FREEBSD AND UNWIND_LIBRARY AND HAVE_LIBUNWIND_H)
     set(ENABLE_BACKTRACE_DEFAULT ON)
 endif()
 
diff --git a/cmake/os.cmake b/cmake/os.cmake
index ea581108b35d492b3582add29e35a2154b90fdf1..0ed554b9b1de1c57d94e442e5471f2cedfdcd481 100644
--- a/cmake/os.cmake
+++ b/cmake/os.cmake
@@ -22,6 +22,41 @@ elseif (${CMAKE_SYSTEM_NAME} STREQUAL "kFreeBSD")
 elseif (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
     set(TARGET_OS_FREEBSD 1)
     find_package_message(PLATFORM "Building for FreeBSD" "${CMAKE_SYSTEM_NAME}")
+
+    # FreeBSD has OpenSSL library installed in /usr as part of a
+    # base system. A user may install OpenSSL from ports / pkg to
+    # /usr/local. It is tricky to use the library from /usr in the
+    # case, because a compilation unit can also depend on
+    # libraries from /usr/local. When -I/usr/local/include is
+    # passed to a compiler it will find openssl/ssl.h from
+    # /usr/local/include first.
+    #
+    # In theory we can create a directory on the build stage and
+    # fill it with symlinks to choosen headers. However this way
+    # does not look as usual way to pick libraries to build
+    # against. I suspect that this is common problem on FreeBSD
+    # and we should wait for some general resolution from FreeBSD
+    # developers rather then work it around.
+    #
+    # Verify that /usr is not set as a directory to pick OpenSSL
+    # library and header files, because it is likely that a user
+    # set it to use the library from a base system, while the
+    # library is also installed into /usr/local.
+    #
+    # It is possible however that a user is aware of the problem,
+    # but want to use -DOPENSSL_ROOT_DIR=<...> CMake option to
+    # choose OpenSSL from /usr anyway. We should not fail the
+    # build and block this ability. Say, a user may know that
+    # there are no OpenSSL libraries in /usr/local, but finds it
+    # convenient to set the CMake option explicitly due to some
+    # external reason.
+    get_filename_component(REAL_OPENSSL_ROOT_DIR "${OPENSSL_ROOT_DIR}"
+                           REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
+    if ("${REAL_OPENSSL_ROOT_DIR}" STREQUAL "/usr")
+        message(WARNING "Using OPENSSL_ROOT_DIR on FreeBSD to choose base "
+                        "system libraries is not supported")
+    endif()
+    unset(REAL_OPENSSL_ROOT_DIR)
 elseif (${CMAKE_SYSTEM_NAME} STREQUAL "NetBSD")
     set(TARGET_OS_NETBSD 1)
     find_package_message(PLATFORM "Building for NetBSD" "${CMAKE_SYSTEM_NAME}")