Phase 6: P-Code-Bibliotheken und Linker abschließen, Cross-Buildplan festhalten

This commit is contained in:
2026-09-07 16:06:23 +02:00
parent 60d37ec79d
commit 25176947ba
33 changed files with 2416 additions and 203 deletions

View File

@@ -0,0 +1,17 @@
CONST WIDTH=2
TYPE Record
value AS LONG
text AS STRING * 4
END TYPE
COMMON SHARED shared&
DIM SHARED state&
DATA 7
SUB Work(a&(), r AS Record, n&)
state&=state&+1
shared&=shared&+1
READ a&(1)
r.value=r.value+n&
r.text="TB"
n&=9
PRINT state&
END SUB

Binary file not shown.

View File

@@ -0,0 +1,92 @@
#!/usr/bin/env python3
"""Dieselben TBL-Bytes auf jedem Releaseziel: Linken und echte Standalone-Ausführung."""
import argparse
import hashlib
import json
import os
from pathlib import Path
import platform
import shutil
import subprocess
import tempfile
DIGEST = '5d25c2f8c95ae535e55a6c84c1ddd0d964358863f4f3c780c50ac4a2eb3594df'
TARGETS = {
('Windows', 'AMD64'): 'x86_64-pc-windows-msvc',
('Darwin', 'arm64'): 'aarch64-apple-darwin',
('Linux', 'x86_64'): 'x86_64-unknown-linux-gnu',
('Linux', 'aarch64'): 'aarch64-unknown-linux-gnu',
}
SOURCE = '''COMMON SHARED shared&
OPEN "round.txt" FOR APPEND AS #1
old&=LOF(1)
PRINT #1, "x"
CLOSE #1
DIM a&(WIDTH)
DIM r AS Record
n&=3
CALL Work(a&(),r,n&)
PRINT a&(1);r.value;n&;shared&
PRINT r.text
IF old&=0 THEN RUN
END
'''
EXPECTED = b' 1 \n 7 3 9 1 \nTB \n' # RUN setzt auch den Textbildschirm zurück.
def run(args, cwd, env):
result = subprocess.run([str(a) for a in args], cwd=cwd, env=env,
input=b'', capture_output=True, timeout=30)
assert result.returncode == 0, (result.args, result.returncode, result.stdout, result.stderr)
return result.stdout.replace(b'\r\n', b'\n')
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--bin-dir', type=Path, default=Path('target/release'))
parser.add_argument('--library', type=Path, default=Path(__file__).resolve().parents[1] / 'libraries/portable.tbl')
args = parser.parse_args()
target = TARGETS.get((platform.system(), platform.machine()))
assert target, f'Kein Releaseziel: {platform.system()} {platform.machine()}'
digest = hashlib.sha256(args.library.read_bytes()).hexdigest()
assert digest == DIGEST, f'Gemeinsames TBL-Artefakt verändert: {digest}'
binaries = args.bin_dir.resolve()
suffix = '.exe' if platform.system() == 'Windows' else ''
compiler = binaries / ('tbc' + suffix)
template_tool = binaries / ('tb-template' + suffix)
env = dict(os.environ, PATH='')
with tempfile.TemporaryDirectory(prefix='tb-library-') as work:
root = Path(work)
reference, clean = root / 'reference', root / 'clean'
reference.mkdir()
clean.mkdir()
library = root / 'library.tbl'
shutil.copyfile(args.library, library)
template = root / ('runtime' + suffix)
shutil.copy2(binaries / ('tbrt' + suffix), template)
run([template_tool, template, target], root, env)
source = root / 'consumer.bas'
source.write_text(SOURCE, encoding='utf-8')
linked = root / 'consumer.tbc'
run([compiler, 'link', source, library, '-o', linked], root, env)
expected = run([compiler, 'run', linked], reference, env)
assert expected == EXPECTED, expected
executable = clean / ('consumer' + suffix)
run([compiler, 'link', source, library, '--exe', '--target', target,
'--template', template, '-o', executable], root, env)
source.unlink()
library.unlink()
linked.unlink()
template.unlink()
Path(str(template) + '.meta').unlink()
actual = run([executable], clean, env)
assert actual == EXPECTED, actual
assert (reference / 'round.txt').read_bytes() == (clean / 'round.txt').read_bytes()
assert (clean / 'round.txt').read_text().splitlines() == ['x', 'x']
assert sorted(p.name for p in clean.iterdir()) == ['consumer' + suffix, 'round.txt']
print(json.dumps({'target': target, 'tbl_sha256': digest, 'native_execution': True,
'source_free': True, 'run_reset': True, 'output': actual.decode()}, ensure_ascii=False))
if __name__ == '__main__':
main()