1*da0073e9SAndroid Build Coastguard Worker#!/usr/bin/env python3 2*da0073e9SAndroid Build Coastguard Worker# Tool quickly rebuild one or two files with debug info 3*da0073e9SAndroid Build Coastguard Worker# Mimics following behavior: 4*da0073e9SAndroid Build Coastguard Worker# - touch file 5*da0073e9SAndroid Build Coastguard Worker# - ninja -j1 -v -n torch_python | sed -e 's/-O[23]/-g/g' -e 's#\[[0-9]\+\/[0-9]\+\] \+##' |sh 6*da0073e9SAndroid Build Coastguard Worker# - Copy libs from build/lib to torch/lib folder 7*da0073e9SAndroid Build Coastguard Worker 8*da0073e9SAndroid Build Coastguard Workerfrom __future__ import annotations 9*da0073e9SAndroid Build Coastguard Worker 10*da0073e9SAndroid Build Coastguard Workerimport subprocess 11*da0073e9SAndroid Build Coastguard Workerimport sys 12*da0073e9SAndroid Build Coastguard Workerfrom pathlib import Path 13*da0073e9SAndroid Build Coastguard Workerfrom typing import Any 14*da0073e9SAndroid Build Coastguard Worker 15*da0073e9SAndroid Build Coastguard Worker 16*da0073e9SAndroid Build Coastguard WorkerPYTORCH_ROOTDIR = Path(__file__).resolve().parent.parent 17*da0073e9SAndroid Build Coastguard WorkerTORCH_DIR = PYTORCH_ROOTDIR / "torch" 18*da0073e9SAndroid Build Coastguard WorkerTORCH_LIB_DIR = TORCH_DIR / "lib" 19*da0073e9SAndroid Build Coastguard WorkerBUILD_DIR = PYTORCH_ROOTDIR / "build" 20*da0073e9SAndroid Build Coastguard WorkerBUILD_LIB_DIR = BUILD_DIR / "lib" 21*da0073e9SAndroid Build Coastguard Worker 22*da0073e9SAndroid Build Coastguard Worker 23*da0073e9SAndroid Build Coastguard Workerdef check_output(args: list[str], cwd: str | None = None) -> str: 24*da0073e9SAndroid Build Coastguard Worker return subprocess.check_output(args, cwd=cwd).decode("utf-8") 25*da0073e9SAndroid Build Coastguard Worker 26*da0073e9SAndroid Build Coastguard Worker 27*da0073e9SAndroid Build Coastguard Workerdef parse_args() -> Any: 28*da0073e9SAndroid Build Coastguard Worker from argparse import ArgumentParser 29*da0073e9SAndroid Build Coastguard Worker 30*da0073e9SAndroid Build Coastguard Worker parser = ArgumentParser(description="Incremental build PyTorch with debinfo") 31*da0073e9SAndroid Build Coastguard Worker parser.add_argument("--verbose", action="store_true") 32*da0073e9SAndroid Build Coastguard Worker parser.add_argument("files", nargs="*") 33*da0073e9SAndroid Build Coastguard Worker return parser.parse_args() 34*da0073e9SAndroid Build Coastguard Worker 35*da0073e9SAndroid Build Coastguard Worker 36*da0073e9SAndroid Build Coastguard Workerdef get_lib_extension() -> str: 37*da0073e9SAndroid Build Coastguard Worker if sys.platform == "linux": 38*da0073e9SAndroid Build Coastguard Worker return "so" 39*da0073e9SAndroid Build Coastguard Worker if sys.platform == "darwin": 40*da0073e9SAndroid Build Coastguard Worker return "dylib" 41*da0073e9SAndroid Build Coastguard Worker raise RuntimeError(f"Usupported platform {sys.platform}") 42*da0073e9SAndroid Build Coastguard Worker 43*da0073e9SAndroid Build Coastguard Worker 44*da0073e9SAndroid Build Coastguard Workerdef create_symlinks() -> None: 45*da0073e9SAndroid Build Coastguard Worker """Creates symlinks from build/lib to torch/lib""" 46*da0073e9SAndroid Build Coastguard Worker if not TORCH_LIB_DIR.exists(): 47*da0073e9SAndroid Build Coastguard Worker raise RuntimeError(f"Can't create symlinks as {TORCH_LIB_DIR} does not exist") 48*da0073e9SAndroid Build Coastguard Worker if not BUILD_LIB_DIR.exists(): 49*da0073e9SAndroid Build Coastguard Worker raise RuntimeError(f"Can't create symlinks as {BUILD_LIB_DIR} does not exist") 50*da0073e9SAndroid Build Coastguard Worker for torch_lib in TORCH_LIB_DIR.glob(f"*.{get_lib_extension()}"): 51*da0073e9SAndroid Build Coastguard Worker if torch_lib.is_symlink(): 52*da0073e9SAndroid Build Coastguard Worker continue 53*da0073e9SAndroid Build Coastguard Worker build_lib = BUILD_LIB_DIR / torch_lib.name 54*da0073e9SAndroid Build Coastguard Worker if not build_lib.exists(): 55*da0073e9SAndroid Build Coastguard Worker raise RuntimeError(f"Can't find {build_lib} corresponding to {torch_lib}") 56*da0073e9SAndroid Build Coastguard Worker torch_lib.unlink() 57*da0073e9SAndroid Build Coastguard Worker torch_lib.symlink_to(build_lib) 58*da0073e9SAndroid Build Coastguard Worker 59*da0073e9SAndroid Build Coastguard Worker 60*da0073e9SAndroid Build Coastguard Workerdef has_build_ninja() -> bool: 61*da0073e9SAndroid Build Coastguard Worker return (BUILD_DIR / "build.ninja").exists() 62*da0073e9SAndroid Build Coastguard Worker 63*da0073e9SAndroid Build Coastguard Worker 64*da0073e9SAndroid Build Coastguard Workerdef is_devel_setup() -> bool: 65*da0073e9SAndroid Build Coastguard Worker output = check_output([sys.executable, "-c", "import torch;print(torch.__file__)"]) 66*da0073e9SAndroid Build Coastguard Worker return output.strip() == str(TORCH_DIR / "__init__.py") 67*da0073e9SAndroid Build Coastguard Worker 68*da0073e9SAndroid Build Coastguard Worker 69*da0073e9SAndroid Build Coastguard Workerdef create_build_plan() -> list[tuple[str, str]]: 70*da0073e9SAndroid Build Coastguard Worker output = check_output( 71*da0073e9SAndroid Build Coastguard Worker ["ninja", "-j1", "-v", "-n", "torch_python"], cwd=str(BUILD_DIR) 72*da0073e9SAndroid Build Coastguard Worker ) 73*da0073e9SAndroid Build Coastguard Worker rc = [] 74*da0073e9SAndroid Build Coastguard Worker for line in output.split("\n"): 75*da0073e9SAndroid Build Coastguard Worker if not line.startswith("["): 76*da0073e9SAndroid Build Coastguard Worker continue 77*da0073e9SAndroid Build Coastguard Worker line = line.split("]", 1)[1].strip() 78*da0073e9SAndroid Build Coastguard Worker if line.startswith(": &&") and line.endswith("&& :"): 79*da0073e9SAndroid Build Coastguard Worker line = line[4:-4] 80*da0073e9SAndroid Build Coastguard Worker line = line.replace("-O2", "-g").replace("-O3", "-g") 81*da0073e9SAndroid Build Coastguard Worker name = line.split("-o ", 1)[1].split(" ")[0] 82*da0073e9SAndroid Build Coastguard Worker rc.append((name, line)) 83*da0073e9SAndroid Build Coastguard Worker return rc 84*da0073e9SAndroid Build Coastguard Worker 85*da0073e9SAndroid Build Coastguard Worker 86*da0073e9SAndroid Build Coastguard Workerdef main() -> None: 87*da0073e9SAndroid Build Coastguard Worker if sys.platform == "win32": 88*da0073e9SAndroid Build Coastguard Worker print("Not supported on Windows yet") 89*da0073e9SAndroid Build Coastguard Worker sys.exit(-95) 90*da0073e9SAndroid Build Coastguard Worker if not is_devel_setup(): 91*da0073e9SAndroid Build Coastguard Worker print( 92*da0073e9SAndroid Build Coastguard Worker "Not a devel setup of PyTorch, please run `python3 setup.py develop --user` first" 93*da0073e9SAndroid Build Coastguard Worker ) 94*da0073e9SAndroid Build Coastguard Worker sys.exit(-1) 95*da0073e9SAndroid Build Coastguard Worker if not has_build_ninja(): 96*da0073e9SAndroid Build Coastguard Worker print("Only ninja build system is supported at the moment") 97*da0073e9SAndroid Build Coastguard Worker sys.exit(-1) 98*da0073e9SAndroid Build Coastguard Worker args = parse_args() 99*da0073e9SAndroid Build Coastguard Worker for file in args.files: 100*da0073e9SAndroid Build Coastguard Worker if file is None: 101*da0073e9SAndroid Build Coastguard Worker continue 102*da0073e9SAndroid Build Coastguard Worker Path(file).touch() 103*da0073e9SAndroid Build Coastguard Worker build_plan = create_build_plan() 104*da0073e9SAndroid Build Coastguard Worker if len(build_plan) == 0: 105*da0073e9SAndroid Build Coastguard Worker return print("Nothing to do") 106*da0073e9SAndroid Build Coastguard Worker if len(build_plan) > 100: 107*da0073e9SAndroid Build Coastguard Worker print("More than 100 items needs to be rebuild, run `ninja torch_python` first") 108*da0073e9SAndroid Build Coastguard Worker sys.exit(-1) 109*da0073e9SAndroid Build Coastguard Worker for idx, (name, cmd) in enumerate(build_plan): 110*da0073e9SAndroid Build Coastguard Worker print(f"[{idx + 1 } / {len(build_plan)}] Building {name}") 111*da0073e9SAndroid Build Coastguard Worker if args.verbose: 112*da0073e9SAndroid Build Coastguard Worker print(cmd) 113*da0073e9SAndroid Build Coastguard Worker subprocess.check_call(["sh", "-c", cmd], cwd=BUILD_DIR) 114*da0073e9SAndroid Build Coastguard Worker create_symlinks() 115*da0073e9SAndroid Build Coastguard Worker 116*da0073e9SAndroid Build Coastguard Worker 117*da0073e9SAndroid Build Coastguard Workerif __name__ == "__main__": 118*da0073e9SAndroid Build Coastguard Worker main() 119