Files
SunnyLand/cmake/Dependencies.cmake
T

256 lines
10 KiB
CMake
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ============================================
# 依赖管理模块
# ============================================
# 功能:智能依赖获取和管理
# 包含FetchContent模块
include(FetchContent)
# 设置FetchContent配置
set(FETCHCONTENT_QUIET OFF)
set(FETCHCONTENT_UPDATES_DISCONNECTED ON)
# ============================================
# 辅助宏:查找或获取依赖(智能浅克隆 + 链接类型控制)
# 用法如下:
#
# 参数说明:
# DEP_NAME - 依赖的内部名称(用于FetchContent和add_subdirectory等)
# PACKAGE_NAME - 依赖的包名(用于find_package查找本地已安装的包)
# GIT_REPO - 依赖的Git仓库地址(用于FetchContent在线获取源码)
# GIT_TAG - 依赖的Git分支、标签或commit hash(用于指定获取源码的版本)
# LOCAL_PATH - 本地源码路径(如 external/SDL),用于本地源码方式
# LINK_TYPE - 链接类型:STATIC(静态) / SHARED(动态) / AUTO(使用全局BUILD_SHARED_LIBS)
# ============================================
macro(find_or_fetch_dependency DEP_NAME PACKAGE_NAME GIT_REPO GIT_TAG LOCAL_PATH LINK_TYPE)
message(STATUS "正在处理依赖: ${DEP_NAME}")
# 确定该库的链接类型
if("${LINK_TYPE}" STREQUAL "STATIC")
set(_LIB_IS_SHARED OFF)
set(_LINK_TYPE_STR "静态")
elseif("${LINK_TYPE}" STREQUAL "SHARED")
set(_LIB_IS_SHARED ON)
set(_LINK_TYPE_STR "动态")
else() # AUTO 或其他值,使用全局设置
set(_LIB_IS_SHARED ${BUILD_SHARED_LIBS})
if(BUILD_SHARED_LIBS)
set(_LINK_TYPE_STR "动态(全局)")
else()
set(_LINK_TYPE_STR "静态(全局)")
endif()
endif()
# 首先尝试查找本地已安装的包
find_package(${PACKAGE_NAME} QUIET)
if(${PACKAGE_NAME}_FOUND OR ${DEP_NAME}_FOUND)
message(STATUS " ✓ 找到本地安装的 ${PACKAGE_NAME}")
# 打印包的路径信息(尝试多种可能的变量)
if(DEFINED ${PACKAGE_NAME}_DIR)
message(STATUS " 路径: ${${PACKAGE_NAME}_DIR}")
elseif(DEFINED ${DEP_NAME}_DIR)
message(STATUS " 路径: ${${DEP_NAME}_DIR}")
elseif(DEFINED ${PACKAGE_NAME}_ROOT)
message(STATUS " 根目录: ${${PACKAGE_NAME}_ROOT}")
elseif(DEFINED ${DEP_NAME}_ROOT)
message(STATUS " 根目录: ${${DEP_NAME}_ROOT}")
elseif(DEFINED ${PACKAGE_NAME}_INCLUDE_DIRS)
message(STATUS " 头文件: ${${PACKAGE_NAME}_INCLUDE_DIRS}")
elseif(DEFINED ${DEP_NAME}_INCLUDE_DIRS)
message(STATUS " 头文件: ${${DEP_NAME}_INCLUDE_DIRS}")
endif()
else()
message(STATUS " ✗ 未找到本地安装,准备从源码构建 [${_LINK_TYPE_STR}]")
# 配置库特定的编译选项(在add_subdirectory/FetchContent之前)
# SDL系列库的特定选项
if("${DEP_NAME}" MATCHES "^SDL" OR "${PACKAGE_NAME}" MATCHES "^SDL")
if(_LIB_IS_SHARED)
set(SDL_SHARED ON CACHE BOOL "" FORCE)
set(SDL_STATIC OFF CACHE BOOL "" FORCE)
else()
set(SDL_SHARED OFF CACHE BOOL "" FORCE)
set(SDL_STATIC ON CACHE BOOL "" FORCE)
endif()
# 禁用SDL测试
set(SDL_TEST_LIBRARY OFF CACHE BOOL "" FORCE)
set(SDL_TESTS OFF CACHE BOOL "" FORCE)
set(SDL_INSTALL_TESTS OFF CACHE BOOL "" FORCE)
endif()
# 其他库的通用选项
set(BUILD_TESTING OFF CACHE BOOL "" FORCE)
set(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
set(BUILD_DOCS OFF CACHE BOOL "" FORCE)
# SDL_image特定选项:禁用可能导致构建问题的格式支持
if("${DEP_NAME}" STREQUAL "SDL3_image")
# 禁用AVIF格式(需要NASM、Meson等复杂工具链)
set(SDLIMAGE_AVIF OFF CACHE BOOL "" FORCE)
set(SDLIMAGE_AVIF_SHARED OFF CACHE BOOL "" FORCE)
set(SDLIMAGE_AVIF_SAVE OFF CACHE BOOL "" FORCE)
# 禁用AVIF的依赖库
set(SDLIMAGE_AVIF_VENDORED OFF CACHE BOOL "" FORCE)
set(SDLIMAGE_DAV1D OFF CACHE BOOL "" FORCE)
set(SDLIMAGE_AOM OFF CACHE BOOL "" FORCE)
# 可选:禁用其他可能有构建问题的格式
# set(SDLIMAGE_JXL OFF CACHE BOOL "" FORCE) # JPEG XL
endif()
# 智能选择:优先本地源码,否则在线获取
set(LOCAL_SOURCE_DIR ${CMAKE_SOURCE_DIR}/${LOCAL_PATH})
if(EXISTS ${LOCAL_SOURCE_DIR})
# 检测到本地源码,使用本地编译
message(STATUS " → 使用本地源码: ${LOCAL_SOURCE_DIR}")
# 临时设置BUILD_SHARED_LIBS影响该库
set(_SAVED_BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS})
set(BUILD_SHARED_LIBS ${_LIB_IS_SHARED} CACHE BOOL "" FORCE)
# add_subdirectory参数说明:
# 1.源码目录(${LOCAL_SOURCE_DIR}),即依赖库的本地源码路径;
# 2.二进制输出目录(${CMAKE_BINARY_DIR}/_deps/${DEP_NAME}-build),即该依赖库的构建输出会放到这里,避免污染主项目的build目录。
add_subdirectory(${LOCAL_SOURCE_DIR} ${CMAKE_BINARY_DIR}/_deps/${DEP_NAME}-build)
# 恢复全局设置
set(BUILD_SHARED_LIBS ${_SAVED_BUILD_SHARED_LIBS} CACHE BOOL "" FORCE)
# 确保命名空间别名存在(兼容性处理)
# 某些库从源码编译时可能不会自动创建带命名空间的ALIAS target
# 这里统一创建 PACKAGE_NAME::PACKAGE_NAME 格式的别名
if(TARGET ${DEP_NAME} AND NOT TARGET ${PACKAGE_NAME}::${PACKAGE_NAME})
message(STATUS " 创建别名: ${PACKAGE_NAME}::${PACKAGE_NAME} -> ${DEP_NAME}")
add_library(${PACKAGE_NAME}::${PACKAGE_NAME} ALIAS ${DEP_NAME})
elseif(TARGET ${PACKAGE_NAME} AND NOT TARGET ${PACKAGE_NAME}::${PACKAGE_NAME})
message(STATUS " 创建别名: ${PACKAGE_NAME}::${PACKAGE_NAME} -> ${PACKAGE_NAME}")
add_library(${PACKAGE_NAME}::${PACKAGE_NAME} ALIAS ${PACKAGE_NAME})
endif()
else()
# 本地源码不存在,使用FetchContent在线获取
message(STATUS " → 本地源码不存在,在线获取: ${GIT_REPO}")
# 智能检测GIT_TAG类型,决定是否使用浅克隆
string(LENGTH "${GIT_TAG}" TAG_LENGTH)
string(REGEX MATCH "^[0-9a-f]+$" IS_HEX "${GIT_TAG}")
# 判断是否为commit hash(40位十六进制字符串)
if(TAG_LENGTH EQUAL 40 AND IS_HEX)
message(STATUS " 版本: commit hash [${GIT_TAG}],完整克隆")
set(USE_SHALLOW FALSE)
else()
message(STATUS " 版本: ${GIT_TAG},浅克隆")
set(USE_SHALLOW TRUE)
endif()
# FetchContent_Declare用于声明一个FetchContent对象,用于在线获取依赖库源码。
# 参数说明:
# DEP_NAME - 依赖的内部名称(用于FetchContent和add_subdirectory等)
# GIT_REPOSITORY - 依赖的Git仓库地址
# GIT_TAG - 依赖的Git分支、标签或commit hash
# GIT_SHALLOW - 是否使用浅克隆(TRUE/FALSE),根据GIT_TAG类型自动判断
# GIT_PROGRESS - 是否显示Git进度(TRUE/FALSE)
# 临时设置BUILD_SHARED_LIBS影响该库
set(_SAVED_BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS})
set(BUILD_SHARED_LIBS ${_LIB_IS_SHARED} CACHE BOOL "" FORCE)
FetchContent_Declare(
${DEP_NAME}
GIT_REPOSITORY ${GIT_REPO}
GIT_TAG ${GIT_TAG}
GIT_SHALLOW ${USE_SHALLOW}
GIT_PROGRESS TRUE
)
FetchContent_MakeAvailable(${DEP_NAME})
# 恢复全局设置
set(BUILD_SHARED_LIBS ${_SAVED_BUILD_SHARED_LIBS} CACHE BOOL "" FORCE)
endif()
endif()
endmacro()
# ============================================
# 设置所有项目依赖
# ============================================
function(setup_project_dependencies)
# SDL3
find_or_fetch_dependency(
SDL3
SDL3
"https://github.com/libsdl-org/SDL.git"
"release-3.4.2"
"external/SDL-release-3.4.2"
AUTO # 使用全局BUILD_SHARED_LIBS设置
)
# SDL3_image
# 注意:已自动禁用AVIF格式支持(需要NASM、Meson等复杂工具链)
# 如需启用AVIF,请修改宏中的SDLIMAGE_AVIF选项,并安装所需工具:
# - NASM: https://www.nasm.us/
# - Meson: pip install meson ninja
# - Perl: https://strawberryperl.com/
find_or_fetch_dependency(
SDL3_image
SDL3_image
"https://github.com/libsdl-org/SDL_image.git"
"release-3.4.0"
"external/SDL_image-release-3.4.0"
AUTO # 使用全局BUILD_SHARED_LIBS设置
)
# SDL3_mixer
find_or_fetch_dependency(
SDL3_mixer
SDL3_mixer
"https://github.com/libsdl-org/SDL_mixer.git"
"release-3.2.0"
"external/SDL_mixer-release-3.2.0"
AUTO # 使用全局BUILD_SHARED_LIBS设置
)
# SDL3_ttf
find_or_fetch_dependency(
SDL3_ttf
SDL3_ttf
"https://github.com/libsdl-org/SDL_ttf.git"
"release-3.2.2"
"external/SDL_ttf-release-3.2.2"
AUTO # 使用全局BUILD_SHARED_LIBS设置
)
# GLM
find_or_fetch_dependency(
glm
glm
"https://github.com/g-truc/glm.git"
"1.0.1"
"external/glm-1.0.1"
STATIC # GLM通常使用静态链接,动态很可能出错
)
# nlohmann-json (header-only库)
# 注意:FetchContent内部名称用json,但find_package用nlohmann_json
find_or_fetch_dependency(
json
nlohmann_json
"https://github.com/nlohmann/json.git"
"v3.12.0"
"external/json-3.12.0"
STATIC # header-only库,实际不影响
)
# spdlog
find_or_fetch_dependency(
spdlog
spdlog
"https://github.com/gabime/spdlog.git"
"v1.15.3"
"external/spdlog-1.15.3"
STATIC # 推荐静态链接,避免运行时依赖
)
endfunction()