Isolate manual artifact validation without package publication
This commit is contained in:
1 parent
98976747c3
commit
d02f1f0b55
75 files changed
+3895
-634
No files matched your search
@@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate cdecl -> stdcall adapters using the pinned managed P/Invoke ABI."""
|
||||
import argparse,re,subprocess,json
|
||||
from pathlib import Path
|
||||
p=argparse.ArgumentParser();p.add_argument('--source',type=Path,required=True);p.add_argument('--toolchain',type=Path,required=True);p.add_argument('--libraries',type=Path,required=True);a=p.parse_args()
|
||||
files=[a.source/'binding/SkiaSharp/SkiaApi.generated.cs',a.source/'binding/HarfBuzzSharp/HarfBuzzApi.generated.cs']
|
||||
text='\n'.join(x.read_text() if x.is_file() else subprocess.check_output(['git','-C',str(a.source),'show','HEAD:'+str(x.relative_to(a.source))],text=True) for x in files)
|
||||
structs={}
|
||||
# Generated structs use public fields; omit properties and methods.
|
||||
for match in re.finditer(r'\bstruct\s+(\w+)\s*\{',text):
|
||||
pos=match.end();depth=1;end=pos
|
||||
while depth:
|
||||
if text[end]=='{':depth+=1
|
||||
if text[end]=='}':depth-=1
|
||||
end+=1
|
||||
block=text[pos:end-1]
|
||||
structs[match[1]]=[m[1].strip() for m in re.finditer(r'^\s*public\s+(.+?)\s+\w+;\s*$',block,re.M)]
|
||||
sizes={}
|
||||
def layout(t):
|
||||
t=re.sub(r'\b(?:ref|out|in|readonly)\b','',t).strip()
|
||||
if '*' in t or t.endswith(('[]','Delegate')):return 4,4
|
||||
if t in sizes:return sizes[t],4
|
||||
if t in structs:raise KeyError(t)
|
||||
if t in ['Int64','UInt64','long','ulong','Double','double']:return 8,4
|
||||
if t in ['Int16','UInt16','short','ushort']:return 2,2
|
||||
if t in ['Byte','SByte','byte','sbyte','Boolean','bool']:return 1,1
|
||||
return 4,4 # enums and generated opaque pointer aliases
|
||||
pending=set(structs)
|
||||
while pending:
|
||||
done=set()
|
||||
for name in sorted(pending):
|
||||
offset=0;align=1
|
||||
try:
|
||||
for t in structs[name]:
|
||||
n,k=layout(t);offset=(offset+k-1)//k*k+n;align=max(align,k)
|
||||
except KeyError:continue
|
||||
sizes[name]=(offset+align-1)//align*align;done.add(name)
|
||||
if not done:raise SystemExit('Unresolved managed struct layout: '+str(pending))
|
||||
pending-=done
|
||||
symbols=set()
|
||||
for path in a.libraries.glob('lib*.a'):
|
||||
result=subprocess.run(['nm','--defined-only',str(path)],capture_output=True,text=True,check=True)
|
||||
symbols.update(re.findall(r'\bT\s+(_(?:sk|gr|hb)_\w+)\s*$',result.stdout,re.M))
|
||||
thunks={}
|
||||
def parameters(s):
|
||||
result=[];depth=0;start=0
|
||||
for i,c in enumerate(s):
|
||||
if c in '[<(':depth+=1
|
||||
elif c in ']> )'.replace(' ',''):depth-=1
|
||||
elif c==',' and depth==0:result.append(s[start:i]);start=i+1
|
||||
result.append(s[start:]);return [v.strip() for v in result if v.strip()]
|
||||
for m in re.finditer(r'internal static (?:extern|partial)\s+.+?\s+((?:sk|gr|hb)_\w+)\s*\((.*?)\);',text,re.S):
|
||||
symbol='_'+m[1]
|
||||
if symbol not in symbols:continue
|
||||
count=0
|
||||
for param in parameters(m[2]):
|
||||
param=re.sub(r'/\*.*?\*/|\[[^\]]+\]','',param).strip();typ=param.rsplit(' ',1)[0]
|
||||
n,_=layout(typ);count+=(n+3)//4*4
|
||||
thunks[symbol+'@'+str(count)]=(symbol,count)
|
||||
if not thunks:raise SystemExit('No x86 exported APIs matched pinned managed bindings')
|
||||
assembly=['.text','.set "@feat.00", 1']
|
||||
for name,(symbol,count) in sorted(thunks.items()):
|
||||
assembly+=['.globl "'+name+'"','"'+name+'":']+['pushl '+str(count)+'(%esp)']*(count//4)
|
||||
assembly+=['calll '+symbol,'addl $'+str(count)+', %esp','retl $'+str(count)]
|
||||
path=a.libraries/'skia_x86_stdcall_thunks.s';path.write_text('\n'.join(assembly)+'\n');obj=path.with_suffix('.o')
|
||||
subprocess.run([str(a.toolchain/'cc'),'-c',str(path),'-o',str(obj)],check=True)
|
||||
subprocess.run([str(a.toolchain/'ar'),'rcs',str(a.libraries/'skia_x86_stdcall_thunks.lib'),str(obj)],check=True)
|
||||
(a.libraries/'x86-thunks.json').write_text(json.dumps({'count':len(thunks),'layouts':sizes,'thunks':thunks},indent=2)+'\n')
|
||||
print('Generated',len(thunks),'x86 stdcall thunks')
|
||||
Reference in new issue
Block a user