#!/bin/sh
set -eu

ROOT=$(CDPATH= cd -- "$(dirname -- "$0")/../.." && pwd)
TARGET="$ROOT/固件/drill_target"
OUT="$TARGET/build"
CC=${ARM_GCC:-arm-none-eabi-gcc}
OBJCOPY=${ARM_OBJCOPY:-arm-none-eabi-objcopy}
SIZE=${ARM_SIZE:-arm-none-eabi-size}

mkdir -p "$OUT"
FLAGS="-mcpu=cortex-m4 -mthumb -mfloat-abi=soft -DSTM32G431xx -std=c11 -Os -g3 -ffreestanding -fno-builtin -fno-common -Wall -Wextra -Werror"
INCLUDES="-I$TARGET/Device/Include -I$ROOT/固件/lamp_target/CMSIS/Core/Include -I$ROOT/固件/lamp_target/include -I$ROOT/固件/drill_driver -I$ROOT/固件/drill_charge"

# shellcheck disable=SC2086
$CC $FLAGS $INCLUDES -c "$TARGET/Device/Source/Templates/system_stm32g4xx.c" -o "$OUT/system_stm32g4xx.o"
# shellcheck disable=SC2086
$CC $FLAGS $INCLUDES -c "$TARGET/src/runtime.c" -o "$OUT/runtime.o"
# shellcheck disable=SC2086
$CC $FLAGS $INCLUDES -c "$TARGET/src/main.c" -o "$OUT/main.o"
# shellcheck disable=SC2086
$CC $FLAGS $INCLUDES -c "$TARGET/src/drill_config_async.c" -o "$OUT/drill_config_async.o"
$CC $FLAGS $INCLUDES -c "$TARGET/src/drill_config_binding.c" -o "$OUT/drill_config_binding.o"
$CC $FLAGS $INCLUDES -c "$TARGET/src/drill_timebase.c" -o "$OUT/drill_timebase.o"
$CC $FLAGS $INCLUDES -c "$TARGET/src/drill_spi_transport.c" -o "$OUT/drill_spi_transport.o"
$CC $FLAGS $INCLUDES -c "$TARGET/src/drill_pwm_stage.c" -o "$OUT/drill_pwm_stage.o"
$CC $FLAGS $INCLUDES -c "$TARGET/src/drill_safe_gpio.c" -o "$OUT/drill_safe_gpio.o"
$CC -mcpu=cortex-m4 -mthumb -mfloat-abi=soft -x assembler-with-cpp -c \
    "$TARGET/startup/startup_stm32g431_minimal.s" -o "$OUT/startup.o"
for source in drv8316 speed_supervisor; do
    # shellcheck disable=SC2086
    $CC $FLAGS $INCLUDES -c "$ROOT/固件/drill_driver/$source.c" -o "$OUT/$source.o"
done
# Compile the FOC current-loop candidate with the STM32G431 hardware FPU ABI.
# It is deliberately kept out of the safe-GPIO-only linked image until the
# observer, ADC/TIM1 timing, and physical motor profile are verified.
$CC -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mthumb -mfloat-abi=hard \
    -DSTM32G431xx -std=c11 -Os -g3 -ffreestanding -fno-builtin -fno-common \
    -Wall -Wextra -Werror -I"$ROOT/固件/drill_driver" \
    -c "$ROOT/固件/drill_driver/motor_foc.c" -o "$OUT/motor_foc.o"
for source in charge_manager charge_registers; do
    # shellcheck disable=SC2086
    $CC $FLAGS $INCLUDES -c "$ROOT/固件/drill_charge/$source.c" -o "$OUT/$source.o"
done

$CC -mcpu=cortex-m4 -mthumb -mfloat-abi=soft -nostdlib \
    -T "$TARGET/linker/stm32g431cb.ld" \
    -Wl,-Map="$OUT/drill_control_g431cb.map",--cref,--build-id=none,--no-undefined,--print-memory-usage \
    -Wl,-z,noexecstack \
    "$OUT/startup.o" "$OUT/system_stm32g4xx.o" "$OUT/runtime.o" "$OUT/main.o" \
    "$OUT/drill_safe_gpio.o" "$OUT/drill_pwm_stage.o" "$OUT/drill_spi_transport.o" "$OUT/drill_timebase.o" "$OUT/drill_config_async.o" "$OUT/drill_config_binding.o" "$OUT/drv8316.o" \
    "$OUT/speed_supervisor.o" "$OUT/charge_manager.o" "$OUT/charge_registers.o" -lgcc \
    -o "$OUT/drill_control_g431cb.elf"

$OBJCOPY -O binary "$OUT/drill_control_g431cb.elf" "$OUT/drill_control_g431cb.bin"
$SIZE "$OUT/drill_control_g431cb.elf" | tee "$OUT/size.txt"
python3 "$TARGET/verify_image.py" "$OUT/drill_control_g431cb.elf" "$OUT/drill_control_g431cb.bin" "$OUT/drill_control_g431cb.map" > "$OUT/build_verification.json"
python3 - "$OUT/build_verification.json" "$OUT/motor_foc.o" <<'PY'
import hashlib
import json
import sys
from pathlib import Path

receipt = Path(sys.argv[1])
object_file = Path(sys.argv[2])
data = json.loads(receipt.read_text(encoding="utf-8"))
data["candidate_object_compile"] = {
    "source": "固件/drill_driver/motor_foc.c",
    "target": "Cortex-M4 / STM32G431",
    "fpu": "fpv4-sp-d16",
    "float_abi": "hard",
    "status": "COMPILE_PASS_NOT_LINKED",
    "object_sha256": hashlib.sha256(object_file.read_bytes()).hexdigest(),
    "linked_into_safe_gpio_image": False,
}
receipt.write_text(json.dumps(data, ensure_ascii=False, indent=2) + "\n",
                   encoding="utf-8")
PY
rm -f "$OUT"/*.o
cat "$OUT/build_verification.json"
