Skip to content

Commit 3341737

Browse files
committed
clean up path
1 parent 09639e8 commit 3341737

File tree

1 file changed

+31
-90
lines changed

1 file changed

+31
-90
lines changed

backends/qualcomm/scripts/download_qnn_sdk.py

Lines changed: 31 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212

1313
from tqdm import tqdm
1414

15-
SDK_DIR = pathlib.Path(__file__).parent.parent / "sdk" / "qnn"
1615
PKG_ROOT = pathlib.Path(__file__).parent.parent
16+
SDK_DIR = PKG_ROOT / "sdk" / "qnn"
1717

1818

1919
def is_linux_x86() -> bool:
@@ -23,10 +23,12 @@ def is_linux_x86() -> bool:
2323
Returns:
2424
bool: True if the system is Linux x86_64, False otherwise.
2525
"""
26-
system = platform.system().lower()
27-
machine = platform.machine().lower()
28-
29-
return system == "linux" and machine in ("x86_64", "amd64", "i386", "i686")
26+
return platform.system().lower() == "linux" and platform.machine().lower() in (
27+
"x86_64",
28+
"amd64",
29+
"i386",
30+
"i686",
31+
)
3032

3133

3234
def _download_qnn_sdk() -> Optional[pathlib.Path]:
@@ -58,16 +60,14 @@ def _download_qnn_sdk() -> Optional[pathlib.Path]:
5860

5961
print(f"Downloading Qualcomm SDK from {qairt_url}...")
6062
try:
61-
# Use urlretrieve with a reporthook to show progress
63+
6264
def make_report_progress():
63-
last_reported = 0 # nonlocal variable
65+
last_reported = 0
6466

6567
def report_progress(block_num, block_size, total_size):
6668
nonlocal last_reported
6769
downloaded = block_num * block_size
6870
percent = downloaded / total_size * 100
69-
70-
# Report every 20%
7171
if percent - last_reported >= 20 or percent >= 100:
7272
print(
7373
f"Downloaded: {downloaded}/{total_size} bytes ({percent:.2f}%)"
@@ -76,25 +76,19 @@ def report_progress(block_num, block_size, total_size):
7676

7777
return report_progress
7878

79-
report_progress = make_report_progress()
80-
urllib.request.urlretrieve(qairt_url, archive_path, report_progress)
79+
urllib.request.urlretrieve(qairt_url, archive_path, make_report_progress())
8180
print("Download completed!")
8281

83-
# Check if file was downloaded successfully
84-
if archive_path.exists():
85-
file_size = archive_path.stat().st_size
86-
print(f"Downloaded file size: {file_size} bytes")
87-
if file_size == 0:
88-
print("WARNING: Downloaded file is empty!")
89-
else:
82+
if archive_path.exists() and archive_path.stat().st_size == 0:
83+
print("WARNING: Downloaded file is empty!")
84+
elif not archive_path.exists():
9085
print("ERROR: File was not downloaded!")
9186
return None
9287

9388
except Exception as e:
9489
print(f"Error during download: {e}")
9590
return None
9691

97-
# Check extraction method
9892
if qairt_url.endswith(".zip"):
9993
print("Extracting ZIP archive...")
10094
_extract_zip(archive_path, qairt_content_dir, SDK_DIR)
@@ -104,7 +98,6 @@ def report_progress(block_num, block_size, total_size):
10498
else:
10599
raise ValueError(f"Unsupported archive format: {qairt_url}")
106100

107-
# Verify extraction
108101
print(f"Verifying extraction to {SDK_DIR}")
109102
if SDK_DIR.exists():
110103
print(f"SDK directory exists. Contents:")
@@ -118,43 +111,30 @@ def report_progress(block_num, block_size, total_size):
118111
return SDK_DIR
119112

120113

121-
# You might also want to add detailed logging to your extraction functions
122114
def _extract_zip(archive_path, content_dir, target_dir):
123115
print(f"Extracting {archive_path} to {target_dir}")
124116
print(f"Looking for content in subdirectory: {content_dir}")
125117

126118
target_dir.mkdir(parents=True, exist_ok=True)
127119

128120
with zipfile.ZipFile(archive_path, "r") as zip_ref:
129-
# Filter files that start with content_dir
130121
files_to_extract = [f for f in zip_ref.namelist() if f.startswith(content_dir)]
131122

132123
for file in tqdm(files_to_extract, desc="Extracting files"):
133-
relative_path = os.path.relpath(file, content_dir)
134-
if relative_path == ".":
135-
continue # skip the root directory itself
136-
137-
target_path = target_dir / relative_path
124+
relative_path = pathlib.Path(file).relative_to(content_dir)
125+
if relative_path == pathlib.Path("."):
126+
continue
138127

128+
out_path = target_dir / relative_path
139129
if file.endswith("/"):
140-
target_path.mkdir(parents=True, exist_ok=True)
130+
out_path.mkdir(parents=True, exist_ok=True)
141131
else:
142-
target_path.parent.mkdir(
143-
parents=True, exist_ok=True
144-
) # ensure parent exists
145-
with zip_ref.open(file) as source, open(target_path, "wb") as target:
146-
shutil.copyfileobj(source, target)
132+
out_path.parent.mkdir(parents=True, exist_ok=True)
133+
with zip_ref.open(file) as src, open(out_path, "wb") as dst:
134+
shutil.copyfileobj(src, dst)
147135

148136

149137
def _extract_tar(archive_path: pathlib.Path, prefix: str, target_dir: pathlib.Path):
150-
"""
151-
Extract files from a tar.gz archive into target_dir, stripping a prefix.
152-
153-
Args:
154-
archive_path (pathlib.Path): Path to the .tar.gz or .tgz archive.
155-
prefix (str): Prefix folder inside the archive to strip.
156-
target_dir (pathlib.Path): Destination directory.
157-
"""
158138
with tarfile.open(archive_path, "r:gz") as tf:
159139
for m in tf.getmembers():
160140
if not m.name.startswith(prefix + "/"):
@@ -170,7 +150,6 @@ def _extract_tar(archive_path: pathlib.Path, prefix: str, target_dir: pathlib.Pa
170150
out_path.parent.mkdir(parents=True, exist_ok=True)
171151
src = tf.extractfile(m)
172152
if src is None:
173-
# Skip non-regular files (links, devices, etc.)
174153
continue
175154
with src, open(out_path, "wb") as dst:
176155
dst.write(src.read())
@@ -179,44 +158,33 @@ def _extract_tar(archive_path: pathlib.Path, prefix: str, target_dir: pathlib.Pa
179158
LLVM_VERSION = "14.0.0"
180159
LIBCXX_BASE_NAME = f"clang+llvm-{LLVM_VERSION}-x86_64-linux-gnu-ubuntu-18.04"
181160
LLVM_URL = f"https://github.com/llvm/llvm-project/releases/download/llvmorg-{LLVM_VERSION}/{LIBCXX_BASE_NAME}.tar.xz"
182-
183161
REQUIRED_LIBS = [
184162
"libc++.so.1.0",
185163
"libc++abi.so.1.0",
186164
"libunwind.so.1",
187165
"libm.so.6",
188-
"libpython3.10.so.1.0", # optional, include if needed
166+
"libpython3.10.so.1.0",
189167
]
190168

191169

192-
def _get_libcxx_dir(pkg_root: pathlib.Path) -> pathlib.Path:
193-
"""Path where libc++ should be staged in the wheel."""
194-
return pkg_root / "sdk" / f"libcxx-{LLVM_VERSION}"
195-
196-
197170
def _stage_libcxx(target_dir: pathlib.Path):
198-
"""Download LLVM tarball and stage only the needed .so files."""
199171
target_dir.mkdir(parents=True, exist_ok=True)
200172

201-
# Already staged?
202173
if all((target_dir / libname).exists() for libname in REQUIRED_LIBS):
203174
print(f"[libcxx] Already staged at {target_dir}, skipping download")
204175
return
205176

206177
temp_tar = pathlib.Path("/tmp") / f"{LIBCXX_BASE_NAME}.tar.xz"
207178
temp_extract = pathlib.Path("/tmp") / LIBCXX_BASE_NAME
208179

209-
# Download tarball if missing
210180
if not temp_tar.exists():
211181
print(f"[libcxx] Downloading {LLVM_URL}")
212182
urllib.request.urlretrieve(LLVM_URL, temp_tar)
213183

214-
# Extract
215184
print(f"[libcxx] Extracting {temp_tar}")
216185
with tarfile.open(temp_tar, "r:xz") as tar:
217186
tar.extractall(temp_extract.parent)
218187

219-
# Copy required .so files
220188
lib_src = temp_extract / "lib"
221189
for fname in REQUIRED_LIBS:
222190
src_path = lib_src / fname
@@ -225,7 +193,6 @@ def _stage_libcxx(target_dir: pathlib.Path):
225193
continue
226194
shutil.copy(src_path, target_dir / fname)
227195

228-
# Create symlinks for libc++/abi
229196
libcxx = target_dir / "libc++.so.1.0"
230197
libcxx_abi = target_dir / "libc++abi.so.1.0"
231198
if libcxx.exists():
@@ -239,24 +206,12 @@ def _stage_libcxx(target_dir: pathlib.Path):
239206

240207

241208
def _load_libcxx_libs(lib_path):
242-
"""
243-
Load libc++ shared libraries from the given directory.
244-
245-
Ensures libc++abi is loaded first, then libc++, then any other .so files.
246-
"""
247209
candidates = list(lib_path.glob("*.so*"))
248-
249210
priority = ["libc++abi", "libc++"]
250-
sorted_candidates = []
251-
252-
for name in priority:
253-
for f in candidates:
254-
if f.name.startswith(name):
255-
sorted_candidates.append(f)
256-
257-
for f in candidates:
258-
if f not in sorted_candidates:
259-
sorted_candidates.append(f)
211+
sorted_candidates = [
212+
f for name in priority for f in candidates if f.name.startswith(name)
213+
]
214+
sorted_candidates += [f for f in candidates if f not in sorted_candidates]
260215

261216
for sofile in sorted_candidates:
262217
try:
@@ -267,27 +222,14 @@ def _load_libcxx_libs(lib_path):
267222

268223

269224
def install_qnn_sdk(force_download: bool = True) -> bool:
270-
"""
271-
Initialize Qualcomm backend:
272-
- Ensure SDK is available (env or packaged/downloaded copy)
273-
- Load QNN libraries
274-
- Stage and load libc++
275-
276-
Returns:
277-
bool: True if QNN was successfully loaded, False otherwise.
278-
"""
279-
280-
# --- Qualcomm SDK handling ---
281-
qnn_sdk_dir = SDK_DIR
282-
print(f"[INIT] qnn_sdk_dir: {qnn_sdk_dir}")
283-
if not qnn_sdk_dir.exists():
225+
print(f"[INIT] SDK_DIR: {SDK_DIR}")
226+
if not SDK_DIR.exists():
284227
print("[INIT] Qualcomm SDK not found. Downloading...")
285228
_download_qnn_sdk()
286229

287-
os.environ["QNN_SDK_ROOT"] = str(qnn_sdk_dir)
230+
os.environ["QNN_SDK_ROOT"] = str(SDK_DIR)
288231

289-
# Load QNN library
290-
qnn_lib = qnn_sdk_dir / "lib" / "x86_64-linux-clang" / "libQnnHtp.so"
232+
qnn_lib = SDK_DIR / "lib" / "x86_64-linux-clang" / "libQnnHtp.so"
291233
print(f"[INIT] qnn_lib: {qnn_lib}")
292234
try:
293235
ctypes.CDLL(str(qnn_lib), mode=ctypes.RTLD_GLOBAL)
@@ -296,9 +238,8 @@ def install_qnn_sdk(force_download: bool = True) -> bool:
296238
print(f"[ERROR] Failed to load QNN library at {qnn_lib}: {e}")
297239
return False
298240

299-
# --- libc++ handling ---
300241
try:
301-
libcxx_dir = _get_libcxx_dir(PKG_ROOT / "sdk")
242+
libcxx_dir = PKG_ROOT / "sdk" / f"libcxx-{LLVM_VERSION}"
302243
_stage_libcxx(libcxx_dir)
303244
_load_libcxx_libs(libcxx_dir)
304245
print(f"[INIT] Loaded libc++ from {libcxx_dir}")

0 commit comments

Comments
 (0)