"""
获取 opapi 二进制绝对路径
Examples 场景下, 用于 built-in 包与 custom 包共存场景下获取正确的 opapi 动态库绝对路径.
"""
import argparse
import logging
import os
import subprocess
from pathlib import Path
class OpApiMgr:
@staticmethod
def has_symbol(file_path: Path, sym: str) -> bool:
cmd = f"nm -D {file_path}".split()
ret = subprocess.run(cmd, capture_output=True, check=True, encoding="utf-8")
ret.check_returncode()
return sym in ret.stdout
@staticmethod
def get_environ_custom_lib_paths() -> list[Path]:
paths: list[Path] = []
env = os.getenv("ASCEND_CUSTOM_OPP_PATH")
if env is None:
logging.debug("ASCEND_CUSTOM_OPP_PATH is none.")
return paths
str_paths = str(env).split(sep=":")
if len(str_paths) == 0:
return paths
for s in str_paths:
if len(s) == 0:
continue
p = Path(s, "op_api/lib/libcust_opapi.so").resolve(strict=False)
if not p.exists():
logging.warning("Skip not exist path(%s)", p)
continue
paths.append(p)
return paths
@staticmethod
def get_default_custom_lib_paths() -> list[Path]:
paths: list[Path] = []
env = os.getenv("ASCEND_OPP_PATH")
if env is None:
logging.warning("ASCEND_OPP_PATH is none.")
return paths
path_env = Path(env).resolve(strict=False)
if not path_env.exists():
logging.warning("ASCEND_CUSTOM_OPP_PATH(%s) not exist.", path_env)
return paths
cfg_file = Path(path_env, "vendors/config.ini").resolve(strict=False)
if not cfg_file.exists():
logging.debug("Config file(%s) not exist.", cfg_file)
return paths
with open(cfg_file) as fh:
lines = fh.readlines()
for line in lines:
if not line.startswith("load_priority="):
continue
sub_str = line[14:]
sub_str = sub_str.split(sep="#")[0]
sub_str = sub_str.replace("\r", "").replace("\n", "").replace(" ", "")
if len(sub_str) == 0:
continue
vendors = sub_str.split(sep=",")
for v in vendors:
if len(v) == 0:
continue
p = Path(path_env, "vendors", v, "op_api/lib/libcust_opapi.so")
if not p.exists():
logging.warning("Skip not exist path(%s)", p)
continue
paths.append(p)
return paths
@staticmethod
def get_default_builtin_lib_paths() -> list[Path]:
paths: list[Path] = []
env = os.getenv("ASCEND_OPP_PATH")
if env is None:
logging.warning("ASCEND_OPP_PATH is none.")
return paths
path_env = Path(env).resolve(strict=False)
if not path_env.exists():
logging.warning("ASCEND_CUSTOM_OPP_PATH(%s) not exist.", path_env)
return paths
shared = Path(path_env, "lib64/libopapi.so").resolve(strict=False)
if not shared.exists():
logging.error("Can't get built-in libopapi.so(%s)", shared)
return paths
paths.append(shared)
return paths
@staticmethod
def judge_lib_path(sym: str) -> Path | None:
path = None
environ_custom_lib_paths = OpApiMgr.get_environ_custom_lib_paths()
default_custom_lib_paths = OpApiMgr.get_default_custom_lib_paths()
default_builtin_lib_paths = OpApiMgr.get_default_builtin_lib_paths()
path_list = environ_custom_lib_paths + default_custom_lib_paths + default_builtin_lib_paths
for p in path_list:
if OpApiMgr.has_symbol(file_path=p, sym=sym):
path = p
break
return path
@staticmethod
def main() -> str:
ps = argparse.ArgumentParser(description="Get opapi path", epilog="Best Regards!")
ps.add_argument("-f", "--func", required=True, nargs=1, type=str, help="Func name")
args = ps.parse_args()
sym = args.func[0]
if sym is None or len(sym) == 0:
return ""
lib = OpApiMgr.judge_lib_path(sym=sym)
if lib is None:
return ""
else:
return str(lib)
if __name__ == "__main__":
logging.basicConfig(format="%(filename)s:%(lineno)d [%(levelname)s] %(message)s", level=logging.INFO)
print(OpApiMgr.main(), end="")