修复add_resource_file

This commit is contained in:
Nanako 2025-04-07 21:42:20 +08:00
parent 2ebd7f9182
commit 4d9ccc73c0
4 changed files with 150 additions and 71 deletions

View File

@ -158,82 +158,160 @@ function(retrieve_files path out_files)
endfunction()
#[=======================================================================[
用于添加资源文件并在编译后复制到目标文件 (可执行文件或库)
:
TARGET_NAME: 目标 (可执行文件或库)
RESOURCE_FILE_PATHS - 一个或多个要复制的资源文件的路径 (可以是相对或绝对路径)
#
# 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_resources TARGET_NAME)
# TARGET_NAME
set(RESOURCE_FILES ${ARGN})
function(add_resource_file)
#
set(options "") #
set(oneValueArgs TARGET_NAME OUTPUT_SUBDIR)
set(multiValueArgs RESOURCE_FILES)
# 检查目标是否存在 (可选,但推荐)
if(NOT TARGET ${TARGET_NAME})
message(FATAL_ERROR "目标 '${TARGET_NAME}' 不存在,无法添加资源。")
return()
#
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()
# **** ()
# 对于多配置生成器 ( Visual Studio, Xcode)使 $<TARGET_FILE_DIR:TARGET_NAME>
# 对于单配置生成器 ( Makefiles, Ninja)使 CMAKE_RUNTIME_OUTPUT_DIRECTORY $<TARGET_FILE_DIR:TARGET_NAME>
if(CMAKE_CONFIGURATION_TYPES)
set(DESTINATION_DIR "$<TARGET_FILE_DIR:${TARGET_NAME}>")
# --- ---
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()
if(CMAKE_RUNTIME_OUTPUT_DIRECTORY)
set(DESTINATION_DIR "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
# 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()
# 使 $<TARGET_FILE_DIR:TARGET_NAME>
set(DESTINATION_DIR "$<TARGET_FILE_DIR:${TARGET_NAME}>")
# 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()
# ****
foreach(RESOURCE_FILE ${RESOURCE_FILES})
set(ABS_RESOURCE_FILE "") # /
# --- ---
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}")
# ****
if(IS_ABSOLUTE "${RESOURCE_FILE}")
#
if(EXISTS "${RESOURCE_FILE}")
set(ABS_RESOURCE_FILE "${RESOURCE_FILE}")
else()
message(WARNING "资源文件未找到 (绝对路径,将跳过): ${RESOURCE_FILE}")
continue() #
endif()
else()
# CMakeLists.txt
set(TEMP_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${RESOURCE_FILE}")
if(EXISTS "${TEMP_PATH}")
set(ABS_RESOURCE_FILE "${TEMP_PATH}")
else()
message(WARNING "资源文件未找到 (相对路径,将跳过): ${RESOURCE_FILE} (相对于: ${CMAKE_CURRENT_SOURCE_DIR})")
continue() #
endif()
# 检查文件是否存在 (在配置时发出警告,有助于早期发现错误)
# 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()
# **** (copy_if_different )
if(IS_DIRECTORY "${ABS_RESOURCE_FILE}")
message(WARNING "提供的资源是一个目录,而非文件 (将跳过): ${ABS_RESOURCE_FILE}. 请使用其他方法复制目录。")
continue()
endif()
# ****
get_filename_component(RESOURCE_FILENAME "${ABS_RESOURCE_FILE}" NAME)
# ****
add_custom_command(
TARGET ${TARGET_NAME} #
POST_BUILD #
COMMAND ${CMAKE_COMMAND} -E copy_if_different # 使 cmake 内建命令复制文件 (仅在文件不同时复制)
"${ABS_RESOURCE_FILE}" # 源文件 (绝对路径)
"${DESTINATION_DIR}/${RESOURCE_FILENAME}" # **** ( + )
COMMENT " ${RESOURCE_FILENAME} ${TARGET_NAME} " #
VERBATIM #
)
# () 便 IDE
# IDE
# target_sources(${TARGET_NAME} PRIVATE "${ABS_RESOURCE_FILE}")
endforeach()
endfunction()
# --- ---
# 使 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()

View File

@ -1,8 +1,5 @@
#include "color.h"
#include <charconv>
#include <vector>
/**
* @brief
*

View File

@ -8,6 +8,7 @@
*/
#include <complex>
#include <optional>
/**
* @class linear_color

View File

@ -9,4 +9,7 @@ add_library(${PROJECT_NAME} STATIC ${SRC_FILES})
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src)
target_link_libraries(${PROJECT_NAME} PUBLIC mirage_core mirage_render tomlplusplus::tomlplusplus)
add_resources(${PROJECT_NAME} src/style/default_style.toml)
add_resource_file(
TARGET_NAME ${PROJECT_NAME}
RESOURCE_FILES src/style/default_style.toml
)