| # 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. |
| # |
| # ============================================================================= |
| # FetchBuildTools.cmake |
| # |
| # Apache Thrift's source build needs a working flex / bison toolchain (m4 too |
| # on Unix). When the host already provides them on PATH we use them as-is. |
| # Otherwise we provision them locally: |
| # |
| # * Linux / macOS - configure-make-install each tool from a tarball into |
| # ${CMAKE_BINARY_DIR}/tools (no sudo required). |
| # * Windows - extract the winflexbison zip and copy |
| # win_flex.exe -> flex.exe, win_bison.exe -> bison.exe. |
| # |
| # Tarballs / zips are resolved with the standard three-stage pattern: |
| # 1. ${IOTDB_OS_DEPS_DIR}/<filename> (or any match for an optional GLOB) |
| # 2. file(DOWNLOAD) when IOTDB_OFFLINE is OFF |
| # 3. FATAL_ERROR otherwise |
| # ============================================================================= |
| |
| set(_tools_prefix "${CMAKE_BINARY_DIR}/tools") |
| set(_tools_bin "${_tools_prefix}/bin") |
| file(MAKE_DIRECTORY "${_tools_bin}") |
| |
| # Make sure any tool we install locally takes precedence over the system PATH |
| # for the remainder of the configure step (and child ExternalProject calls). |
| if(WIN32) |
| set(ENV{PATH} "${_tools_bin};$ENV{PATH}") |
| else() |
| set(ENV{PATH} "${_tools_bin}:$ENV{PATH}") |
| endif() |
| |
| set(M4_VERSION "1.4.19" CACHE STRING "GNU m4 version to build when missing") |
| set(FLEX_VERSION "2.6.4" CACHE STRING "GNU flex version to build when missing") |
| set(BISON_VERSION "3.8" CACHE STRING "GNU bison version to build when missing") |
| set(WINFLEXBISON_VERSION "2.5.25" |
| CACHE STRING "winflexbison version to download when no local zip is present") |
| |
| set(_m4_url "https://ftp.gnu.org/gnu/m4/m4-${M4_VERSION}.tar.gz") |
| set(_flex_url "https://github.com/westes/flex/releases/download/v${FLEX_VERSION}/flex-${FLEX_VERSION}.tar.gz") |
| set(_bison_url "https://ftp.gnu.org/gnu/bison/bison-${BISON_VERSION}.tar.gz") |
| set(_winflexbison_url |
| "https://github.com/lexxmark/winflexbison/releases/download/v${WINFLEXBISON_VERSION}/win_flex_bison-${WINFLEXBISON_VERSION}.zip") |
| set(_winflexbison_filename "win_flex_bison-${WINFLEXBISON_VERSION}.zip") |
| |
| include(ProcessorCount) |
| ProcessorCount(_jobs) |
| if(_jobs LESS 1) |
| set(_jobs 1) |
| endif() |
| |
| # Resolve tarball: prefer the exact filename in ${IOTDB_OS_DEPS_DIR}/, then |
| # any path matching GLOB_PATTERN (caller-supplied wildcard for relaxed naming, |
| # e.g. win_flex_bison*.zip), and finally fall back to a download. |
| function(_iotdb_resolve_tarball OUT_VAR FILENAME URL) |
| cmake_parse_arguments(ARG "" "GLOB_PATTERN" "" ${ARGN}) |
| |
| set(_local "${IOTDB_OS_DEPS_DIR}/${FILENAME}") |
| if(EXISTS "${_local}") |
| set(${OUT_VAR} "${_local}" PARENT_SCOPE) |
| return() |
| endif() |
| |
| if(ARG_GLOB_PATTERN) |
| file(GLOB _matches "${IOTDB_OS_DEPS_DIR}/${ARG_GLOB_PATTERN}") |
| if(_matches) |
| list(GET _matches 0 _hit) |
| message(STATUS "[BuildTools] reusing ${_hit}") |
| set(${OUT_VAR} "${_hit}" PARENT_SCOPE) |
| return() |
| endif() |
| endif() |
| |
| if(IOTDB_OFFLINE) |
| set(_hint "${FILENAME}") |
| if(ARG_GLOB_PATTERN) |
| set(_hint "${FILENAME} (or any ${ARG_GLOB_PATTERN})") |
| endif() |
| message(FATAL_ERROR |
| "[BuildTools] IOTDB_OFFLINE=ON but ${_hint} is missing in " |
| "${IOTDB_OS_DEPS_DIR}.") |
| endif() |
| |
| message(STATUS "[BuildTools] downloading ${URL}") |
| file(DOWNLOAD "${URL}" "${_local}" SHOW_PROGRESS STATUS _st TLS_VERIFY ON) |
| list(GET _st 0 _code) |
| if(NOT _code EQUAL 0) |
| list(GET _st 1 _msg) |
| file(REMOVE "${_local}") |
| message(FATAL_ERROR "[BuildTools] download failed for ${FILENAME}: ${_msg}") |
| endif() |
| set(${OUT_VAR} "${_local}" PARENT_SCOPE) |
| endfunction() |
| |
| # Configure-make-install <name> from <tarball> into ${_tools_prefix}. |
| function(_iotdb_build_autotools NAME TARBALL EXTRACTED_DIRNAME) |
| set(_src_root "${CMAKE_BINARY_DIR}/_deps/${NAME}") |
| set(_marker "${_tools_prefix}/.${NAME}-installed") |
| if(EXISTS "${_marker}") |
| return() |
| endif() |
| file(REMOVE_RECURSE "${_src_root}") |
| file(MAKE_DIRECTORY "${_src_root}") |
| message(STATUS "[BuildTools] extracting ${TARBALL}") |
| file(ARCHIVE_EXTRACT INPUT "${TARBALL}" DESTINATION "${_src_root}") |
| set(_src "${_src_root}/${EXTRACTED_DIRNAME}") |
| if(NOT EXISTS "${_src}/configure") |
| message(FATAL_ERROR |
| "[BuildTools] expected configure script at ${_src}/configure") |
| endif() |
| message(STATUS "[BuildTools] building ${NAME} -> ${_tools_prefix}") |
| # flex 2.6.4: reallocarray() needs _GNU_SOURCE on glibc 2.26+ (westes/flex#241). |
| set(_env_prefix "") |
| if(NAME STREQUAL "flex" AND CMAKE_SYSTEM_NAME STREQUAL "Linux") |
| set(_env_prefix env CFLAGS=-D_GNU_SOURCE CXXFLAGS=-D_GNU_SOURCE) |
| endif() |
| if(_env_prefix) |
| execute_process( |
| COMMAND ${_env_prefix} ./configure --prefix=${_tools_prefix} |
| WORKING_DIRECTORY "${_src}" |
| RESULT_VARIABLE _rc) |
| else() |
| execute_process( |
| COMMAND ./configure --prefix=${_tools_prefix} |
| WORKING_DIRECTORY "${_src}" |
| RESULT_VARIABLE _rc) |
| endif() |
| if(NOT _rc EQUAL 0) |
| message(FATAL_ERROR "[BuildTools] configure failed for ${NAME}") |
| endif() |
| if(_env_prefix) |
| execute_process( |
| COMMAND ${_env_prefix} make -j${_jobs} |
| WORKING_DIRECTORY "${_src}" |
| RESULT_VARIABLE _rc) |
| else() |
| execute_process( |
| COMMAND make -j${_jobs} |
| WORKING_DIRECTORY "${_src}" |
| RESULT_VARIABLE _rc) |
| endif() |
| if(NOT _rc EQUAL 0) |
| message(FATAL_ERROR "[BuildTools] make failed for ${NAME}") |
| endif() |
| if(_env_prefix) |
| execute_process( |
| COMMAND ${_env_prefix} make install |
| WORKING_DIRECTORY "${_src}" |
| RESULT_VARIABLE _rc) |
| else() |
| execute_process( |
| COMMAND make install |
| WORKING_DIRECTORY "${_src}" |
| RESULT_VARIABLE _rc) |
| endif() |
| if(NOT _rc EQUAL 0) |
| message(FATAL_ERROR "[BuildTools] make install failed for ${NAME}") |
| endif() |
| file(TOUCH "${_marker}") |
| endfunction() |
| |
| # ============================================================================= |
| # Windows branch - winflexbison |
| # ============================================================================= |
| if(WIN32) |
| # Stage 1: pick up an existing flex/bison if the host already provides it. |
| find_program(FLEX_EXECUTABLE NAMES flex win_flex) |
| find_program(BISON_EXECUTABLE NAMES bison win_bison) |
| |
| if(FLEX_EXECUTABLE AND BISON_EXECUTABLE) |
| message(STATUS "[BuildTools] using system flex = ${FLEX_EXECUTABLE}") |
| message(STATUS "[BuildTools] using system bison = ${BISON_EXECUTABLE}") |
| set(IOTDB_LOCAL_TOOLS_BIN "${_tools_bin}" CACHE INTERNAL "") |
| return() |
| endif() |
| |
| # Stage 2/3: resolve and extract the winflexbison zip into _tools_bin. |
| _iotdb_resolve_tarball(_wfb_zip |
| "${_winflexbison_filename}" |
| "${_winflexbison_url}" |
| GLOB_PATTERN "win_flex_bison*.zip") |
| |
| set(_wfb_marker "${_tools_bin}/.winflexbison-installed") |
| if(NOT EXISTS "${_wfb_marker}") |
| message(STATUS "[BuildTools] extracting ${_wfb_zip}") |
| file(ARCHIVE_EXTRACT INPUT "${_wfb_zip}" DESTINATION "${_tools_bin}") |
| |
| if(NOT EXISTS "${_tools_bin}/win_flex.exe" OR NOT EXISTS "${_tools_bin}/win_bison.exe") |
| message(FATAL_ERROR |
| "[BuildTools] win_flex.exe / win_bison.exe not found after " |
| "extracting ${_wfb_zip} into ${_tools_bin}.") |
| endif() |
| |
| # Copy with renamed targets so thrift's CMakeLists sees flex/bison. |
| execute_process(COMMAND ${CMAKE_COMMAND} -E copy |
| "${_tools_bin}/win_flex.exe" "${_tools_bin}/flex.exe" |
| RESULT_VARIABLE _rc) |
| if(NOT _rc EQUAL 0) |
| message(FATAL_ERROR "[BuildTools] failed to copy win_flex.exe -> flex.exe") |
| endif() |
| execute_process(COMMAND ${CMAKE_COMMAND} -E copy |
| "${_tools_bin}/win_bison.exe" "${_tools_bin}/bison.exe" |
| RESULT_VARIABLE _rc) |
| if(NOT _rc EQUAL 0) |
| message(FATAL_ERROR "[BuildTools] failed to copy win_bison.exe -> bison.exe") |
| endif() |
| file(TOUCH "${_wfb_marker}") |
| endif() |
| |
| find_program(FLEX_EXECUTABLE flex PATHS "${_tools_bin}" NO_DEFAULT_PATH REQUIRED) |
| find_program(BISON_EXECUTABLE bison PATHS "${_tools_bin}" NO_DEFAULT_PATH REQUIRED) |
| |
| message(STATUS "[BuildTools] flex = ${FLEX_EXECUTABLE}") |
| message(STATUS "[BuildTools] bison = ${BISON_EXECUTABLE}") |
| set(IOTDB_LOCAL_TOOLS_BIN "${_tools_bin}" CACHE INTERNAL "") |
| return() |
| endif() |
| |
| # ============================================================================= |
| # Linux / macOS branch - m4 / flex / bison from autotools tarballs |
| # ============================================================================= |
| |
| # m4 (flex/bison both depend on this) |
| find_program(M4_EXECUTABLE m4) |
| if(NOT M4_EXECUTABLE) |
| _iotdb_resolve_tarball(_m4_tarball "m4-${M4_VERSION}.tar.gz" "${_m4_url}") |
| _iotdb_build_autotools(m4 "${_m4_tarball}" "m4-${M4_VERSION}") |
| find_program(M4_EXECUTABLE m4 PATHS "${_tools_bin}" NO_DEFAULT_PATH REQUIRED) |
| endif() |
| message(STATUS "[BuildTools] m4 = ${M4_EXECUTABLE}") |
| |
| # flex |
| find_program(FLEX_EXECUTABLE flex) |
| if(NOT FLEX_EXECUTABLE) |
| _iotdb_resolve_tarball(_flex_tarball "flex-${FLEX_VERSION}.tar.gz" "${_flex_url}") |
| _iotdb_build_autotools(flex "${_flex_tarball}" "flex-${FLEX_VERSION}") |
| find_program(FLEX_EXECUTABLE flex PATHS "${_tools_bin}" NO_DEFAULT_PATH REQUIRED) |
| endif() |
| message(STATUS "[BuildTools] flex = ${FLEX_EXECUTABLE}") |
| |
| # bison |
| find_program(BISON_EXECUTABLE bison) |
| if(NOT BISON_EXECUTABLE) |
| _iotdb_resolve_tarball(_bison_tarball "bison-${BISON_VERSION}.tar.gz" "${_bison_url}") |
| _iotdb_build_autotools(bison "${_bison_tarball}" "bison-${BISON_VERSION}") |
| find_program(BISON_EXECUTABLE bison PATHS "${_tools_bin}" NO_DEFAULT_PATH REQUIRED) |
| endif() |
| message(STATUS "[BuildTools] bison = ${BISON_EXECUTABLE}") |
| |
| # Expose the bin dir for downstream ExternalProject_Add calls. |
| set(IOTDB_LOCAL_TOOLS_BIN "${_tools_bin}" CACHE INTERNAL "") |