nemotron-ocr-v2 / nemotron-ocr /hatch_build.py
Ryan Chesler
improve install docs and process
65abd8a
Raw
History Blame Contribute Delete
2.83 kB
# SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
from __future__ import annotations
import os
import sys
import subprocess
from pathlib import Path
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
def _extension_up_to_date(project_root: Path) -> bool:
"""Return True if a built .so exists and is newer than all sources.
Respects the following directories:
- src/nemotron_ocr_cpp (Python shim and built .so location)
- cpp/ (C++/CUDA sources)
- scripts/ (build script)
"""
extension_dir = project_root / "src" / "nemotron_ocr_cpp"
candidates = list(extension_dir.glob("_nemotron_ocr_cpp*.so"))
if not candidates:
return False
newest_so_mtime = max(p.stat().st_mtime for p in candidates)
newest_src_mtime = 0.0
for directory in (project_root / "cpp", project_root / "scripts", extension_dir):
if not directory.exists():
continue
for path in directory.rglob("*"):
if not path.is_file():
continue
if path.suffix in {".cu", ".cpp", ".cuh", ".h", ".py"}:
mtime = path.stat().st_mtime
if mtime > newest_src_mtime:
newest_src_mtime = mtime
return newest_so_mtime >= newest_src_mtime
def _get_platform_tag() -> str:
"""Return a PEP 425 platform tag for the current system."""
import sysconfig
platform = sysconfig.get_platform().replace("-", "_").replace(".", "_")
return platform
class CustomBuildHook(BuildHookInterface):
def initialize(self, version: str, build_data: dict) -> None:
project_root = Path(__file__).parent
script_path = project_root / "scripts" / "build-extension.py"
env = os.environ.copy()
env.setdefault("BUILD_CPP_EXTENSION", "1")
force_rebuild = env.get("BUILD_CPP_FORCE", "0") == "1"
build_enabled = env.get("BUILD_CPP_EXTENSION", "1") == "1"
if not build_enabled:
return
if not force_rebuild and _extension_up_to_date(project_root):
pass # skip rebuild, but still set the tag below
else:
subprocess.run(
[
os.fspath(sys.executable),
os.fspath(script_path),
],
cwd=os.fspath(project_root),
env=env,
check=True,
)
# Tag the wheel as platform-specific so the .so is usable
python_tag = f"cp{sys.version_info.major}{sys.version_info.minor}"
abi_tag = python_tag
platform_tag = _get_platform_tag()
build_data["tag"] = f"{python_tag}-{abi_tag}-{platform_tag}"
build_data["pure_python"] = False