511 lines
16 KiB
Bash
511 lines
16 KiB
Bash
#!/bin/bash
|
|
#
|
|
# ./wolfssl-arduino.sh INSTALL
|
|
# export ARDUINO_ROOT=/home/$USER/Arduino/libraries
|
|
#
|
|
# ./wolfssl-arduino.sh INSTALL /mnt/c/Users/gojimmypi/Documents/Arduino/libraries
|
|
#
|
|
# usage:
|
|
#
|
|
# ./compile_all_examples.sh board_list.txt [FQBN]
|
|
#
|
|
# example: compile all FQBN items in board_list.txt
|
|
#
|
|
# ./compile_all_examples.sh board_list.txt
|
|
#
|
|
# example: compile just the teensy:avr:teensy40 board in board_list.txt
|
|
#
|
|
# ./compile_all_examples.sh board_list.txt teensy:avr:teensy40
|
|
#
|
|
# >>>>>>>>>>>>> EDIT WITH CAUTION <<<<<<<<<<<<<
|
|
#
|
|
# This script is pulled in by https://github.com/wolfSSL/wolfssl/blob/master/.github/workflows/arduino.yml
|
|
#
|
|
|
|
# Run shell check to ensure this a good script.
|
|
# Specify the executable shell checker you want to use:
|
|
MY_SHELLCHECK="shellcheck"
|
|
|
|
# Check if the executable is available in the PATH
|
|
if command -v "$MY_SHELLCHECK" >/dev/null 2>&1; then
|
|
# Run your command here
|
|
$MY_SHELLCHECK "$0" || exit 1
|
|
else
|
|
echo "$MY_SHELLCHECK is not installed. Please install it if changes to this script have been made."
|
|
exit 1
|
|
fi
|
|
|
|
set +e
|
|
|
|
# Configuration parameters
|
|
SHOW_DIR_CONTENTS=0
|
|
SHOW_USER_SETTINGS=0
|
|
SHOW_BOARD_LIST=0
|
|
SHOW_EXAMPLE_LIST=0
|
|
|
|
# need to reassign ARDUINO_ROOT in this run
|
|
ARDUINO_ROOT="$HOME/Arduino/libraries"
|
|
|
|
# Used for column alignment; e.g. len(wolfssl_client_dtls) + 2
|
|
MAX_FQBN_LEN=21
|
|
unset TARGET_FQBN
|
|
|
|
# default board list is board_list.txt, may be overridden
|
|
BOARD_LIST="./board_list.txt"
|
|
|
|
# Unicode in a UTF8 file
|
|
ICON_OK=$(printf "\xE2\x9C\x85")
|
|
ICON_WARN=$(printf "\xE2\x9A\xA0")
|
|
ICON_FAIL=$(printf "\xE2\x9D\x8C")
|
|
|
|
# Check if board list specified.
|
|
if [ $# -gt 0 ]; then
|
|
# First parameter may be alternate fqbn list
|
|
if [[ -f "$1" ]]; then
|
|
BOARD_LIST="$1"
|
|
echo "Using specified fqbn list file: $BOARD_LIST"
|
|
else
|
|
echo "Error: Parameter specified for board list file does not exist: $1"
|
|
exit 1
|
|
fi
|
|
else
|
|
echo "Usage:"
|
|
echo " $0 board_list.txt [FQBN]"
|
|
fi
|
|
|
|
if [ $# -gt 1 ]; then
|
|
TARGET_FQBN="$2"
|
|
echo "Looking for $TARGET_FQBN"
|
|
fi
|
|
|
|
# Internal variables
|
|
BOARD_CT=0
|
|
BOARD_COMPILE_CT=0
|
|
BOARD_SKIP_CT=0
|
|
BOARD_FAIL_CT=0
|
|
EXAMPLE_CT=0
|
|
THIS_FOUND_FLAG=0
|
|
|
|
# Assume success unless proven otherwise
|
|
SUCCESS="true"
|
|
|
|
# Some example names, re-initialized later
|
|
EXAMPLES=(wolfssl_client wolfssl_client_dtls server)
|
|
|
|
# associative array, where the keys are arbitrary strings
|
|
declare -A DISABLED # per FQBN: DISABLED["example-name"]=1
|
|
declare -A COMMENT # per FQBN: COMMENT["example-name"]="some comment"
|
|
declare -A VALID_EXAMPLES # set of valid example names
|
|
|
|
# Indexed arrays to hold results
|
|
declare -a SUMMARY_STATUS
|
|
declare -a SUMMARY_BOARD
|
|
declare -a SUMMARY_EXAMPLE
|
|
|
|
echo "Icon check:"
|
|
printf '--OK: %s; Warn: %s; Not OK: %s\n' "$ICON_OK" "$ICON_WARN" "$ICON_FAIL"
|
|
|
|
if [[ $SHOW_DIR_CONTENTS -ne 0 ]]; then
|
|
echo "********************************************************************************"
|
|
echo "Installed libraries:"
|
|
echo "********************************************************************************"
|
|
ls "$ARDUINO_ROOT" -al
|
|
|
|
echo "********************************************************************************"
|
|
echo "wolfssl:"
|
|
echo "********************************************************************************"
|
|
ls "$ARDUINO_ROOT/wolfssl" -al
|
|
|
|
echo "********************************************************************************"
|
|
echo "wolfssl/src:"
|
|
echo "********************************************************************************"
|
|
ls "$ARDUINO_ROOT/wolfssl/src/" -al
|
|
|
|
echo "********************************************************************************"
|
|
echo "********************************************************************************"
|
|
ls "$ARDUINO_ROOT/wolfssl/src/user_settings.h" -al
|
|
echo "********************************************************************************"
|
|
echo "********************************************************************************"
|
|
fi
|
|
if [[ $SHOW_USER_SETTINGS -ne 0 ]]; then
|
|
cat "$ARDUINO_ROOT/wolfssl/src/user_settings.h"
|
|
echo "********************************************************************************"
|
|
echo "********************************************************************************"
|
|
fi
|
|
if [[ $SHOW_BOARD_LIST -ne 0 ]]; then
|
|
echo "Begin compile for $BOARD_LIST"
|
|
cat "$BOARD_LIST"
|
|
echo "--------------------------------------------------------------------------------"
|
|
fi
|
|
if [[ $SHOW_EXAMPLE_LIST -ne 0 ]]; then
|
|
echo "Examples found:"
|
|
find ./ -mindepth 1 -maxdepth 1 -type d
|
|
echo "********************************************************************************"
|
|
echo "********************************************************************************"
|
|
fi
|
|
|
|
|
|
#FAIL_LIST=() # items like "fqbn example exitcode"
|
|
#OVERALL_OK=1 # flip to 0 on first failure
|
|
|
|
# -------- helper functions --------
|
|
|
|
strip_cr() {
|
|
if [[ $1 == *$'\r' ]]; then
|
|
printf '%s' "${1%$'\r'}"
|
|
else
|
|
printf '%s' "$1"
|
|
fi
|
|
}
|
|
|
|
is_skip() {
|
|
# skip blank lines or lines that start with # (leading spaces allowed)
|
|
# [[ -z $1 || $1 =~ ^[[:space:]]*# ]]
|
|
local line="$1"
|
|
LINE_VALUE=""
|
|
LINE_COMMENT=""
|
|
|
|
# Trim leading/trailing spaces from the whole line
|
|
line="${line#"${line%%[![:space:]]*}"}" # trim leading
|
|
line="${line%"${line##*[![:space:]]}"}" # trim trailing
|
|
|
|
# Blank line?
|
|
if [[ -z $line ]]; then
|
|
# echo "is_skip early return 0"
|
|
return 0
|
|
fi
|
|
|
|
# Split at first '#'
|
|
LINE_VALUE="${line%%#*}"
|
|
LINE_COMMENT=""
|
|
if [[ $line == *"#"* ]]; then
|
|
LINE_COMMENT="${line#*#}"
|
|
fi
|
|
|
|
# Trim each part
|
|
LINE_VALUE="${LINE_VALUE%"${LINE_VALUE##*[![:space:]]}"}"
|
|
LINE_VALUE="${LINE_VALUE#"${LINE_VALUE%%[![:space:]]*}"}"
|
|
# echo "LINE_VALUE=$LINE_VALUE"
|
|
|
|
LINE_COMMENT="${LINE_COMMENT%"${LINE_COMMENT##*[![:space:]]}"}"
|
|
LINE_COMMENT="${LINE_COMMENT#"${LINE_COMMENT%%[![:space:]]*}"}"
|
|
# echo "LINE_COMMENT=$LINE_COMMENT"
|
|
|
|
# Pure comment line (no value)
|
|
if [[ -z $LINE_VALUE ]]; then
|
|
# echo "is_skip return 0"
|
|
return 0
|
|
fi
|
|
|
|
# Not a skip line
|
|
# echo "is_skip return 1"
|
|
return 1
|
|
} #is_skip
|
|
|
|
norm_key() {
|
|
# lowercase only, preserve underscores and dashes
|
|
printf '%s' "${1,,}"
|
|
} # norm_key
|
|
|
|
discover_examples() {
|
|
EXAMPLES=()
|
|
EXAMPLE_CT=0
|
|
|
|
echo "Discovering examples in current directory $(pwd)"
|
|
# Read NUL-separated paths to handle spaces safely
|
|
while IFS= read -r -d '' d; do
|
|
# strip leading "./" so we keep just the dir name
|
|
local name="${d#./}"
|
|
EXAMPLES+=("$name")
|
|
echo "Found example directory: $name"
|
|
((EXAMPLE_CT++))
|
|
done < <(find ./ -mindepth 1 -maxdepth 1 -type d -print0 | sort -z)
|
|
|
|
# Optional: filter out hidden dirs or known exclusions
|
|
# local keep=()
|
|
# for e in "${EXAMPLES[@]}"; do
|
|
# [[ $e == .* ]] && continue # skip hidden like .git
|
|
# [[ $e == build || $e == out ]] && continue
|
|
# keep+=("$e")
|
|
# done
|
|
# EXAMPLES=("${keep[@]}")
|
|
} # discover_examples
|
|
|
|
build_valid_examples() {
|
|
local e key
|
|
for e in "${EXAMPLES[@]}"; do
|
|
key=$(norm_key "$e")
|
|
VALID_EXAMPLES["$key"]=1
|
|
done
|
|
} # build_valid_examples
|
|
|
|
warn_unknown_flag() {
|
|
# $1 is raw flag text after --no-
|
|
# $2 is current FQBN for context
|
|
printf '%s WARN: Unknown example in flag "--no-%s" under FQBN "%s" (ignored)\n' "$ICON_WARN" "$1" "$2" >&2
|
|
} # warn_unknown_flag
|
|
|
|
set_flag() {
|
|
# flag looks like --no-name
|
|
local raw=${1#--no-}
|
|
local key
|
|
key=$(norm_key "$raw")
|
|
# echo "this key = $key"
|
|
if [[ -n ${VALID_EXAMPLES[$key]+x} ]]; then
|
|
DISABLED["$key"]=1
|
|
COMMENT["$key"]="$2"
|
|
else
|
|
warn_unknown_flag "$raw" "$BOARD"
|
|
fi
|
|
} # set_flag
|
|
|
|
clear_flags() {
|
|
local k
|
|
for k in "${!DISABLED[@]}"; do
|
|
unset -v "DISABLED[$k]"
|
|
unset -v "COMMENT[$k]"
|
|
done
|
|
THIS_FOUND_FLAG=0
|
|
} # clear_flags
|
|
|
|
is_disabled() {
|
|
# return 0 if disabled for this FQBN, else 1
|
|
local key
|
|
key=$(norm_key "$1")
|
|
# echo "checking $key"
|
|
if [[ -n ${DISABLED[$key]+x} ]]; then
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
} # is_disabled
|
|
|
|
comment_for() {
|
|
local key
|
|
key=$(norm_key "$1")
|
|
printf '%s' "${COMMENT[$key]}"
|
|
} # comment_for
|
|
|
|
has_comment() {
|
|
local key value
|
|
key=$(norm_key "$1")
|
|
|
|
# Key must exist
|
|
if [[ ! -v COMMENT[$key] ]]; then
|
|
return 1
|
|
fi
|
|
|
|
value=${COMMENT[$key]}
|
|
|
|
# Remove all whitespace for the check
|
|
local trimmed="${value//[[:space:]]/}"
|
|
|
|
if [[ -n $trimmed ]]; then
|
|
return 0 # true: (not and error) has a non-blank comment
|
|
else
|
|
return 1 # false: (error) empty or whitespace only
|
|
fi
|
|
} # has_comment
|
|
|
|
# Optional for each EXAMPLE / BOARD
|
|
#
|
|
#while IFS= read -r EXAMPLE; do
|
|
# echo "Checking example: for $EXAMPLE"
|
|
# while IFS= read -r BOARD; do
|
|
# # Clean board names,
|
|
# BOARD="${BOARD//$'\r'/}" # Remove carriage returns from the line
|
|
#
|
|
# # Skip any non-board fqbn lines
|
|
# if [[ "$BOARD" =~ ^[[:space:]]*$ ]]; then
|
|
# continue #skip blank lines
|
|
# fi#
|
|
#
|
|
# if [[ "$BOARD" == \#* || "$BOARD" == " "*#* ]]; then
|
|
# continue # Skip comments and lines starting with space + #
|
|
# fi
|
|
#
|
|
# echo "Checking $EXAMPLE for $BOARD"
|
|
|
|
|
|
# *************************************************************************************
|
|
#
|
|
discover_examples
|
|
build_valid_examples
|
|
# *************************************************************************************
|
|
|
|
peek=
|
|
echo "Here we go!"
|
|
|
|
#*************************************************************************************
|
|
# Read fqbn BOARD from $BOARD_LIST (typically ./board_list.txt)
|
|
#*************************************************************************************
|
|
while :; do
|
|
# read next FQBN line, some next lines might be hints to disable compile: --no-[n]
|
|
if [[ -n $peek ]]; then
|
|
line=$peek
|
|
peek=
|
|
else
|
|
IFS= read -r line || break
|
|
fi
|
|
|
|
line=$(strip_cr "$line")
|
|
if [[ "$line" == "exit" ]]; then
|
|
echo "Encountered exit in $BOARD_LIST; aborting"
|
|
break
|
|
fi
|
|
|
|
|
|
if is_skip "$line"; then
|
|
# echo "This line skipped: $line"
|
|
continue
|
|
fi
|
|
|
|
BOARD="${line//$'\r'/}" # Remove carriage returns from the line
|
|
|
|
if [[ -z ${TARGET_FQBN:-} || "$TARGET_FQBN" == "$BOARD" ]]; then
|
|
echo ""
|
|
echo "*************************************************************************************"
|
|
echo "Testing board: $BOARD"
|
|
echo "*************************************************************************************"
|
|
echo "Checking flags..."
|
|
fi
|
|
|
|
clear_flags
|
|
|
|
# collect any --no- lines under this FQBN
|
|
while IFS= read -r next; do
|
|
next=$(strip_cr "$next")
|
|
|
|
# echo "--calling is_skip with next=$next"
|
|
if is_skip "$next"; then
|
|
# echo "--skip! $next"
|
|
continue
|
|
fi
|
|
|
|
# echo " checking [$next] is like --no"
|
|
if [[ $LINE_VALUE == --no-* ]]; then
|
|
if [[ -z ${TARGET_FQBN:-} || "$TARGET_FQBN" == "$BOARD" ]]; then
|
|
# Only print if we are compiling this FQBN
|
|
if [[ -n "$LINE_COMMENT" ]]; then
|
|
echo "$LINE_VALUE: $LINE_COMMENT"
|
|
else
|
|
echo "$LINE_VALUE: (No comment provided; Consider adding reason in $BOARD_LIST)"
|
|
fi
|
|
fi
|
|
set_flag "$LINE_VALUE" "$LINE_COMMENT"
|
|
THIS_FOUND_FLAG=1
|
|
continue
|
|
# else
|
|
# not a line stat starts with --no
|
|
fi
|
|
|
|
peek=$next
|
|
break
|
|
done
|
|
|
|
# echo "Flags done..."
|
|
|
|
# Typically at the end, or when multiple blank lines encountered
|
|
# if [[ -z $next && -z $peek ]]; then
|
|
# echo "Continue, skipping blank line..."
|
|
# continue
|
|
# fi
|
|
|
|
|
|
# Only print divider if we are testing multiple FQBN, not just the specified parameter
|
|
if [[ -z ${TARGET_FQBN:-} || "$TARGET_FQBN" == "$BOARD" ]]; then
|
|
if [[ $THIS_FOUND_FLAG -ne 0 ]]; then
|
|
echo "-------------------------------------------------------------------------------------"
|
|
fi
|
|
echo "Begin Board: $BOARD"
|
|
|
|
echo "-------------------------------------------------------------------------------------"
|
|
((BOARD_CT++))
|
|
THIS_EXAMPLE_CT=0
|
|
for EXAMPLE in "${EXAMPLES[@]}"; do
|
|
start_time=$(date +%s) # record start time (epoch seconds)
|
|
echo "Checking $EXAMPLE for $BOARD"
|
|
if is_disabled "$EXAMPLE"; then
|
|
echo "Skipped"
|
|
((BOARD_SKIP_CT++))
|
|
|
|
if has_comment "$EXAMPLE"; then
|
|
this_comment=$(comment_for "$EXAMPLE")
|
|
echo "Comment: $this_comment"
|
|
else
|
|
echo "No comment in $BOARD_LIST for disable reason on $EXAMPLE example."
|
|
fi
|
|
else
|
|
# If otherwise not excluded, compile this $EXAMPLE for this $BOARD
|
|
((BOARD_COMPILE_CT++))
|
|
echo "arduino-cli compile --fqbn \"$BOARD\" \"$EXAMPLE\""
|
|
arduino-cli compile --fqbn "$BOARD" "$EXAMPLE"
|
|
EXIT_CODE=$?
|
|
if [ $EXIT_CODE -ne 0 ]; then
|
|
echo "$ICON_FAIL Compilation failed for $EXAMPLE on $BOARD (Exit code: $EXIT_CODE)"
|
|
((BOARD_FAIL_CT++))
|
|
SUCCESS=false
|
|
SUMMARY_STATUS+=("$ICON_FAIL")
|
|
else
|
|
echo "$ICON_OK Compilation succeeded for $EXAMPLE on $BOARD"
|
|
SUMMARY_STATUS+=("$ICON_OK")
|
|
fi # exit code
|
|
|
|
SUMMARY_BOARD+=("$BOARD")
|
|
SUMMARY_EXAMPLE+=("$EXAMPLE")
|
|
fi # is_disabled check
|
|
|
|
end_time=$(date +%s) # record end time
|
|
elapsed=$(( end_time - start_time ))
|
|
echo "Block took ${elapsed} seconds"
|
|
|
|
if [[ $THIS_EXAMPLE_CT -lt $EXAMPLE_CT ]]; then
|
|
echo "-------------------------------------------------------------------------------------"
|
|
fi
|
|
((THIS_EXAMPLE_CT++))
|
|
done # for each example
|
|
else
|
|
echo "Skipped $BOARD, looking for only $TARGET_FQBN"
|
|
fi
|
|
done < "$BOARD_LIST" # for each BOARD
|
|
|
|
|
|
# Optional for each EXAMPLE / BOARD
|
|
#
|
|
# done < board_list.txt # for each BOARD
|
|
#done < <(find ./sketches -mindepth 1 -maxdepth 1 -type d) # for each EXAMPLE directory name
|
|
|
|
echo "Done!"
|
|
echo "-------------------------------------------------------------------------------------"
|
|
echo "Boards found: $BOARD_CT"
|
|
echo "Examples found: $EXAMPLE_CT"
|
|
echo "Board Examples: $(( ${BOARD_CT:-0} * ${EXAMPLE_CT:-0} ))"
|
|
echo "Compilation Summary:"
|
|
printf "%-4s %-*s %-*s\n" "STAT" "$MAX_FQBN_LEN" "EXAMPLE" "$MAX_FQBN_LEN" "BOARD"
|
|
printf "%-4s %-*s %-*s\n" "----" "$MAX_FQBN_LEN" "-------" "$MAX_FQBN_LEN" "-----"
|
|
|
|
for i in "${!SUMMARY_STATUS[@]}"; do
|
|
printf "%-4s %-*s %-*s\n" \
|
|
"${SUMMARY_STATUS[$i]}" \
|
|
"$MAX_FQBN_LEN" "${SUMMARY_EXAMPLE[$i]}" \
|
|
"$MAX_FQBN_LEN" "${SUMMARY_BOARD[$i]}"
|
|
done
|
|
|
|
if [ "$SUCCESS" = true ]; then
|
|
echo "$ICON_OK All $BOARD_COMPILE_CT sketches compiled successfully! $BOARD_SKIP_CT board examples skipped (see $BOARD_LIST)."
|
|
else
|
|
case "$BOARD_FAIL_CT" in
|
|
0)
|
|
echo "$ICON_FAIL no sketches failed to compile. Other error?"
|
|
;;
|
|
1)
|
|
echo "$ICON_FAIL 1 sketch failed to compile."
|
|
;;
|
|
*)
|
|
echo "$ICON_FAIL $BOARD_FAIL_CT sketches failed to compile."
|
|
;;
|
|
esac
|
|
|
|
exit 1
|
|
fi
|