背景:Code Review 报告 §10.3 / §11.5 建议「替换 std::to_wstring / std::to_string,
可去掉 gdtoa 链(≈33 KB)」。本轮把它做完,并给出这条建议的**真实边界**。
一、新增 `Utf8Util::FormatInteger*`(手写十进制展开,不经 printf)
* `FormatInteger(long long)` / `FormatIntegerUnsigned(unsigned long long)` /
`FormatIntegerNarrow(long long)`(后者供 MatLoader 拼 HDF5 成员路径)。
* 语义与 `std::to_wstring` / `std::to_string` 完全一致:`0` → `"0"`、负数带 `-`、
`LLONG_MIN` 用模 2^64 语义取绝对值(不会溢出)。
* 这样做的直接理由:预编译 libstdc++ 的 `to_string` 内部转调 `__mingw_swprintf`,
工程里只要留一处,MinGW 的 printf 引擎(`mingw_wpformat.o`)+ gdtoa 就必然被链入。
二、全仓替换(76 处 `to_wstring` + 2 处 `to_string`,20 个文件)
* `MatLoader.cpp` 的 `TrimNumber` 整数分支也改为 `FormatInteger`(它曾是产物里
**最后一个**引用 MinGW printf 的调用点)。
* 需要的地方补 `#include "Utf8Util.hpp"`(仅 `MatLoader.cpp` 一个新 include,其余由
`PlotViewInternal` / `SignalPanelInternal` / `ApplicationInternal` / `DataModelInternal`
已经包含)。
三、⚠️ 实测结论:gdtoa **去不掉**(把这件事彻底查清并写进 Makefile 注释)
* 只替换 `to_wstring`/`to_string`:**−1,024 B**(787,968 → 786,944)。
* 再叠加 `-D__USE_MINGW_ANSI_STDIO=0`(把 `swprintf` 让给系统 UCRT):**0 字节**。
* 根因(定位到文件与行):libstdc++ 的
`lib/gcc/.../include/c++/x86_64-w64-mingw32/bits/os_defines.h:48-51` **无条件**执行
`#undef __USE_MINGW_ANSI_STDIO` + `#define __USE_MINGW_ANSI_STDIO 1`
(注释:libstdc++ depends on POSIX-definitions of those functions)。
`g++ -E -dM` 实测最终值恒为 1 ⇒ **任何 C++ TU 的 `swprintf` / `strtod` 都是 MinGW 版本**,
命令行无法覆盖。
* 要真省这 33 KB 只能自己实现「浮点 → 十进制(正确舍入)」与「浮点解析的
十六进制/inf/nan 分支」,等价于重写 gdtoa。**判定:不做**(风险 >> 收益)。
* 该开关已回退,Makefile 里保留一段说明,避免后续接手者重复这两次实验。
四、验证
* 新增单元测试 `integer_replacement_matches_std`:12 个有符号样本(含 LLONG_MIN/MAX)
+ 5 个无符号样本(含 ULLONG_MAX),与 `std::to_wstring` **逐字符对照**,
并校验窄/宽版本内容一致。
* `UnitTests`:`checks=260 failed=0 cases=19`(新增 41 条断言)。
* `OffscreenChecks -all`:6 个检查全 PASS,`checks=87 failed=0`。
* `panels -mode compare`:7 个面板像素哈希与几何**逐项不变**
(整数文本从 `to_wstring` 换到手写实现后,渲染结果零差异 —— 这是最强的语义证据)。
* release 全量零 error / 零 warning;产物 787,968 → **786,944 B**。
360 lines
14 KiB
Makefile
360 lines
14 KiB
Makefile
# 目标文件名称
|
||
TARGET_FILE_NAME = Target
|
||
|
||
# 编译目录
|
||
BUILD_DIR = Build
|
||
|
||
# Release 编译子目录
|
||
SUB_DIR_RELEASE = Release
|
||
|
||
# Debug 编译子目录
|
||
SUB_DIR_DEBUG = Debug
|
||
|
||
# ⚠️ 产物体积**预警阈值**(用户 2026-10-29 更新):**1MB(1,048,576 B)**。
|
||
# 这不是"不许超过":**超过仍可发布**,但到达阈值时必须主动提醒用户,
|
||
# 并说明"超在哪一段(`.text` / `.rdata` / `.xdata`+`.pdata` / `.rsrc`)、由哪个改动贡献"。
|
||
# 旧红线 900KB / 800KB 均已作废。
|
||
# 查段构成的命令(排查超限原因的标准做法):objdump -h Build/Release/Target.exe
|
||
RELEASE_OPT = -Oz
|
||
|
||
# ---- 体积相关编译开关 ------------------------------------------------------
|
||
# ⚠️ 曾经有一个 `LAYOUT_BOUNDS` 开关(声称能剔除"显示布局边界"调试叠加层),
|
||
# 但它从来没有被任何 `#if` 引用过 —— 是个**名实不符**的死开关,已删除(2026-10-29 审计)。
|
||
# 该叠加层现在是**正式功能**(设置菜单里的开关),随产物一起编译;
|
||
# 要真正把它变成可剔除项,需要给每个组件的 `BuildBoxes` 重载都加 `#if`,
|
||
# 代价远大于它占的十几 KB(当前产物 791,552 B,离 1MB 预警线还有 250+ KB)。
|
||
|
||
# NO_EXCEPTIONS:1 = 用 `-fno-exceptions` 构建(省 `.xdata`+`.pdata` 约 28KB)。
|
||
# ⚠️ 代价:所有"按数据规模预留大块内存"的地方必须用 `MemProbe.hpp` 的
|
||
# `MemReserveIfRoom()` **预检验**,不能再靠 try/catch。
|
||
# 兜底:`Application::Initialize` 里安装了 `MemInstallTerminateHandler()`
|
||
# (万一仍有遗漏,OOM 时弹一次带建议的模态提示后干净退出,而不是静默消失)。
|
||
NO_EXCEPTIONS = 1
|
||
|
||
# LTO:1 = 链接时优化(实测 −94KB)。构建时间约翻倍。
|
||
# ⚠️ **切换 LTO 必须 `make clean`**:LTO 与非 LTO 目标文件混链会让
|
||
# GCC 15.2.0 在 `binds_to_current_def_p` 处 ICE(已实测复现)。
|
||
# ⚠️ 开启 LTO 后 `-Wa,...,-ahlms` 的 `.lst` 汇编清单不再生成(lto-wrapper 会丢弃并告警),
|
||
# 因此 `ASM_LISTING` 在 LTO 下为空。
|
||
LTO = 1
|
||
# ---------------------------------------------------------------------------
|
||
|
||
# Debug 优化等级
|
||
DEBUG_OPT = -O0
|
||
|
||
# GUI或CUI编译选项 [0]CUI/Console [1]GUI
|
||
GUI = 1
|
||
|
||
# C编译标准
|
||
C_STD = c17
|
||
|
||
# C++编译标准
|
||
CXX_STD = c++17
|
||
|
||
# 源文件编码定义
|
||
INPUT_CHAR_ENCODING = UTF-8
|
||
|
||
# 编译产物单字节字符(char)编码定义
|
||
OUTPUT_CHAR_ENCODING = GBK
|
||
|
||
# 编译产物宽字符(wchar_t)编码定义
|
||
OUTPUT_WCHAR_ENCODING = UTF-16LE
|
||
|
||
# 编译工具前缀
|
||
COMPLIER_PREFIX = \
|
||
|
||
# C编译工具
|
||
C_COMPLIER = $(strip $(COMPLIER_PREFIX))gcc
|
||
|
||
# C++编译工具
|
||
CXX_COMPLIER = $(strip $(COMPLIER_PREFIX))g++
|
||
|
||
# Windows 资源文件编译工具
|
||
WIN_RES_COMPLIER = windres
|
||
|
||
##################################################################################
|
||
|
||
# 链接库
|
||
LIB_LINK = \
|
||
-lgdi32 \
|
||
-lgdiplus \
|
||
-lmsimg32 \
|
||
-lcomdlg32 \
|
||
-ld3d11 \
|
||
-ldwmapi \
|
||
-ld3dcompiler \
|
||
|
||
# C定义
|
||
C_DEFS = \
|
||
_UNICODE \
|
||
UNICODE \
|
||
|
||
# C头文件目录
|
||
C_INCLUDES_PATHS = \
|
||
|
||
# C源文件目录
|
||
C_SOURCES_PATHS = \
|
||
|
||
# C额外单个源文件
|
||
C_EXTERA_SOURCES = \
|
||
|
||
# C++定义
|
||
CXX_DEFS = \
|
||
_UNICODE \
|
||
UNICODE \
|
||
|
||
# C++ 头文件目录
|
||
# ⚠️ 目录约定:**所有头文件(.hpp)只放在 `Inc`**,`Src` 只放实现(.cpp)。
|
||
# `*Internal.hpp`(组件内部共享的常量/工具,如 `PlotViewInternal.hpp`)同样属于头文件,
|
||
# 历史上曾被放在 `Src` 下(那里也能编译,因为编译器会先找 `#include` 所在目录),
|
||
# 但那是靠“同目录优先”隐式生效的 —— 一旦文件被搬走就会无声失效。现已全部移入 `Inc`。
|
||
CXX_INCLUDES_PATHS = \
|
||
Utilities/Inc \
|
||
Resources/Inc \
|
||
Components/Main/Inc \
|
||
Components/Shared/Inc \
|
||
Components/Application/Inc \
|
||
Components/TabBar/Inc \
|
||
Components/Toolbar/Inc \
|
||
Components/SignalPanel/Inc \
|
||
Components/PlotView/Inc \
|
||
|
||
# C++源文件目录
|
||
CXX_SOURCES_PATHS = \
|
||
Utilities/Src \
|
||
Components/Main/Src \
|
||
Components/Shared/Src \
|
||
Components/Application/Src \
|
||
Components/TabBar/Src \
|
||
Components/Toolbar/Src \
|
||
Components/SignalPanel/Src \
|
||
Components/PlotView/Src \
|
||
|
||
# C++额外单个源文件
|
||
CXX_EXTERA_SOURCES = \
|
||
|
||
# Windows 资源文件脚本头文件路径
|
||
WIN_RESOURCE_INCLUDES_PATHS = \
|
||
Resources \
|
||
Resources/Inc \
|
||
# Windows 资源文件脚本输入代码页(对应 INPUT_CHAR_ENCODING = UTF-8)
|
||
WIN_RESOURCE_CODEPAGE = 65001
|
||
# Windows 资源文件脚本列表
|
||
WIN_RESOURCE_SCRIPTS = \
|
||
Resources/JustDataInspector.rc \
|
||
|
||
##################################################################################
|
||
|
||
# C编译选项
|
||
CFLAGS = $(foreach text,$(C_DEFS),$(addprefix -D,$(text))) \
|
||
$(foreach path,$(C_INCLUDES_PATHS),$(addprefix -I,$(path))) \
|
||
-std=$(strip $(C_STD)) \
|
||
-finput-charset=$(strip $(INPUT_CHAR_ENCODING)) \
|
||
-fexec-charset=$(strip $(OUTPUT_CHAR_ENCODING)) \
|
||
-fwide-exec-charset=$(strip $(OUTPUT_WCHAR_ENCODING)) \
|
||
-static \
|
||
$(FUNC_SECTIONS) \
|
||
-Wall \
|
||
-MMD -MP -MF"$(@:%.o=%.d)" \
|
||
|
||
# C++编译选项
|
||
CXXFLAGS = $(foreach text,$(CXX_DEFS),$(addprefix -D,$(text))) \
|
||
$(foreach path,$(CXX_INCLUDES_PATHS),$(addprefix -I,$(path))) \
|
||
-std=$(strip $(CXX_STD)) \
|
||
-finput-charset=$(strip $(INPUT_CHAR_ENCODING)) \
|
||
-fexec-charset=$(strip $(OUTPUT_CHAR_ENCODING)) \
|
||
-fwide-exec-charset=$(strip $(OUTPUT_WCHAR_ENCODING)) \
|
||
-static \
|
||
$(FUNC_SECTIONS) \
|
||
-Wall \
|
||
-MMD -MP -MF"$(@:%.o=%.d)" \
|
||
-lstdc++ \
|
||
|
||
|
||
# 链接选项
|
||
LDFLAGS = -Wl,-Map,$(basename $@).map \
|
||
$(GC_SECTIONS) \
|
||
|
||
##################################################################################
|
||
|
||
# GUI与CUI选项附加
|
||
ifeq ($(GUI), 1)
|
||
LDFLAGS += -mwindows
|
||
else
|
||
LDFLAGS += -mconsole
|
||
endif
|
||
|
||
# ---- 体积/行为相关开关(必须在 CFLAGS / CXXFLAGS / LDFLAGS 定义之后)--------
|
||
# 说明:这些是 `=` / `+=` 的递归变量,make 在展开 recipe 时才求值,
|
||
# 因此放在 LDFLAGS 定义之后仍然能正确作用到前面的 CFLAGS / LDFLAGS。
|
||
|
||
ifeq ($(strip $(NO_EXCEPTIONS)), 1)
|
||
CXXFLAGS += -fno-exceptions
|
||
endif
|
||
|
||
# ---- RTTI:全项目不使用 `dynamic_cast` / `typeid` ----
|
||
# 2026-11-04 审查:唯一的 `dynamic_cast`(Toolbar::BuildBoxes)是多余的强转,
|
||
# 已改为直接使用已有的 `UiButtonWidget*`。RTTI 会链入 `cp-demangle.o`
|
||
# (Release map 实测 56,320 B)+ `type_info` 表,最小复现程序实测 +75,264 B。
|
||
NO_RTTI = 1
|
||
ifeq ($(strip $(NO_RTTI)), 1)
|
||
CXXFLAGS += -fno-rtti
|
||
endif
|
||
|
||
# ---- SEH 展开表:只对 Release 关闭 `-fasynchronous-unwind-tables` ----
|
||
# 2026-11-04 审查实测:**只对 Release** 关闭后产物从 829,440 → 793,088 B(**−36,352 B**),
|
||
# 因为 `-fno-exceptions` 下绝大多数函数不再需要 `.pdata`/`.xdata`。
|
||
# * `.pdata` 只用于栈回溯(崩溃诊断);本程序不打印栈回溯,功能不受影响。
|
||
# * ⚠️ 代价:Release 崩溃时 WER 拿不到可靠调用栈(Debug 构建保留完整展开表)。
|
||
# * ⚠️ 全关(`-fno-unwind-tables`)会链接失败(历史踩坑),**不要**打开。
|
||
RELEASE_ONLY_OPT = -fno-asynchronous-unwind-tables
|
||
|
||
# ---- 关于「把 `swprintf` 交给系统 UCRT」:**在 C++ 里做不到**,别再试 ----
|
||
# 动机:MinGW 的 ANSI stdio(`mingw_wpformat.o`)会链入 gdtoa 整套
|
||
# (`strtodg` / `gdtoa` / `gethex` / `hexnan`),map 实测 ≈33 KB。
|
||
#
|
||
# 本轮实测(2026-11-04,两次独立实验):
|
||
# 1. 把全仓 76 处 `std::to_wstring` + 2 处 `std::to_string` 换成
|
||
# `Utf8Util::FormatInteger*`(手写十进制展开):**−1,024 B**(787,968 → 786,944)。
|
||
# 这一步是有效的,且去掉了 libstdc++ 的 `to_string` 对 printf 的依赖。
|
||
# 2. 再加 `-D__USE_MINGW_ANSI_STDIO=0`:**0 字节**,`mingw_wpformat.o` 仍在。
|
||
#
|
||
# 原因(已定位到具体文件与行):libstdc++ 在
|
||
# lib/gcc/x86_64-w64-mingw32/<ver>/include/c++/x86_64-w64-mingw32/bits/os_defines.h
|
||
# 里**无条件**执行:
|
||
# #undef __USE_MINGW_ANSI_STDIO
|
||
# #define __USE_MINGW_ANSI_STDIO 1
|
||
# 注释写着 "libstdc++ depends on POSIX-definitions of those functions"。
|
||
# 也就是说:**任何 C++ 翻译单元**里的 `swprintf` / `strtod` 都必然是 MinGW 版本,
|
||
# 命令行开关无法覆盖(`g++ -E -dM` 实测最终值恒为 1)。
|
||
#
|
||
# ⇒ 要真省掉这 33 KB,只能连**浮点格式化**也自己实现(等价于重写 gdtoa 的
|
||
# 正确舍入十进制展开)与**浮点解析**的十六进制/inf/nan 分支。风险远大于收益,
|
||
# 判定:**不做**。保留证据:`Tools/UnitTests` 的 `stdio_mingw_vs_ucrt_formats`
|
||
# (13.6 万次调用逐字符比对,0 差异)说明两套 printf 在这些格式上完全等价,
|
||
# 将来若平台换了 C 运行库,这条测试可直接复用。
|
||
|
||
# 丢弃未被引用的函数/数据(非 LTO 时还需要配合 -ffunction-sections 才有粒度)。
|
||
GC_SECTIONS = -Wl,--gc-sections
|
||
|
||
ifeq ($(strip $(LTO)), 1)
|
||
# LTO 自己就做跨编译单元的内联与去重,不需要再开 function-sections;
|
||
# 实测 `-flto` 与 `-ffunction-sections -fdata-sections` 同时打开会让
|
||
# GCC 15.2.0 在 `binds_to_current_def_p (symtab.cc:2598)` 处 ICE。
|
||
FUNC_SECTIONS =
|
||
CFLAGS += -flto
|
||
CXXFLAGS += -flto
|
||
# ⚠️ `-flto-partition=one` 是绕过上面那个 ICE 的关键:
|
||
# 默认的多分区 LTRANS 在解析 COMDAT 定义时必崩(同一份代码拆成 11 个分区稳定复现,
|
||
# 单分区从未复现)。代价是 LTRANS 只能串行,全量构建比非 LTO 慢约一倍。
|
||
LDFLAGS += -flto -flto-partition=one
|
||
# lto-wrapper 会丢弃 -Wa 的汇编清单并告警,故 LTO 下不生成 .lst。
|
||
ASM_LISTING =
|
||
ASM_LISTING_C =
|
||
else
|
||
FUNC_SECTIONS = -ffunction-sections -fdata-sections
|
||
ASM_LISTING = -Wa,-a,-ad,-ahlms=$(@:%.o=%.lst)
|
||
ASM_LISTING_C = -Wa,-a,-ad,-alms=$(@:%.o=%.lst)
|
||
endif
|
||
# ---------------------------------------------------------------------------
|
||
|
||
# C目标文件及索引目录关联
|
||
OBJECTS = $(notdir $(C_EXTERA_SOURCES:.c=.o))
|
||
OBJECTS += $(subst .c,.o,$(notdir $(foreach path,$(C_SOURCES_PATHS),$(wildcard $(path)/*.c))))
|
||
vpath %.c $(sort $(dir $(C_EXTERA_SOURCES))) $(sort $(C_SOURCES_PATHS))
|
||
|
||
# C++目标文件及索引目录关联
|
||
OBJECTS += $(notdir $(CXX_EXTERA_SOURCES:.cpp=.o))
|
||
OBJECTS += $(subst .cpp,.o,$(notdir $(foreach path,$(CXX_SOURCES_PATHS),$(wildcard $(path)/*.cpp))))
|
||
vpath %.cpp $(sort $(dir $(CXX_EXTERA_SOURCES))) $(sort $(CXX_SOURCES_PATHS))
|
||
|
||
# Windows资源文件及索引目录关联
|
||
OBJECTS += $(notdir $(WIN_RESOURCE_SCRIPTS:.rc=.o))
|
||
vpath %.rc $(sort $(dir $(WIN_RESOURCE_SCRIPTS)))
|
||
|
||
|
||
# Release 目标文件
|
||
RELEASE_OBJECTS = $(addprefix $(BUILD_DIR)/$(SUB_DIR_RELEASE)/,$(OBJECTS))
|
||
|
||
# Debug 目标文件
|
||
DEBUG_OBJECTS = $(addprefix $(BUILD_DIR)/$(SUB_DIR_DEBUG)/,$(OBJECTS))
|
||
|
||
##################################################################################
|
||
|
||
# all任务 目标为 release 和 debug 产物
|
||
all: $(BUILD_DIR)/$(SUB_DIR_RELEASE)/$(TARGET_FILE_NAME).exe $(BUILD_DIR)/$(SUB_DIR_DEBUG)/$(TARGET_FILE_NAME).exe
|
||
@echo ====== [All] Build Procedure Accomplished ======
|
||
|
||
# release任务 目标为 release 产物
|
||
release: $(BUILD_DIR)/$(SUB_DIR_RELEASE)/$(TARGET_FILE_NAME).exe
|
||
@echo ====== [Release] Build Procedure Accomplished ======
|
||
|
||
# debug任务 目标为 debug 产物
|
||
debug: $(BUILD_DIR)/$(SUB_DIR_DEBUG)/$(TARGET_FILE_NAME).exe
|
||
@echo ====== [Debug] Build Procedure Accomplished ======
|
||
|
||
# 清理任务
|
||
clean: $(BUILD_DIR)
|
||
powershell rm -r $(BUILD_DIR)
|
||
|
||
# 构建目录生成
|
||
$(BUILD_DIR):
|
||
powershell mkdir $@
|
||
|
||
# Release 工作目录生成
|
||
$(BUILD_DIR)/$(SUB_DIR_RELEASE): | $(BUILD_DIR)
|
||
powershell mkdir $@
|
||
|
||
# Debug 工作目录生成
|
||
$(BUILD_DIR)/$(SUB_DIR_DEBUG): | $(BUILD_DIR)
|
||
powershell mkdir $@
|
||
|
||
# Release 最终可执行文件编译任务
|
||
$(BUILD_DIR)/$(SUB_DIR_RELEASE)/$(TARGET_FILE_NAME).exe: $(RELEASE_OBJECTS)
|
||
@echo ====== [Release] All File Compiled. Now Linking... ======
|
||
$(CXX_COMPLIER) $(RELEASE_OBJECTS) -static -s -o $@ $(LIB_LINK) $(LDFLAGS)
|
||
@echo ====== [Release] Program Link Finished ======
|
||
|
||
# Debug 最终可执行文件编译任务
|
||
$(BUILD_DIR)/$(SUB_DIR_DEBUG)/$(TARGET_FILE_NAME).exe: $(DEBUG_OBJECTS)
|
||
@echo ====== [Debug] All File Compiled. Now Linking... ======
|
||
$(CXX_COMPLIER) $(DEBUG_OBJECTS) -static -g -o $@ $(LIB_LINK) $(LDFLAGS)
|
||
@echo ====== [Debug] Program Link Finished ======
|
||
|
||
# C Release 目标文件编译
|
||
$(BUILD_DIR)/$(SUB_DIR_RELEASE)/%.o: %.c Makefile | $(BUILD_DIR)/$(SUB_DIR_RELEASE)
|
||
@echo ====== [Release] C Source File "$<" Compiling... ======
|
||
$(C_COMPLIER) -c $(CFLAGS) $(RELEASE_OPT) $(RELEASE_ONLY_OPT) $(ASM_LISTING_C) $< -o $@
|
||
|
||
# C++ Release 目标文件编译
|
||
$(BUILD_DIR)/$(SUB_DIR_RELEASE)/%.o: %.cpp Makefile | $(BUILD_DIR)/$(SUB_DIR_RELEASE)
|
||
@echo ====== [Release] C++ Source File "$<" Compiling... ======
|
||
$(CXX_COMPLIER) -c $(CXXFLAGS) $(RELEASE_OPT) $(RELEASE_ONLY_OPT) $(ASM_LISTING) $< -o $@
|
||
|
||
# Release 资源脚本文件编译
|
||
$(BUILD_DIR)/$(SUB_DIR_RELEASE)/%.o: %.rc Makefile | $(BUILD_DIR)/$(SUB_DIR_RELEASE)
|
||
@echo ====== [Release] Windows Resource Script File "$<" Compiling... ======
|
||
$(WIN_RES_COMPLIER) -c $(WIN_RESOURCE_CODEPAGE) $(foreach path,$(WIN_RESOURCE_INCLUDES_PATHS),$(addprefix -I,$(path))) $< -o $@
|
||
|
||
# C Debug 目标文件编译
|
||
# ⚠️ 2026-11-04 审查修正:原来这里误用了 `$(RELEASE_OPT)`,导致 `DEBUG_OPT = -O0`
|
||
# **从未生效**(Debug 实际上也是 -Oz,且不带 `-g`,根本无法调试)。
|
||
$(BUILD_DIR)/$(SUB_DIR_DEBUG)/%.o: %.c Makefile | $(BUILD_DIR)/$(SUB_DIR_DEBUG)
|
||
@echo ====== [Debug] C Source File "$<" Compiling... ======
|
||
$(C_COMPLIER) -c $(CFLAGS) $(DEBUG_OPT) -g $(ASM_LISTING_C) $< -o $@
|
||
|
||
# C++ Debug 目标文件编译
|
||
$(BUILD_DIR)/$(SUB_DIR_DEBUG)/%.o: %.cpp Makefile | $(BUILD_DIR)/$(SUB_DIR_DEBUG)
|
||
@echo ====== [Debug] C++ Source File "$<" Compiling... ======
|
||
$(CXX_COMPLIER) -c $(CXXFLAGS) $(DEBUG_OPT) -g $(ASM_LISTING) $< -o $@
|
||
|
||
# Debug 资源脚本文件编译
|
||
$(BUILD_DIR)/$(SUB_DIR_DEBUG)/%.o: %.rc Makefile | $(BUILD_DIR)/$(SUB_DIR_DEBUG)
|
||
@echo ====== [Debug] Windows Resource Script File "$<" Compiling... ======
|
||
$(WIN_RES_COMPLIER) -c $(WIN_RESOURCE_CODEPAGE) $(foreach path,$(WIN_RESOURCE_INCLUDES_PATHS),$(addprefix -I,$(path))) $< -o $@
|
||
|
||
|
||
# 依赖关系
|
||
-include $(RELEASE_OBJECTS:.o=.d)
|
||
-include $(DEBUG_OBJECTS:.o=.d)
|