init
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
/.idea
|
||||||
|
/cmake-*
|
||||||
6
.gitmodules
vendored
Normal file
6
.gitmodules
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[submodule "third_party/SDL"]
|
||||||
|
path = third_party/SDL
|
||||||
|
url = https://github.com/libsdl-org/SDL.git
|
||||||
|
[submodule "third_party/SDL_ttf"]
|
||||||
|
path = third_party/SDL_ttf
|
||||||
|
url = https://github.com/libsdl-org/SDL_ttf.git
|
||||||
34
CMakeLists.txt
Normal file
34
CMakeLists.txt
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#
|
||||||
|
# project: mirage
|
||||||
|
#
|
||||||
|
cmake_minimum_required(VERSION 3.21)
|
||||||
|
project(mirage)
|
||||||
|
|
||||||
|
include(cmake/project_cpp_standard.cmake)
|
||||||
|
set_cpp_standard(23)
|
||||||
|
|
||||||
|
include(cmake/retrieve_files.cmake)
|
||||||
|
include(cmake/detect_os.cmake)
|
||||||
|
include(cmake/config_macos.cmake)
|
||||||
|
include(cmake/compile_shaders.cmake)
|
||||||
|
include(cmake/mingw_dll.cmake)
|
||||||
|
include(cmake/mirage_utils.cmake)
|
||||||
|
|
||||||
|
# 配置输出目录
|
||||||
|
configure_project_defaults()
|
||||||
|
|
||||||
|
# 如果是Debug模式, 添加宏定义
|
||||||
|
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||||
|
add_definitions(-DDEBUG=1)
|
||||||
|
else ()
|
||||||
|
add_definitions(-DDEBUG=0)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
add_subdirectory(third_party/SDL)
|
||||||
|
add_subdirectory(third_party/SDL_ttf)
|
||||||
|
|
||||||
|
SET(SRC_FILES)
|
||||||
|
retrieve_files(${CMAKE_CURRENT_SOURCE_DIR}/src SRC_FILES)
|
||||||
|
add_executable(learn ${SRC_FILES})
|
||||||
|
target_include_directories(learn PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||||
|
target_link_libraries(learn SDL3-static SDL3_ttf-static)
|
||||||
0
cache/shader_paths.txt
vendored
Normal file
0
cache/shader_paths.txt
vendored
Normal file
115
cmake/compile_shaders.cmake
Normal file
115
cmake/compile_shaders.cmake
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
include(CMakeParseArguments)
|
||||||
|
|
||||||
|
# 查找Python解释器
|
||||||
|
find_package(Python3 REQUIRED)
|
||||||
|
|
||||||
|
# 存储脚本路径
|
||||||
|
set(SHADER_COMPILE_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/tools/compile_shaders.py")
|
||||||
|
|
||||||
|
# 在cache目录下创建着色器目录.txt
|
||||||
|
set(SHADER_PATH_FILE ${CMAKE_CURRENT_SOURCE_DIR}/cache/shader_paths.txt)
|
||||||
|
file(REMOVE ${SHADER_PATH_FILE})
|
||||||
|
file(WRITE ${SHADER_PATH_FILE} "")
|
||||||
|
|
||||||
|
# 添加着色器目录的函数
|
||||||
|
# 参数:
|
||||||
|
# path: 要添加的包含 .slang 着色器文件的目录路径
|
||||||
|
# 功能:
|
||||||
|
# 1. 将路径转换为适合目标系统的格式 (特别是处理 Cygwin)。
|
||||||
|
# 2. 将路径追加到 SHADER_PATH_FILE 指定的文件中。
|
||||||
|
# 3. 查找指定路径下的所有 .slang 文件。
|
||||||
|
# 4. 将找到的 .slang 文件添加为 CMake 配置的依赖项,
|
||||||
|
# 以便在这些文件更改时触发重新配置。
|
||||||
|
# 注意:
|
||||||
|
# - 需要在使用此函数前定义 CMAKE_BINARY_DIR 和 SHADER_PATH_FILE 变量。
|
||||||
|
# 例如: set(SHADER_PATH_FILE ${CMAKE_BINARY_DIR}/shader_paths.txt)
|
||||||
|
# - 假定 SHADER_PATH_FILE 的使用者期望接收适合其环境的路径格式
|
||||||
|
# (此处在 Cygwin 下转换为 Windows 格式)。
|
||||||
|
function(add_mirage_shader_directory path)
|
||||||
|
# 检查 SHADER_PATH_FILE 变量是否已定义
|
||||||
|
if(NOT DEFINED SHADER_PATH_FILE)
|
||||||
|
message(FATAL_ERROR "**错误**: SHADER_PATH_FILE 变量未定义。请在使用 add_mirage_shader_directory 前设置此变量。")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# 获取绝对路径以确保一致性
|
||||||
|
get_filename_component(abs_path ${path} ABSOLUTE)
|
||||||
|
|
||||||
|
# 保存用于文件操作和写入文件的路径变量
|
||||||
|
set(path_to_write ${abs_path})
|
||||||
|
|
||||||
|
# 如果是cygwin环境, 需要转换路径为Windows格式
|
||||||
|
if (CYGWIN)
|
||||||
|
message(STATUS "检测到 Cygwin 环境,尝试使用 cygpath 转换路径: ${abs_path}")
|
||||||
|
# **关键点**: 使用 cygpath -w 将 Cygwin 路径转换为 Windows 路径
|
||||||
|
execute_process(
|
||||||
|
COMMAND cygpath -w ${abs_path}
|
||||||
|
OUTPUT_VARIABLE path_windows
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE # 去除可能的尾随空格
|
||||||
|
RESULT_VARIABLE cygpath_result
|
||||||
|
ERROR_QUIET # 如果 cygpath 不存在或失败,则不显示错误,但检查 result
|
||||||
|
)
|
||||||
|
|
||||||
|
if(cygpath_result EQUAL 0 AND path_windows) # 检查 cygpath 是否成功执行并有输出
|
||||||
|
# 更新用于写入文件的路径
|
||||||
|
set(path_to_write ${path_windows})
|
||||||
|
message(STATUS "路径已成功转换为 Windows 格式: ${path_to_write}")
|
||||||
|
else()
|
||||||
|
# 如果 cygpath 失败或未找到,发出警告,并回退到原始路径
|
||||||
|
message(WARNING "无法使用 cygpath 转换路径 ${abs_path}。将使用原始路径。请确保 cygpath 在系统 PATH 中。")
|
||||||
|
# path_to_write 保持为 abs_path
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# 将(可能已转换的)路径写入shader_paths.txt
|
||||||
|
# **关键点**: 追加路径到 ${SHADER_PATH_FILE}
|
||||||
|
file(APPEND ${SHADER_PATH_FILE} "${path_to_write}\n")
|
||||||
|
|
||||||
|
# 查找目录下的所有 .slang 文件,包括子目录
|
||||||
|
# **关键点**: 递归查找 ${abs_path} 目录下的 *.slang 文件
|
||||||
|
file(GLOB_RECURSE SHADER_FILES LIST_DIRECTORIES false "${abs_path}/*.slang")
|
||||||
|
|
||||||
|
# 设置依赖关系,当shader文件变化时重新运行CMake配置
|
||||||
|
# **关键点**: 将着色器文件添加为 CMake 配置依赖项
|
||||||
|
foreach(SHADER_FILE ${SHADER_FILES})
|
||||||
|
get_filename_component(ABS_SHADER_FILE ${SHADER_FILE} ABSOLUTE)
|
||||||
|
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${ABS_SHADER_FILE})
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# **关键点**: 输出状态消息,告知用户已添加目录
|
||||||
|
message(STATUS "添加着色器源文件目录: ${path_to_write}")
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
set(SHADER_COMPILE_ARGS "")
|
||||||
|
set(SHADER_SHDC "")
|
||||||
|
if (WIN32 OR CYGWIN)
|
||||||
|
list(APPEND SHADER_COMPILE_ARGS "--hlsl")
|
||||||
|
set(SHADER_SHDC ${MIRAGE_ROOT_DIR}/tools/win_mirage_shdc.exe)
|
||||||
|
elseif (APPLE)
|
||||||
|
list(APPEND SHADER_COMPILE_ARGS "--metal")
|
||||||
|
set(SHADER_SHDC ${MIRAGE_ROOT_DIR}/tools/mac_mirage_shdc)
|
||||||
|
else()
|
||||||
|
list(APPEND SHADER_COMPILE_ARGS "--glsl")
|
||||||
|
set(SHADER_SHDC ${MIRAGE_ROOT_DIR}/tools/linux_mirage_shdc)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "使用着色器编译器: ${SHADER_SHDC}")
|
||||||
|
|
||||||
|
# 如果是Debug模式, 添加--debug选项
|
||||||
|
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||||
|
list(APPEND SHADER_COMPILE_ARGS "--debug")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
# 添加编译目标, 调用tools/compile_shaders.py
|
||||||
|
add_custom_target(compile_shaders ALL
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${SHADER_COMPILE_SCRIPT}
|
||||||
|
--shdc ${SHADER_SHDC}
|
||||||
|
--shader_list ${SHADER_PATH_FILE}
|
||||||
|
${SHADER_COMPILE_ARGS}
|
||||||
|
COMMENT "编译着色器"
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
# 定义一个函数,将编译着色器作为其他目标的依赖
|
||||||
|
function(add_shader_dependencies target)
|
||||||
|
add_dependencies(${target} compile_shaders)
|
||||||
|
endfunction()
|
||||||
16
cmake/config_macos.cmake
Normal file
16
cmake/config_macos.cmake
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
# 如果是Macos
|
||||||
|
if (APPLE)
|
||||||
|
# 获取 Homebrew 安装的 libomp 路径
|
||||||
|
execute_process(
|
||||||
|
COMMAND brew --prefix libomp
|
||||||
|
OUTPUT_VARIABLE HOMEBREW_LIBOMP_PATH
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
|
|
||||||
|
# 设置 OpenMP 路径变量
|
||||||
|
set(OpenMP_CXX_FLAGS "-Xpreprocessor -fopenmp -I${HOMEBREW_LIBOMP_PATH}/include")
|
||||||
|
set(OpenMP_CXX_LIB_NAMES "omp")
|
||||||
|
set(OpenMP_omp_LIBRARY "${HOMEBREW_LIBOMP_PATH}/lib/libomp.dylib")
|
||||||
|
enable_language(OBJC OBJCXX)
|
||||||
|
endif ()
|
||||||
42
cmake/configure_glfw_native.cmake
Normal file
42
cmake/configure_glfw_native.cmake
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
function(configure_glfw_native target)
|
||||||
|
# 检测操作系统
|
||||||
|
if(WIN32)
|
||||||
|
target_compile_definitions(${target} PRIVATE GLFW_EXPOSE_NATIVE_WIN32)
|
||||||
|
message(STATUS "公开 GLFW 原生 Win32 API")
|
||||||
|
elseif(APPLE)
|
||||||
|
target_compile_definitions(${target} PRIVATE GLFW_EXPOSE_NATIVE_COCOA)
|
||||||
|
message(STATUS "公开 GLFW 原生 Cocoa API")
|
||||||
|
elseif(UNIX)
|
||||||
|
# 对于 Unix-like 系统,我们需要进一步检测
|
||||||
|
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||||
|
# 检测 Wayland
|
||||||
|
find_package(Wayland)
|
||||||
|
if(Wayland_FOUND)
|
||||||
|
target_compile_definitions(${target} PRIVATE GLFW_EXPOSE_NATIVE_WAYLAND)
|
||||||
|
message(STATUS "公开 GLFW 原生 Wayland API")
|
||||||
|
else()
|
||||||
|
# 如果没有 Wayland,默认使用 X11
|
||||||
|
target_compile_definitions(${target} PRIVATE GLFW_EXPOSE_NATIVE_X11)
|
||||||
|
message(STATUS "公开 GLFW 原生 X11 API")
|
||||||
|
endif()
|
||||||
|
elseif(CMAKE_SYSTEM_NAME MATCHES "FreeBSD|OpenBSD|NetBSD")
|
||||||
|
# BSD 系统通常使用 X11
|
||||||
|
target_compile_definitions(${target} PRIVATE GLFW_EXPOSE_NATIVE_X11)
|
||||||
|
message(STATUS "公开 BSD 的 GLFW 原生 X11 API")
|
||||||
|
else()
|
||||||
|
message(WARNING "未知的类 Unix 系统,GLFW 原生 API 可能无法正确暴露")
|
||||||
|
endif()
|
||||||
|
elseif (ANDROID)
|
||||||
|
target_compile_definitions(${target} PRIVATE GLFW_EXPOSE_NATIVE_ANDROID)
|
||||||
|
message(STATUS "公开 GLFW 原生 Android API")
|
||||||
|
else()
|
||||||
|
message(WARNING "未知作系统,GLFW 原生 API 可能无法正确暴露")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# 对于 EGL 支持,你可能需要额外的检测
|
||||||
|
# 这里我们简单地为所有非 Windows 和非 macOS 系统启用它
|
||||||
|
if(NOT WIN32 AND NOT APPLE)
|
||||||
|
target_compile_definitions(${target} PRIVATE GLFW_EXPOSE_NATIVE_EGL)
|
||||||
|
message(STATUS "公开 GLFW 原生 EGL API")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
131
cmake/detect_os.cmake
Normal file
131
cmake/detect_os.cmake
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
|
||||||
|
# 定义一个函数,为指定的目标添加操作系统和架构相关的预处理器定义
|
||||||
|
function(add_os_definitions target)
|
||||||
|
# 检查 target 参数是否提供
|
||||||
|
if(NOT target)
|
||||||
|
message(FATAL_ERROR "函数 add_os_definitions 需要一个 target 参数。")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# --- 阶段 1: 确定宏的值 ---
|
||||||
|
|
||||||
|
# 初始化所有平台、架构和特性宏的值为 0
|
||||||
|
set(mirage_def_windows 0)
|
||||||
|
set(mirage_def_macos 0)
|
||||||
|
set(mirage_def_linux 0)
|
||||||
|
set(mirage_def_freebsd 0)
|
||||||
|
set(mirage_def_ios 0)
|
||||||
|
set(mirage_def_android 0)
|
||||||
|
set(mirage_def_cygwin 0)
|
||||||
|
set(mirage_def_unix 0)
|
||||||
|
set(mirage_def_posix 0)
|
||||||
|
set(mirage_def_mobile 0)
|
||||||
|
set(mirage_def_arch_64bit 0)
|
||||||
|
set(mirage_def_arch_32bit 0)
|
||||||
|
|
||||||
|
# -- 操作系统检测与赋值 --
|
||||||
|
# 注意检测顺序:优先检测更具体的平台
|
||||||
|
if(CYGWIN)
|
||||||
|
# Cygwin 环境比较特殊,它在 Windows 上模拟 Unix
|
||||||
|
set(mirage_def_windows 1) # 基础是 Windows
|
||||||
|
set(mirage_def_cygwin 1) # 明确是 Cygwin
|
||||||
|
set(mirage_def_unix 1) # 提供 Unix API
|
||||||
|
set(mirage_def_posix 1) # 提供 POSIX API
|
||||||
|
message(STATUS "检测到 **Cygwin** 环境 (运行于 Windows)")
|
||||||
|
elseif(WIN32)
|
||||||
|
# 非 Cygwin 的 Windows 环境 (MSVC, MinGW, etc.)
|
||||||
|
set(mirage_def_windows 1)
|
||||||
|
message(STATUS "检测到 **Windows** 操作系统 (非 Cygwin)")
|
||||||
|
elseif(ANDROID)
|
||||||
|
# Android 平台 (通常需要特定工具链设置 ANDROID 变量)
|
||||||
|
set(mirage_def_android 1)
|
||||||
|
set(mirage_def_unix 1) # Android NDK 基于 Unix
|
||||||
|
set(mirage_def_posix 1) # NDK 提供 POSIX API
|
||||||
|
set(mirage_def_mobile 1) # 移动平台
|
||||||
|
message(STATUS "检测到 **Android** 操作系统")
|
||||||
|
elseif(IOS)
|
||||||
|
# iOS 平台 (通常需要特定工具链设置 IOS 变量)
|
||||||
|
# 需要在 APPLE 之前判断,因为 iOS 下 APPLE 也为 TRUE
|
||||||
|
set(mirage_def_ios 1)
|
||||||
|
set(mirage_def_unix 1) # iOS (Darwin) 基于 Unix
|
||||||
|
set(mirage_def_posix 1) # 提供 POSIX API
|
||||||
|
set(mirage_def_mobile 1) # 移动平台
|
||||||
|
message(STATUS "检测到 **iOS** 操作系统")
|
||||||
|
elseif(APPLE)
|
||||||
|
# 此时排除了 iOS,确定是 macOS
|
||||||
|
set(mirage_def_macos 1)
|
||||||
|
set(mirage_def_unix 1) # macOS (Darwin) 基于 Unix
|
||||||
|
set(mirage_def_posix 1) # 提供 POSIX API
|
||||||
|
message(STATUS "检测到 **macOS** 操作系统")
|
||||||
|
elseif(UNIX)
|
||||||
|
# 此时排除了 Apple, Android, Cygwin 的其他 Unix-like 系统
|
||||||
|
set(mirage_def_unix 1)
|
||||||
|
set(mirage_def_posix 1)
|
||||||
|
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||||
|
set(mirage_def_linux 1)
|
||||||
|
message(STATUS "检测到 **Linux** 操作系统")
|
||||||
|
elseif(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
|
||||||
|
set(mirage_def_freebsd 1)
|
||||||
|
message(STATUS "检测到 **FreeBSD** 操作系统")
|
||||||
|
else()
|
||||||
|
message(WARNING "检测到未知的 类Unix 操作系统: ${CMAKE_SYSTEM_NAME}")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
message(WARNING "检测到未知的操作系统: ${CMAKE_SYSTEM_NAME}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# -- 架构检测与赋值 --
|
||||||
|
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
|
set(mirage_def_arch_64bit 1)
|
||||||
|
set(mirage_def_arch_32bit 0) # 明确设置为 0
|
||||||
|
message(STATUS "检测到 **64-bit** 架构")
|
||||||
|
elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||||
|
set(mirage_def_arch_64bit 0) # 明确设置为 0
|
||||||
|
set(mirage_def_arch_32bit 1)
|
||||||
|
message(STATUS "检测到 **32-bit** 架构")
|
||||||
|
else()
|
||||||
|
# 对于未知或未定义的指针大小,两者都保持 0
|
||||||
|
message(WARNING "无法明确检测到 32-bit 或 64-bit 架构 (CMAKE_SIZEOF_VOID_P = ${CMAKE_SIZEOF_VOID_P})。将两者都设置为 0。")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# --- 阶段 2: 组装定义列表 ---
|
||||||
|
set(definitions_list "") # 初始化空列表
|
||||||
|
|
||||||
|
# 添加平台定义
|
||||||
|
list(APPEND definitions_list "MIRAGE_PLATFORM_WINDOWS=${mirage_def_windows}")
|
||||||
|
list(APPEND definitions_list "MIRAGE_PLATFORM_MACOS=${mirage_def_macos}")
|
||||||
|
list(APPEND definitions_list "MIRAGE_PLATFORM_LINUX=${mirage_def_linux}")
|
||||||
|
list(APPEND definitions_list "MIRAGE_PLATFORM_FREEBSD=${mirage_def_freebsd}")
|
||||||
|
list(APPEND definitions_list "MIRAGE_PLATFORM_IOS=${mirage_def_ios}")
|
||||||
|
list(APPEND definitions_list "MIRAGE_PLATFORM_ANDROID=${mirage_def_android}")
|
||||||
|
list(APPEND definitions_list "MIRAGE_PLATFORM_CYGWIN=${mirage_def_cygwin}")
|
||||||
|
|
||||||
|
# 添加架构定义
|
||||||
|
list(APPEND definitions_list "MIRAGE_PLATFORM_ARCH_64BIT=${mirage_def_arch_64bit}")
|
||||||
|
list(APPEND definitions_list "MIRAGE_PLATFORM_ARCH_32BIT=${mirage_def_arch_32bit}")
|
||||||
|
|
||||||
|
# 添加特性定义
|
||||||
|
list(APPEND definitions_list "MIRAGE_PLATFORM_UNIX=${mirage_def_unix}")
|
||||||
|
list(APPEND definitions_list "MIRAGE_PLATFORM_POSIX=${mirage_def_posix}")
|
||||||
|
list(APPEND definitions_list "MIRAGE_PLATFORM_IS_MOBILE=${mirage_def_mobile}")
|
||||||
|
|
||||||
|
# --- 阶段 3: 应用所有定义 ---
|
||||||
|
# **关键:使用一次调用将所有定义添加到目标**
|
||||||
|
if(definitions_list) # 确保列表非空
|
||||||
|
target_compile_definitions(${target} PUBLIC ${definitions_list})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# 函数作用域结束时,mirage_def_* 变量会自动销毁,无需显式 unset
|
||||||
|
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# --- 使用示例 ---
|
||||||
|
# project(MyProject)
|
||||||
|
# add_executable(my_app main.c)
|
||||||
|
#
|
||||||
|
# # 调用函数为 my_app 添加平台定义
|
||||||
|
# add_os_definitions(my_app)
|
||||||
|
#
|
||||||
|
# # 你也可以为库调用
|
||||||
|
# # add_library(my_lib STATIC my_lib.c)
|
||||||
|
# # add_os_definitions(my_lib)
|
||||||
41
cmake/mingw_dll.cmake
Normal file
41
cmake/mingw_dll.cmake
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
|
||||||
|
function(auto_copy_mingw_dll target)
|
||||||
|
if(MINGW)
|
||||||
|
# 获取MinGW目录
|
||||||
|
get_filename_component(MINGW_DIR ${CMAKE_CXX_COMPILER} PATH)
|
||||||
|
|
||||||
|
# 根据你的环境调整DLL列表
|
||||||
|
set(MINGW_DLLS
|
||||||
|
"libstdc++-6.dll"
|
||||||
|
# "libgcc_s_dw2-1.dll"
|
||||||
|
"libgcc_s_seh-1.dll"
|
||||||
|
"libwinpthread-1.dll"
|
||||||
|
"libbz2-1.dll"
|
||||||
|
"libbrotlidec.dll"
|
||||||
|
"libbrotlicommon.dll"
|
||||||
|
"libharfbuzz-0.dll"
|
||||||
|
"libpng16-16.dll"
|
||||||
|
"zlib1.dll"
|
||||||
|
"libglib-2.0-0.dll"
|
||||||
|
"libfreetype-6.dll"
|
||||||
|
"libgraphite2.dll"
|
||||||
|
"libintl-8.dll"
|
||||||
|
"libpcre2-8-0.dll"
|
||||||
|
"libiconv-2.dll"
|
||||||
|
)
|
||||||
|
|
||||||
|
foreach(DLL ${MINGW_DLLS})
|
||||||
|
# 检查文件是否存在
|
||||||
|
if(EXISTS "${MINGW_DIR}/${DLL}")
|
||||||
|
add_custom_command(TARGET ${target} POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||||
|
"${MINGW_DIR}/${DLL}"
|
||||||
|
"$<TARGET_FILE_DIR:${target}>"
|
||||||
|
COMMENT "Copying ${DLL} to output directory"
|
||||||
|
VERBATIM)
|
||||||
|
else()
|
||||||
|
message(WARNING "DLL not found: ${MINGW_DIR}/${DLL}")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
44
cmake/mirage_utils.cmake
Normal file
44
cmake/mirage_utils.cmake
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
|
||||||
|
# 定义一个函数来配置项目的默认设置
|
||||||
|
# 这包括设置输出目录和项目根目录变量
|
||||||
|
function(configure_project_defaults)
|
||||||
|
# 检查是否在顶层 CMakeLists.txt 中调用 (可选但推荐)
|
||||||
|
# 确保 CMAKE_SOURCE_DIR 和 CMAKE_CURRENT_SOURCE_DIR 相同
|
||||||
|
if(NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
||||||
|
message(WARNING "configure_project_defaults() 应该在项目的根 CMakeLists.txt 中调用。")
|
||||||
|
# 如果您确实需要在子目录中设置不同的根目录,请调整此逻辑
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# --- 配置输出目录 ---
|
||||||
|
# 使用 CMAKE_BINARY_DIR 作为基础构建目录
|
||||||
|
# ${CMAKE_BINARY_DIR} 指向您配置 CMake 时指定的构建目录
|
||||||
|
# 例如,在 CLion 中通常是 cmake-build-debug 或 cmake-build-release
|
||||||
|
# 如果手动运行 cmake ..,它就是您运行 cmake 命令的目录
|
||||||
|
|
||||||
|
# **设置可执行文件输出路径**:
|
||||||
|
# 对于单配置生成器 (如 Makefiles, Ninja), 可执行文件将位于 <build>/bin/
|
||||||
|
# 对于多配置生成器 (如 Visual Studio, Xcode), CMake 通常会自动在此路径下附加配置名称
|
||||||
|
# (例如 <build>/bin/Debug/, <build>/bin/Release/)
|
||||||
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin CACHE PATH "Directory for runtime executables")
|
||||||
|
message(STATUS "运行时输出目录设置为: ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
|
||||||
|
|
||||||
|
# **设置库文件输出路径 (共享库和静态库)**:
|
||||||
|
# 规则同上,库文件将位于 <build>/lib/ 或 <build>/lib/<Config>/
|
||||||
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib CACHE PATH "Directory for shared libraries")
|
||||||
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib CACHE PATH "Directory for static libraries")
|
||||||
|
message(STATUS "库输出目录设置为: ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}")
|
||||||
|
message(STATUS "存档输出目录设置为: ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}")
|
||||||
|
|
||||||
|
# --- 提示 ---
|
||||||
|
# 这种全局设置输出目录的方法对于中小型项目是常见的。
|
||||||
|
# 对于更复杂的项目或需要更细粒度控制的情况,可以考虑为每个目标(target)单独设置输出目录属性:
|
||||||
|
# 例如:
|
||||||
|
# add_executable(my_app main.cpp)
|
||||||
|
# set_target_properties(my_app PROPERTIES
|
||||||
|
# RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/executables"
|
||||||
|
# )
|
||||||
|
# add_library(my_lib STATIC my_lib.cpp)
|
||||||
|
# set_target_properties(my_lib PROPERTIES
|
||||||
|
# ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/static_libs"
|
||||||
|
# )
|
||||||
|
endfunction()
|
||||||
85
cmake/project_cpp_standard.cmake
Normal file
85
cmake/project_cpp_standard.cmake
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
# 函数:设置 C++ 标准及相关编译选项
|
||||||
|
# 参数 standard: 需要设置的 C++ 标准版本 (例如 11, 14, 17, 20, 23)
|
||||||
|
function(set_cpp_standard standard)
|
||||||
|
# --- 参数验证 ---
|
||||||
|
set(VALID_STANDARDS 11 14 17 20 23 26) # 定义支持的 C++ 标准列表
|
||||||
|
list(FIND VALID_STANDARDS ${standard} _standard_index) # 查找 standard 是否在列表中
|
||||||
|
if(_standard_index EQUAL -1) # 如果未找到
|
||||||
|
message(WARNING "**非标准 C++ 版本**: ${standard}。支持的版本有: ${VALID_STANDARDS}")
|
||||||
|
# 可选:可以设置为一个默认值或停止配置
|
||||||
|
# message(FATAL_ERROR "不支持的 C++ 标准: ${standard}")
|
||||||
|
# set(standard 17) # 或者设置为默认值,例如 C++17
|
||||||
|
# message(WARNING "已将 C++ 标准设置为默认值: ${standard}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# --- 设置 C++ 标准 ---
|
||||||
|
# 指定需要的 C++ 标准,设置到父作用域,使其对调用者定义的 target 生效
|
||||||
|
set(CMAKE_CXX_STANDARD ${standard} PARENT_SCOPE)
|
||||||
|
# **强制要求此标准**,如果编译器不支持则配置时报错
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON PARENT_SCOPE)
|
||||||
|
# **禁用编译器特定的扩展**,使用更纯粹的标准 C++
|
||||||
|
set(CMAKE_CXX_EXTENSIONS OFF PARENT_SCOPE)
|
||||||
|
|
||||||
|
# --- 平台特定设置 ---
|
||||||
|
if(WIN32 OR CYGWIN)
|
||||||
|
# 为 Windows 定义 UNICODE 宏
|
||||||
|
add_definitions(-DUNICODE -D_UNICODE)
|
||||||
|
# 可选:添加 WIN32_LEAN_AND_MEAN 以减少 Windows 头文件包含,加快编译速度
|
||||||
|
# add_definitions(-DWIN32_LEAN_AND_MEAN)
|
||||||
|
message(STATUS "为 Windows 添加 UNICODE 定义")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# --- 编译器特定设置 ---
|
||||||
|
if(MSVC)
|
||||||
|
# **设置源代码和执行字符集为 UTF-8**
|
||||||
|
add_compile_options(/utf-8)
|
||||||
|
# **强制 MSVC 正确设置 __cplusplus 宏**,以便代码能准确判断 C++ 标准
|
||||||
|
add_compile_options(/Zc:__cplusplus)
|
||||||
|
# **设置警告级别为 W4** (较高警告级别)
|
||||||
|
add_compile_options(/W4)
|
||||||
|
# **禁用特定警告:C4100 未使用的形参** (有时用于接口兼容性)
|
||||||
|
add_compile_options(/wd4100)
|
||||||
|
# 禁用特定警告:C4996 使用了被标记为否决的函数或变量 (例如一些旧的 CRT 函数)
|
||||||
|
add_compile_options(/wd4996)
|
||||||
|
message(STATUS "为 MSVC 添加特定编译选项: /utf-8 /Zc:__cplusplus /W4 /wd4100 /wd4996")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# GCC/Clang 特定选项
|
||||||
|
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||||
|
# **启用常用警告**
|
||||||
|
add_compile_options(-Wall -Wextra)
|
||||||
|
# **禁用未使用参数的警告** (与 MSVC 的 /wd4100 对应)
|
||||||
|
add_compile_options(-Wno-unused-parameter)
|
||||||
|
# **设置输入和执行字符集为 UTF-8** (对应 MSVC 的 /utf-8)
|
||||||
|
# 这有助于处理源代码中的 UTF-8 字符,并影响运行时字符编码,但控制台本身的显示需要环境配合
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -finput-charset=UTF-8 -fexec-charset=UTF-8")
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -finput-charset=UTF-8 -fexec-charset=UTF-8")
|
||||||
|
|
||||||
|
# 根据 C++ 标准添加特定警告 (C++17 及以上)
|
||||||
|
if(${standard} GREATER 14)
|
||||||
|
# **启用阴影变量警告和非虚析构函数警告**
|
||||||
|
add_compile_options(-Wshadow -Wnon-virtual-dtor)
|
||||||
|
message(STATUS "为 GCC/Clang (C++${CMAKE_CXX_STANDARD}) 添加额外警告: -Wshadow -Wnon-virtual-dtor")
|
||||||
|
endif()
|
||||||
|
message(STATUS "为 GCC/Clang 添加特定编译选项: -Wall -Wextra -Wno-unused-parameter -finput-charset=UTF-8 -fexec-charset=UTF-8")
|
||||||
|
# 注意: 控制台/终端的 UTF-8 输出显示通常还需要操作系统环境的配合 (例如 Linux/macOS 终端本身设置,Windows下 chcp 65001)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# MinGW 特定设置 (通常在 Windows 上使用 GCC 工具链)
|
||||||
|
if(MINGW)
|
||||||
|
message(STATUS "检测到 MinGW 编译器")
|
||||||
|
# 如果使用了 C++17 或更高版本, 可能需要链接 libstdc++exp 以支持 <filesystem> 等特性
|
||||||
|
if(${standard} GREATER 14)
|
||||||
|
message(STATUS "**为 MinGW C++${CMAKE_CXX_STANDARD} 添加 libstdc++fs 库依赖** (用于 <filesystem>)")
|
||||||
|
# 注意:较新版本的 MinGW 可能不再需要显式链接,或者需要链接的是 -lstdc++fs
|
||||||
|
# link_libraries() 会影响后续所有 target,更推荐使用 target_link_libraries()
|
||||||
|
# 这里暂时保留 link_libraries(),但建议后续根据具体 target 调整
|
||||||
|
# 尝试链接 stdc++fs,这在较新的 MinGW 中更常见用于 <filesystem>
|
||||||
|
# link_libraries(-lstdc++fs)
|
||||||
|
# 如果链接 -lstdc++fs 失败,可以尝试回退到 -lstdc++exp
|
||||||
|
link_libraries(-lstdc++exp)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "**C++ 标准已设置为: c++${standard}**")
|
||||||
|
endfunction()
|
||||||
316
cmake/retrieve_files.cmake
Normal file
316
cmake/retrieve_files.cmake
Normal file
@@ -0,0 +1,316 @@
|
|||||||
|
#[=======================================================================[
|
||||||
|
平台匹配检查函数
|
||||||
|
参数:
|
||||||
|
platform: 平台标识符 (windows|linux|mac|mobile|desktop)
|
||||||
|
is_match: 输出变量,表示当前平台是否匹配
|
||||||
|
#]=======================================================================]
|
||||||
|
function(is_current_platform platform is_match)
|
||||||
|
# 设置默认值为TRUE(用于未知平台)
|
||||||
|
set(matches FALSE)
|
||||||
|
|
||||||
|
if(platform STREQUAL "windows")
|
||||||
|
if(WIN32 OR CYGWIN)
|
||||||
|
set(matches TRUE)
|
||||||
|
endif()
|
||||||
|
elseif(platform STREQUAL "linux")
|
||||||
|
if(UNIX AND NOT APPLE)
|
||||||
|
set(matches TRUE)
|
||||||
|
endif()
|
||||||
|
elseif(platform STREQUAL "mac")
|
||||||
|
if(APPLE AND NOT IOS)
|
||||||
|
set(matches TRUE)
|
||||||
|
endif()
|
||||||
|
elseif(platform STREQUAL "ios")
|
||||||
|
if(IOS)
|
||||||
|
set(matches TRUE)
|
||||||
|
endif()
|
||||||
|
elseif(platform STREQUAL "android")
|
||||||
|
if(ANDROID)
|
||||||
|
set(matches TRUE)
|
||||||
|
endif()
|
||||||
|
# 添加对unix平台的支持
|
||||||
|
elseif(platform STREQUAL "unix")
|
||||||
|
if(UNIX)
|
||||||
|
set(matches TRUE)
|
||||||
|
endif()
|
||||||
|
elseif(platform STREQUAL "mobile")
|
||||||
|
if(ANDROID OR IOS)
|
||||||
|
set(matches TRUE)
|
||||||
|
endif()
|
||||||
|
elseif(platform STREQUAL "desktop")
|
||||||
|
if(WIN32 OR (UNIX AND NOT APPLE) OR (APPLE AND NOT IOS))
|
||||||
|
set(matches TRUE)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
# 未知平台标识,默认匹配
|
||||||
|
set(matches TRUE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(${is_match} ${matches} PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
#[=======================================================================[
|
||||||
|
主文件检索函数
|
||||||
|
参数:
|
||||||
|
path: 要检索的根目录路径
|
||||||
|
extension: 文件扩展名列表
|
||||||
|
out_files: 输出变量名,将包含筛选后的文件列表
|
||||||
|
#]=======================================================================]
|
||||||
|
function(retrieve_files_custom path extension out_files)
|
||||||
|
# 1. 参数验证
|
||||||
|
if(NOT IS_DIRECTORY "${path}")
|
||||||
|
message(WARNING "错误:目录 '${path}' 不存在")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "正在检索目录: ${path}")
|
||||||
|
|
||||||
|
# 2. 构建文件匹配模式
|
||||||
|
set(file_patterns "")
|
||||||
|
foreach(ext IN LISTS extension)
|
||||||
|
list(APPEND file_patterns "${path}/*.${ext}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# 3. 递归查找所有匹配的文件
|
||||||
|
file(GLOB_RECURSE found_files
|
||||||
|
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
CONFIGURE_DEPENDS ${file_patterns}
|
||||||
|
)
|
||||||
|
|
||||||
|
# 4. 处理找到的文件
|
||||||
|
set(filtered_files "")
|
||||||
|
foreach(current_file IN LISTS found_files)
|
||||||
|
# 4.1 获取文件所在目录
|
||||||
|
get_filename_component(file_dir "${current_file}" DIRECTORY)
|
||||||
|
string(REPLACE "/" ";" dir_components "${file_dir}")
|
||||||
|
|
||||||
|
# 4.2 检查平台兼容性
|
||||||
|
set(should_skip_file FALSE)
|
||||||
|
set(found_platform_dir FALSE)
|
||||||
|
|
||||||
|
foreach(dir_name IN LISTS dir_components)
|
||||||
|
# 检查是否是平台相关目录
|
||||||
|
if(dir_name MATCHES "^(windows|linux|mac|ios|android|unix|mobile|desktop)$")
|
||||||
|
set(found_platform_dir TRUE)
|
||||||
|
is_current_platform(${dir_name} platform_matches)
|
||||||
|
if(NOT platform_matches)
|
||||||
|
set(should_skip_file TRUE)
|
||||||
|
break()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# 如果文件需要跳过,继续处理下一个文件
|
||||||
|
if(should_skip_file)
|
||||||
|
continue()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# 4.3 添加符合条件的文件
|
||||||
|
list(APPEND filtered_files "${current_file}")
|
||||||
|
|
||||||
|
# 4.4 设置IDE文件分组
|
||||||
|
# 计算相对路径作为分组名称
|
||||||
|
get_filename_component(root_abs_path "${path}" ABSOLUTE)
|
||||||
|
get_filename_component(file_dir_abs_path "${file_dir}" ABSOLUTE)
|
||||||
|
file(RELATIVE_PATH group_path "${root_abs_path}" "${file_dir_abs_path}")
|
||||||
|
|
||||||
|
# 处理根目录的特殊情况
|
||||||
|
if(group_path STREQUAL ".")
|
||||||
|
set(group_name "")
|
||||||
|
else()
|
||||||
|
string(REPLACE "/" "\\" group_name "${group_path}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# 创建IDE分组
|
||||||
|
source_group("${group_name}" FILES "${current_file}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# 5. 设置输出变量
|
||||||
|
set(${out_files} ${filtered_files} PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
#[=======================================================================[
|
||||||
|
便捷封装函数
|
||||||
|
自动处理常见文件扩展名,针对不同平台添加特定文件类型
|
||||||
|
#]=======================================================================]
|
||||||
|
function(retrieve_files path out_files)
|
||||||
|
# 设置基础文件类型
|
||||||
|
set(file_extensions
|
||||||
|
"h" # 头文件
|
||||||
|
"hpp" # C++头文件
|
||||||
|
"ini" # 配置文件
|
||||||
|
"cpp" # C++源文件
|
||||||
|
"c" # C源文件
|
||||||
|
"ixx" # C++20模块文件
|
||||||
|
)
|
||||||
|
|
||||||
|
# 针对Mac平台添加额外文件类型
|
||||||
|
if(APPLE)
|
||||||
|
list(APPEND file_extensions "mm") # Objective-C++源文件
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# 执行文件检索
|
||||||
|
set(temp_files "")
|
||||||
|
retrieve_files_custom(${path} "${file_extensions}" temp_files)
|
||||||
|
|
||||||
|
# 合并结果到输出变量
|
||||||
|
set(${out_files} ${${out_files}} ${temp_files} PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
#[=======================================================================[
|
||||||
|
# 用于添加资源文件并在编译后复制到最终可执行文件所在目录
|
||||||
|
# 注意:此函数依赖于 CMAKE_RUNTIME_OUTPUT_DIRECTORY 或 EXECUTABLE_OUTPUT_PATH
|
||||||
|
# 变量的设置,以确定可执行文件的输出目录。请确保在项目中设置了其中之一。
|
||||||
|
#
|
||||||
|
# 参数:
|
||||||
|
# TARGET_NAME: (必需) - 关联的目标 (库或可执行文件) 的名称。
|
||||||
|
# 资源复制命令将在 TARGET_NAME 构建后执行。
|
||||||
|
# RESOURCE_FILES: (必需) - 一个或多个要复制的资源文件的路径列表 (相对或绝对)
|
||||||
|
# OUTPUT_SUBDIR: (可选) - 相对于可执行文件输出目录的子目录路径 (例如 "assets")
|
||||||
|
#
|
||||||
|
# 例子:
|
||||||
|
# # 确保设置了可执行文件输出目录 (通常在顶层 CMakeLists.txt)
|
||||||
|
# set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
||||||
|
#
|
||||||
|
# # 添加库
|
||||||
|
# add_library(my_lib STATIC src/my_lib.cpp)
|
||||||
|
#
|
||||||
|
# # 添加资源到 my_lib,但复制到最终可执行文件的输出目录下的 'config' 子目录
|
||||||
|
# add_resource_file(
|
||||||
|
# TARGET_NAME my_lib
|
||||||
|
# RESOURCE_FILES config/settings.json config/defaults.ini
|
||||||
|
# OUTPUT_SUBDIR config
|
||||||
|
# )
|
||||||
|
#
|
||||||
|
# # 添加可执行文件
|
||||||
|
# add_executable(my_app main.cpp)
|
||||||
|
# target_link_libraries(my_app PRIVATE my_lib)
|
||||||
|
#
|
||||||
|
# # 添加 my_app 的资源,复制到可执行文件输出目录的根目录
|
||||||
|
# add_resource_file(
|
||||||
|
# TARGET_NAME my_app
|
||||||
|
# RESOURCE_FILES assets/icon.png
|
||||||
|
# )
|
||||||
|
#]=======================================================================]
|
||||||
|
function(add_resource_file)
|
||||||
|
# 定义预期的参数
|
||||||
|
set(options "") # 无布尔选项
|
||||||
|
set(oneValueArgs TARGET_NAME OUTPUT_SUBDIR)
|
||||||
|
set(multiValueArgs RESOURCE_FILES)
|
||||||
|
|
||||||
|
# 解析传递给函数的参数
|
||||||
|
cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||||
|
|
||||||
|
# --- 参数验证 ---
|
||||||
|
if(NOT ARG_TARGET_NAME)
|
||||||
|
message(FATAL_ERROR "**add_resource_file**: **缺少必需参数** **TARGET_NAME**.")
|
||||||
|
endif()
|
||||||
|
if(NOT ARG_RESOURCE_FILES)
|
||||||
|
message(FATAL_ERROR "**add_resource_file**: **缺少必需参数** **RESOURCE_FILES**.")
|
||||||
|
endif()
|
||||||
|
if(NOT TARGET ${ARG_TARGET_NAME})
|
||||||
|
message(WARNING "**add_resource_file**: 目标 '${ARG_TARGET_NAME}' (尚)不存在。请确保在调用 add_executable/add_library('${ARG_TARGET_NAME}') 之后调用此函数。")
|
||||||
|
# 即使目标尚不存在,仍然尝试配置命令。CMake通常能处理好依赖关系。
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# --- 确定最终可执行文件的目标基础目录 ---
|
||||||
|
set(DESTINATION_BASE "")
|
||||||
|
if(DEFINED CMAKE_RUNTIME_OUTPUT_DIRECTORY AND CMAKE_RUNTIME_OUTPUT_DIRECTORY)
|
||||||
|
set(DESTINATION_BASE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
|
||||||
|
elseif(DEFINED EXECUTABLE_OUTPUT_PATH AND EXECUTABLE_OUTPUT_PATH)
|
||||||
|
# EXECUTABLE_OUTPUT_PATH 是旧变量,但也检查一下
|
||||||
|
set(DESTINATION_BASE "${EXECUTABLE_OUTPUT_PATH}")
|
||||||
|
else()
|
||||||
|
# 如果是多配置生成器(如 Visual Studio, Xcode),需要考虑配置类型
|
||||||
|
get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||||
|
if(is_multi_config)
|
||||||
|
# 对于多配置,没有单一的顶级运行时目录变量。
|
||||||
|
# 可以考虑使用 $<OUTPUT_DIRECTORY> 配合一个已知的可执行文件名,但这会使函数复杂化。
|
||||||
|
# 最好的做法是要求用户设置 CMAKE_RUNTIME_OUTPUT_DIRECTORY_<CONFIG>
|
||||||
|
# 或者我们直接报错,强制用户设置 CMAKE_RUNTIME_OUTPUT_DIRECTORY
|
||||||
|
message(FATAL_ERROR "**add_resource_file**: **无法确定可执行文件输出目录**。请在您的项目中设置 **CMAKE_RUNTIME_OUTPUT_DIRECTORY** 变量 (例如 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY \"\${CMAKE_BINARY_DIR}/bin\"))。对于多配置生成器,可能需要设置 CMAKE_RUNTIME_OUTPUT_DIRECTORY_<CONFIG> 变量。")
|
||||||
|
else()
|
||||||
|
# 对于单配置生成器(如 Makefiles, Ninja),可以默认到 CMAKE_BINARY_DIR
|
||||||
|
set(DESTINATION_BASE "${CMAKE_BINARY_DIR}")
|
||||||
|
message(WARNING "**add_resource_file**: **未设置 CMAKE_RUNTIME_OUTPUT_DIRECTORY**。默认将资源复制到 CMAKE_BINARY_DIR ('${CMAKE_BINARY_DIR}')。强烈建议设置 CMAKE_RUNTIME_OUTPUT_DIRECTORY 以获得可预测的行为。")
|
||||||
|
endif()
|
||||||
|
# message(FATAL_ERROR "**add_resource_file**: **无法确定可执行文件输出目录**。请在您的项目中设置 **CMAKE_RUNTIME_OUTPUT_DIRECTORY** 变量 (例如 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY \"\${CMAKE_BINARY_DIR}/bin\"))。")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# 处理子目录
|
||||||
|
set(DESTINATION_DIR "${DESTINATION_BASE}") # 默认目标目录
|
||||||
|
if(ARG_OUTPUT_SUBDIR)
|
||||||
|
# 清理子目录路径字符串
|
||||||
|
string(STRIP "${ARG_OUTPUT_SUBDIR}" _subdir)
|
||||||
|
if(IS_ABSOLUTE "${_subdir}")
|
||||||
|
message(FATAL_ERROR "**add_resource_file**: **OUTPUT_SUBDIR** ('${ARG_OUTPUT_SUBDIR}') **必须是相对路径**。")
|
||||||
|
else()
|
||||||
|
# 移除可能存在的前导/后导斜杠,以便干净地拼接路径
|
||||||
|
string(REGEX REPLACE "^[/\\\\]+" "" _subdir "${_subdir}")
|
||||||
|
string(REGEX REPLACE "[/\\\\]+$" "" _subdir "${_subdir}")
|
||||||
|
if(_subdir) # 仅当子目录清理后非空时才追加
|
||||||
|
set(DESTINATION_DIR "${DESTINATION_BASE}/${_subdir}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# --- 准备源文件路径 ---
|
||||||
|
set(ABS_RESOURCE_FILES "")
|
||||||
|
foreach(RESOURCE_FILE ${ARG_RESOURCE_FILES})
|
||||||
|
get_filename_component(RESOURCE_FILE_REALPATH "${RESOURCE_FILE}" REALPATH BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
|
# if(IS_ABSOLUTE "${RESOURCE_FILE}")
|
||||||
|
# # 如果已经是绝对路径,直接使用
|
||||||
|
# list(APPEND ABS_RESOURCE_FILES "${RESOURCE_FILE}")
|
||||||
|
# else()
|
||||||
|
# # 如果是相对路径,相对于当前源目录进行解析
|
||||||
|
# list(APPEND ABS_RESOURCE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/${RESOURCE_FILE}")
|
||||||
|
# endif()
|
||||||
|
list(APPEND ABS_RESOURCE_FILES "${RESOURCE_FILE_REALPATH}")
|
||||||
|
|
||||||
|
# 检查文件是否存在 (在配置时发出警告,有助于早期发现错误)
|
||||||
|
# list(GET ABS_RESOURCE_FILES -1 _current_abs_file) # 获取刚才添加的绝对路径
|
||||||
|
if(NOT EXISTS "${RESOURCE_FILE_REALPATH}")
|
||||||
|
message(WARNING "**add_resource_file**: **资源文件** '${RESOURCE_FILE}' (解析为 '${RESOURCE_FILE_REALPATH}') **在配置时不存在**。")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# --- 添加自定义命令 ---
|
||||||
|
# 使用 add_custom_command 在目标构建完成后执行复制操作
|
||||||
|
if(ABS_RESOURCE_FILES) # 确保有文件需要复制
|
||||||
|
# 注意:DESTINATION_DIR 可能包含特定于配置的路径(例如,如果 CMAKE_RUNTIME_OUTPUT_DIRECTORY
|
||||||
|
# 设置为 ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin)。
|
||||||
|
# add_custom_command 的 COMMAND 参数在构建时执行,此时这些变量/生成器表达式已解析。
|
||||||
|
add_custom_command(
|
||||||
|
TARGET ${ARG_TARGET_NAME}
|
||||||
|
POST_BUILD # 指定在目标构建之后执行
|
||||||
|
# 步骤 1: 确保目标目录存在 (copy_if_different 不会创建目录)
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E make_directory "${DESTINATION_DIR}"
|
||||||
|
# 步骤 2: 复制文件
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different # 使用CMake内置命令复制(仅当文件不同时)
|
||||||
|
${ABS_RESOURCE_FILES} # 要复制的源文件列表(绝对路径)
|
||||||
|
"${DESTINATION_DIR}" # 最终可执行文件所在的目标目录 (带引号以处理空格)
|
||||||
|
COMMENT "为 ${ARG_TARGET_NAME} 将资源复制到可执行文件目录: ${DESTINATION_DIR}..." # 构建时显示的注释
|
||||||
|
VERBATIM # 确保参数(尤其是路径和生成器表达式)被正确处理
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
message(WARNING "**add_resource_file**: 没有有效的资源文件提供给目标 '${ARG_TARGET_NAME}'。")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# --- 可选: 将资源文件添加到 IDE 项目结构中 ---
|
||||||
|
if(ABS_RESOURCE_FILES)
|
||||||
|
set(_source_group_name "Resource Files") # 基础组名
|
||||||
|
if(ARG_OUTPUT_SUBDIR)
|
||||||
|
# 使用与目标目录结构匹配的组名
|
||||||
|
string(STRIP "${ARG_OUTPUT_SUBDIR}" _clean_subdir)
|
||||||
|
string(REPLACE "\\" "/" _clean_subdir "${_clean_subdir}") # 统一使用正斜杠
|
||||||
|
string(REGEX REPLACE "^[/]+" "" _clean_subdir "${_clean_subdir}")
|
||||||
|
string(REGEX REPLACE "[/]+$" "" _clean_subdir "${_clean_subdir}")
|
||||||
|
if(_clean_subdir)
|
||||||
|
set(_source_group_name "Resource Files/${_clean_subdir}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
# 使用 source_group 将文件添加到 IDE 的指定组下
|
||||||
|
source_group(${_source_group_name} FILES ${ABS_RESOURCE_FILES})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
endfunction()
|
||||||
69
src/main.cpp
Normal file
69
src/main.cpp
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
//
|
||||||
|
// Created by 46944 on 25-5-21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
#include "SDL3/SDL_init.h"
|
||||||
|
#include "SDL3/SDL_render.h"
|
||||||
|
#include "SDL3/SDL_video.h"
|
||||||
|
#include "SDL3/SDL_log.h"
|
||||||
|
#include "SDL3/SDL_timer.h"
|
||||||
|
#include "SDL3_ttf/SDL_ttf.h"
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
SDL_Init(SDL_INIT_VIDEO);
|
||||||
|
SDL_Window* window = SDL_CreateWindow("Hello World", 640, 480, 0);
|
||||||
|
if (window == nullptr) {
|
||||||
|
SDL_Log("Could not create window: %s", SDL_GetError());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
SDL_Renderer* renderer = SDL_CreateRenderer(window, "direct3d11");
|
||||||
|
if (renderer == nullptr) {
|
||||||
|
SDL_Log("Could not create renderer: %s", SDL_GetError());
|
||||||
|
SDL_DestroyWindow(window);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
TTF_Init();
|
||||||
|
auto text_engine = TTF_CreateRendererTextEngine(renderer);
|
||||||
|
if (text_engine == nullptr) {
|
||||||
|
SDL_Log("Could not create text engine: %s", SDL_GetError());
|
||||||
|
SDL_DestroyRenderer(renderer);
|
||||||
|
SDL_DestroyWindow(window);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
TTF_Font* font = TTF_OpenFont("C:/Windows/Fonts/Arial.ttf", 24);
|
||||||
|
if (font == nullptr) {
|
||||||
|
SDL_Log("Could not open font: %s", SDL_GetError());
|
||||||
|
TTF_DestroyRendererTextEngine(text_engine);
|
||||||
|
SDL_DestroyRenderer(renderer);
|
||||||
|
SDL_DestroyWindow(window);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
SDL_Color color = { 255, 255, 255, 255 };
|
||||||
|
auto text_surface = TTF_RenderText_Solid(font, "Hello World", 0, color);
|
||||||
|
SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, text_surface);
|
||||||
|
|
||||||
|
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
|
||||||
|
|
||||||
|
SDL_RenderTexture(renderer, texture, nullptr, nullptr);
|
||||||
|
|
||||||
|
SDL_RenderClear(renderer);
|
||||||
|
SDL_RenderPresent(renderer);
|
||||||
|
|
||||||
|
SDL_Event e;
|
||||||
|
while (true) {
|
||||||
|
if (!SDL_PollEvent(&e)) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (e.type == SDL_EVENT_QUIT) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SDL_DestroyRenderer(renderer);
|
||||||
|
SDL_DestroyWindow(window);
|
||||||
|
SDL_Quit();
|
||||||
|
TTF_Quit();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
1
third_party/SDL
vendored
Submodule
1
third_party/SDL
vendored
Submodule
Submodule third_party/SDL added at b8e055ce64
1
third_party/SDL_ttf
vendored
Submodule
1
third_party/SDL_ttf
vendored
Submodule
Submodule third_party/SDL_ttf added at b9e7e9381b
Reference in New Issue
Block a user