# ---------------------------------------------------------------------------
# ADLicenseGen (Altium .alf 生成器) -- 还原工程构建
#
#   make            用 MinGW-w64 i686 交叉编译出 32 位 GUI 程序（Linux 可构建）
#   make check      构建 + 跑 5 层验证的第 ③④⑤ 层（PE 结构 / 字符串 / 工程）
#   make all-check  连同第 ①② 层（算法对拍 + 资源对比）一起跑
#   make info       打印产物与原样本的导入表/节表对比
#
# 原样本：MSVC 14.0 (VS2015 U3) / x86 / **静态 CRT** / Release
# 本工程 Linux 侧的目标是**行为等价**，不是二进制复刻（见 README.md）。
# ---------------------------------------------------------------------------
CROSS   ?= i686-w64-mingw32-
CC      := $(CROSS)gcc
WINDRES := $(CROSS)windres

CFLAGS  ?= -O2 -Wall -Wextra -Wno-unused-parameter \
           -DWIN32_LEAN_AND_MEAN -D_WIN32_WINNT=0x0501 -Ires -Isrc
LDFLAGS ?= -mwindows -Wl,-Map=build/ADLicenseGen.map
LIBS    := -lkernel32 -luser32 -lcomctl32 -lcomdlg32 -lshell32 -ladvapi32

SRC_DIR := src
RES_DIR := res
SRCS    := \
	$(SRC_DIR)/main.c \
	$(SRC_DIR)/winutil.c \
	$(SRC_DIR)/loader.c \
	$(SRC_DIR)/alfcore.c \
	$(SRC_DIR)/crypto.c

HDRS    := $(SRC_DIR)/alfcore.h $(SRC_DIR)/crypto.h $(SRC_DIR)/loader.h \
           $(SRC_DIR)/winutil.h $(SRC_DIR)/keys.h $(RES_DIR)/resource.h
RES_SRC := $(RES_DIR)/ADLicenseGen.rc $(RES_DIR)/app_100.ico \
           $(RES_DIR)/app_101.ico $(RES_DIR)/app.manifest

OUT     := build/ADLicenseGen.exe
RES     := build/ADLicenseGen_res.o

.PHONY: all clean check all-check info dist

all: build $(RES) $(OUT)

build:
	@mkdir -p build

# windres 在 res/ 目录下执行（.rc 内的 .ico/.manifest 是相对路径）
# 输出 COFF 对象（-O coff）供 gcc 链接
$(RES): $(RES_SRC)
	@cd $(RES_DIR) && $(WINDRES) -O coff -i ADLicenseGen.rc -o ../$(RES)
	@echo "[+] compiled resources -> $(RES)"

$(OUT): $(SRCS) $(HDRS) $(RES)
	$(CC) $(CFLAGS) $(SRCS) $(RES) -o $@ $(LDFLAGS) $(LIBS)
	@echo "[+] built $@  $$(stat -c%s $@) bytes"

# 第 ③④⑤ 层：PE 结构 / 字符串 / MSVC 工程一致性
check: $(OUT)
	python3 tools/verify_rebuild.py $(OUT)

# 第 ⑥ 层：真实 .alf 样本（需要 ../Licenses/，缺失时自动跳过）
real-check:
	python3 tools/inspect_licenses.py
	python3 tests/test_real_alf.py

# 全部 6 层（① 算法对拍 / ② 资源 / ③④⑤ PE+工程 / ⑥ 真实样本）
all-check: check real-check
	python3 tools/verify_alfcore.py
	python3 tools/verify_resources.py
	python3 tests/test_alf.py

info: $(OUT)
	@echo "=== generated ==="
	@$(CROSS)objdump -p $(OUT) | grep -i "DLL Name" | sort -u
	@echo "=== original ==="
	@$(CROSS)objdump -p "$(CURDIR)/../ADLicenseGen.exe" 2>/dev/null | grep -i "DLL Name" | sort -u || true

# ---------------------------------------------------------------------------
# 可选: 体积优化构建（对应 shfolder 的 `make slim`）
#
# 与原样本（MSVC /MT /GL /LTCG，88,576 B）的方向一致：
#   * -ffunction-sections -fdata-sections + -Wl,--gc-sections  删除未引用代码
#   * -s (strip)                                               去掉 DWARF（约 45%）
# 实测: 138,779 -> ~34 KB
# ---------------------------------------------------------------------------
SLIM_DIR     := build/slim
SLIM_OUT     := $(SLIM_DIR)/ADLicenseGen.exe
# 注意: **不要**加 -fdata-sections —— 它会把 461 KB 的静态缓冲从 .bss 挪进
# .data（占文件空间），产物反而膨胀到 495 KB。只对函数做 section GC。
SLIM_CFLAGS  := $(CFLAGS) -ffunction-sections -fno-ident
SLIM_LDFLAGS := -mwindows -Wl,--gc-sections -s

.PHONY: slim
slim: build
	@mkdir -p $(SLIM_DIR)
	@cd $(RES_DIR) && $(WINDRES) -O coff -i ADLicenseGen.rc -o ../$(SLIM_DIR)/res.o
	$(CC) $(SLIM_CFLAGS) $(SRCS) $(SLIM_DIR)/res.o -o $(SLIM_OUT) $(SLIM_LDFLAGS) $(LIBS)
	@echo "[+] built $(SLIM_OUT)  $$(stat -c%s $(SLIM_OUT)) bytes"

# ---------------------------------------------------------------------------
# 可选: 无 CRT 构建（-nostdlib）
#
# 目标：像原样本那样**不依赖任何 CRT DLL**（导入表只剩 6 个系统 DLL）。
# 配方:
#   * -nostdlib          不链接 mingw CRT / msvcrt
#   * -DALF_NOCRT        启用 src/nocrt.c（自实现 mem*/isspace + PE 入口）
#   * -Wl,-e,WinMainCRTStartup   用自定义入口替代 crt0
#   * --gc-sections -s   删除死代码 + strip
# 实测: 导入表由 7 个模块降为 6 个（无 msvcrt.dll）
# ---------------------------------------------------------------------------
NOCRT_DIR     := build/nocrt
NOCRT_OUT     := $(NOCRT_DIR)/ADLicenseGen.exe
NOCRT_CFLAGS  := $(CFLAGS) -ffunction-sections -fno-ident -DALF_NOCRT
NOCRT_LDFLAGS := -mwindows -nostdlib -Wl,-e,_WinMainCRTStartup -Wl,--gc-sections -s
NOCRT_SRCS    := $(SRC_DIR)/nocrt.c $(SRCS)

.PHONY: nocrt
nocrt: build
	@mkdir -p $(NOCRT_DIR)
	@cd $(RES_DIR) && $(WINDRES) -O coff -i ADLicenseGen.rc -o ../$(NOCRT_DIR)/res.o
	$(CC) $(NOCRT_CFLAGS) $(NOCRT_SRCS) $(NOCRT_DIR)/res.o -o $(NOCRT_OUT) $(NOCRT_LDFLAGS) $(LIBS)
	@echo "[+] built $(NOCRT_OUT)  $$(stat -c%s $(NOCRT_OUT)) bytes"

# 只清 MinGW 侧的产物。
# **不要**写成 `rm -rf build` —— build/msvc/ 里放的是 VS/msbuild 的产物
# （见 msvc/README.md），那是另一条工具链的输出，make clean 不该越界删除。
clean:
	rm -f  $(OUT) $(OUT:.exe=.map) build/ADLicenseGen_res.o
	rm -rf $(SLIM_DIR) $(NOCRT_DIR)
