Проверить VSIX после разделения и принять размерный эталон SDK
This commit is contained in:
@@ -86,12 +86,12 @@ sdbg-tests: tools lib
|
|||||||
$(PYTHON) -m unittest discover -s tests/sdbg -v
|
$(PYTHON) -m unittest discover -s tests/sdbg -v
|
||||||
|
|
||||||
# Размерный регресс: сверить _CODE всех программ с docs/size_baseline.tsv.
|
# Размерный регресс: сверить _CODE всех программ с docs/size_baseline.tsv.
|
||||||
size-check:
|
size-check: tests
|
||||||
$(PYTHON) toolchain/size_check.py
|
$(PYTHON) toolchain/size_check.py --require $(TESTS)
|
||||||
|
|
||||||
# Принять текущие размеры как эталон (после осознанных изменений).
|
# Принять текущие размеры как эталон (после осознанных изменений).
|
||||||
size-baseline:
|
size-baseline: tests
|
||||||
$(PYTHON) toolchain/size_check.py --update
|
$(PYTHON) toolchain/size_check.py --update --require $(TESTS)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(MAKE) -C toolchain/mkexe clean
|
$(MAKE) -C toolchain/mkexe clean
|
||||||
|
|||||||
@@ -249,14 +249,14 @@ debug packages, носители, снимки, внешние источник
|
|||||||
их документы и историю. Критерий: каждый продукт собирается и проходит
|
их документы и историю. Критерий: каждый продукт собирается и проходит
|
||||||
доступные host/MAME проверки из изолированного клона без Examples и
|
доступные host/MAME проверки из изолированного клона без Examples и
|
||||||
других приложений.
|
других приложений.
|
||||||
6. **Реализовано; остаётся ручная проверка установленного VSIX после разделения — выделить extension.** Научить VS Code находить SDK DAP независимо от
|
6. **Выполнено — выделить extension.** Научить VS Code находить SDK DAP независимо от
|
||||||
workspace, запускать build/run/debug приложения и показывать ошибки
|
workspace, запускать build/run/debug приложения и показывать ошибки
|
||||||
разрешения путей/версий. Проверить VSIX в отдельном workspace SprPoP
|
разрешения путей/версий. Проверить VSIX в отдельном workspace SprPoP
|
||||||
или Volkov, а не только в `C-Compiler`. Критерий: F5 строит debug package,
|
или Volkov, а не только в `C-Compiler`. Критерий: F5 строит debug package,
|
||||||
ждёт DSS, доходит до `main`, принимает breakpoint/logpoint и клавиатуру;
|
ждёт DSS, доходит до `main`, принимает breakpoint/logpoint и клавиатуру;
|
||||||
опция родного окна MAME работает на macOS. Windows остаётся явно
|
опция родного окна MAME работает на macOS. Windows остаётся явно
|
||||||
ограниченной до отдельной реализации host transport.
|
ограниченной до отдельной реализации host transport.
|
||||||
7. **Выполнено с открытым размерным baseline — очистить SDK и документы.** Заменить корневые цели, release-скрипт,
|
7. **Выполнено — очистить SDK и документы.** Заменить корневые цели, release-скрипт,
|
||||||
README, `AGENTS.md`, инструкции автотеста/отладки и рабочие ссылки.
|
README, `AGENTS.md`, инструкции автотеста/отладки и рабочие ссылки.
|
||||||
Проверить `make`, `make -C libc`, `make -C libbgi`, `make size-check`,
|
Проверить `make`, `make -C libc`, `make -C libbgi`, `make size-check`,
|
||||||
SDK host/sdbg tests и отдельные проекты. Критерий: в SDK нет tracked
|
SDK host/sdbg tests и отдельные проекты. Критерий: в SDK нет tracked
|
||||||
@@ -276,15 +276,25 @@ SprPoP, Volkov и PoP-Archive PoC. Живые последовательные D
|
|||||||
|
|
||||||
Extension воспроизводимо упакован через `npm ci && npm run package` и VSIX
|
Extension воспроизводимо упакован через `npm ci && npm run package` и VSIX
|
||||||
версии 0.2.0 установлен в локальный VS Code. Рецепт и `package-lock.json`
|
версии 0.2.0 установлен в локальный VS Code. Рецепт и `package-lock.json`
|
||||||
хранятся в VSCode-Sprinter.
|
хранятся в VSCode-Sprinter. Изолированный профиль VS Code с файлами
|
||||||
|
установленного VSIX выполнил F5-сценарий SprPoP: задача `make SRC_DEBUG=1
|
||||||
|
hdd` завершилась, DAP остановился в `src/sprpop.c:264` (`main`). Проверка
|
||||||
|
шла через API extension host; автоматизировать физическое нажатие F5 через
|
||||||
|
macOS Accessibility из текущего окружения не удалось.
|
||||||
|
|
||||||
`make size-check` пока не принят: текущий baseline показывает 12 старых
|
Эталон `make size-check` разобран и обновлён. Десять тестов, использующих
|
||||||
увеличений (обычно +9 байт, `openenv` +188) и несколько исчезнувших прежних
|
`open()`, выросли на 9 байт из-за исправления таблицы режимов ESTEX после
|
||||||
тестов. Реорганизация не меняла libc/libbgi, поэтому эталон автоматически не
|
предыдущего эталона (ревизия `879f2ba`). `openenv` вырос на 188 байт: те же
|
||||||
перезаписывался; расхождения нужно разобрать отдельно. После разделения ещё
|
9 байт и новый тест записи через `O_RDONLY`. Для `w3bgfx` прежняя запись
|
||||||
нужен ручной F5-прогон установленного VSIX в чистом workspace. Несколько
|
5243 байта была несвежей: пересборка в отдельном worktree самой ревизии
|
||||||
одновременных MAME, маршрутизация MCP между ними и Windows transport остаются
|
`879f2ba` тем же SDCC дала 5257 байт, как и текущая сборка. Других
|
||||||
явно непроверенными сценариями.
|
изменений размеров свежих карт нет. Теперь `size-check` сначала собирает
|
||||||
|
обязательные SDK-тесты, требует их свежие карты и пропускает устаревшие
|
||||||
|
артефакты необязательных тестов; `size-baseline` сохраняет их прежние
|
||||||
|
значения, пока эти тесты не собраны заново.
|
||||||
|
|
||||||
|
Несколько одновременных MAME, маршрутизация MCP между ними и Windows
|
||||||
|
transport остаются явно непроверенными сценариями.
|
||||||
|
|
||||||
Каждый этап заканчивается проверкой в отдельном репозитории и просмотром Git
|
Каждый этап заканчивается проверкой в отдельном репозитории и просмотром Git
|
||||||
diff. Новые Git remote для выделенных репозиториев и публикация их релизов
|
diff. Новые Git remote для выделенных репозиториев и публикация их релизов
|
||||||
|
|||||||
+13
-13
@@ -1,4 +1,4 @@
|
|||||||
# Эталон размеров _CODE (байт); обновление: python3 toolchain/size_check.py --update
|
# Эталон размеров _CODE (байт); обновление: make size-baseline
|
||||||
accfill 3797
|
accfill 3797
|
||||||
accop 7067
|
accop 7067
|
||||||
argv 3445
|
argv 3445
|
||||||
@@ -14,18 +14,18 @@ bgitest 3762
|
|||||||
bios_text 4475
|
bios_text 4475
|
||||||
blitperf 5860
|
blitperf 5860
|
||||||
blitw 4939
|
blitw 4939
|
||||||
cat 927
|
cat 936
|
||||||
cblstream 5944
|
cblstream 5953
|
||||||
cbltest 6090
|
cbltest 6090
|
||||||
cblwav 6183
|
cblwav 6192
|
||||||
conio 4619
|
conio 4619
|
||||||
conio2 3943
|
conio2 3943
|
||||||
convbench 3508
|
convbench 3508
|
||||||
dec_test 874
|
dec_test 874
|
||||||
errno 5980
|
errno 5989
|
||||||
fbench 8149
|
fbench 8158
|
||||||
fdmax 6087
|
fdmax 6096
|
||||||
filetest 10611
|
filetest 10620
|
||||||
fpsdiv 4870
|
fpsdiv 4870
|
||||||
gets 523
|
gets 523
|
||||||
gfx_dbuf 5207
|
gfx_dbuf 5207
|
||||||
@@ -40,26 +40,26 @@ ls 4849
|
|||||||
malloc 4475
|
malloc 4475
|
||||||
mem_test 4569
|
mem_test 4569
|
||||||
mouse 4396
|
mouse 4396
|
||||||
openenv 6138
|
openenv 6326
|
||||||
pageflip 6334
|
pageflip 6334
|
||||||
palfile 5406
|
palfile 5406
|
||||||
ptime 5758
|
ptime 5758
|
||||||
rt_test 5216
|
rt_test 5216
|
||||||
scroll 6744
|
scroll 6744
|
||||||
seek 4202
|
seek 4211
|
||||||
simple 969
|
simple 969
|
||||||
solidt 11595
|
solidt 11604
|
||||||
spranim 9431
|
spranim 9431
|
||||||
spriteclip 4119
|
spriteclip 4119
|
||||||
sprites 6791
|
sprites 6791
|
||||||
stattest 7563
|
stattest 7572
|
||||||
stdlib 6657
|
stdlib 6657
|
||||||
stest2 3658
|
stest2 3658
|
||||||
strtest 1354
|
strtest 1354
|
||||||
text_palette 5038
|
text_palette 5038
|
||||||
timedir 5468
|
timedir 5468
|
||||||
w0page 8831
|
w0page 8831
|
||||||
w3bgfx 5243
|
w3bgfx 5257
|
||||||
w3big 3673
|
w3big 3673
|
||||||
w3huge 3700
|
w3huge 3700
|
||||||
w3probe 3556
|
w3probe 3556
|
||||||
|
|||||||
|
+68
-21
@@ -4,14 +4,18 @@ size_check.py — размерный регресс-тест: сравнение
|
|||||||
docs/size_baseline.tsv.
|
docs/size_baseline.tsv.
|
||||||
|
|
||||||
Использование:
|
Использование:
|
||||||
python3 toolchain/size_check.py # сверка с эталоном
|
make size-check # собрать обязательные тесты и сверить с эталоном
|
||||||
python3 toolchain/size_check.py --update # перезаписать эталон
|
make size-baseline # принять свежие размеры, сохранив необязательные
|
||||||
|
|
||||||
Логика: собираем _CODE из .map каждой программы под tests/, сравниваем с
|
Логика: собираем _CODE из свежей .map каждой программы под tests/, сравниваем с
|
||||||
эталоном. Любое отличие печатается; выход 1 — если есть РОСТ (случайное
|
эталоном. Карты, оставшиеся от другой цели или более старые, чем входы
|
||||||
|
сборки, пропускаются. Любое отличие печатается; выход 1 — если есть РОСТ (случайное
|
||||||
разжирение libc), 0 — если только уменьшения/без изменений. Новые
|
разжирение libc), 0 — если только уменьшения/без изменений. Новые
|
||||||
программы (нет в эталоне) — предупреждение, добавить через --update.
|
программы (нет в эталоне) — предупреждение, добавить через --update.
|
||||||
Запускать после `make all`.
|
--update заменяет размеры собранных тестов, сохраняя эталоны необязательных
|
||||||
|
тестов, которые сейчас не собирались.
|
||||||
|
Прямой запуск скрипта рассчитан на уже собранные тесты; Make-цели сами
|
||||||
|
собирают обязательный набор и передают его через --require.
|
||||||
|
|
||||||
ТОЛЬКО tests/, без отдельного репозитория Examples: регресс ловит разжирение libc, а для этого
|
ТОЛЬКО tests/, без отдельного репозитория Examples: регресс ловит разжирение libc, а для этого
|
||||||
хватает мелких тестов — каждый тянет свой кусок библиотеки и пересобирается
|
хватает мелких тестов — каждый тянет свой кусок библиотеки и пересобирается
|
||||||
@@ -20,18 +24,20 @@ docs/size_baseline.tsv.
|
|||||||
`make all` они убраны (см. корневой Makefile).
|
`make all` они убраны (см. корневой Makefile).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
import glob
|
import glob
|
||||||
import os
|
import os
|
||||||
|
from pathlib import Path
|
||||||
import re
|
import re
|
||||||
import sys
|
|
||||||
|
|
||||||
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
BASELINE = os.path.join(ROOT, "docs", "size_baseline.tsv")
|
BASELINE = os.path.join(ROOT, "docs", "size_baseline.tsv")
|
||||||
|
|
||||||
|
|
||||||
def collect():
|
def collect():
|
||||||
"""Имя программы → размер _CODE (байт) по свежим .map."""
|
"""Имя программы → размер _CODE (байт) по свежим .map своей цели."""
|
||||||
sizes = {}
|
sizes = {}
|
||||||
|
skipped = set()
|
||||||
pats = [
|
pats = [
|
||||||
os.path.join(ROOT, "tests", "*", ".sprinter-cc-*", "*.map"),
|
os.path.join(ROOT, "tests", "*", ".sprinter-cc-*", "*.map"),
|
||||||
]
|
]
|
||||||
@@ -41,13 +47,43 @@ def collect():
|
|||||||
# .map должен лежать в своей папке .sprinter-cc-<name>
|
# .map должен лежать в своей папке .sprinter-cc-<name>
|
||||||
if os.path.basename(os.path.dirname(map_path)) != ".sprinter-cc-" + name:
|
if os.path.basename(os.path.dirname(map_path)) != ".sprinter-cc-" + name:
|
||||||
continue
|
continue
|
||||||
|
project = Path(map_path).parents[1]
|
||||||
|
makefile = project / "Makefile"
|
||||||
|
if not makefile.is_file():
|
||||||
|
continue
|
||||||
|
declared = re.search(r"^EXAMPLE\s*[:?+]?=\s*(\S+)",
|
||||||
|
makefile.read_text(), re.M)
|
||||||
|
if not declared or declared.group(1) != name:
|
||||||
|
# Например, старый .sprinter-cc-w3bankgfx рядом с w3bgfx.
|
||||||
|
continue
|
||||||
|
flags = makefile.read_text()
|
||||||
|
safe = "--safe" in flags
|
||||||
|
gfx = "--gfx" in flags
|
||||||
|
variant = "_safe" if safe else ""
|
||||||
|
# app.mk сам по себе не является входом линкера: его изменения
|
||||||
|
# учитываются сборкой через sdbg-config и CC_FLAGS. Проверяем
|
||||||
|
# только реальные входы, иначе правка run-цели объявит все карты
|
||||||
|
# устаревшими, хотя размер программы не менялся.
|
||||||
|
dependencies = [makefile, Path(ROOT) / "bin/sprinter-cc",
|
||||||
|
Path(ROOT) / "toolchain/mkexe/mkexe",
|
||||||
|
Path(ROOT) / f"lib/sprinter{variant}.lib"]
|
||||||
|
if gfx:
|
||||||
|
dependencies.append(Path(ROOT) / f"lib/bgi256{variant}.lib")
|
||||||
|
dependencies.extend(project.glob("*.c"))
|
||||||
|
dependencies.extend(project.glob("*.h"))
|
||||||
|
dependencies.extend((Path(ROOT) / "runtime").glob("*.s"))
|
||||||
|
if any(not path.is_file() or
|
||||||
|
os.path.getmtime(map_path) + 1 < path.stat().st_mtime
|
||||||
|
for path in dependencies):
|
||||||
|
skipped.add(name)
|
||||||
|
continue
|
||||||
with open(map_path, encoding="utf-8", errors="replace") as f:
|
with open(map_path, encoding="utf-8", errors="replace") as f:
|
||||||
for line in f:
|
for line in f:
|
||||||
m = re.match(r"^_CODE\s+([0-9A-Fa-f]+)\s+([0-9A-Fa-f]+)", line)
|
m = re.match(r"^_CODE\s+([0-9A-Fa-f]+)\s+([0-9A-Fa-f]+)", line)
|
||||||
if m:
|
if m:
|
||||||
sizes[name] = int(m.group(2), 16)
|
sizes[name] = int(m.group(2), 16)
|
||||||
break
|
break
|
||||||
return sizes
|
return sizes, skipped
|
||||||
|
|
||||||
|
|
||||||
def load_baseline():
|
def load_baseline():
|
||||||
@@ -64,23 +100,33 @@ def load_baseline():
|
|||||||
|
|
||||||
|
|
||||||
def save_baseline(sizes):
|
def save_baseline(sizes):
|
||||||
|
accepted = load_baseline()
|
||||||
|
accepted.update(sizes)
|
||||||
with open(BASELINE, "w") as f:
|
with open(BASELINE, "w") as f:
|
||||||
f.write("# Эталон размеров _CODE (байт); обновление: "
|
f.write("# Эталон размеров _CODE (байт); обновление: "
|
||||||
"python3 toolchain/size_check.py --update\n")
|
"make size-baseline\n")
|
||||||
for name in sorted(sizes):
|
for name in sorted(accepted):
|
||||||
f.write(f"{name}\t{sizes[name]}\n")
|
f.write(f"{name}\t{accepted[name]}\n")
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
update = "--update" in sys.argv
|
parser = argparse.ArgumentParser(description="Проверка размера _CODE SDK-тестов")
|
||||||
sizes = collect()
|
parser.add_argument("--update", action="store_true")
|
||||||
|
parser.add_argument("--require", nargs="*", default=[], metavar="TEST")
|
||||||
|
args = parser.parse_args()
|
||||||
|
sizes, skipped = collect()
|
||||||
|
missing = set(args.require) - sizes.keys()
|
||||||
|
if missing:
|
||||||
|
print("size_check: нет свежей карты для обязательных тестов: " +
|
||||||
|
", ".join(sorted(missing)))
|
||||||
|
return 2
|
||||||
if not sizes:
|
if not sizes:
|
||||||
print("size_check: .map не найдены — сначала `make all`")
|
print("size_check: свежие .map не найдены — сначала `make all`")
|
||||||
return 2
|
return 2
|
||||||
|
|
||||||
if update:
|
if args.update:
|
||||||
save_baseline(sizes)
|
save_baseline(sizes)
|
||||||
print(f"size_check: эталон обновлён ({len(sizes)} программ) → "
|
print(f"size_check: эталон обновлён ({len(sizes)} свежих программ) → "
|
||||||
f"{os.path.relpath(BASELINE, ROOT)}")
|
f"{os.path.relpath(BASELINE, ROOT)}")
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
@@ -90,17 +136,18 @@ def main():
|
|||||||
return 2
|
return 2
|
||||||
|
|
||||||
grew = 0
|
grew = 0
|
||||||
for name in sorted(set(sizes) | set(base)):
|
for name in sorted(sizes):
|
||||||
new, old = sizes.get(name), base.get(name)
|
new, old = sizes.get(name), base.get(name)
|
||||||
if new is None:
|
if old is None:
|
||||||
print(f" {name}: исчез из сборки (был {old} Б)")
|
|
||||||
elif old is None:
|
|
||||||
print(f" {name}: НОВЫЙ ({new} Б) — добавить в эталон (--update)")
|
print(f" {name}: НОВЫЙ ({new} Б) — добавить в эталон (--update)")
|
||||||
elif new != old:
|
elif new != old:
|
||||||
mark = "РОСТ" if new > old else "ок, меньше"
|
mark = "РОСТ" if new > old else "ок, меньше"
|
||||||
print(f" {name}: {old} -> {new} ({new - old:+d} Б) [{mark}]")
|
print(f" {name}: {old} -> {new} ({new - old:+d} Б) [{mark}]")
|
||||||
if new > old:
|
if new > old:
|
||||||
grew += 1
|
grew += 1
|
||||||
|
if skipped:
|
||||||
|
print(f"size_check: {len(skipped)} устаревших карт пропущено: " +
|
||||||
|
", ".join(sorted(skipped)))
|
||||||
if grew:
|
if grew:
|
||||||
print(f"size_check: {grew} программ(ы) ВЫРОСЛИ — проверить правки libc")
|
print(f"size_check: {grew} программ(ы) ВЫРОСЛИ — проверить правки libc")
|
||||||
return 1
|
return 1
|
||||||
@@ -109,4 +156,4 @@ def main():
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
sys.exit(main())
|
raise SystemExit(main())
|
||||||
|
|||||||
Reference in New Issue
Block a user