Skip to content

Commit f15e5b4

Browse files
committed
try upgrade libc
1 parent 90eaa92 commit f15e5b4

File tree

1 file changed

+115
-0
lines changed

1 file changed

+115
-0
lines changed

backends/qualcomm/scripts/download_qnn_sdk.py

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@
66
import platform
77
import re
88
import shutil
9+
import sys
910
import tarfile
1011
import tempfile
1112
import urllib.request
1213
import zipfile
1314
from typing import Dict, List, Optional, Tuple
1415

16+
1517
logger = logging.getLogger(__name__)
1618
logger.addHandler(logging.NullHandler())
1719

@@ -241,6 +243,115 @@ def _extract_tar(archive_path: pathlib.Path, prefix: str, target_dir: pathlib.Pa
241243
dst.write(src.read())
242244

243245

246+
####################
247+
# libc management
248+
####################
249+
250+
GLIBC_ROOT = pathlib.Path("/tmp/glibc-2.34")
251+
GLIBC_LOADER = GLIBC_ROOT / "lib" / "ld-linux-x86-64.so.2"
252+
GLIBC_LIBDIR = GLIBC_ROOT / "lib"
253+
GLIBC_REEXEC_GUARD = "QNN_GLIBC_REEXEC"
254+
255+
256+
def _parse_ver_tuple(s: str) -> Tuple[int, int]:
257+
parts = re.findall(r"\d+", s)
258+
return (int(parts[0]), int(parts[1])) if len(parts) >= 2 else (0, 0)
259+
260+
261+
def _detect_glibc_version() -> Optional[Tuple[int, int]]:
262+
for path in REQUIRED_LIBC_LIBS:
263+
try:
264+
out = subprocess.check_output([path, "--version"], stderr=subprocess.STDOUT)
265+
first = out.decode(errors="ignore").split("\n", 1)[0]
266+
m = re.search(r"version\s+(\d+\.\d+)", first, re.IGNORECASE)
267+
if m:
268+
vt = _parse_ver_tuple(m.group(1))
269+
logger.info("[glibc] Found %s version %s", path, vt)
270+
return vt
271+
except Exception as e:
272+
logger.info("[glibc] Skipped %s (%s)", path, e)
273+
return None
274+
275+
276+
def _install_glibc_234():
277+
"""Download and build glibc 2.34 into /tmp/glibc-2.34 if missing."""
278+
if GLIBC_LOADER.exists():
279+
logger.info("[glibc] Found existing glibc-2.34 at %s", GLIBC_ROOT)
280+
return
281+
282+
logger.info(
283+
"[glibc] Installing glibc 2.34 into %s ... this may take a while", GLIBC_ROOT
284+
)
285+
url = "https://ftp.gnu.org/gnu/libc/glibc-2.34.tar.xz"
286+
287+
with tempfile.TemporaryDirectory() as tmpdir:
288+
tarball = pathlib.Path(tmpdir) / "glibc-2.34.tar.xz"
289+
urllib.request.urlretrieve(url, tarball)
290+
logger.info("[glibc] Downloaded %s", url)
291+
build_dir = pathlib.Path(tmpdir) / "glibc-build"
292+
src_dir = pathlib.Path(tmpdir) / "glibc-2.34"
293+
os.makedirs(build_dir, exist_ok=True)
294+
295+
# Extract
296+
logger.info("[glibc] Extracting source...")
297+
with tarfile.open(tarball, "r:xz") as tf:
298+
tf.extractall(path=tmpdir)
299+
300+
# Configure and build
301+
logger.info("[glibc] Configuring build...")
302+
subprocess.check_call(
303+
["../glibc-2.34/configure", f"--prefix={GLIBC_ROOT}"],
304+
cwd=build_dir,
305+
)
306+
logger.info("[glibc] Building (this may take several minutes)...")
307+
subprocess.check_call(["make", "-j", str(os.cpu_count())], cwd=build_dir)
308+
logger.info("[glibc] Installing...")
309+
subprocess.check_call(["make", "install"], cwd=build_dir)
310+
311+
if GLIBC_LOADER.exists():
312+
logger.info("[glibc] Successfully installed glibc 2.34 at %s", GLIBC_ROOT)
313+
else:
314+
logger.error(
315+
"[glibc] Install finished but loader not found at %s", GLIBC_LOADER
316+
)
317+
318+
319+
def _reexec_with_new_glibc_if_needed(min_required=(2, 29)):
320+
if os.environ.get(GLIBC_REEXEC_GUARD) == "1":
321+
logger.debug("[glibc] Already re-executed once; skipping loop.")
322+
return
323+
324+
vt = _detect_glibc_version()
325+
if vt is None:
326+
logger.warn("[glibc] Could not detect system glibc version.")
327+
elif vt < min_required:
328+
logger.warn("[glibc] System glibc %s < required %s", vt, min_required)
329+
else:
330+
logger.info("[glibc] System glibc %s >= required %s", vt, min_required)
331+
return
332+
333+
_install_glibc_234()
334+
if not GLIBC_LOADER.exists():
335+
logger.error("[glibc] Loader still missing at %s", GLIBC_LOADER)
336+
return
337+
338+
argv = [
339+
str(GLIBC_LOADER),
340+
"--library-path",
341+
str(GLIBC_LIBDIR),
342+
sys.executable,
343+
] + sys.argv
344+
env = os.environ.copy()
345+
env[GLIBC_REEXEC_GUARD] = "1"
346+
347+
logger.warn("[glibc] Re-executing under new loader: %s", argv)
348+
os.execvpe(str(GLIBC_LOADER), argv, env)
349+
350+
351+
####################
352+
# libc++ management
353+
####################
354+
244355
LLVM_VERSION = "14.0.0"
245356
LIBCXX_BASE_NAME = f"clang+llvm-{LLVM_VERSION}-x86_64-linux-gnu-ubuntu-18.04"
246357
LLVM_URL = f"https://github.com/llvm/llvm-project/releases/download/llvmorg-{LLVM_VERSION}/{LIBCXX_BASE_NAME}.tar.xz"
@@ -437,6 +548,10 @@ def install_qnn_sdk() -> bool:
437548
Returns:
438549
True if both steps succeeded (or were already satisfied), else False.
439550
"""
551+
logger.info("[QNN] Starting SDK installation")
552+
# Re-exec with glibc 2.34 if needed.
553+
_reexec_with_new_glibc_if_needed()
554+
440555
if _ensure_libcxx_stack():
441556
if _ensure_qnn_sdk_lib():
442557
return True

0 commit comments

Comments
 (0)