include(FetchContent)
set(PLATFORM "${CMAKE_SYSTEM_PROCESSOR}")
function(_download_file_with_retry url cache_file do_verify expected_sha256)
set(max_retries 5)
set(attempt 1)
while(attempt LESS_EQUAL max_retries)
message(STATUS "Downloading (${attempt}/${max_retries}): ${url}")
file(DOWNLOAD "${url}" "${cache_file}"
TLS_VERIFY OFF
STATUS st
)
list(GET st 0 code)
if(code EQUAL 0)
if(do_verify)
file(SHA256 "${cache_file}" current_sha256)
if(current_sha256 STREQUAL expected_sha256)
message(STATUS "Download OK and SHA256 verified: ${cache_file}")
return()
else()
message(WARNING "SHA256 mismatch after download, retrying...")
file(REMOVE "${cache_file}")
endif()
else()
message(STATUS "Download OK and SHA256 check disabled: ${cache_file}")
return()
endif()
else()
message(WARNING "Download failed with code ${code}, retrying...")
file(REMOVE "${cache_file}")
endif()
execute_process(COMMAND ${CMAKE_COMMAND} -E sleep 0.001)
math(EXPR attempt "${attempt} + 1")
endwhile()
message(FATAL_ERROR "Failed to download file after ${max_retries} attempts: ${url}")
endfunction()
function(_download_file url cache_file expected_sha256)
set(do_verify TRUE)
if(NOT expected_sha256)
set(do_verify FALSE)
endif()
if(EXISTS "${cache_file}" AND do_verify)
file(SHA256 "${cache_file}" current_sha256)
if(current_sha256 STREQUAL expected_sha256)
message(STATUS "File already exists and passed SHA256 check: ${cache_file}")
return()
else()
message(WARNING "SHA256 mismatch, redownloading: ${cache_file}")
file(REMOVE "${cache_file}")
endif()
elseif(EXISTS "${cache_file}" AND NOT do_verify)
message(STATUS "File exists and SHA256 check disabled: ${cache_file}")
return()
endif()
_download_file_with_retry("${url}" "${cache_file}" "${do_verify}" "${expected_sha256}")
endfunction()
function(_is_complete_source is_complete dir file_pattern)
if(NOT EXISTS "${dir}")
set(${is_complete} FALSE PARENT_SCOPE)
return()
endif()
file(GLOB entries "${dir}/*")
if(NOT entries)
set(${is_complete} FALSE PARENT_SCOPE)
return()
endif()
file(GLOB core "${dir}/${file_pattern}")
if(NOT core)
message(STATUS "Missing core file: ${file_pattern}")
set(${is_complete} FALSE PARENT_SCOPE)
return()
endif()
set(${is_complete} TRUE PARENT_SCOPE)
endfunction()
function(_download_open_source_with_path opensource_name src_path cache_dir)
string(JSON DEPENDENCIES_COUNT LENGTH "${DEP_JSON_STRING}")
math(EXPR DEPENDENCIES_COUNT "${DEPENDENCIES_COUNT} - 1")
if(src_path AND NOT src_path STREQUAL "")
set(src_dir "${src_path}")
else()
message(FATAL_ERROR
"Dependency '${opensource_name}' requires a valid src_path, "
"but none was provided. Please specify a non-empty source path."
)
endif()
set(found_dep FALSE)
foreach(INDEX RANGE "${DEPENDENCIES_COUNT}")
string(JSON DEP_NAME MEMBER "${DEP_JSON_STRING}" "${INDEX}")
if(NOT "${DEP_NAME}" STREQUAL "${opensource_name}")
continue()
endif()
set(found_dep TRUE)
# Get 3rd package type.
string(JSON DEP_TYPE GET "${DEP_JSON_STRING}" "${DEP_NAME}" "type")
# file type
if("${DEP_TYPE}" STREQUAL "file")
string(JSON DEP_URL GET "${DEP_JSON_STRING}" "${DEP_NAME}" "url")
string(JSON CACHE_FILE_NAME GET "${DEP_JSON_STRING}" "${DEP_NAME}" "fileName")
if(NOT "${DEP_URL}" STREQUAL "")
string(CONFIGURE "${DEP_URL}" download_url)
message(STATUS "Begin to download ${DEP_NAME} from ${download_url}")
string(JSON SHA256 GET "${DEP_JSON_STRING}" "${DEP_NAME}" "sha256")
_download_file("${download_url}" "${cache_dir}/${CACHE_FILE_NAME}" "${SHA256}")
FetchContent_Declare(
"${DEP_NAME}"
URL file://${cache_dir}/${CACHE_FILE_NAME}
SOURCE_DIR "${src_dir}"
)
FetchContent_Populate(${DEP_NAME})
endif()
endif()
# git type
if("${DEP_TYPE}" STREQUAL "git")
string(JSON DEP_REPO GET "${DEP_JSON_STRING}" "${DEP_NAME}" "url")
string(JSON DEP_TAG GET "${DEP_JSON_STRING}" "${DEP_NAME}" "tag")
if(NOT "${DEP_REPO}" STREQUAL "")
message(STATUS "Begin to download ${DEP_NAME} from ${DEP_REPO}")
FetchContent_Declare(
"${DEP_NAME}"
SOURCE_DIR "${src_dir}"
GIT_REPOSITORY "${DEP_REPO}"
GIT_TAG "${DEP_TAG}"
)
FetchContent_Populate(${DEP_NAME})
endif()
endif()
break()
message(FATAL_ERROR "Unknown dependency type: ${DEP_TYPE}")
endforeach()
if(NOT found_dep)
message(FATAL_ERROR "Dependency not found: ${opensource_name}")
endif()
message(STATUS "Successfully downloaded ${opensource_name}")
endfunction()
function(download_open_source pkg_name file_pattern output_dir)
set(PKG_DIR "${THIRD_PARTY_SRC_DIR}/${pkg_name}")
_is_complete_source(complete "${PKG_DIR}" "${file_pattern}")
if(complete)
message(STATUS "Download completed: ${pkg_name}")
return()
endif()
if(EXISTS "${PKG_DIR}")
message(STATUS "Cleaning ${PKG_DIR}")
file(REMOVE_RECURSE "${PKG_DIR}")
endif()
if(NOT EXISTS "${output_dir}")
file(MAKE_DIRECTORY "${output_dir}")
endif()
_download_open_source_with_path("${pkg_name}" "${PKG_DIR}" "${output_dir}")
endfunction()
function(apply_patches COMPONENT_SRC_DIR FILE_GLOB_PATTERN)
file(GLOB PKG_LIST "${COMPONENT_SRC_DIR}/SOURCE/${FILE_GLOB_PATTERN}")
list(GET PKG_LIST 0 PKG_DIR)
if(NOT PKG_DIR)
message(FATAL_ERROR "No package directory found in ${COMPONENT_SRC_DIR}/SOURCE")
endif()
file(GLOB SPEC_FILE "${COMPONENT_SRC_DIR}/*.spec")
if(NOT SPEC_FILE)
message(FATAL_ERROR "Spec file not found in ${COMPONENT_SRC_DIR}")
endif()
file(STRINGS "${SPEC_FILE}" PATCH_LINES REGEX "^Patch[0-9]*:")
foreach(LINE ${PATCH_LINES})
string(REGEX REPLACE "^Patch[0-9]*:[ \t]*" "" PATCH_FILE "${LINE}")
set(PATCH_PATH "${COMPONENT_SRC_DIR}/${PATCH_FILE}")
if(EXISTS "${PATCH_PATH}")
execute_process(
COMMAND patch -p1
WORKING_DIRECTORY ${PKG_DIR}
INPUT_FILE ${PATCH_PATH}
OUTPUT_QUIET
)
else()
message(WARNING "Patch file not found: ${PATCH_PATH}")
endif()
endforeach()
endfunction()
function(get_ABI_option_value)
if(DEFINED USE_CXX11_ABI)
if(${USE_CXX11_ABI} STREQUAL "0" OR ${USE_CXX11_ABI} STREQUAL "1")
message("
==================================
Using ABI = ${USE_CXX11_ABI}
==================================
")
return()
endif()
endif()
execute_process(
COMMAND python3 ${CMAKE_CURRENT_LIST_DIR}/../scripts/get_cxx11_abi_flag.py -f torch
OUTPUT_VARIABLE _CXX_ABI_FLAG
RESULT_VARIABLE _status
ERROR_QUIET
)
if(NOT _status EQUAL 0)
message(WARNING "Failed to get ABI flag from torch, using default = 0")
set(USE_CXX11_ABI 0 PARENT_SCOPE)
return()
endif()
string(STRIP "${_CXX_ABI_FLAG}" _CXX_ABI_FLAG)
if(NOT _CXX_ABI_FLAG MATCHES "^[01]$")
message(WARNING "Invalid ABI flag '${_CXX_ABI_FLAG}', using default = 0")
set(USE_CXX11_ABI 0 PARENT_SCOPE)
return()
endif()
message("
==================================
Using ABI = ${_CXX_ABI_FLAG}
==================================
")
set(USE_CXX11_ABI ${_CXX_ABI_FLAG} PARENT_SCOPE)
endfunction()
function(ensure_aslr_level target_level)
execute_process(
COMMAND cat /proc/sys/kernel/randomize_va_space
OUTPUT_VARIABLE current_level
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(NOT current_level STREQUAL "${target_level}")
message(STATUS "Current ASLR level is ${current_level}, updating to ${target_level}")
execute_process(
COMMAND sudo sh -c "echo ${target_level} > /proc/sys/kernel/randomize_va_space"
RESULT_VARIABLE result
)
if(NOT result EQUAL 0)
message(WARNING "Failed to set ASLR level. You may need sudo permission.")
else()
message(STATUS "ASLR level successfully updated to ${target_level}")
endif()
else()
message(STATUS "ASLR level is already ${target_level}, no change needed.")
endif()
endfunction()
function(get_architecture ARCH)
execute_process(COMMAND arch COMMAND tr -d "\n" OUTPUT_VARIABLE ARCHITECTURE)
if (ARCHITECTURE STREQUAL "x86_64")
message("Compiling PS lib for architecture: ${ARCHITECTURE}")
add_compile_options(-mavx)
elseif (ARCHITECTURE STREQUAL "aarch64")
message("Compiling PS lib for architecture: ${ARCHITECTURE}")
else()
message(FATAL_ERROR "The target arch is not supported: ${ARCHITECTURE}")
endif()
set(${ARCH} "${ARCHITECTURE}" PARENT_SCOPE)
endfunction()
function(find_pytorch OUT_VAR)
execute_process(
COMMAND python3 -c "import torch, os; print(os.path.dirname(os.path.abspath(torch.__file__)))"
OUTPUT_VARIABLE TORCH_PATH
ERROR_VARIABLE PYTHON_ERROR
OUTPUT_STRIP_TRAILING_WHITESPACE
)
string(FIND "${PYTHON_ERROR}" "ModuleNotFoundError" TORCH_ERROR_FOUND)
if(NOT TORCH_ERROR_FOUND EQUAL -1)
message(FATAL_ERROR "Python 'torch' module not found!")
endif()
set(${OUT_VAR} "${TORCH_PATH}" PARENT_SCOPE)
message(STATUS "Found Python torch at: ${TORCH_PATH}")
endfunction()