blob: 165736dd1602cc35914bf6594b9d39bf6289f944 [file]
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
# =============================================================================
# FetchOpenSSL.cmake (only included when WITH_SSL=ON)
#
# Apache Thrift 0.24 (bundled by this client) builds against OpenSSL 3.x.
#
# By default, a fixed OpenSSL source release is downloaded, checksum-verified,
# built as shared libraries, and installed under ${CMAKE_BINARY_DIR}/_deps.
# Set IOTDB_OPENSSL_FROM_SOURCE=OFF to opt into a compatible system OpenSSL.
#
# Side effects:
# Defines imported targets OpenSSL::SSL / OpenSSL::Crypto via find_package
# so callers can just link against them.
# =============================================================================
# Version built from source by default. Named distinctly
# from find_package's OPENSSL_VERSION output variable to avoid collisions.
set(OPENSSL_FALLBACK_VERSION "3.5.8"
CACHE STRING "OpenSSL version built from source when no system OpenSSL is found")
set(OPENSSL_FALLBACK_SHA256
"a8f84a39918ec6415ce765d9b429d313ba97b8143169c172e734b9514464f5b2"
CACHE STRING "SHA-256 checksum of the pinned OpenSSL source archive")
# Build OpenSSL from source even if a system one exists, making release
# packages independent of the build host's OpenSSL installation.
option(IOTDB_OPENSSL_FROM_SOURCE
"Ignore any system OpenSSL and build OpenSSL ${OPENSSL_FALLBACK_VERSION} from source" ON)
if(NOT IOTDB_OPENSSL_FROM_SOURCE)
find_package(OpenSSL QUIET)
if(OpenSSL_FOUND)
message(STATUS "[OpenSSL] using system OpenSSL ${OPENSSL_VERSION}")
return()
endif()
endif()
# --- Build the pinned OpenSSL source release ---------------------------------
set(_ossl_tarname "openssl-${OPENSSL_FALLBACK_VERSION}.tar.gz")
set(_ossl_tarball "${IOTDB_OS_DEPS_DIR}/${_ossl_tarname}")
set(_ossl_download_required ON)
if(EXISTS "${_ossl_tarball}")
file(SHA256 "${_ossl_tarball}" _ossl_existing_sha256)
if(_ossl_existing_sha256 STREQUAL "${OPENSSL_FALLBACK_SHA256}")
set(_ossl_download_required OFF)
elseif(IOTDB_OFFLINE)
message(FATAL_ERROR
"[OpenSSL] checksum mismatch for offline archive ${_ossl_tarball}: "
"expected ${OPENSSL_FALLBACK_SHA256}, got ${_ossl_existing_sha256}")
else()
message(STATUS "[OpenSSL] replacing archive with an invalid checksum")
file(REMOVE "${_ossl_tarball}")
endif()
endif()
if(_ossl_download_required)
if(IOTDB_OFFLINE)
message(FATAL_ERROR
"[OpenSSL] IOTDB_OFFLINE=ON but ${_ossl_tarname} is missing in ${IOTDB_OS_DEPS_DIR}.")
endif()
set(_ossl_url
"https://github.com/openssl/openssl/releases/download/openssl-${OPENSSL_FALLBACK_VERSION}/${_ossl_tarname}")
message(STATUS "[OpenSSL] downloading ${_ossl_url}")
file(DOWNLOAD "${_ossl_url}" "${_ossl_tarball}"
SHOW_PROGRESS TLS_VERIFY ON
EXPECTED_HASH "SHA256=${OPENSSL_FALLBACK_SHA256}" STATUS _st)
list(GET _st 0 _code)
if(NOT _code EQUAL 0)
list(GET _st 1 _msg)
file(REMOVE "${_ossl_tarball}")
message(FATAL_ERROR "[OpenSSL] download failed: ${_msg}")
endif()
endif()
set(_ossl_root "${CMAKE_BINARY_DIR}/_deps/openssl")
set(_ossl_src "${_ossl_root}/src/openssl-${OPENSSL_FALLBACK_VERSION}")
set(_ossl_inst "${_ossl_root}/install")
set(_ossl_stamp "${_ossl_root}/.built-${OPENSSL_FALLBACK_VERSION}")
if(NOT EXISTS "${_ossl_stamp}")
file(REMOVE_RECURSE "${_ossl_root}/src")
file(MAKE_DIRECTORY "${_ossl_root}/src")
message(STATUS "[OpenSSL] extracting ${_ossl_tarball}")
file(ARCHIVE_EXTRACT INPUT "${_ossl_tarball}" DESTINATION "${_ossl_root}/src")
message(STATUS "[OpenSSL] configuring -> ${_ossl_inst}")
if(WIN32)
# Git for Windows also ships a minimal Perl, but it lacks modules required by OpenSSL.
find_program(_ossl_perl NAMES perl.exe perl
PATHS "C:/Strawberry/perl/bin" NO_DEFAULT_PATH)
if(NOT _ossl_perl)
find_program(_ossl_perl NAMES perl.exe perl REQUIRED)
endif()
find_program(_vswhere NAMES vswhere.exe
PATHS "$ENV{ProgramFiles}/Microsoft Visual Studio/Installer"
"C:/Program Files (x86)/Microsoft Visual Studio/Installer")
if(NOT _vswhere)
message(FATAL_ERROR "[OpenSSL] vswhere.exe was not found")
endif()
if(CMAKE_GENERATOR MATCHES "Visual Studio ([0-9]+)")
set(_vs_major "${CMAKE_MATCH_1}")
math(EXPR _vs_next_major "${_vs_major} + 1")
set(_vs_range "[${_vs_major}.0,${_vs_next_major}.0)")
else()
set(_vs_range "[15.0,19.0)")
endif()
execute_process(
COMMAND "${_vswhere}" -latest -products * -version "${_vs_range}"
-requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64
-property installationPath
OUTPUT_VARIABLE _vs_install OUTPUT_STRIP_TRAILING_WHITESPACE
RESULT_VARIABLE _rc)
if(NOT _rc EQUAL 0 OR NOT _vs_install)
message(FATAL_ERROR "[OpenSSL] a matching Visual Studio C++ toolchain was not found")
endif()
file(TO_NATIVE_PATH "${_vs_install}/VC/Auxiliary/Build/vcvars64.bat" _vcvars)
file(TO_NATIVE_PATH "${_ossl_inst}" _ossl_inst_native)
file(TO_NATIVE_PATH "${_ossl_src}" _ossl_src_native)
file(TO_NATIVE_PATH "${_ossl_perl}" _ossl_perl_native)
set(_ossl_build_script "${_ossl_root}/build-openssl.cmd")
file(WRITE "${_ossl_build_script}"
"@echo on\r\n"
"call \"${_vcvars}\"\r\n"
"if errorlevel 1 exit /b %errorlevel%\r\n"
"cd /d \"${_ossl_src_native}\"\r\n"
"\"${_ossl_perl_native}\" Configure VC-WIN64A --prefix=\"${_ossl_inst_native}\" --openssldir=\"${_ossl_inst_native}\\ssl\" shared no-tests no-asm\r\n"
"if errorlevel 1 exit /b %errorlevel%\r\n"
"nmake\r\n"
"if errorlevel 1 exit /b %errorlevel%\r\n"
"nmake install_sw\r\n")
execute_process(COMMAND cmd /d /c "${_ossl_build_script}" RESULT_VARIABLE _rc)
if(NOT _rc EQUAL 0)
message(FATAL_ERROR "[OpenSSL] Windows source build failed (rc=${_rc})")
endif()
else()
include(ProcessorCount)
ProcessorCount(_jobs)
if(_jobs LESS 1)
set(_jobs 1)
endif()
execute_process(
COMMAND ./config --prefix=${_ossl_inst} --openssldir=${_ossl_inst}/ssl shared no-tests
WORKING_DIRECTORY "${_ossl_src}"
RESULT_VARIABLE _rc)
if(NOT _rc EQUAL 0)
message(FATAL_ERROR "[OpenSSL] config failed (rc=${_rc})")
endif()
message(STATUS "[OpenSSL] building (-j${_jobs})")
execute_process(
COMMAND make -j${_jobs}
WORKING_DIRECTORY "${_ossl_src}"
RESULT_VARIABLE _rc)
if(NOT _rc EQUAL 0)
message(FATAL_ERROR "[OpenSSL] make failed (rc=${_rc})")
endif()
execute_process(
COMMAND make install_sw
WORKING_DIRECTORY "${_ossl_src}"
RESULT_VARIABLE _rc)
if(NOT _rc EQUAL 0)
message(FATAL_ERROR "[OpenSSL] make install_sw failed (rc=${_rc})")
endif()
endif()
file(TOUCH "${_ossl_stamp}")
endif()
if(APPLE)
# OpenSSL's Darwin build records its absolute installation prefix in each dylib. Rewrite the
# IDs before iotdb_session links against them so both the client and libssl resolve the bundled
# libraries relative to the package's lib/ directory.
find_program(_install_name_tool NAMES install_name_tool REQUIRED)
find_program(_otool NAMES otool REQUIRED)
find_library(_ossl_ssl_dylib NAMES ssl
PATHS "${_ossl_inst}/lib" "${_ossl_inst}/lib64" NO_DEFAULT_PATH)
find_library(_ossl_crypto_dylib NAMES crypto
PATHS "${_ossl_inst}/lib" "${_ossl_inst}/lib64" NO_DEFAULT_PATH)
if(NOT _ossl_ssl_dylib OR NOT _ossl_crypto_dylib)
message(FATAL_ERROR "[OpenSSL] built Darwin dylibs were not found")
endif()
get_filename_component(_ossl_ssl_real "${_ossl_ssl_dylib}" REALPATH)
get_filename_component(_ossl_crypto_real "${_ossl_crypto_dylib}" REALPATH)
get_filename_component(_ossl_ssl_name "${_ossl_ssl_real}" NAME)
get_filename_component(_ossl_crypto_name "${_ossl_crypto_real}" NAME)
execute_process(
COMMAND "${_install_name_tool}" -id "@rpath/${_ossl_ssl_name}" "${_ossl_ssl_real}"
RESULT_VARIABLE _rc)
if(NOT _rc EQUAL 0)
message(FATAL_ERROR "[OpenSSL] failed to make the libssl install name relocatable")
endif()
execute_process(
COMMAND "${_install_name_tool}" -id "@rpath/${_ossl_crypto_name}" "${_ossl_crypto_real}"
RESULT_VARIABLE _rc)
if(NOT _rc EQUAL 0)
message(FATAL_ERROR "[OpenSSL] failed to make the libcrypto install name relocatable")
endif()
execute_process(COMMAND "${_otool}" -L "${_ossl_ssl_real}"
OUTPUT_VARIABLE _ossl_ssl_dependencies RESULT_VARIABLE _rc)
if(NOT _rc EQUAL 0)
message(FATAL_ERROR "[OpenSSL] failed to inspect libssl dependencies")
endif()
string(REGEX MATCH "[^\n\t ]*libcrypto[^\n\t ]*\\.dylib"
_ossl_crypto_dependency "${_ossl_ssl_dependencies}")
if(NOT _ossl_crypto_dependency)
message(FATAL_ERROR "[OpenSSL] libssl does not reference the expected libcrypto dylib")
endif()
if(NOT _ossl_crypto_dependency STREQUAL "@rpath/${_ossl_crypto_name}")
execute_process(
COMMAND "${_install_name_tool}" -change "${_ossl_crypto_dependency}"
"@rpath/${_ossl_crypto_name}" "${_ossl_ssl_real}"
RESULT_VARIABLE _rc)
if(NOT _rc EQUAL 0)
message(FATAL_ERROR "[OpenSSL] failed to make the libssl dependency relocatable")
endif()
endif()
endif()
set(OPENSSL_ROOT_DIR "${_ossl_inst}" CACHE PATH "OpenSSL root" FORCE)
set(OPENSSL_USE_STATIC_LIBS OFF)
find_package(OpenSSL REQUIRED)
message(STATUS "[OpenSSL] built locally (shared) at ${OPENSSL_ROOT_DIR}")