#!/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"