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/protocol/iec104 # iec104_comm.h([comm] 段契约头,供 IEC104_SOURCES 编译;道G task-8) ${PROJECT_ROOT}/App/log # sys_log.h(运行/自检记录引擎,双端共享核心) ${PROJECT_ROOT}/App/algo # prot_set.h(定值模型纯算法,双端共享核心;见 ALGO_SOURCES) ${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 ${UI_DIR}/ui_w_records.c ${UI_DIR}/ui_w_editor.c ${UI_DIR}/ui_w_setlist.c ${UI_DIR}/ui_page_action.c ${UI_DIR}/ui_data.c # 数据快照存侧(道E task-14;写侧 App/app/ui_data_feed.c 不进模拟器,见 scripts/check_registration.py) ${UI_DIR}/ui_w_soe.c # SOE 记录组件(道E task-14;reader 已在批 2 两端绑定) ${UI_DIR}/ui_w_setview.c # 定值查看视图模型(道E task-15 批 3:四张视图表 + Q10 换算 + 越界反显) ${UI_DIR}/ui_w_ytview.c # 遥测整定视图模型(道F task-7:死区/系数两页共用注入表视图 + 落盘确认状态机) ${UI_DIR}/ui_page_soe.c ${UI_DIR}/ui_page_view_param.c ${UI_DIR}/ui_page_view_plate.c ${UI_DIR}/ui_page_view_set.c ${UI_DIR}/ui_page_view_word.c ${UI_DIR}/ui_page_yx.c ${UI_DIR}/ui_page_clear.c ${UI_DIR}/ui_page_clock.c ${UI_DIR}/ui_page_reset.c ${UI_DIR}/ui_page_calib.c ${UI_DIR}/ui_page_deadband.c ${UI_DIR}/ui_page_comm.c ${UI_DIR}/ui_page_accident.c ${UI_DIR}/ui_page_alarm.c ${UI_DIR}/ui_page_oper.c ${UI_DIR}/ui_page_runreport.c ${UI_DIR}/ui_page_start.c ${UI_DIR}/ui_page_yk.c ${UI_DIR}/ui_page_wave_manual.c ${UI_DIR}/ui_page_wave_play.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 ) # 保护定值模型(App/algo/prot_set.c 零平台依赖,双端共享核心)。 # 模拟器只需要"出厂默认定值"来发布 UI 快照帧(main.c 的 sim_publish_data_frames), # 不在这里复制一份 40 项数字——抄表就等于造第二真相(同 scripts/check_font_charset.py # "单一规则源"的同一治理口径)。 set(ALGO_SOURCES ${PROJECT_ROOT}/App/algo/prot_set.c # 录波段格式与录波环(故障录波 P1/P2):两份都是零平台依赖纯逻辑——不 include HAL/CMSIS/RTOS、 # 不调 FatFs、不建 RTOS 对象、无 malloc。模拟器必须一起编译,因为「录波回放」页要在模拟器里 # 出真波形(峰值换算走 wave_store_code_to_milli,取数走 wave_ring_read_ch),数据由 # simulator/main.c 的合成节拍喂进 ring —— 与 prot_set.c 同一条「双端共享核心、不造第二真相」 # 口径,因此两份都**不进** scripts/check_registration.py 的 SIM_EXEMPT。 ${PROJECT_ROOT}/App/algo/wave_store.c ${PROJECT_ROOT}/App/algo/wave_ring.c ) # IEC 104 [comm] 配置段(道G task-8):模拟器运行期不跑 104 任务、无消费路径, # 本 TU 仅为双端注册事实一致而编译(iec104 其余 .c 走 scripts 白名单逐个点名, # 白名单是门禁地盘不在这里扩——新配对模块按 new-source-file 口径进显式源列表)。 set(IEC104_SOURCES ${PROJECT_ROOT}/App/protocol/iec104/iec104_comm.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} ${ALGO_SOURCES} ${IEC104_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" "$/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}")