binding_stable_integration.py (5063B)
1 #!/usr/bin/env python3 2 """Build the source-owned stable binding pass and screen a self-rebuild. 3 4 This is artifact preparation/testing, NOT an accepted compiler generation pair. 5 Only the stable source candidate changes; shipped bundles and generation selection stay pinned. 6 """ 7 import argparse,hashlib,json,time 8 from pathlib import Path 9 from bootstrap_generations import source_map 10 from binding_substitution import ROOT,tree_bytes 11 from bundle_dag import read,Intern 12 from float_multiply import Runner,sha 13 14 15 def main(): 16 p=argparse.ArgumentParser(description=__doc__) 17 p.add_argument('tricu',type=Path);p.add_argument('--directory',type=Path,required=True) 18 args=p.parse_args();root=args.directory.resolve() 19 mapping=ROOT/'bootstrap/compiler-source-map.v1' 20 text,entries,required=source_map(mapping,ROOT,'source_build') 21 meta=json.loads((ROOT/'bootstrap/stable-compiler.json').read_text()) 22 assert sha(ROOT/meta['bundle'])==meta['sha256'] 23 for row in meta['sources']: 24 if row['alias']!='source_stable':assert sha(ROOT/row['path'])==row['sha256'],('unexpected-source-drift',row['path']) 25 certificates=json.loads((ROOT/'bootstrap/binding-certificates.json').read_text()) 26 assert sha(ROOT/certificates['source'])==certificates['source_sha256'] 27 root.mkdir(parents=True,exist_ok=False);workspace=root/'workspace';workspace.mkdir() 28 for alias,(_,path,_) in entries.items():(workspace/(alias+'.tri')).write_bytes((ROOT/path).read_bytes()) 29 (root/'source-map.v1').write_text(text) 30 (workspace/'driver.tri').write_text('!import source_build as B\n!export sourceBuildGraph\nsourceBuildGraph = B.sourceBuildGraphStable\n') 31 runner=Runner(args.tricu,root,1800,memory_mib=8192) 32 report=dict(complete=False,accepted=False,generation_pair=False,backend='stable', 33 profile='source-module.stable.v1',harness_sha256=sha(Path(__file__)), 34 runtime_sha256=sha(args.tricu),accepted_compiler_sha256=meta['sha256'],map_sha256=sha(mapping), 35 certificate_manifest_sha256=sha(ROOT/'bootstrap/binding-certificates.json'), 36 sources={alias:sha(workspace/(alias+'.tri')) for alias in entries},stages=[]) 37 try: 38 tool=runner.imported(ROOT/meta['bundle'],'accepted') 39 for stage in range(2): 40 store=root/f'stage-{stage}-store';bundle=root/f'stage-{stage}.arboricx';start=time.monotonic() 41 runner.run(f'build-{stage}',['compile','--file',workspace/'driver.tri','--toolchain',tool, 42 '--tool-store',runner.store,'--store',store,'--output',bundle,'--compile-timeout','720'],750) 43 record=dict(stage=stage,selected_compiler=tool,bundle_sha256=sha(bundle),seconds=time.monotonic()-start, 44 modules={},certificates={}) 45 report['stages'].append(record) 46 for alias in ['source_binding_support','source_binding','source_stable','source_unit']: 47 manifest=(store/'cache/source-build'/alias).read_text().split('\t')[2] 48 out=root/f'stage-{stage}-{alias}.arboricx' 49 runner.run(f'export-{stage}-{alias}',['export','--store',store,'--module',manifest,'--output',out]) 50 record['modules'][alias]=dict(manifest=manifest,bundle_sha256=sha(out)) 51 _,_,nodes,exports,_=read(root/f'stage-{stage}-source_binding_support.arboricx') 52 for name,contract in certificates['contracts'].items(): 53 digest=hashlib.sha256(tree_bytes(nodes,exports[name])).hexdigest() 54 assert digest==contract['tree_sha256'],('certificate identity changed',stage,name) 55 record['certificates'][name]=digest 56 # Keep original stable lowering, not the old experimental patched 57 # stable module. Only the separately selected backend uses the pass. 58 intern=Intern();fixture=read(ROOT/'test/fixtures/compiler-library.arboricx') 59 stable=read(root/f'stage-{stage}-source_stable.arboricx') 60 fi=intern.graph(fixture[2]);si=intern.graph(stable[2]) 61 for name,index in stable[3].items(): 62 if name not in ['stableCompileCore','sourceCompileStableDefinition','sourceCompileStableDefinitionWith']: 63 assert si[index]==fi[fixture[3]['source_stable.'+name]],('unexpected stable export change',stage,name) 64 record['stable_lowering_and_other_exports_unchanged']=True 65 tool=runner.imported(bundle,f'candidate-{stage}') 66 report['exact_self_rebuild']=((root/'stage-0.arboricx').read_bytes()==(root/'stage-1.arboricx').read_bytes()) 67 for alias in report['stages'][0]['modules']: 68 report['stages'][1]['modules'][alias]['same_as_stage_0']=((root/f'stage-0-{alias}.arboricx').read_bytes()==(root/f'stage-1-{alias}.arboricx').read_bytes()) 69 report['complete']=True 70 print('BUILT stable binding candidate; exact self-rebuild:',report['exact_self_rebuild']) 71 finally:(root/'report.json').write_text(json.dumps(report,indent=2)+'\n') 72 73 74 if __name__=='__main__':main()