206 lines
8.6 KiB
Bash
Executable File
206 lines
8.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# run_debugtest.sh — Launch a small MARTe2 app under DebugService + the web debugger
|
|
#
|
|
# Usage:
|
|
# ./run_debugtest.sh [OPTIONS]
|
|
#
|
|
# Options:
|
|
# -m <MARTe2_DIR> Override MARTe2 installation dir (default: $MARTe2_DIR)
|
|
# -c <MARTe2_Components_DIR> Override MARTe2-components dir (default: $MARTe2_Components_DIR)
|
|
# -b <BUILD_TARGET> Build target (default: x86-linux)
|
|
# -f <CFG> MARTe2 config (default: Test/Configurations/debug_test.cfg)
|
|
# -t <STATE> RealTimeState to start in (default: State1)
|
|
# -p <PORT> Debugger web UI port (default: 7777)
|
|
# -S Safe mode: do NOT allow FORCE/PAUSE/RESUME/STEP/BREAK
|
|
# from the browser (they are enabled by default here,
|
|
# since exercising them is the point of this script)
|
|
# -s Skip building — run with whatever is already built
|
|
# -h Show this help
|
|
#
|
|
# What it runs:
|
|
# MARTeApp.ex with debug_test.cfg — three RT threads over a LinuxTimer:
|
|
# GAM1 (1 kHz counter/time), GAM2 (1 Hz + a ConstantGAM float),
|
|
# GAM3 (100-sample block), plus a +DebugService object.
|
|
# Client/debugger (Go) — serves the browser debugger; the page connects to the
|
|
# app's control port itself, so the app can be restarted underneath it.
|
|
#
|
|
# Ports used:
|
|
# 8080/tcp DebugService control (text commands)
|
|
# 8081/udp DebugService trace telemetry
|
|
# 8082/tcp TcpLogger (auto-injected by DebugService)
|
|
# 7777/tcp Debugger web UI (default, override with -p)
|
|
# The three DebugService ports come from the config file, not from this script.
|
|
#
|
|
# Environment:
|
|
# MARTe2_DIR must be set (or passed via -m)
|
|
# MARTe2_Components_DIR must be set (or passed via -c)
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
BUILD_TARGET="${TARGET:-x86-linux}"
|
|
MARTe_CFG="${SCRIPT_DIR}/Test/Configurations/debug_test.cfg"
|
|
MARTe_STATE="State1"
|
|
UI_PORT=7777
|
|
DANGEROUS=1
|
|
SKIP_BUILD=0
|
|
|
|
# ── Parse arguments ───────────────────────────────────────────────────────────
|
|
while getopts "m:c:b:f:t:p:Ssh" opt; do
|
|
case "$opt" in
|
|
m) MARTe2_DIR="$OPTARG" ;;
|
|
c) MARTe2_Components_DIR="$OPTARG" ;;
|
|
b) BUILD_TARGET="$OPTARG" ;;
|
|
f) MARTe_CFG="$OPTARG" ;;
|
|
t) MARTe_STATE="$OPTARG" ;;
|
|
p) UI_PORT="$OPTARG" ;;
|
|
S) DANGEROUS=0 ;;
|
|
s) SKIP_BUILD=1 ;;
|
|
h)
|
|
sed -n '2,40p' "$0" | grep '^#' | sed 's/^# \?//'
|
|
exit 0
|
|
;;
|
|
*) echo "Unknown option: -$OPTARG" >&2; exit 1 ;;
|
|
esac
|
|
done
|
|
|
|
# ── Validate environment ──────────────────────────────────────────────────────
|
|
if [[ -z "${MARTe2_DIR:-}" ]]; then
|
|
echo "ERROR: MARTe2_DIR is not set. Source env.sh first or pass -m <dir>."
|
|
echo " source ${SCRIPT_DIR}/env.sh"
|
|
exit 1
|
|
fi
|
|
if [[ -z "${MARTe2_Components_DIR:-}" ]]; then
|
|
echo "ERROR: MARTe2_Components_DIR is not set. Source env.sh first or pass -c <dir>."
|
|
exit 1
|
|
fi
|
|
if [[ ! -f "$MARTe_CFG" ]]; then
|
|
echo "ERROR: MARTe2 config not found: ${MARTe_CFG}"
|
|
exit 1
|
|
fi
|
|
|
|
BUILD_DIR="${SCRIPT_DIR}/Build/${BUILD_TARGET}"
|
|
COMP_DIR="${MARTe2_Components_DIR}/Build/${BUILD_TARGET}/Components"
|
|
DEBUGGER_DIR="${SCRIPT_DIR}/Client/debugger"
|
|
DEBUGGER_BIN="${DEBUGGER_DIR}/marte2debugger"
|
|
|
|
MARTE2_BIN="${MARTe2_DIR}/Build/${BUILD_TARGET}/App/MARTeApp.ex"
|
|
if [[ ! -x "$MARTE2_BIN" ]]; then
|
|
echo "ERROR: MARTeApp.ex not found at ${MARTe2_DIR}/Build/${BUILD_TARGET}/App/"
|
|
exit 1
|
|
fi
|
|
|
|
# The DebugService ports live in the config, so read them back rather than
|
|
# printing numbers this script does not actually control.
|
|
cfg_port() {
|
|
grep -E "^[[:space:]]*$1[[:space:]]*=" "$MARTe_CFG" \
|
|
| head -1 | tr -d ' \t' | cut -d= -f2 || true
|
|
}
|
|
CTRL_PORT="$(cfg_port ControlPort)"; CTRL_PORT="${CTRL_PORT:-8080}"
|
|
UDP_PORT="$(cfg_port UdpPort)"; UDP_PORT="${UDP_PORT:-8081}"
|
|
LOG_PORT="$(cfg_port LogPort)"; LOG_PORT="${LOG_PORT:-8082}"
|
|
|
|
# ── Build ─────────────────────────────────────────────────────────────────────
|
|
if [[ "$SKIP_BUILD" -eq 0 ]]; then
|
|
echo "==> Building MARTe2 components (TARGET=${BUILD_TARGET})..."
|
|
make -C "${SCRIPT_DIR}" -f Makefile.gcc core TARGET="${BUILD_TARGET}" 2>&1 | tail -5
|
|
|
|
echo "==> Building debugger client..."
|
|
(cd "${DEBUGGER_DIR}" && go build -o marte2debugger .)
|
|
|
|
echo "==> Build done."
|
|
fi
|
|
|
|
if [[ ! -x "$DEBUGGER_BIN" ]]; then
|
|
echo "ERROR: debugger client not found: ${DEBUGGER_BIN}"
|
|
echo " Build it with: cd Client/debugger && go build -o marte2debugger ."
|
|
exit 1
|
|
fi
|
|
|
|
# ── Library path ──────────────────────────────────────────────────────────────
|
|
# DebugService pulls in TCPLogger and UDPStream; everything the config names
|
|
# beyond MARTe2 core (LinuxTimer, RealTimeThreadSynchronisation,
|
|
# LoggerDataSource, IOGAM, ConstantGAM) is dlopen'd from MARTe2-components.
|
|
export LD_LIBRARY_PATH="\
|
|
${MARTe2_DIR}/Build/${BUILD_TARGET}/Core:\
|
|
${BUILD_DIR}/Components/Interfaces/DebugService:\
|
|
${BUILD_DIR}/Components/Interfaces/TCPLogger:\
|
|
${BUILD_DIR}/Components/Interfaces/UDPStream:\
|
|
${COMP_DIR}/DataSources/LinuxTimer:\
|
|
${COMP_DIR}/DataSources/RealTimeThreadSynchronisation:\
|
|
${COMP_DIR}/DataSources/LoggerDataSource:\
|
|
${COMP_DIR}/GAMs/IOGAM:\
|
|
${COMP_DIR}/GAMs/ConstantGAM:\
|
|
${LD_LIBRARY_PATH:-}"
|
|
|
|
# ── Cleanup handler ───────────────────────────────────────────────────────────
|
|
MARTE_PID=""
|
|
UI_PID=""
|
|
|
|
cleanup() {
|
|
echo ""
|
|
echo "==> Shutting down..."
|
|
[[ -n "$UI_PID" ]] && kill "$UI_PID" 2>/dev/null || true
|
|
[[ -n "$MARTE_PID" ]] && kill "$MARTE_PID" 2>/dev/null || true
|
|
wait "$UI_PID" 2>/dev/null || true
|
|
wait "$MARTE_PID" 2>/dev/null || true
|
|
echo "==> Done."
|
|
}
|
|
trap cleanup EXIT INT TERM
|
|
|
|
# ── Launch MARTe2 ─────────────────────────────────────────────────────────────
|
|
echo ""
|
|
echo "==> Launching MARTe2 under DebugService..."
|
|
echo " Binary : ${MARTE2_BIN}"
|
|
echo " Config : ${MARTe_CFG}"
|
|
echo " State : ${MARTe_STATE}"
|
|
echo ""
|
|
|
|
"${MARTE2_BIN}" \
|
|
-l RealTimeLoader \
|
|
-f "${MARTe_CFG}" \
|
|
-s "${MARTe_STATE}" &
|
|
MARTE_PID="$!"
|
|
|
|
# Give the app time to reach the state and bind the DebugService control port.
|
|
sleep 1
|
|
if ! kill -0 "$MARTE_PID" 2>/dev/null; then
|
|
echo "ERROR: MARTe2 exited during startup — see the log above."
|
|
exit 1
|
|
fi
|
|
|
|
# ── Launch the debugger web client ────────────────────────────────────────────
|
|
echo "==> Launching debugger client (:${UI_PORT})..."
|
|
DANGEROUS_FLAG=()
|
|
if [[ "$DANGEROUS" -eq 1 ]]; then
|
|
DANGEROUS_FLAG=(-enable-dangerous-commands)
|
|
fi
|
|
|
|
"${DEBUGGER_BIN}" -addr ":${UI_PORT}" "${DANGEROUS_FLAG[@]}" &
|
|
UI_PID="$!"
|
|
|
|
sleep 0.5
|
|
|
|
# ── Status ────────────────────────────────────────────────────────────────────
|
|
echo ""
|
|
echo " MARTe2 PID : ${MARTE_PID}"
|
|
echo " Debugger PID : ${UI_PID}"
|
|
echo ""
|
|
echo " Debugger UI : http://localhost:${UI_PORT}/"
|
|
echo " DebugService : control tcp/${CTRL_PORT}, trace udp/${UDP_PORT}, log tcp/${LOG_PORT}"
|
|
if [[ "$DANGEROUS" -eq 1 ]]; then
|
|
echo " FORCE/PAUSE/RESUME/STEP/BREAK: enabled (pass -S to disable)"
|
|
else
|
|
echo " FORCE/PAUSE/RESUME/STEP/BREAK: disabled (-S)"
|
|
fi
|
|
echo ""
|
|
echo " In the browser, press Connect (defaults to 127.0.0.1:${CTRL_PORT}),"
|
|
echo " then Discover to list the app's GAMs and signals."
|
|
echo ""
|
|
echo " Press Ctrl-C to stop both processes."
|
|
echo ""
|
|
|
|
# ── Wait until either child exits ─────────────────────────────────────────────
|
|
wait -n "${MARTE_PID}" "${UI_PID}" 2>/dev/null || true
|
|
echo "==> A process exited — stopping the other."
|