dafc18f5ed
启动 docs/任务规划/README.md 的 W6 UI 扩展簇(用户裁定,覆盖 2026-10-11
的"本轮不排期")。四个工作包,全部验证通过。
## U1 设计令牌层(零行为变化)
新建 Drivers/BSP/UI/ui_tokens.h(20 个宏),框架 + 7 个页面 + App/task/
ui_task.c 全部接入。屏幕几何**复用 ui_port.h 既有 UI_SCREEN_W/H**,不重复
定义;令牌头自身只 include ui_port.h,不把 LVGL 拖进全部消费者。
补收了报告没列但代码里真重复的量:UI_TEXT_BAND_H 15(7 次)、列表左右边界
与每页行数(各 4 个页面逐字复制)、推流协议几何与显示几何同源(此前硬编码
3200 且注释写着"须与 UI_FB_SIZE 一致"——典型漂移隐患)、UI_TASK_TICK_MS
(ui_port_step 与 osDelay 必须同值,原先靠注释维系)。
故意不收页面私有几何与"同形不同义"的值(device_info 的 pitch=15 与列表
UI_ROW_PITCH=14 合并即改像素)。
## U3 页面注册表与生成器(删手工分发)
ui_page_registry.{c,h} 由生成器产出,**手工 menu_content_page_for() 已删
除**(仓库内仅存 2 处历史说明注释)。密码页按代码实况**单独出口**
(ui_page_registry_password())——它非节点绑定,任何 #P 叶子进同一页。
顺带落地此前判定"U1 阶段做不了"的共享 flat 样式 ui_style.{c,h}。
生成器除产注册表外**自动把新 .c 写进 uvprojx 与 CMakeLists.txt**,且
**双向对账**:加页打印 registered、删页打印 pruned,不留死条目;并双向
校验(#page 找不到实例报错、实例未被任何 #page 引用也报错)。
## U4 门禁补强(35 个钩子)
新增 font-charset 钩子(scripts/check_font_charset.py):复用
tools/font_gen 的同一套提取与 cmap 解析规则(importlib 直载,零第二套
规则),A 段查源码在用 vs 字符集、B 段查字符集 vs 字体 cmap。
registration-check 补第 ④ 类:实测原规则对"进了两端构建但没接描述符表"
的页面**全绿**——desc 被链接器剥离、编译链接全过、菜单永远打不开的死代码。
仍照不出的两项已如实写进文档(枚举漏加归 @build、菜单树漏挂归 golden)。
## 字体子集瘦身(D 案,4 留 3 删)
ui_cn_chars.txt 122→119 字(恰删 上/电/重,零新增)。异/常/片/芯 进
KEEP_EXTRA 带理由白名单:它们曾在 9eb1bd63 被写进中文自检描述落盘
/log/selftest.log(定长 64B 记录跨固件持久),删字形会使历史故障记录
渲染空白且不可逆。保留字按**必需**处理,反向有牙——谁只跑 extract_cn
把它们静默洗掉,钩子直接 FAIL 并逐字打印理由。
--strict 口径为"未知冗余 = 0"而非"冗余 = 0"。
## 验证
@build 0 错 0 警;ER_IROM1 232,052 B(较 HEAD −228 B)、RW_IRAM1
75,232 B **零增量**、RW_CCM 87.9% 未变。golden:菜单 8 状态全像素一致 +
内容页 11 页逐字节一致,**参考图 sha256 差异 0 条**(未用 --update 刷
基线);池水位菜单基线 5368 B、开页-关页往返 5448 B 与 U1 时相同。
38 个在途修改文件逐个核对 BOM/CRLF/U+FFFD 全部与 HEAD 一致。
L0 33 钩子 + L0.5 16 runner / 1104 断言全绿;check_doc_links --all
142 篇、无法判定 0;mem-budget / mem-numbers 已回填。
## 单位成本实测(U5 排期依据)
临时页 zzprobe 绑到"遥信量"叶子 → 只跑生成器 → 带页 @build 0/0 →
注册表出现 {5u, &ui_page_zzprobe_desc} → 回滚后 6 个产出文件 zzprobe
残留计数均 0、重编回基线。
**结论:新增一页 = 3 处人工(新 .c + 新 .h + 菜单树那一行加
#page=<名>)+ 1 条生成器命令,手工编辑注册文件 0 处。**
据此修正报告原口径"8 处降到 1 处"——那个 1 只在"1 处对既有文件的修改"
意义下成立,页面自身 2 个文件本就要写,真实处数是 3。
## 文档同步与两处自我修正
§0.1 UI 行 B → B+;§6.1「内容页」「设计令牌」两行按实况回填;§6.5 U1/U3
状态更新;§6 顶部加"建议栏不可照抄"总警示(本轮四次证伪:ui_port.h 已有
同名宏、LV_COLOR_BLACK/WHITE 不存在且极性反了、27 页实为目标页数现存 7
个、生成器草图漏密码页非节点绑定)。
两处改口:① §6.5 U4 从我上一版**误写的 3/3 改回 2/3**——"golden 脚本早已
存在"不等于"已进自动门禁",两个 golden 脚本至今未挂 pre-commit,该缺口
单列为待办;② 原计划"分三笔提交"**作废**,U1 与 U3 改同一批文件、文件内
交叠,硬切会产生不可编译的中间态,故整波一笔。
191 lines
7.6 KiB
CMake
191 lines
7.6 KiB
CMake
cmake_minimum_required(VERSION 3.15)
|
||
project(lvgl_sim C)
|
||
|
||
#=============================================================================
|
||
# 路径配置(相对于 simulator/ 目录)
|
||
#=============================================================================
|
||
set(PROJECT_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/..")
|
||
set(LVGL_DIR "${PROJECT_ROOT}/Lib/lvgl")
|
||
set(UI_DIR "${PROJECT_ROOT}/Drivers/BSP/UI")
|
||
set(NET_DIR "${PROJECT_ROOT}/Drivers/BSP/NET")
|
||
set(NETCFG_DIR "${PROJECT_ROOT}/Drivers/BSP/NETCFG")
|
||
set(SDL2_DIR "${CMAKE_CURRENT_SOURCE_DIR}/SDL2/SDL2-2.32.10")
|
||
|
||
#=============================================================================
|
||
# 编译标准
|
||
#=============================================================================
|
||
set(CMAKE_C_STANDARD 99)
|
||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||
|
||
# Windows 控制台输出(显示 printf)
|
||
if(WIN32)
|
||
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
|
||
endif()
|
||
|
||
# MSVC:源码为 UTF-8 编码(含中文注释),强制按 UTF-8 解析消除 C4819 警告
|
||
if(MSVC)
|
||
add_compile_options(/utf-8)
|
||
endif()
|
||
|
||
#=============================================================================
|
||
# SDL2 头文件路径(需先于 add_subdirectory 定义,供 LVGL SDL 驱动使用)
|
||
#=============================================================================
|
||
# LVGL SDL 驱动内部 #include "SDL2/SDL.h",include 目录下已有 SDL2/ 子目录
|
||
set(SDL2_INCLUDE_DIR "${SDL2_DIR}/include" CACHE PATH "SDL2 include directory for LVGL")
|
||
|
||
#=============================================================================
|
||
# LVGL 子目录(引用项目自带的 LVGL v9.3.0 源码)
|
||
#=============================================================================
|
||
# LVGL 内部会自动检测 lv_conf.h(通过 LV_CONF_INCLUDE_SIMPLE 宏)
|
||
# 需要将 simulator 目录加入 LVGL 的包含路径,使其能找到 lv_conf.h
|
||
set(LV_CONF_DIR "${CMAKE_CURRENT_SOURCE_DIR}" CACHE PATH "Directory containing lv_conf.h for LVGL")
|
||
add_subdirectory("${LVGL_DIR}" lvgl_build)
|
||
|
||
#=============================================================================
|
||
# 包含路径
|
||
#=============================================================================
|
||
include_directories(
|
||
${CMAKE_CURRENT_SOURCE_DIR} # lv_conf.h (LVGL 找), dbg_log.h
|
||
${CMAKE_CURRENT_SOURCE_DIR}/sim # sim_port.h 等模拟器平台层
|
||
${LVGL_DIR} # lvgl.h
|
||
${LVGL_DIR}/src # lvgl 内部头文件
|
||
${UI_DIR} # ui_menu.h, ui_font_cn_12.h
|
||
${NET_DIR} # net_socket.h / net_types.h(net_* API 双端共享核心)
|
||
${NETCFG_DIR} # net_cfg.h(网络配置,双端共享核心)
|
||
${PROJECT_ROOT}/test/board # test_config.h / net_latency_test.h(共享核心
|
||
# ui_net_sink.c、net_socket.c 引含;探针默认关闭,
|
||
# 声明宿主安全;2026-09-21 修复模拟器构建断链;
|
||
# 2026-10-02 测试目录重构后头文件移入 test/board/)
|
||
${PROJECT_ROOT}/App/cfg # cfg_file.h / cfg_file_store.h(通用配置文件引擎,双端共享核心)
|
||
${PROJECT_ROOT}/App/log # sys_log.h(运行/自检记录引擎,双端共享核心)
|
||
${PROJECT_ROOT}/Drivers/BSP # dbg_log.h(使用 simulator 的 dbg_cfg.h 配置)
|
||
${SDL2_DIR}/include # SDL2 头文件
|
||
)
|
||
|
||
#=============================================================================
|
||
# SDL2 库(使用本地预编译版本)
|
||
#=============================================================================
|
||
set(SDL2_INCLUDE_PARENT "${SDL2_DIR}/include")
|
||
set(SDL2_LIB_X64 "${SDL2_DIR}/lib/x64")
|
||
|
||
#=============================================================================
|
||
# 源文件
|
||
#=============================================================================
|
||
set(SIM_SOURCES
|
||
main.c
|
||
sim/sim_port.c
|
||
sim/sim_latency_stub.c # 探针符号宿主空实现(ui_net_sink.c 引用,见文件头注释)
|
||
)
|
||
|
||
# UI 源文件(与 MCU 端共用,直接编译)
|
||
set(UI_SOURCES
|
||
${UI_DIR}/ui_menu.c
|
||
${UI_DIR}/ui_menu_view.c
|
||
${UI_DIR}/ui_content_page.c
|
||
${UI_DIR}/ui_deco.c
|
||
${UI_DIR}/ui_page_device_info.c
|
||
${UI_DIR}/ui_page_ac.c
|
||
${UI_DIR}/ui_page_dc.c
|
||
${UI_DIR}/ui_page_password.c
|
||
${UI_DIR}/ui_page_net_cfg.c
|
||
${UI_DIR}/ui_page_runlog.c
|
||
${UI_DIR}/ui_page_selftest.c
|
||
${UI_DIR}/ui_standby.c
|
||
${UI_DIR}/ui_menu_tab.c
|
||
${UI_DIR}/ui_font_cn_12.c
|
||
${UI_DIR}/ui_net_sink.c
|
||
${UI_DIR}/ui_page_registry.c
|
||
${UI_DIR}/ui_style.c
|
||
)
|
||
|
||
# 运行/自检记录引擎(双端共享核心 + 平台存储后端;MCU 端编 sys_log_mcu.c,见 Keil 工程)
|
||
set(SYSLOG_SOURCES
|
||
sim/sim_syslog.c
|
||
)
|
||
|
||
# 网络配置(双端共享核心 + cfg_file 引擎 + 平台存储后端;MCU 端编 cfg_file_store_mcu.c,见 Keil 工程)
|
||
set(NETCFG_SOURCES
|
||
${NETCFG_DIR}/net_cfg.c
|
||
${NETCFG_DIR}/ftp_cfg.c
|
||
${PROJECT_ROOT}/App/cfg/cfg_file.c
|
||
sim/cfg_file_store_sim.c
|
||
)
|
||
|
||
# 网络后端(net_* 核心 API 的 Winsock 实现 + UI 推流平台后端;MCU 端另编 net_socket.c 与 _mcu 后端)
|
||
set(NET_SOURCES
|
||
sim/net_socket_sim.c
|
||
sim/ui_net_sink_backend_sim.c
|
||
)
|
||
|
||
#=============================================================================
|
||
# 构建可执行文件
|
||
#=============================================================================
|
||
add_executable(lvgl_sim WIN32 ${SIM_SOURCES} ${UI_SOURCES} ${NETCFG_SOURCES} ${SYSLOG_SOURCES} ${NET_SOURCES})
|
||
|
||
target_compile_definitions(lvgl_sim PRIVATE
|
||
LV_CONF_INCLUDE_SIMPLE # 让 lvgl.h 找到 lv_conf.h
|
||
LV_LVGL_H_INCLUDE_SIMPLE # ui_font_cn_12.c 内部 include 简化
|
||
WIN32_LEAN_AND_MEAN # 防止 Windows.h 拉入 winsock.h(与 winsock2.h 冲突)
|
||
NET_NO_OS # 剥离 net_socket.h 的 FreeRTOS 相关接口(纯 BSD Socket)
|
||
)
|
||
|
||
target_include_directories(lvgl_sim PRIVATE
|
||
${SDL2_INCLUDE_PARENT} # SDL2/SDL.h 路径
|
||
)
|
||
|
||
target_link_directories(lvgl_sim PRIVATE
|
||
${SDL2_LIB_X64}
|
||
)
|
||
|
||
target_link_libraries(lvgl_sim
|
||
lvgl
|
||
SDL2
|
||
SDL2main
|
||
ws2_32
|
||
)
|
||
|
||
# 数学库(非 MSVC)
|
||
if(NOT MSVC)
|
||
target_link_libraries(lvgl_sim m pthread)
|
||
endif()
|
||
|
||
# Windows 子系统:控制台(显示 printf 输出)
|
||
if(WIN32)
|
||
if(MSVC)
|
||
target_link_options(lvgl_sim PRIVATE "/SUBSYSTEM:CONSOLE")
|
||
else()
|
||
target_link_options(lvgl_sim PRIVATE "-mconsole")
|
||
endif()
|
||
endif()
|
||
|
||
# 复制 SDL2.dll 到输出目录
|
||
add_custom_command(TARGET lvgl_sim POST_BUILD
|
||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||
"${SDL2_LIB_X64}/SDL2.dll"
|
||
"$<TARGET_FILE_DIR:lvgl_sim>/SDL2.dll"
|
||
COMMENT "Copying SDL2.dll to output directory"
|
||
)
|
||
|
||
#=============================================================================
|
||
# 自定义目标:运行模拟器
|
||
#=============================================================================
|
||
add_custom_target(run COMMAND ${CMAKE_BINARY_DIR}/lvgl_sim DEPENDS lvgl_sim)
|
||
|
||
#=============================================================================
|
||
# 调试模式额外警告
|
||
#=============================================================================
|
||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||
message(STATUS "Debug mode enabled for simulator")
|
||
if(MSVC)
|
||
target_compile_options(lvgl_sim PRIVATE /W4)
|
||
else()
|
||
target_compile_options(lvgl_sim PRIVATE -Wall -Wextra -Wpedantic)
|
||
endif()
|
||
endif()
|
||
|
||
message(STATUS "=== LVGL Simulator ===")
|
||
message(STATUS "Screen: 160x160, 1bpp monochrome")
|
||
message(STATUS "LVGL dir: ${LVGL_DIR}")
|
||
message(STATUS "UI dir: ${UI_DIR}")
|
||
message(STATUS "SDL2: ${SDL2_DIR}")
|