gemini-code-assist[bot] commented on code in PR #19719:
URL: https://github.com/apache/tvm/pull/19719#discussion_r3388857619


##########
python/tvm/libinfo.py:
##########
@@ -44,289 +50,58 @@ def package_lib_paths() -> list[Path]:
     pick the basenames they want (e.g. ``libtvm_runtime.so``) and the load
     mode; this function only returns the search path.
     """
-    pkg = Path(__file__).parent  # python/tvm/
+    pkg = _rel_top_directory()  # python/tvm/
     paths: list[Path] = []
     if os.environ.get("TVM_LIBRARY_PATH"):
         paths.append(Path(os.environ["TVM_LIBRARY_PATH"]))
     paths += [
         pkg / "lib",  # wheel layout
-        pkg.parent.parent / "build" / "lib",  # dev: <worktree>/build/lib
-        pkg.parent.parent / "lib",  # dev: <worktree>/lib
+        _dev_top_directory() / "build" / "lib",  # dev: <worktree>/build/lib
+        _dev_top_directory() / "lib",  # dev: <worktree>/lib
     ]
     return paths
 
 
-_BACKEND_RUNTIME_LIBS = ["cuda", "vulkan", "opencl", "metal", "rocm", 
"hexagon", "extra"]
-
-
-def load_backend_libs(runtime_lib_path: str) -> None:
-    """Try to load each known backend runtime DSO; failures are silent."""
-    runtime_dir = Path(runtime_lib_path).resolve().parent
-    for backend in _BACKEND_RUNTIME_LIBS:
-        try:
-            load_lib_ctypes(
-                package="tvm",
-                target_name=f"tvm_runtime_{backend}",
-                mode="RTLD_GLOBAL",
-                extra_lib_paths=[runtime_dir],
-            )
-        except (OSError, FileNotFoundError, RuntimeError):
-            pass
-
-
-def split_env_var(env_var, split):
-    """Splits environment variable string.
-
-    Parameters
-    ----------
-    env_var : str
-        Name of environment variable.
-
-    split : str
-        String to split env_var on.
-
-    Returns
-    -------
-    splits : list(string)
-        If env_var exists, split env_var. Otherwise, empty list.
-    """
-    if os.environ.get(env_var, None):
-        return [p.strip() for p in os.environ[env_var].split(split)]
-    return []
-
-
-def get_dll_directories():
-    """Get the possible dll directories"""
-    # NB: This will either be the source directory (if TVM is run
-    # inplace) or the install directory (if TVM is installed).
-    # An installed TVM's curr_path will look something like:
-    #   $PREFIX/lib/python3.6/site-packages/tvm/_ffi
-    ffi_dir = os.path.dirname(os.path.realpath(os.path.expanduser(__file__)))
-    source_dir = os.path.join(ffi_dir, "..", "..")
-    install_lib_dir = os.path.join(ffi_dir, "..", "..", "..")
-
-    dll_path = []
-
-    if os.environ.get("TVM_LIBRARY_PATH", None):
-        dll_path.append(os.environ["TVM_LIBRARY_PATH"])
-
-    if sys.platform.startswith("linux") or sys.platform.startswith("freebsd"):
-        dll_path.extend(split_env_var("LD_LIBRARY_PATH", ":"))
-        dll_path.extend(split_env_var("PATH", ":"))
-    elif sys.platform.startswith("darwin"):
-        dll_path.extend(split_env_var("DYLD_LIBRARY_PATH", ":"))
-        dll_path.extend(split_env_var("PATH", ":"))
-    elif sys.platform.startswith("win32"):
-        dll_path.extend(split_env_var("PATH", ";"))
-
-    # Pip lib directory
-    dll_path.append(ffi_dir)
-    dll_path.append(os.path.join(ffi_dir, "lib"))
-    # Default CMake build directory: shared libs are placed under build/lib/
-    # to mirror the tvm-ffi layout (so wheel install + dev-mode dlopen find
-    # them via the same `lib/` subdir).
-    dll_path.append(os.path.join(source_dir, "build", "lib"))
-    dll_path.append(os.path.join(source_dir, "build", "lib", "Release"))
-    dll_path.append(os.path.join(source_dir, "build"))
-    dll_path.append(os.path.join(source_dir, "build", "Release"))
-    # Default make build directory
-    dll_path.append(os.path.join(source_dir, "lib"))
-
-    dll_path.append(install_lib_dir)
-
-    # use extra TVM_HOME environment for finding libraries.
-    if os.environ.get("TVM_HOME", None):
-        tvm_source_home_dir = os.environ["TVM_HOME"]
-    else:
-        tvm_source_home_dir = source_dir
-
-    if os.path.isdir(tvm_source_home_dir):
-        dll_path.append(os.path.join(tvm_source_home_dir, "web", "dist", 
"wasm"))
-        dll_path.append(os.path.join(tvm_source_home_dir, "web", "dist"))
+def find_libtvm_runtime() -> str:
+    """Find the ``libtvm_runtime`` shared library.
 
-    dll_path = [os.path.realpath(x) for x in dll_path]
-    return [x for x in dll_path if os.path.isdir(x)]
-
-
-def find_lib_path(name=None, search_path=None, optional=False):
-    """Find dynamic library files.
-
-    Parameters
-    ----------
-    name : list of str
-        List of names to be found.
-
-    Returns
-    -------
-    lib_path : list(string)
-        List of all found path to the libraries
+    Mirrors :func:`tvm_ffi.libinfo.find_libtvm_ffi`: derive the platform
+    basename via :func:`tvm_ffi.libinfo._find_library_by_basename` (which also
+    searches ``package_lib_paths()`` so the dev ``build/lib`` and wheel ``lib``
+    layouts are covered), then resolve/normalize the path.
     """
-    use_runtime = use_runtime_lib()
-    dll_path = get_dll_directories()
-    # When the caller asks for a specific ``name`` we honour it directly
-    # regardless of TVM_USE_RUNTIME_LIB; that env var is interpreted by
-    # ``base.py::_load_lib`` to choose which name to ask for. This avoids
-    # the runtime/compiler dual-list logic below from making `name` paths
-    # unreachable when the user sets TVM_USE_RUNTIME_LIB.
-    if name is not None:
-        use_runtime = False
-
-    if search_path is not None:
-        if isinstance(search_path, list):
-            dll_path = dll_path + search_path
-        else:
-            dll_path.append(search_path)
-
-    if name is not None:
-        if isinstance(name, list):
-            lib_dll_path = []
-            for n in name:
-                lib_dll_path += [os.path.join(p, n) for p in dll_path]
-        else:
-            lib_dll_path = [os.path.join(p, name) for p in dll_path]
-        runtime_dll_path = []
-        ext_lib_dll_path = []
-    else:
-        if sys.platform.startswith("win32"):
-            lib_dll_names = ["libtvm_compiler.dll", "tvm_compiler.dll"]
-            runtime_dll_names = ["libtvm_runtime.dll", "tvm_runtime.dll"]
-            ext_lib_dll_names = [
-                
"3rdparty/cutlass_fpA_intB_gemm/cutlass_kernels/libfpA_intB_gemm.dll",
-                "3rdparty/libflash_attn/src/libflash_attn.dll",
-            ]
-        elif sys.platform.startswith("darwin"):
-            lib_dll_names = ["libtvm_compiler.dylib"]
-            runtime_dll_names = ["libtvm_runtime.dylib"]
-            ext_lib_dll_names = []
-        else:
-            lib_dll_names = ["libtvm_compiler.so"]
-            runtime_dll_names = ["libtvm_runtime.so"]
-            ext_lib_dll_names = [
-                
"3rdparty/cutlass_fpA_intB_gemm/cutlass_kernels/libfpA_intB_gemm.so",
-                "3rdparty/libflash_attn/src/libflash_attn.so",
-            ]
-
-        name = lib_dll_names + runtime_dll_names + ext_lib_dll_names
-        lib_dll_path = [
-            os.path.join(p, name)
-            for name in lib_dll_names
-            for p in dll_path
-            if not p.endswith("python/tvm")
-        ]
-        runtime_dll_path = [
-            os.path.join(p, name)
-            for name in runtime_dll_names
-            for p in dll_path
-            if not p.endswith("python/tvm")
-        ]
-        ext_lib_dll_path = [os.path.join(p, name) for name in 
ext_lib_dll_names for p in dll_path]
-    if not use_runtime:
-        # try to find lib_dll_path
-        lib_found = [p for p in lib_dll_path if os.path.exists(p) and 
os.path.isfile(p)]
-        lib_found += [p for p in runtime_dll_path if os.path.exists(p) and 
os.path.isfile(p)]
-        lib_found += [p for p in ext_lib_dll_path if os.path.exists(p) and 
os.path.isfile(p)]
-    else:
-        # try to find runtime_dll_path
-        use_runtime = True
-        lib_found = [p for p in runtime_dll_path if os.path.exists(p) and 
os.path.isfile(p)]
-
-    if not lib_found:
-        if not optional:
-            message = (
-                f"Cannot find libraries: {name}\n"
-                + "List of candidates:\n"
-                + "\n".join(lib_dll_path + runtime_dll_path)
-            )
-            raise RuntimeError(message)
-        return None
-
-    if use_runtime:
-        sys.stderr.write(f"Loading runtime library {lib_found[0]}... exec 
only\n")
-        sys.stderr.flush()
-    return lib_found
-
-
-def find_include_path(name=None, search_path=None, optional=False):
-    """Find header files for C compilation.
-
-    Parameters
-    ----------
-    name : list of str
-        List of directory names to be searched.
-
-    Returns
-    -------
-    include_path : list(string)
-        List of all found paths to header files.
+    candidate = tvm_ffi_libinfo._find_library_by_basename(
+        "tvm", "tvm_runtime", extra_lib_paths=package_lib_paths()
+    )
+    if ret := tvm_ffi_libinfo._resolve_and_validate([candidate], cond=lambda 
_: True):
+        return ret

Review Comment:
   ![medium](https://www.gstatic.com/codereviewagent/medium-priority.svg)
   
   If `_find_library_by_basename` fails to find the library, it may return 
`None`. Passing `[None]` to `_resolve_and_validate` can lead to an unhandled 
`TypeError` (e.g., when performing path operations on `None`). Guarding against 
`None` ensures a clean `RuntimeError` is raised instead.
   
   ```suggestion
       if candidate is not None:
           if ret := tvm_ffi_libinfo._resolve_and_validate([candidate], 
cond=lambda _: True):
               return ret
   ```



##########
python/tvm/contrib/hexagon/build.py:
##########
@@ -73,15 +71,8 @@ def _get_hexagon_rpc_lib_dir() -> pathlib.Path:
     pathlib.Path :
         The path to the Hexagon API directory.
     """
-    global HEXAGON_RPC_LIB_DIR
     if HEXAGON_RPC_LIB_DIR is None:
-        for path in libinfo.find_lib_path():
-            rpc_dir = os.path.join(os.path.dirname(path), "hexagon_api_output")
-            if os.path.isdir(rpc_dir):
-                HEXAGON_RPC_LIB_DIR = rpc_dir
-                break
-        else:
-            raise RuntimeError("hexagon_api binaries not found, please define 
HEXAGON_RPC_LIB_DIR")
+        raise RuntimeError("hexagon_api binaries not found, please define 
HEXAGON_RPC_LIB_DIR")

Review Comment:
   ![medium](https://www.gstatic.com/codereviewagent/medium-priority.svg)
   
   Evaluating `HEXAGON_RPC_LIB_DIR` only at module import time means that if a 
user sets the `HEXAGON_RPC_LIB_DIR` environment variable dynamically in their 
Python script after importing TVM, it will not be detected. Re-reading the 
environment variable dynamically inside the function if it is currently `None` 
makes the configuration much more robust.
   
   ```suggestion
           global HEXAGON_RPC_LIB_DIR
           HEXAGON_RPC_LIB_DIR = os.environ.get("HEXAGON_RPC_LIB_DIR")
           if HEXAGON_RPC_LIB_DIR is None:
               raise RuntimeError("hexagon_api binaries not found, please 
define HEXAGON_RPC_LIB_DIR")
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to