feat(freebsd): full FreeBSD 15.0 compatibility
Some checks failed
CI / Test (Linux) (push) Has been cancelled
CI / Test (Windows MSVC) (push) Has been cancelled
CI / Clippy (push) Has been cancelled
CI / Format (push) Has been cancelled

- board: detect cuaU* serial ports in fallback scanner, filter .init/.lock nodes
- board: fall through to OS scan when arduino-cli returns empty (serial-discovery
  uses unsupported Linux syscalls on FreeBSD)
- board: recognize cuaU* port names as USB in is_usb()
- upload.sh: fix silent exit under set -euo pipefail when vid_pid grep finds
  nothing (|| true on LOCAL_PORT and LOCAL_VID_PID greps)
- upload.sh: add cuaU to auto-detect port pattern
- doctor: detect dialer and operator group membership, offer --fix for both
- doctor: detect avr-size installed but not on PATH, offer --fix to add to
  shell rc file via detect_shell_rc()
- doctor: context-aware hardware section (suppress misleading messages when
  groups not yet applied)
- doctor: FreeBSD-specific troubleshooting hints throughout
- devices: suppress arduino-cli board detection section on FreeBSD (broken
  due to serial-discovery syscall issues)
- devices: always show USB hub tip on FreeBSD
- devices: FreeBSD-specific troubleshooting checklist with sequential numbering
  on all platforms
This commit is contained in:
Eric Ratliff
2026-03-15 17:02:32 -05:00
parent d86c79b9cb
commit bb4b2f4162
8 changed files with 528 additions and 125 deletions

View File

@@ -38,8 +38,29 @@ toml_get() {
}
toml_array() {
(grep "^$1 " "$CONFIG" 2>/dev/null || true) | head -1 \
| sed 's/.*\[//; s/\].*//; s/"//g; s/,/ /g' | tr -s ' '
# Handles both single-line: key = ["a", "b"]
# and multiline: key = [
# "a",
# "b",
# ]
awk -v key="$1" '
$0 ~ ("^" key " *= *\\[") {
collecting = 1
buf = $0
if (index($0, "]") > 0) { collecting = 0 }
}
collecting && NR > 1 { buf = buf " " $0 }
collecting && index($0, "]") > 0 && NR > 1 { collecting = 0 }
!collecting && buf != "" {
gsub(/.*\[/, "", buf)
gsub(/\].*/, "", buf)
gsub(/"/, "", buf)
gsub(/,/, " ", buf)
print buf
buf = ""
exit
}
' "$CONFIG" | tr -s " "
}
toml_section_get() {

View File

@@ -24,6 +24,17 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
TEST_DIR="$SCRIPT_DIR/test"
BUILD_DIR="$TEST_DIR/build"
# Portable CPU count -- BSD make requires a number after -j, GNU make does not
cpu_count() {
if command -v nproc &>/dev/null; then
nproc
elif command -v sysctl &>/dev/null; then
sysctl -n hw.ncpu
else
echo 4
fi
}
# Color output
if [[ -t 1 ]]; then
RED=$'\033[0;31m'; GRN=$'\033[0;32m'; CYN=$'\033[0;36m'
@@ -67,6 +78,8 @@ if ! command -v cmake &>/dev/null; then
echo " Install:" >&2
if [[ "$(uname)" == "Darwin" ]]; then
echo " brew install cmake" >&2
elif [[ "$(uname)" == "FreeBSD" ]]; then
echo " sudo pkg install cmake" >&2
else
echo " sudo apt install cmake (Debian/Ubuntu)" >&2
echo " sudo dnf install cmake (Fedora)" >&2
@@ -102,7 +115,7 @@ if [[ ! -f "$BUILD_DIR/CMakeCache.txt" ]]; then
fi
info "Building tests..."
cmake --build "$BUILD_DIR" --parallel 2>&1 | \
cmake --build "$BUILD_DIR" --parallel "$(cpu_count)" 2>&1 | \
while IFS= read -r line; do echo " $line"; done
echo ""

View File

@@ -17,6 +17,17 @@ set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
BUILD_DIR="$SCRIPT_DIR/build"
# Portable CPU count -- BSD make requires a number after -j, GNU make does not
cpu_count() {
if command -v nproc &>/dev/null; then
nproc
elif command -v sysctl &>/dev/null; then
sysctl -n hw.ncpu
else
echo 4
fi
}
# Color output
if [[ -t 1 ]]; then
RED=$'\033[0;31m'; GRN=$'\033[0;32m'; CYN=$'\033[0;36m'
@@ -40,7 +51,7 @@ for arg in "$@"; do
esac
done
command -v cmake &>/dev/null || die "cmake not found. Install: sudo apt install cmake"
command -v cmake &>/dev/null || die "cmake not found. Install: pkg install cmake (FreeBSD), apt install cmake (Debian/Ubuntu), dnf install cmake (Fedora)"
command -v g++ &>/dev/null || command -v clang++ &>/dev/null || die "No C++ compiler found"
command -v git &>/dev/null || die "git not found (needed to fetch Google Test)"
@@ -55,7 +66,7 @@ if [[ ! -f "$BUILD_DIR/CMakeCache.txt" ]]; then
fi
info "Building tests..."
cmake --build "$BUILD_DIR" --parallel
cmake --build "$BUILD_DIR" --parallel "$(cpu_count)"
echo ""
info "${BLD}Running tests...${RST}"

View File

@@ -39,8 +39,29 @@ toml_get() {
}
toml_array() {
(grep "^$1 " "$CONFIG" 2>/dev/null || true) | head -1 \
| sed 's/.*\[//; s/\].*//; s/"//g; s/,/ /g' | tr -s ' '
# Handles both single-line: key = ["a", "b"]
# and multiline: key = [
# "a",
# "b",
# ]
awk -v key="$1" '
$0 ~ ("^" key " *= *\\[") {
collecting = 1
buf = $0
if (index($0, "]") > 0) { collecting = 0 }
}
collecting && NR > 1 { buf = buf " " $0 }
collecting && index($0, "]") > 0 && NR > 1 { collecting = 0 }
!collecting && buf != "" {
gsub(/.*\[/, "", buf)
gsub(/\].*/, "", buf)
gsub(/"/, "", buf)
gsub(/,/, " ", buf)
print buf
buf = ""
exit
}
' "$CONFIG" | tr -s " "
}
toml_section_get() {
@@ -69,8 +90,8 @@ LOCAL_CONFIG="$SCRIPT_DIR/.anvil.local"
LOCAL_PORT=""
LOCAL_VID_PID=""
if [[ -f "$LOCAL_CONFIG" ]]; then
LOCAL_PORT="$(grep '^port ' "$LOCAL_CONFIG" 2>/dev/null | head -1 | sed 's/.*= *"\{0,1\}\([^"]*\)"\{0,1\}/\1/' | tr -d ' ')"
LOCAL_VID_PID="$(grep '^vid_pid ' "$LOCAL_CONFIG" 2>/dev/null | head -1 | sed 's/.*= *"\{0,1\}\([^"]*\)"\{0,1\}/\1/' | tr -d ' ')"
LOCAL_PORT="$(grep '^port ' "$LOCAL_CONFIG" 2>/dev/null | head -1 | sed 's/.*= *"\{0,1\}\([^"]*\)"\{0,1\}/\1/' | tr -d ' ' || true)"
LOCAL_VID_PID="$(grep '^vid_pid ' "$LOCAL_CONFIG" 2>/dev/null | head -1 | sed 's/.*= *"\{0,1\}\([^"]*\)"\{0,1\}/\1/' | tr -d ' ' || true)"
fi
SKETCH_DIR="$SCRIPT_DIR/$SKETCH_NAME"
BUILD_DIR="$SCRIPT_DIR/.build"
@@ -195,7 +216,7 @@ if [[ -z "$PORT" ]]; then
PORT=$(arduino-cli board list 2>/dev/null \
| grep -i "serial" \
| awk '{print $1}' \
| grep -E 'ttyUSB|ttyACM|COM' \
| grep -E 'ttyUSB|ttyACM|cuaU|COM' \
| head -1)
if [[ -z "$PORT" ]]; then