blob: f26ad643ff4d8497f0de780396c83706a70e590f [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.
#
# =============================================================================
# FetchThrift.cmake
#
# Downloads (or uses a local copy of) the Apache Thrift source tarball and
# builds it from source as a static-only, runtime-and-compiler artifact. The
# build runs at configure time so the thrift compiler is available for the
# code generation step that follows.
#
# Exported variables:
# THRIFT_EXECUTABLE - path to the thrift binary that just got built
# THRIFT_INCLUDE_DIR - include directory containing <thrift/Thrift.h>
# THRIFT_STATIC_LIB_PATH- path to libthrift.a / thriftmd.lib
# THRIFT_RUNTIME_LIB_DIR- directory containing the static thrift library
# (and any other build artifacts you may want to
# bundle with the SDK)
#
# Imported targets:
# iotdb_thrift_static - INTERFACE-compatible IMPORTED target that
# propagates include dirs and the static lib.
# iotdb_thrift_external - phony custom target representing the build
# (use add_dependencies(<your-target> iotdb_thrift_external)
# to ensure the thrift build runs first).
# =============================================================================
include(ExternalProject)
set(_thrift_dirname "thrift-${THRIFT_VERSION}")
set(_thrift_tarname "${_thrift_dirname}.tar.gz")
# ---------------------------------------------------------------------------
# Resolve tarball (local cache -> download)
# ---------------------------------------------------------------------------
set(_thrift_tarball "${IOTDB_OS_DEPS_DIR}/${_thrift_tarname}")
if(NOT EXISTS "${_thrift_tarball}")
if(IOTDB_OFFLINE)
message(FATAL_ERROR
"[Thrift] IOTDB_OFFLINE=ON but ${_thrift_tarname} is missing in "
"${IOTDB_OS_DEPS_DIR}.")
endif()
set(_thrift_url "https://archive.apache.org/dist/thrift/${THRIFT_VERSION}/${_thrift_tarname}")
message(STATUS "[Thrift] downloading ${_thrift_url}")
file(DOWNLOAD "${_thrift_url}" "${_thrift_tarball}"
SHOW_PROGRESS TLS_VERIFY ON STATUS _thrift_dl)
list(GET _thrift_dl 0 _code)
if(NOT _code EQUAL 0)
list(GET _thrift_dl 1 _msg)
file(REMOVE "${_thrift_tarball}")
message(FATAL_ERROR "[Thrift] download failed: ${_msg}")
endif()
endif()
# ---------------------------------------------------------------------------
# Extract once into ${CMAKE_BINARY_DIR}/_deps/thrift/src
# ---------------------------------------------------------------------------
set(_thrift_root "${CMAKE_BINARY_DIR}/_deps/thrift")
set(_thrift_src "${_thrift_root}/src/${_thrift_dirname}")
set(_thrift_build "${_thrift_root}/build")
set(_thrift_install "${_thrift_root}/install")
set(_thrift_marker "${_thrift_root}/.extracted-${THRIFT_VERSION}")
set(_thrift_build_config "Release")
if(MSVC AND CMAKE_BUILD_TYPE)
set(_thrift_build_config "${CMAKE_BUILD_TYPE}")
endif()
if(NOT EXISTS "${_thrift_marker}")
file(REMOVE_RECURSE "${_thrift_root}/src")
file(MAKE_DIRECTORY "${_thrift_root}/src")
message(STATUS "[Thrift] extracting ${_thrift_tarball}")
file(ARCHIVE_EXTRACT INPUT "${_thrift_tarball}"
DESTINATION "${_thrift_root}/src")
file(TOUCH "${_thrift_marker}")
endif()
if(NOT EXISTS "${_thrift_src}/CMakeLists.txt")
message(FATAL_ERROR
"[Thrift] could not find ${_thrift_src}/CMakeLists.txt after "
"extracting ${_thrift_tarball}.")
endif()
# ---------------------------------------------------------------------------
# ExternalProject_Add: build thrift at *configure* time so the produced
# binary / library can immediately drive code generation and linking.
# ---------------------------------------------------------------------------
set(_thrift_cmake_args
# CMake 4.x rejects Thrift 0.21's cmake_minimum_required(3.0); set policy first.
"-DCMAKE_POLICY_VERSION_MINIMUM=3.5"
"-DCMAKE_INSTALL_PREFIX=${_thrift_install}"
"-DCMAKE_BUILD_TYPE=${_thrift_build_config}"
"-DBUILD_JAVA=OFF"
"-DBUILD_NODEJS=OFF"
"-DBUILD_JAVASCRIPT=OFF"
"-DBUILD_PYTHON=OFF"
"-DBUILD_TESTING=OFF"
"-DBUILD_TUTORIALS=OFF"
"-DBUILD_SHARED_LIBS=OFF"
"-DWITH_SHARED_LIB=OFF"
"-DWITH_STATIC_LIB=ON"
"-DCMAKE_POSITION_INDEPENDENT_CODE=ON"
"-DCMAKE_POLICY_DEFAULT_CMP0091=NEW"
"-DCMAKE_CXX_STANDARD=11")
if(BOOST_INCLUDE_DIR)
list(APPEND _thrift_cmake_args
"-DBoost_INCLUDE_DIR=${BOOST_INCLUDE_DIR}"
"-DBOOST_INCLUDEDIR=${BOOST_INCLUDE_DIR}")
endif()
if(MSVC)
list(APPEND _thrift_cmake_args
"-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
else()
set(_thrift_cxxflags "-fPIC")
if(IOTDB_USE_CXX11_ABI)
set(_thrift_cxxflags "${_thrift_cxxflags} -D_GLIBCXX_USE_CXX11_ABI=${IOTDB_USE_CXX11_ABI}")
endif()
list(APPEND _thrift_cmake_args
"-DCMAKE_C_FLAGS=-fPIC"
"-DCMAKE_CXX_FLAGS=${_thrift_cxxflags}")
endif()
if(WITH_SSL)
list(APPEND _thrift_cmake_args "-DWITH_OPENSSL=ON")
else()
list(APPEND _thrift_cmake_args "-DWITH_OPENSSL=OFF")
endif()
# Run the ExternalProject build immediately so the thrift compiler is
# available for the subsequent code-generation step. We do this by
# invoking cmake twice via execute_process and only register a phony
# ExternalProject for dependency ordering.
if(IOTDB_USE_CXX11_ABI)
set(_thrift_abi_stamp "-abi${IOTDB_USE_CXX11_ABI}")
else()
set(_thrift_abi_stamp "-abidefault")
endif()
set(_thrift_stamp "${_thrift_build}/.built-${THRIFT_VERSION}-${_thrift_build_config}-mdll${_thrift_abi_stamp}")
if(NOT EXISTS "${_thrift_stamp}")
file(MAKE_DIRECTORY "${_thrift_build}")
message(STATUS "[Thrift] configuring ${_thrift_dirname}")
# When we built m4/flex/bison locally, make sure CMake passes the
# updated PATH down to the nested cmake invocation.
if(IOTDB_LOCAL_TOOLS_BIN)
set(_thrift_env "PATH=${IOTDB_LOCAL_TOOLS_BIN}:$ENV{PATH}")
endif()
if(CMAKE_GENERATOR_PLATFORM)
set(_gen_platform_arg "-A" "${CMAKE_GENERATOR_PLATFORM}")
else()
set(_gen_platform_arg "")
endif()
execute_process(
COMMAND ${CMAKE_COMMAND}
-G "${CMAKE_GENERATOR}"
${_gen_platform_arg}
${_thrift_cmake_args}
"${_thrift_src}"
WORKING_DIRECTORY "${_thrift_build}"
RESULT_VARIABLE _rc)
if(NOT _rc EQUAL 0)
message(FATAL_ERROR "[Thrift] configure step failed (rc=${_rc})")
endif()
message(STATUS "[Thrift] building (${_thrift_build_config})")
execute_process(
COMMAND ${CMAKE_COMMAND} --build . --config ${_thrift_build_config} --target install
WORKING_DIRECTORY "${_thrift_build}"
RESULT_VARIABLE _rc)
if(NOT _rc EQUAL 0)
message(FATAL_ERROR "[Thrift] build/install step failed (rc=${_rc})")
endif()
file(TOUCH "${_thrift_stamp}")
endif()
# ---------------------------------------------------------------------------
# Locate produced artifacts
# ---------------------------------------------------------------------------
set(THRIFT_INCLUDE_DIR "${_thrift_install}/include" CACHE PATH "" FORCE)
# Thrift binary
if(WIN32)
find_program(THRIFT_EXECUTABLE
NAMES thrift
HINTS "${_thrift_install}/bin" "${_thrift_build}/bin/Release"
"${_thrift_build}/compiler/cpp/Release"
"${_thrift_build}/compiler/cpp/bin/Release"
NO_DEFAULT_PATH)
else()
find_program(THRIFT_EXECUTABLE
NAMES thrift
HINTS "${_thrift_install}/bin"
"${_thrift_build}/bin"
"${_thrift_build}/compiler/cpp/bin"
"${_thrift_build}/compiler/cpp"
NO_DEFAULT_PATH)
endif()
if(NOT THRIFT_EXECUTABLE)
message(FATAL_ERROR
"[Thrift] could not find the thrift binary under ${_thrift_install} or ${_thrift_build}")
endif()
message(STATUS "[Thrift] THRIFT_EXECUTABLE = ${THRIFT_EXECUTABLE}")
# Thrift static library (search a few standard install/lib locations).
set(_thrift_libname_candidates)
if(MSVC)
if(_thrift_build_config STREQUAL "Debug")
list(APPEND _thrift_libname_candidates thriftmdd.lib thriftmd.lib thriftmtd.lib thriftmt.lib thrift.lib)
else()
list(APPEND _thrift_libname_candidates thriftmd.lib thriftmt.lib thrift.lib)
endif()
else()
list(APPEND _thrift_libname_candidates libthrift.a)
endif()
set(THRIFT_STATIC_LIB_PATH "")
foreach(_dir
"${_thrift_install}/lib"
"${_thrift_install}/lib64"
"${_thrift_build}/lib"
"${_thrift_build}/lib/Release"
"${_thrift_build}/lib/release")
if(THRIFT_STATIC_LIB_PATH)
break()
endif()
foreach(_n ${_thrift_libname_candidates})
if(EXISTS "${_dir}/${_n}")
set(THRIFT_STATIC_LIB_PATH "${_dir}/${_n}")
set(THRIFT_RUNTIME_LIB_DIR "${_dir}")
break()
endif()
endforeach()
endforeach()
if(NOT THRIFT_STATIC_LIB_PATH)
message(FATAL_ERROR
"[Thrift] could not locate the thrift static library under ${_thrift_install}/lib")
endif()
message(STATUS "[Thrift] THRIFT_STATIC_LIB_PATH = ${THRIFT_STATIC_LIB_PATH}")
# Cache as well so subsequent reconfigures keep the same values.
set(THRIFT_STATIC_LIB_PATH "${THRIFT_STATIC_LIB_PATH}" CACHE FILEPATH "" FORCE)
set(THRIFT_RUNTIME_LIB_DIR "${THRIFT_RUNTIME_LIB_DIR}" CACHE PATH "" FORCE)
# ---------------------------------------------------------------------------
# Imported target wrapping the static library.
# ---------------------------------------------------------------------------
if(NOT TARGET iotdb_thrift_static)
add_library(iotdb_thrift_static STATIC IMPORTED GLOBAL)
set_target_properties(iotdb_thrift_static PROPERTIES
IMPORTED_LOCATION "${THRIFT_STATIC_LIB_PATH}"
INTERFACE_INCLUDE_DIRECTORIES "${THRIFT_INCLUDE_DIR}")
endif()
# Phony target so downstream code can express ordering deps.
if(NOT TARGET iotdb_thrift_external)
add_custom_target(iotdb_thrift_external ALL)
endif()