# 设置交叉编译目标系统为通用（无操作系统）
set(CMAKE_SYSTEM_NAME Generic)
# 设置目标处理器架构为ARM
set(CMAKE_SYSTEM_PROCESSOR ARM)
# 设置系统版本号
set(CMAKE_SYSTEM_VERSION 1)

# 指定CMake最低版本要求
cmake_minimum_required(VERSION 3.31.12)

# [优化] 设置交叉编译查找规则
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)     # 不在目标系统查找程序
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)      # 只在目标系统查找库
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)      # 只在目标系统查找头文件
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)      # 只在目标系统查找包

# 设置编译目标类型为静态库，跳过编译器测试
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)

# [优化] 编译器检查
if(NOT CMAKE_C_COMPILER)
    message(FATAL_ERROR "ARM GCC编译器未找到，请安装arm-none-eabi-gcc工具链")
endif()

# 项目定义，支持C、C++和汇编语言
project(Project C CXX ASM)

# 设置C++标准为C++17
set(CMAKE_CXX_STANDARD 17)
# 设置C标准为C11
set(CMAKE_C_STANDARD 11)

# 添加核心编译选项
add_compile_options(
        -mcpu=cortex-m3        # 指定CPU内核为Cortex-M3
        -mthumb                # 使用Thumb指令集
        -mthumb-interwork      # 支持ARM/Thumb指令集交互

        # 代码段优化选项
        -ffunction-sections    # 将每个函数放在独立的段中
        -fdata-sections        # 将每个数据放在独立的段中
        -fno-common            # 禁止未初始化变量使用公共段
        -fmessage-length=0     # 错误消息不限制长度

        # 警告选项
        -Wall                  # 开启所有警告
        -Wextra                # 开启额外警告
        -Wno-unused-parameter  # 抑制未使用参数警告
)

# 启用汇编器文件预处理
add_compile_options($<$<COMPILE_LANGUAGE:ASM>:-x$<SEMICOLON>assembler-with-cpp>)

# [优化] 构建类型配置
string(TOUPPER "${CMAKE_BUILD_TYPE}" BUILD_TYPE_UPPER)
if("${BUILD_TYPE_UPPER}" STREQUAL "RELEASE")
    message(STATUS "Release模式：速度最大化优化")
    add_compile_options(-Ofast)
elseif("${BUILD_TYPE_UPPER}" STREQUAL "RELWITHDEBINFO")
    message(STATUS "RelWithDebInfo模式：速度优化，包含调试信息")
    add_compile_options(-Ofast -g)
elseif("${BUILD_TYPE_UPPER}" STREQUAL "MINSIZEREL")
    message(STATUS "MinSizeRel模式：代码大小最小化优化")
    add_compile_options(-Os)
else()
    message(STATUS "Debug模式：最小优化，包含完整调试信息")
    add_compile_options(-Og -g -DDEBUG)
endif()

# 添加预处理器宏定义
add_compile_definitions(
        USE_STDPERIPH_DRIVER
        STM32F10X_HD
)

# [我加的] 添加头文件搜索路径 - 根据你的项目结构调整
include_directories(
        App
        VoiletBspStm32F10x/Bsp/Inc
        VoiletBspStm32F10x/StdLib/Inc
        VoiletBspStm32F10x/System
        VoiletBspStm32F10x/System/Cmsis/Inc
        VoiletBspStm32F10x/ThirdParty/LetterShell/Inc
)

# [我加的] 自动收集源文件（递归搜索指定目录下的所有源文件）
file(GLOB_RECURSE SOURCES
        VoiletBspStm32F10x/System/Startup/Gcc/startup_stm32f10x_hd.s
        App/*.c
        VoiletBspStm32F10x/Bsp/Src/*.c
        VoiletBspStm32F10x/StdLib/Src/*.c
        VoiletBspStm32F10x/System/*.c
        VoiletBspStm32F10x/System/Cmsis/Src/*.c
        VoiletBspStm32F10x/ThirdParty/LetterShell/Src/*.c
)
# [我加的] 排除模板文件和测试套件
list(FILTER SOURCES EXCLUDE REGEX ".*template.*")
list(FILTER SOURCES EXCLUDE REGEX ".*TestSuite.*")
list(FILTER SOURCES EXCLUDE REGEX ".*ARMCC.*")

# [我加的] 显示找到的源文件信息
message(STATUS "找到的源文件数量: ${SOURCES}")
foreach(source ${SOURCES})
    get_filename_component(FILENAME ${source} NAME)
    message(STATUS "  - ${FILENAME}")
endforeach()

# [我加的] 排除模板文件
list(FILTER SOURCES EXCLUDE REGEX ".*template.*")

# [我加的] 显示找到的源文件信息
message(STATUS "找到的源文件数量: ${SOURCES}")
foreach(source ${SOURCES})
    get_filename_component(FILENAME ${source} NAME)
    message(STATUS "  - ${FILENAME}")
endforeach()

# 设置链接脚本路径
set(LINKER_SCRIPT ${CMAKE_SOURCE_DIR}/VoiletBspStm32F10x/System/LinkScripts/Gcc/stm32_flash_ze.ld)

# 检查链接脚本是否存在
if(NOT EXISTS "${LINKER_SCRIPT}")
    message(FATAL_ERROR "链接脚本不存在，请检查路径: ${LINKER_SCRIPT}")
else()
    message(STATUS "链接脚本验证成功: ${LINKER_SCRIPT}")
endif()

# [修正] 链接器选项语法
add_link_options(
        # 链接器优化选项
        "LINKER:-gc-sections"           # 垃圾回收未使用的段
        "LINKER:--print-memory-usage"   # 打印内存使用情况
        "LINKER:-Map=${PROJECT_BINARY_DIR}/${PROJECT_NAME}.map"  # 生成内存映射文件

        # CPU架构选项
        -mcpu=cortex-m3
        -mthumb
        -mthumb-interwork

        # 指定链接脚本
        -T "${LINKER_SCRIPT}"

        # 标准库规格
        -specs=nano.specs          # 使用精简版C库
        -specs=nosys.specs         # 无系统调用支持
)

# 创建可执行文件目标
add_executable(${PROJECT_NAME}.elf ${SOURCES}
        App/main.c
        App/main.h)

# [优化] 添加自定义目标用于分析
add_custom_target(size
        COMMAND ${CMAKE_SIZE_UTIL} ${PROJECT_NAME}.elf
        DEPENDS ${PROJECT_NAME}.elf
        COMMENT "分析程序内存使用情况"
)

# 设置输出文件路径
set(HEX_FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.hex)
set(BIN_FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.bin)

# 添加自定义命令生成HEX和BIN文件
add_custom_command(
        TARGET ${PROJECT_NAME}.elf
        POST_BUILD
        COMMAND ${CMAKE_OBJCOPY} -Oihex $<TARGET_FILE:${PROJECT_NAME}.elf> ${HEX_FILE}
        COMMAND ${CMAKE_OBJCOPY} -Obinary $<TARGET_FILE:${PROJECT_NAME}.elf> ${BIN_FILE}
        COMMENT "Generate HEX and BIN files: ${HEX_FILE}, ${BIN_FILE}"
)

# [优化] 显示构建信息
message(STATUS "目标MCU: Cortex-M3")
message(STATUS "链接脚本: ${LINKER_SCRIPT}")
message(STATUS "编译器: ${CMAKE_C_COMPILER}")
