22
33import asyncio
44import dataclasses
5+ import hashlib
56import json
7+ import os
68import pathlib
79import re
810import shutil
2022
2123TOOLS_JIT_BUILD = pathlib .Path (__file__ ).resolve ()
2224TOOLS_JIT = TOOLS_JIT_BUILD .parent
25+ TOOLS_JIT_STENCILS = TOOLS_JIT / "stencils"
2326TOOLS = TOOLS_JIT .parent
2427CPYTHON = TOOLS .parent
2528PYTHON_EXECUTOR_CASES_C_H = CPYTHON / "Python" / "executor_cases.c.h"
@@ -43,6 +46,20 @@ class _Target(typing.Generic[_S, _R]):
4346 verbose : bool = False
4447 known_symbols : dict [str , int ] = dataclasses .field (default_factory = dict )
4548
49+ def _compute_digest (self , out : pathlib .Path ) -> str :
50+ hasher = hashlib .sha256 ()
51+ hasher .update (self .triple .encode ())
52+ hasher .update (self .debug .to_bytes ())
53+ # These dependencies are also reflected in _JITSources in regen.targets:
54+ hasher .update (PYTHON_EXECUTOR_CASES_C_H .read_bytes ())
55+ hasher .update ((out / "pyconfig.h" ).read_bytes ())
56+ for dirpath , _ , filenames in sorted (os .walk (TOOLS_JIT )):
57+ if pathlib .Path (dirpath ) == TOOLS_JIT_STENCILS :
58+ continue
59+ for filename in filenames :
60+ hasher .update (pathlib .Path (dirpath , filename ).read_bytes ())
61+ return hasher .hexdigest ()
62+
4663 async def _parse (self , path : pathlib .Path ) -> _stencils .StencilGroup :
4764 group = _stencils .StencilGroup ()
4865 args = ["--disassemble" , "--reloc" , f"{ path } " ]
@@ -170,6 +187,15 @@ def build(self, out: pathlib.Path, *, force: bool = False) -> None:
170187 request = "Please report any issues you encounter." .center (len (warning ))
171188 outline = "=" * len (warning )
172189 print ("\n " .join (["" , outline , warning , request , outline , "" ]))
190+ digest = f"{ self ._compute_digest (out )} \n "
191+ jit_stencils = out / "jit_stencils.h"
192+ jit_stencils_digest = out / "jit_stencils.h.digest"
193+
194+ if not force and jit_stencils_digest .exists () and jit_stencils .exists ():
195+ if jit_stencils_digest .read_text () == digest :
196+ return
197+
198+ # We need to ignore the version number for Darwin targets
173199 target = self .triple
174200 darwin_index = target .find ("-darwin" )
175201 if darwin_index != - 1 :
@@ -191,6 +217,7 @@ def build(self, out: pathlib.Path, *, force: bool = False) -> None:
191217 raise
192218 finally :
193219 jit_stencils_new .unlink (missing_ok = True )
220+ jit_stencils_digest .write_text (digest )
194221
195222
196223class _COFF (
0 commit comments