-
Notifications
You must be signed in to change notification settings - Fork 48
Expand file tree
/
Copy pathcompiler.py
More file actions
135 lines (103 loc) · 3.87 KB
/
compiler.py
File metadata and controls
135 lines (103 loc) · 3.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
"""Core compiler logic for ddbc_bindings.
Locates and runs the platform-specific build script
(``build.sh`` / ``build.bat``) in ``mssql_python/pybind/``.
"""
import sys
import subprocess
from pathlib import Path
from typing import Optional
from .platform_utils import get_platform_info
def find_pybind_dir() -> Path:
"""Find the pybind directory containing build scripts."""
# Try relative to this file first (for installed package)
possible_paths = [
Path(__file__).parent.parent / "mssql_python" / "pybind",
Path.cwd() / "mssql_python" / "pybind",
]
# Check for platform-appropriate build script
build_script = "build.bat" if sys.platform.startswith("win") else "build.sh"
for path in possible_paths:
if path.exists() and (path / build_script).exists():
return path
raise FileNotFoundError(
f"Could not find mssql_python/pybind directory with {build_script}. "
"Make sure you're running from the project root."
)
def compile_ddbc(
arch: Optional[str] = None,
coverage: bool = False,
verbose: bool = True,
) -> bool:
"""
Compile ddbc_bindings using the platform-specific build script.
Args:
arch: Target architecture (Windows only: x64, x86, arm64)
coverage: Enable coverage instrumentation (Linux/macOS only)
verbose: Print build output
Returns:
True if build succeeded, False otherwise
Raises:
FileNotFoundError: If build script is not found
RuntimeError: If build fails
"""
pybind_dir = find_pybind_dir()
if arch is None:
arch, _ = get_platform_info()
if sys.platform.startswith("win"):
return _run_windows_build(pybind_dir, arch, verbose)
else:
return _run_unix_build(pybind_dir, coverage, verbose)
def _run_windows_build(pybind_dir: Path, arch: str, verbose: bool) -> bool:
"""Run build.bat on Windows."""
build_script = pybind_dir / "build.bat"
if not build_script.exists():
raise FileNotFoundError(f"Build script not found: {build_script}")
cmd = [str(build_script), arch]
if verbose:
print(f"[build_backend] Running: {' '.join(cmd)}")
print(f"[build_backend] Working directory: {pybind_dir}")
result = subprocess.run(
cmd,
cwd=pybind_dir,
check=False,
capture_output=not verbose,
)
if result.returncode != 0:
if not verbose:
if result.stdout:
print(result.stdout.decode(), file=sys.stderr)
if result.stderr:
print(result.stderr.decode(), file=sys.stderr)
raise RuntimeError(f"build.bat failed with exit code {result.returncode}")
if verbose:
print("[build_backend] Windows build completed successfully!")
return True
def _run_unix_build(pybind_dir: Path, coverage: bool, verbose: bool) -> bool:
"""Run build.sh on macOS/Linux."""
build_script = pybind_dir / "build.sh"
if not build_script.exists():
raise FileNotFoundError(f"Build script not found: {build_script}")
# Make sure the script is executable
build_script.chmod(0o755)
cmd = ["bash", str(build_script)]
if coverage:
cmd.append("--coverage")
if verbose:
print(f"[build_backend] Running: {' '.join(cmd)}")
print(f"[build_backend] Working directory: {pybind_dir}")
result = subprocess.run(
cmd,
cwd=pybind_dir,
check=False,
capture_output=not verbose,
)
if result.returncode != 0:
if not verbose:
if result.stdout:
print(result.stdout.decode(), file=sys.stderr)
if result.stderr:
print(result.stderr.decode(), file=sys.stderr)
raise RuntimeError(f"build.sh failed with exit code {result.returncode}")
if verbose:
print("[build_backend] Unix build completed successfully!")
return True