Skip to content

Commit d393b32

Browse files
committed
fixup! deps: update libffi to 3.6.0
1 parent d658f44 commit d393b32

1 file changed

Lines changed: 134 additions & 0 deletions

File tree

deps/libffi/preprocess_asm.py

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
#!/usr/bin/env python3
2+
3+
import argparse
4+
import os
5+
from pathlib import Path
6+
import re
7+
import shlex
8+
import shutil
9+
import subprocess
10+
import sys
11+
12+
13+
def split_command(value):
14+
if not value:
15+
return None
16+
value = value.strip()
17+
if not value:
18+
return None
19+
return shlex.split(value, posix=(os.name != 'nt'))
20+
21+
22+
def find_compiler():
23+
for var in ('CC', 'CXX'):
24+
command = split_command(os.environ.get(var))
25+
if command and shutil.which(command[0]):
26+
return command
27+
28+
for name in ('cl.exe', 'cl', 'clang-cl.exe', 'clang-cl', 'cc', 'clang', 'gcc'):
29+
path = shutil.which(name)
30+
if path:
31+
return [path]
32+
33+
raise RuntimeError('Unable to locate a compiler for preprocessing assembly')
34+
35+
36+
def find_armasm64():
37+
"""Find armasm64.exe in the PATH or common Visual Studio locations."""
38+
# First check PATH
39+
path = shutil.which('armasm64.exe')
40+
if path:
41+
return path
42+
43+
# Check common VS locations via environment
44+
vc_install_dir = os.environ.get('VCINSTALLDIR', '')
45+
if vc_install_dir:
46+
candidate = os.path.join(vc_install_dir, 'bin', 'Hostx64', 'arm64', 'armasm64.exe')
47+
if os.path.exists(candidate):
48+
return candidate
49+
candidate = os.path.join(vc_install_dir, 'bin', 'Hostarm64', 'arm64', 'armasm64.exe')
50+
if os.path.exists(candidate):
51+
return candidate
52+
53+
raise RuntimeError('Unable to locate armasm64.exe')
54+
55+
56+
def normalize_path(value):
57+
return str(value).strip().strip('"')
58+
59+
60+
def unique_paths(paths):
61+
seen = set()
62+
result = []
63+
for path in paths:
64+
if path in seen:
65+
continue
66+
seen.add(path)
67+
result.append(path)
68+
return result
69+
70+
71+
def preprocess(args):
72+
compiler = find_compiler()
73+
input_path = normalize_path(args.input)
74+
output = Path(normalize_path(args.output))
75+
include_dirs = [normalize_path(include_dir) for include_dir in args.include_dir]
76+
include_dirs.append(str(output.parent))
77+
include_dirs = unique_paths(include_dirs)
78+
output.parent.mkdir(parents=True, exist_ok=True)
79+
80+
if os.name == 'nt' and Path(compiler[0]).name.lower() in ('cl.exe', 'cl', 'clang-cl.exe', 'clang-cl'):
81+
command = compiler + ['/nologo', '/EP', '/TC']
82+
command += [f'/I{include_dir}' for include_dir in include_dirs]
83+
command += [f'/D{define}' for define in args.define]
84+
command += [input_path]
85+
else:
86+
command = compiler + ['-E', '-P', '-x', 'c']
87+
command += [f'-I{include_dir}' for include_dir in include_dirs]
88+
command += [f'-D{define}' for define in args.define]
89+
command += [input_path]
90+
91+
result = subprocess.run(command, capture_output=True, text=True)
92+
if result.returncode != 0:
93+
sys.stderr.write(result.stderr)
94+
raise RuntimeError(f'Preprocessing failed: {" ".join(command)}')
95+
96+
# Strip all preprocessor directives that assemblers can't handle
97+
# (e.g., armasm64.exe doesn't accept any # directives)
98+
# Remove lines starting with # (preprocessor output like #line, # 1 "file", etc.)
99+
lines = result.stdout.splitlines(keepends=True)
100+
cleaned_lines = [line for line in lines if not line.lstrip().startswith('#')]
101+
cleaned = ''.join(cleaned_lines)
102+
103+
output.write_text(cleaned, encoding='utf-8')
104+
105+
# If --assemble is specified, also run the assembler to produce an object file
106+
if args.assemble:
107+
assemble_output = Path(normalize_path(args.assemble))
108+
assemble_output.parent.mkdir(parents=True, exist_ok=True)
109+
110+
armasm64 = find_armasm64()
111+
asm_command = [armasm64, '-nologo', '-g', str(output), '-o', str(assemble_output)]
112+
113+
asm_result = subprocess.run(asm_command, capture_output=True, text=True)
114+
if asm_result.returncode != 0:
115+
sys.stderr.write(asm_result.stderr)
116+
sys.stderr.write(asm_result.stdout)
117+
raise RuntimeError(f'Assembly failed: {" ".join(asm_command)}')
118+
119+
120+
def main(argv=None):
121+
parser = argparse.ArgumentParser(description='Preprocess libffi assembly source')
122+
parser.add_argument('--input', required=True)
123+
parser.add_argument('--output', required=True)
124+
parser.add_argument('--include-dir', action='append', default=[])
125+
parser.add_argument('--define', action='append', default=[])
126+
parser.add_argument('--assemble', help='Also assemble the output to this object file')
127+
args = parser.parse_args(argv)
128+
129+
preprocess(args)
130+
return 0
131+
132+
133+
if __name__ == '__main__':
134+
raise SystemExit(main())

0 commit comments

Comments
 (0)