From 9d15c76d773f807ba3aa7e6e3a6b3930f44a197a Mon Sep 17 00:00:00 2001 From: Oleg Kulachenko Date: Sat, 18 Apr 2026 16:37:45 +0300 Subject: [PATCH 1/2] Fix incorrect `sh` references in build.sh usage docs The script uses bash-specific features (arrays, [[ ]], shopt, ${@:2}), but the usage examples and synopsis in global_usage() all referenced `sh build.sh`, which would fail on a strict POSIX shell. Replace all occurrences with `bash build.sh` to match the shebang and actual requirements. Signed-off-by: Oleg Kulachenko --- build.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/build.sh b/build.sh index 313c4c47a0..ac90c4b302 100755 --- a/build.sh +++ b/build.sh @@ -3,7 +3,7 @@ global_usage() { cat - < [target] +bash build.sh [target] Commands: help|usage|-h|--help: Shows this message. @@ -17,19 +17,19 @@ Commands: Examples: Build firmware for the "RAK_4631_repeater" device target -$ sh build.sh build-firmware RAK_4631_repeater +$ bash build.sh build-firmware RAK_4631_repeater Build all firmwares for device targets containing the string "RAK_4631" -$ sh build.sh build-matching-firmwares +$ bash build.sh build-matching-firmwares Build all companion firmwares -$ sh build.sh build-companion-firmwares +$ bash build.sh build-companion-firmwares Build all repeater firmwares -$ sh build.sh build-repeater-firmwares +$ bash build.sh build-repeater-firmwares Build all chat room server firmwares -$ sh build.sh build-room-server-firmwares +$ bash build.sh build-room-server-firmwares Environment Variables: DISABLE_DEBUG=1: Disables all debug logging flags (MESH_DEBUG, MESH_PACKET_LOGGING, etc.) @@ -39,11 +39,11 @@ Examples: Build without debug logging: $ export FIRMWARE_VERSION=v1.0.0 $ export DISABLE_DEBUG=1 -$ sh build.sh build-firmware RAK_4631_repeater +$ bash build.sh build-firmware RAK_4631_repeater Build with debug logging (default, uses flags from variant files): $ export FIRMWARE_VERSION=v1.0.0 -$ sh build.sh build-firmware RAK_4631_repeater +$ bash build.sh build-firmware RAK_4631_repeater EOF } From dc25e1136af60c12454e5b868632414c23536ad8 Mon Sep 17 00:00:00 2001 From: Oleg Kulachenko Date: Sat, 18 Apr 2026 16:54:13 +0300 Subject: [PATCH 2/2] Fix all shellcheck warnings in build.sh Address style, info, and warning-level issues reported by `shellcheck build.sh -severity=style -o all -s bash`: - Use mapfile instead of word-splitting command substitution (SC2207) - Quote all variable expansions to prevent globbing/splitting (SC2086) - Prefer [[ ]] over [ ] for bash tests (SC2292) - Add braces to all variable references (SC2250) - Fix pipe return value masking in get_pio_envs() (SC2312) - Add default case to top-level case statement (SC2249) - Assign TARGETS as array instead of string (SC2124) - Use explicit -n for non-empty string checks (SC2244) - Suppress SC2154 for environment variable DISABLE_DEBUG - Replace grep|sed pipe with single sed -n in get_pio_envs() Signed-off-by: Oleg Kulachenko --- build.sh | 100 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 63 insertions(+), 37 deletions(-) diff --git a/build.sh b/build.sh index ac90c4b302..f4b50a5f77 100755 --- a/build.sh +++ b/build.sh @@ -49,7 +49,9 @@ EOF # get a list of pio env names that start with "env:" get_pio_envs() { - pio project config | grep 'env:' | sed 's/env://' + local pio_output + pio_output=$(pio project config) || return $? + sed -n 's/^env://p' <<< "${pio_output}" } # Catch cries for help before doing anything else. @@ -62,6 +64,9 @@ case $1 in get_pio_envs exit 0 ;; + *) + # Fall through to main command handling below + ;; esac # cache project config json for use in get_platform_for_env() @@ -70,10 +75,15 @@ PIO_CONFIG_JSON=$(pio project config --json-output) # $1 should be the string to find (case insensitive) get_pio_envs_containing_string() { shopt -s nocasematch - envs=($(get_pio_envs)) + local env_list envs + env_list=$(get_pio_envs) || return $? + mapfile -t envs <<< "${env_list}" + if [[ ${#envs[@]} -gt 0 && -z "${envs[-1]}" ]]; then + unset 'envs[-1]' + fi for env in "${envs[@]}"; do - if [[ "$env" == *${1}* ]]; then - echo $env + if [[ "${env}" == *"${1}"* ]]; then + echo "${env}" fi done } @@ -81,10 +91,15 @@ get_pio_envs_containing_string() { # $1 should be the string to find (case insensitive) get_pio_envs_ending_with_string() { shopt -s nocasematch - envs=($(get_pio_envs)) + local env_list envs + env_list=$(get_pio_envs) || return $? + mapfile -t envs <<< "${env_list}" + if [[ ${#envs[@]} -gt 0 && -z "${envs[-1]}" ]]; then + unset 'envs[-1]' + fi for env in "${envs[@]}"; do - if [[ "$env" == *${1} ]]; then - echo $env + if [[ "${env}" == *"${1}" ]]; then + echo "${env}" fi done } @@ -93,11 +108,11 @@ get_pio_envs_ending_with_string() { # $1 should be the environment name get_platform_for_env() { local env_name=$1 - echo "$PIO_CONFIG_JSON" | python3 -c " + echo "${PIO_CONFIG_JSON}" | python3 -c " import sys, json, re data = json.load(sys.stdin) for section, options in data: - if section == 'env:$env_name': + if section == 'env:${env_name}': for key, value in options: if key == 'build_flags': for flag in value: @@ -110,7 +125,8 @@ for section, options in data: # disable all debug logging flags if DISABLE_DEBUG=1 is set disable_debug_flags() { - if [ "$DISABLE_DEBUG" == "1" ]; then + # shellcheck disable=SC2154 + if [[ "${DISABLE_DEBUG}" == "1" ]]; then export PLATFORMIO_BUILD_FLAGS="${PLATFORMIO_BUILD_FLAGS} -UMESH_DEBUG -UBLE_DEBUG_LOGGING -UWIFI_DEBUG_LOGGING -UBRIDGE_DEBUG -UGPS_NMEA_DEBUG -UCORE_DEBUG_LEVEL -UESPNOW_DEBUG_LOGGING -UDEBUG_RP2040_WIRE -UDEBUG_RP2040_SPI -UDEBUG_RP2040_CORE -UDEBUG_RP2040_PORT -URADIOLIB_DEBUG_SPI -UCFG_DEBUG -URADIOLIB_DEBUG_BASIC -URADIOLIB_DEBUG_PROTOCOL" fi } @@ -118,7 +134,7 @@ disable_debug_flags() { # build firmware for the provided pio env in $1 build_firmware() { # get env platform for post build actions - ENV_PLATFORM=($(get_platform_for_env $1)) + ENV_PLATFORM=$(get_platform_for_env "$1") # get git commit sha COMMIT_HASH=$(git rev-parse --short HEAD) @@ -127,7 +143,7 @@ build_firmware() { FIRMWARE_BUILD_DATE=$(date '+%d-%b-%Y') # get FIRMWARE_VERSION, which should be provided by the environment - if [ -z "$FIRMWARE_VERSION" ]; then + if [[ -z "${FIRMWARE_VERSION}" ]]; then echo "FIRMWARE_VERSION must be set in environment" exit 1 fi @@ -147,49 +163,59 @@ build_firmware() { disable_debug_flags # build firmware target - pio run -e $1 + pio run -e "$1" # build merge-bin for esp32 fresh install, copy .bins to out folder (e.g: Heltec_v3_room_server-v1.0.0-SHA.bin) - if [ "$ENV_PLATFORM" == "ESP32_PLATFORM" ]; then - pio run -t mergebin -e $1 - cp .pio/build/$1/firmware.bin out/${FIRMWARE_FILENAME}.bin 2>/dev/null || true - cp .pio/build/$1/firmware-merged.bin out/${FIRMWARE_FILENAME}-merged.bin 2>/dev/null || true + if [[ "${ENV_PLATFORM}" == "ESP32_PLATFORM" ]]; then + pio run -t mergebin -e "$1" + cp ".pio/build/$1/firmware.bin" "out/${FIRMWARE_FILENAME}.bin" 2>/dev/null || true + cp ".pio/build/$1/firmware-merged.bin" "out/${FIRMWARE_FILENAME}-merged.bin" 2>/dev/null || true fi # build .uf2 for nrf52 boards, copy .uf2 and .zip to out folder (e.g: RAK_4631_Repeater-v1.0.0-SHA.uf2) - if [ "$ENV_PLATFORM" == "NRF52_PLATFORM" ]; then - python3 bin/uf2conv/uf2conv.py .pio/build/$1/firmware.hex -c -o .pio/build/$1/firmware.uf2 -f 0xADA52840 - cp .pio/build/$1/firmware.uf2 out/${FIRMWARE_FILENAME}.uf2 2>/dev/null || true - cp .pio/build/$1/firmware.zip out/${FIRMWARE_FILENAME}.zip 2>/dev/null || true + if [[ "${ENV_PLATFORM}" == "NRF52_PLATFORM" ]]; then + python3 bin/uf2conv/uf2conv.py ".pio/build/$1/firmware.hex" -c -o ".pio/build/$1/firmware.uf2" -f 0xADA52840 + cp ".pio/build/$1/firmware.uf2" "out/${FIRMWARE_FILENAME}.uf2" 2>/dev/null || true + cp ".pio/build/$1/firmware.zip" "out/${FIRMWARE_FILENAME}.zip" 2>/dev/null || true fi # for stm32, copy .bin and .hex to out folder - if [ "$ENV_PLATFORM" == "STM32_PLATFORM" ]; then - cp .pio/build/$1/firmware.bin out/${FIRMWARE_FILENAME}.bin 2>/dev/null || true - cp .pio/build/$1/firmware.hex out/${FIRMWARE_FILENAME}.hex 2>/dev/null || true + if [[ "${ENV_PLATFORM}" == "STM32_PLATFORM" ]]; then + cp ".pio/build/$1/firmware.bin" "out/${FIRMWARE_FILENAME}.bin" 2>/dev/null || true + cp ".pio/build/$1/firmware.hex" "out/${FIRMWARE_FILENAME}.hex" 2>/dev/null || true fi # for rp2040, copy .bin and .uf2 to out folder - if [ "$ENV_PLATFORM" == "RP2040_PLATFORM" ]; then - cp .pio/build/$1/firmware.bin out/${FIRMWARE_FILENAME}.bin 2>/dev/null || true - cp .pio/build/$1/firmware.uf2 out/${FIRMWARE_FILENAME}.uf2 2>/dev/null || true + if [[ "${ENV_PLATFORM}" == "RP2040_PLATFORM" ]]; then + cp ".pio/build/$1/firmware.bin" "out/${FIRMWARE_FILENAME}.bin" 2>/dev/null || true + cp ".pio/build/$1/firmware.uf2" "out/${FIRMWARE_FILENAME}.uf2" 2>/dev/null || true fi } # firmwares containing $1 will be built build_all_firmwares_matching() { - envs=($(get_pio_envs_containing_string "$1")) + local env_list envs + env_list=$(get_pio_envs_containing_string "$1") || return $? + mapfile -t envs <<< "${env_list}" + if [[ ${#envs[@]} -gt 0 && -z "${envs[-1]}" ]]; then + unset 'envs[-1]' + fi for env in "${envs[@]}"; do - build_firmware $env + build_firmware "${env}" done } # firmwares ending with $1 will be built build_all_firmwares_by_suffix() { - envs=($(get_pio_envs_ending_with_string "$1")) + local env_list envs + env_list=$(get_pio_envs_ending_with_string "$1") || return $? + mapfile -t envs <<< "${env_list}" + if [[ ${#envs[@]} -gt 0 && -z "${envs[-1]}" ]]; then + unset 'envs[-1]' + fi for env in "${envs[@]}"; do - build_firmware $env + build_firmware "${env}" done } @@ -251,18 +277,18 @@ mkdir -p out # handle script args if [[ $1 == "build-firmware" ]]; then - TARGETS=${@:2} - if [ "$TARGETS" ]; then - for env in $TARGETS; do - build_firmware $env + TARGETS=("${@:2}") + if [[ -n "${TARGETS[*]}" ]]; then + for env in "${TARGETS[@]}"; do + build_firmware "${env}" done else echo "usage: $0 build-firmware " exit 1 fi elif [[ $1 == "build-matching-firmwares" ]]; then - if [ "$2" ]; then - build_all_firmwares_matching $2 + if [[ -n "$2" ]]; then + build_all_firmwares_matching "$2" else echo "usage: $0 build-matching-firmwares " exit 1