Sprinter: добавить отладку C-исходников и интеграцию VS Code
This commit is contained in:
+65
-10
@@ -65,6 +65,8 @@
|
||||
# --max-allocs N SDCC --max-allocs-per-node (default: 100000 — smaller/
|
||||
# faster code at the cost of compile time; pass a lower
|
||||
# value, e.g. SDCC's own default 3000, to compile faster).
|
||||
# --src-debug карта C/asm для всех пользовательских модулей
|
||||
# --src-debug-file FILE карта выбранного TU (повторяемый, вместо --src-debug)
|
||||
# --debug enable runtime diagnostics — defines DEBUG_RT for both
|
||||
# sdcc (-DDEBUG_RT) and the crt0 assembly (prepended
|
||||
# `DEBUG_RT = 1`). Exposes runtime introspection symbols
|
||||
@@ -81,6 +83,18 @@
|
||||
|
||||
set -eo pipefail
|
||||
|
||||
# Можно выбрать интерпретатор без личного пути в репозитории.
|
||||
SPRINTER_PYTHON="${SPRINTER_PYTHON:-python3}"
|
||||
|
||||
# Отладочная сборка публикуется транзакционно отдельным драйвером.
|
||||
if [[ "${SPRINTER_SDBG_ACTIVE:-}" != 1 ]]; then
|
||||
for arg in "$@"; do
|
||||
if [[ "$arg" == --src-debug || "$arg" == --src-debug-file ]]; then
|
||||
exec "$SPRINTER_PYTHON" "$(dirname "$0")/../toolchain/sdbg_driver.py" "$0" "$@"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# ------- Locate the toolchain ------------------------------------------------
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
PROJ_ROOT="$( cd "$SCRIPT_DIR/.." && pwd )"
|
||||
@@ -109,6 +123,8 @@ LOAD_ADDR=""
|
||||
ENTRY_ADDR=""
|
||||
STACK_ADDR="0xBFFE"
|
||||
STACK_SIZE="" # if set, used to compute HEAP_TOP = STACK_ADDR + 1 - STACK_SIZE
|
||||
SRC_DEBUG=0
|
||||
SRC_DEBUG_FILES=()
|
||||
DEBUG_RT=0 # if 1, prepend `DEBUG_RT = 1` to crt0 + pass -DDEBUG_RT to sdcc
|
||||
VERBOSE=0
|
||||
USER_INCS=()
|
||||
@@ -135,6 +151,7 @@ SAFE_LIBS=0 # if 1, prefer *_safe.lib variants (fallback to standard)
|
||||
# ------- Parse args ----------------------------------------------------------
|
||||
usage() {
|
||||
sed -n '3,28p' "$0" | sed 's/^# \{0,1\}//'
|
||||
echo ' --src-debug / --src-debug-file FILE: карта исходников C и asm'
|
||||
exit "${1:-0}"
|
||||
}
|
||||
|
||||
@@ -166,6 +183,10 @@ while [[ $# -gt 0 ]]; do
|
||||
--mkexe) MKEXE_EXTRA+=("$2"); shift 2;;
|
||||
--max-allocs) MAX_ALLOCS="$2"; shift 2;;
|
||||
--gfx) GFX_MODE="$2"; shift 2;;
|
||||
--src-debug) SRC_DEBUG=1; shift;;
|
||||
--src-debug-file)
|
||||
[[ $# -ge 2 ]] || { echo "--src-debug-file требует FILE" >&2; exit 1; }
|
||||
SRC_DEBUG_FILES+=("$2"); shift 2;;
|
||||
--debug) DEBUG_RT=1; shift;;
|
||||
--safe) SAFE_LIBS=1; shift;;
|
||||
-v) VERBOSE=1; shift;;
|
||||
@@ -415,14 +436,44 @@ else
|
||||
fi
|
||||
run "$SDASZ80" -o "$HEAP_TOP_REL" "$HEAP_TOP_SRC"
|
||||
|
||||
# Единый путь компиляции выбранных C-модулей с картой исходников.
|
||||
compile_c() {
|
||||
local src="$1" rel="$2" selected=$SRC_DEBUG candidate
|
||||
shift 2
|
||||
for candidate in "${SRC_DEBUG_FILES[@]}"; do
|
||||
[[ "$src" -ef "$candidate" ]] && selected=1
|
||||
done
|
||||
if [[ $selected -eq 1 ]]; then
|
||||
run "$SPRINTER_PYTHON" "$PROJ_ROOT/toolchain/sdbg_build.py" compile \
|
||||
--sdcc "$SDCC" --assembler "$SDASZ80" --source "$src" --output "$rel" \
|
||||
-- "${CC_FLAGS[@]}" "$@"
|
||||
elif [[ "${SPRINTER_SDBG_ACTIVE:-}" == 1 ]]; then
|
||||
run "$SPRINTER_PYTHON" "$PROJ_ROOT/toolchain/sdbg_build.py" compile --plain \
|
||||
--sdcc "$SDCC" --assembler "$SDASZ80" --source "$src" --output "$rel" \
|
||||
-- "${CC_FLAGS[@]}" "$@"
|
||||
else
|
||||
run "$SDCC" "${CC_FLAGS[@]}" "$@" -c -o "$rel" "$src"
|
||||
fi
|
||||
}
|
||||
|
||||
# Уникальные имена объектов в debug-пакете допускают одинаковые basename.
|
||||
object_path() {
|
||||
local prefix="$1" src="$2"
|
||||
if [[ "${SPRINTER_SDBG_ACTIVE:-}" == 1 ]]; then
|
||||
"$SPRINTER_PYTHON" -c 'import hashlib, pathlib, sys; p=pathlib.Path(sys.argv[3]); print(sys.argv[1]+"/"+sys.argv[2]+p.stem+"_"+hashlib.sha256(str(p.resolve()).encode()).hexdigest()[:12]+".rel")' "$WORK" "$prefix" "$src"
|
||||
else
|
||||
echo "$WORK/$prefix$(basename "$src" .c).rel"
|
||||
fi
|
||||
}
|
||||
|
||||
# 2. user sources → .rel (HOME)
|
||||
USER_RELS=()
|
||||
CC_FLAGS=(-mz80 --no-std-crt0 --std-c99 --opt-code-size -I "$INC_DIR" -I "$BGI_INC_DIR" "${USER_INCS[@]}" "${USER_DEFS[@]}")
|
||||
[[ $DEBUG_RT -eq 1 ]] && CC_FLAGS+=(-DDEBUG_RT)
|
||||
[[ -n "$MAX_ALLOCS" ]] && CC_FLAGS+=(--max-allocs-per-node "$MAX_ALLOCS")
|
||||
for src in "${SOURCES[@]}"; do
|
||||
rel="$WORK/$(basename "$src" .c).rel"
|
||||
run "$SDCC" "${CC_FLAGS[@]}" -c -o "$rel" "$src"
|
||||
rel=$(object_path "" "$src")
|
||||
compile_c "$src" "$rel"
|
||||
USER_RELS+=("$rel")
|
||||
done
|
||||
|
||||
@@ -431,9 +482,8 @@ done
|
||||
# остаются в обычном _DATA (W2). Прямые вызовы, без трамплинов.
|
||||
if [[ ${#W3_SPECS[@]} -gt 0 ]]; then
|
||||
for src in "${W3_SPECS[@]}"; do
|
||||
rel="$WORK/w3_$(basename "$src" .c).rel"
|
||||
run "$SDCC" "${CC_FLAGS[@]}" --codeseg W3CODE --constseg W3CODE \
|
||||
-c -o "$rel" "$src"
|
||||
rel=$(object_path "w3_" "$src")
|
||||
compile_c "$src" "$rel" --codeseg W3CODE --constseg W3CODE
|
||||
W3_RELS+=("$rel")
|
||||
done
|
||||
W3_LD_FLAGS+=("-Wl-b_W3CODE=0xC000")
|
||||
@@ -469,7 +519,7 @@ if [[ "$CRT0_TYPE" == "banked" ]]; then
|
||||
for spec in "${BANK_SPECS[@]}"; do
|
||||
bank_n="${spec%%=*}"
|
||||
bank_src="${spec#*=}"
|
||||
rel="$WORK/bank${bank_n}_$(basename "$bank_src" .c).rel"
|
||||
rel=$(object_path "bank${bank_n}_" "$bank_src")
|
||||
# По умолчанию --dataseg НЕ задаём: писучие данные банкового
|
||||
# модуля (глобалы, file-static, статики функций) остаются в
|
||||
# общем _DATA, то есть в W1/W2 — они замаплены всегда и видны
|
||||
@@ -484,10 +534,9 @@ if [[ "$CRT0_TYPE" == "banked" ]]; then
|
||||
[[ "$bl" == "$bank_n" ]] && bank_local=1
|
||||
done
|
||||
[[ $bank_local -eq 1 ]] && bank_data_flags=(--dataseg "BANK${bank_n}")
|
||||
run "$SDCC" "${CC_FLAGS[@]}" \
|
||||
compile_c "$bank_src" "$rel" \
|
||||
--codeseg "BANK${bank_n}" --constseg "BANK${bank_n}" \
|
||||
"${bank_data_flags[@]}" \
|
||||
-c -o "$rel" "$bank_src"
|
||||
"${bank_data_flags[@]}"
|
||||
BANK_RELS+=("$rel")
|
||||
# Virtual address: bank_n in upper byte, BANK_LOW16 in low half.
|
||||
addr=$(printf "0x%X" $(( (bank_n << 16) | BANK_LOW16 )))
|
||||
@@ -500,6 +549,7 @@ fi
|
||||
IHX="$WORK/$(basename "$OUT" .exe).ihx"
|
||||
LINK_FLAGS=(-mz80 --no-std-crt0 --std-c99 --opt-code-size
|
||||
--code-loc "$CODE_LOC" --data-loc "$DATA_LOC")
|
||||
[[ "${SPRINTER_SDBG_ACTIVE:-}" == 1 ]] && LINK_FLAGS+=(--debug)
|
||||
LINK_FLAGS+=("${BANK_LD_FLAGS[@]}")
|
||||
LINK_FLAGS+=("${W3_LD_FLAGS[@]}")
|
||||
for f in "${LD_EXTRA[@]}"; do LINK_FLAGS+=("$f"); done
|
||||
@@ -529,7 +579,7 @@ fi
|
||||
# Отчёт по раскладке памяти + проверка лимитов — для ЛЮБОЙ модели памяти
|
||||
# (сколько свободно в W1/W2, W3 при --w3, и в каждом банке при --bank).
|
||||
if [[ -f "${IHX%.ihx}.map" ]]; then
|
||||
python3 "$CHECK_BANKS" "${IHX%.ihx}.map" \
|
||||
"$SPRINTER_PYTHON" "$CHECK_BANKS" "${IHX%.ihx}.map" \
|
||||
--mode "$MEMORY_MODE" --heap-top "$HEAP_TOP_VAL" --stack "$STACK_ADDR" || true
|
||||
fi
|
||||
|
||||
@@ -544,4 +594,9 @@ MK_PREFIX+=("${MKEXE_EXTRA[@]}")
|
||||
MK_PREFIX+=(-L "$LOAD_ADDR" -E "$ENTRY_ADDR" -S "$STACK_ADDR" -o "$OUT")
|
||||
run "$MKEXE" "${MK_PREFIX[@]}" "$IHX"
|
||||
|
||||
if [[ "${SPRINTER_SDBG_ACTIVE:-}" == 1 ]]; then
|
||||
"$SPRINTER_PYTHON" "$PROJ_ROOT/toolchain/sdbg_driver.py" --metadata "$WORK" \
|
||||
"$OUT" "$MEMORY_MODE" "$CODE_LOC" "$DATA_LOC" "$LOAD_ADDR" "$ENTRY_ADDR" "$STACK_ADDR"
|
||||
fi
|
||||
|
||||
echo "sprinter-cc: wrote $OUT"
|
||||
|
||||
Reference in New Issue
Block a user