Sprinter: добавить отладку C-исходников и интеграцию VS Code
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Живой DAP-проход: C-макрос → breakpoint → обе console без DSS-вывода."""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
||||
sys.path.insert(0, str(ROOT/'toolchain'))
|
||||
from run_vscode_dap_probe import receive, send, wait_response
|
||||
from sdbg.server import rpc_call
|
||||
|
||||
|
||||
def main():
|
||||
provider = 'osx' if '--osx' in sys.argv else 'sdbg'
|
||||
source = ROOT/'tests/sdbg/fixtures/logmacro.c'
|
||||
with tempfile.TemporaryDirectory(prefix='sprinter-macro-live-') as temp:
|
||||
exe = Path(temp)/'logmacro.exe'
|
||||
build = subprocess.run([str(ROOT/'bin/sprinter-cc'), '-o', str(exe),
|
||||
'--src-debug', str(source)], cwd=ROOT,
|
||||
env=dict(os.environ, SPRINTER_PYTHON=sys.executable),
|
||||
capture_output=True, text=True)
|
||||
if build.returncode:
|
||||
raise RuntimeError('Не собрано приложение с SDBG_LOG: '+build.stdout+build.stderr)
|
||||
process = subprocess.Popen([sys.executable, str(ROOT/'toolchain/sdbg_dap.py')], cwd=ROOT,
|
||||
stdin=subprocess.PIPE, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
buffer = b''
|
||||
try:
|
||||
send(process, 1, 'initialize')
|
||||
_, buffer, _ = wait_response(process, buffer, 'initialize', 10)
|
||||
send(process, 2, 'launch', {'build': str(exe.with_name('.sprinter-cc-logmacro')),
|
||||
'debugger': provider, 'dssTimeout': 30})
|
||||
launched, buffer, events = wait_response(process, buffer, 'launch', 80)
|
||||
if not any(event.get('event') == 'initialized' for event in events):
|
||||
event, buffer = receive(process, buffer, 5)
|
||||
if event.get('event') != 'initialized':
|
||||
raise RuntimeError('Нет DAP initialized: '+str(event))
|
||||
send(process, 3, 'configurationDone')
|
||||
_, buffer, _ = wait_response(process, buffer, 'configurationDone', 10)
|
||||
send(process, 4, 'stackTrace')
|
||||
frames, buffer, _ = wait_response(process, buffer, 'stackTrace', 10)
|
||||
if not frames['body']['stackFrames'][0]['name'].startswith('main'):
|
||||
raise RuntimeError('Перед стартом нет main: '+str(frames['body']['stackFrames']))
|
||||
send(process, 5, 'continue')
|
||||
_, buffer, events = wait_response(process, buffer, 'continue', 10)
|
||||
outputs = [event for event in events if event.get('event') == 'output']
|
||||
deadline = time.monotonic()+25
|
||||
while not any('total=1\n' == event.get('body', {}).get('output') for event in outputs):
|
||||
if time.monotonic() >= deadline:
|
||||
raise RuntimeError('SDBG_LOG не пришёл в DAP Debug Console: '+str(outputs[-4:]))
|
||||
event, buffer = receive(process, buffer, deadline-time.monotonic())
|
||||
if event.get('event') == 'terminated':
|
||||
raise RuntimeError('DAP завершился до авторского лога')
|
||||
if event.get('event') == 'output': outputs.append(event)
|
||||
socket = launched['body']['socket']
|
||||
tail = rpc_call(socket, 'mame_console_tail', {'count': 50}, timeout=6)
|
||||
if not any('total=1' in line for line in tail['lines']):
|
||||
raise RuntimeError('В debugger console MAME нет total=1: '+str(tail))
|
||||
print(json.dumps({'event': 'macro_dual_console_verified',
|
||||
'provider': provider, 'dap_output': 'total=1',
|
||||
'mame_console': [line for line in tail['lines'] if 'total=1' in line],
|
||||
'entry': launched['body']['entry']}, ensure_ascii=False), flush=True)
|
||||
send(process, 6, 'disconnect')
|
||||
wait_response(process, buffer, 'disconnect', 10)
|
||||
finally:
|
||||
if process.poll() is None: process.terminate()
|
||||
try: _, stderr = process.communicate(timeout=8)
|
||||
except subprocess.TimeoutExpired:
|
||||
process.kill()
|
||||
_, stderr = process.communicate()
|
||||
if stderr:
|
||||
print(stderr.decode(errors='replace')[-3000:], file=sys.stderr)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
try: main()
|
||||
except (RuntimeError, TimeoutError, OSError, KeyError, ValueError) as error:
|
||||
print('macro-log-probe: '+str(error), file=sys.stderr)
|
||||
sys.exit(1)
|
||||
Reference in New Issue
Block a user