# =============================================================================
# arm-none-eabi-toolchain.cmake - STM32F407VGT6 (Cortex-M4F) 크로스 컴파일 툴체인
#
# 사용:
#   cmake -S firmware -B firmware/build -G Ninja \
#         -DCMAKE_TOOLCHAIN_FILE=firmware/cmake/arm-none-eabi-toolchain.cmake
#
# 대상: Cortex-M4F, 하드웨어 단정밀도 FPU(FPv4-SP-D16), Thumb.
# 폐쇄망(air-gapped): newlib-nano + nosys stub 으로 자급식 바이너리 생성.
#   - 외부 런타임/네트워크 의존 없음(빌드 산출물 자체 완결).
# =============================================================================

# ── 베어메탈/RTOS 타깃: OS 없음 → Generic ────────────────────────────────────
set(CMAKE_SYSTEM_NAME       Generic)
set(CMAKE_SYSTEM_PROCESSOR  arm)

# CMake 가 호스트 라이브러리/헤더를 찾지 않도록(크로스 빌드 격리).
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)

# ── 툴 위치 탐색 ─────────────────────────────────────────────────────────────
# PATH 에서 arm-none-eabi-* 를 찾는다. 다른 경로면 -DTOOLCHAIN_PREFIX 로 지정.
#   예) -DTOOLCHAIN_PREFIX="C:/Program Files (x86)/Arm/.../bin/arm-none-eabi-"
if(NOT DEFINED TOOLCHAIN_PREFIX)
    set(TOOLCHAIN_PREFIX "arm-none-eabi-")
endif()

# Windows 실행파일 확장자(.exe) 처리: PATH 탐색 시 자동 인식되지만 명시 경로 대비.
if(WIN32)
    set(TC_EXT ".exe")
else()
    set(TC_EXT "")
endif()

set(CMAKE_C_COMPILER    "${TOOLCHAIN_PREFIX}gcc${TC_EXT}")
set(CMAKE_CXX_COMPILER  "${TOOLCHAIN_PREFIX}g++${TC_EXT}")
set(CMAKE_ASM_COMPILER  "${TOOLCHAIN_PREFIX}gcc${TC_EXT}")
set(CMAKE_OBJCOPY       "${TOOLCHAIN_PREFIX}objcopy${TC_EXT}" CACHE FILEPATH "objcopy")
set(CMAKE_OBJDUMP       "${TOOLCHAIN_PREFIX}objdump${TC_EXT}" CACHE FILEPATH "objdump")
set(CMAKE_SIZE          "${TOOLCHAIN_PREFIX}size${TC_EXT}"    CACHE FILEPATH "size")
set(CMAKE_AR            "${TOOLCHAIN_PREFIX}ar${TC_EXT}"      CACHE FILEPATH "ar")

# ── try_compile: 실행파일이 아닌 정적 라이브러리로 검증 ──────────────────────
# 베어메탈 타깃은 링커 스크립트/startup 없이 실행파일을 만들 수 없으므로
# CMake 의 컴파일러 식별 단계에서 STATIC_LIBRARY 를 사용한다.
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)

# ── CPU/FPU 아키텍처 플래그 (C / C++ / ASM / LINK 공통) ──────────────────────
set(CPU_FLAGS "-mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16")

# 함수/데이터 섹션 분리 → 링크 시 미사용 섹션 제거(--gc-sections)로 크기 최소화.
set(OPT_FLAGS "-ffunction-sections -fdata-sections")

# 공통 컴파일 플래그(언어 무관). CMAKE_<LANG>_FLAGS_INIT 은 캐시 채우기 전 1회 적용.
set(CMAKE_C_FLAGS_INIT   "${CPU_FLAGS} ${OPT_FLAGS}")
set(CMAKE_CXX_FLAGS_INIT "${CPU_FLAGS} ${OPT_FLAGS} -fno-exceptions -fno-rtti")
set(CMAKE_ASM_FLAGS_INIT "${CPU_FLAGS} -x assembler-with-cpp")

# ── 링크 플래그 ──────────────────────────────────────────────────────────────
# newlib-nano(--specs=nano.specs): 작은 libc.
# nosys(--specs=nosys.specs): _read/_write/_sbrk 등 시스템콜을 빈 stub 로 제공
#   → 폐쇄망/베어메탈에서 OS 없이 링크 성립. (printf 의 retarget 은 applog/UART 측에서.)
# --gc-sections: 미사용 코드 제거. -Map: 메모리 맵 산출(크기 분석/디버깅).
# -u _printf_float: newlib-nano 의 vsnprintf/printf 가 %f 를 처리하도록 부동소수
#   포맷 코어를 강제 링크한다(약 +7KB flash, 1MB 중 무시할 수준). app_sht30.c 등
#   진단 로그가 온습도를 %.2f 로 출력하므로 필요하다. (서버로 보내는 본문은
#   jb_fixed2() 로 printf 없이 만들므로 wire 계약과는 무관하다.)
set(CMAKE_EXE_LINKER_FLAGS_INIT
    "${CPU_FLAGS} --specs=nano.specs --specs=nosys.specs \
-u _printf_float \
-Wl,--gc-sections \
-Wl,--print-memory-usage \
-Wl,--no-warn-rwx-segments")
