#!/usr/bin/env bash
# Build the Handshake Ledger app for a given device, with all the macOS
# native-toolchain env wrangling that cargo-ledger and the secure SDK assume.
#
# Usage:  ./scripts/build [stax|flex|nanox|nanosplus]   (default: stax)
#
# Prerequisites (one-time setup):
#   brew install --cask gcc-arm-embedded         # ARM bare-metal toolchain
#   brew install llvm                            # llvm-objcopy, llvm-nm
#   cargo install --git https://github.com/LedgerHQ/cargo-ledger cargo-ledger
#   cargo ledger setup                            # installs target.json files
#   git clone --depth=1 --branch API_LEVEL_25 \
#     https://github.com/LedgerHQ/ledger-secure-sdk ~/.ledger-sdk/secure-sdk-25
#   # API level must match the device firmware:
#   #   Stax SE 1.9.1 → API_LEVEL_25.
#   # If install fails with status 0x511f, you're probably on the wrong level:
#   # re-clone the SDK at the matching API_LEVEL_NN branch and override
#   # LEDGER_SDK_PATH for the build.
#   python3 -m pip install --user --break-system-packages Pillow
#   # Patch the rustup-installed link_wrap.sh to be macOS-portable:
#   sed -i '' 's|stat -c %s|wc -c <|' \
#     ~/.rustup/toolchains/$(rustup show active-toolchain | cut -d' ' -f1)/lib/rustlib/$(rustc -vV | sed -n 's/host: //p')/bin/link_wrap.sh

set -euo pipefail

DEVICE="${1:-stax}"
ARM_BIN="/Applications/ArmGNUToolchain/15.2.rel1/arm-none-eabi/bin"
LLVM_BIN="/opt/homebrew/opt/llvm/bin"
SDK="${LEDGER_SDK_PATH:-$HOME/.ledger-sdk/secure-sdk-25}"

if [[ ! -x "$ARM_BIN/arm-none-eabi-gcc" ]]; then
  echo "ARM toolchain not found at $ARM_BIN: install with: brew install --cask gcc-arm-embedded"
  exit 1
fi
if [[ ! -x "$LLVM_BIN/llvm-objcopy" ]]; then
  echo "llvm-objcopy not found at $LLVM_BIN: install with: brew install llvm"
  exit 1
fi
if [[ ! -f "$SDK/install_params.py" ]]; then
  echo "BOLOS Secure SDK not found at $SDK: see prerequisites in this script"
  exit 1
fi

# The Nano NBGL sources use `uint`, a BSD spelling that arm-none-eabi-gcc
# accepts and the clang this script drives does not, so nanosplus and nanox
# fail to compile out of the box. `uint32_t` is the right width for the two
# loop counters that use it (lib_nbgl/src/nbgl_use_case_nanos.c:373,1581).
EXTRA_CFLAGS=""
if [[ "$DEVICE" == "nanosplus" || "$DEVICE" == "nanox" ]]; then
  EXTRA_CFLAGS="-Duint=uint32_t"
fi

PATH="$ARM_BIN:$LLVM_BIN:$PATH" \
LEDGER_SDK_PATH="$SDK" \
CFLAGS="${CFLAGS:-} $EXTRA_CFLAGS" \
cargo ledger build "$DEVICE" "${@:2}"

# cargo-ledger's post-build expects an Intel HEX next to the manifest but
# silently produces nothing on macOS: generate it from the ELF.
ELF="target/$DEVICE/release/app-handshake"
HEX="$ELF.hex"
if [[ -f "$ELF" && ( ! -f "$HEX" || "$ELF" -nt "$HEX" ) ]]; then
  "$LLVM_BIN/llvm-objcopy" -O ihex "$ELF" "$HEX"
  echo "wrote $HEX"
fi

# cargo-ledger also fails to write the ledgerctl manifest on macOS. Generate it
# from the ELF, so `dataSize` can never drift from the binary being installed:
# an undersized dataSize installs cleanly and then refuses to launch.
"$(dirname "$0")/gen-manifest" "$DEVICE"
