This is an automated email from the ASF dual-hosted git repository.

tqchen pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm-ffi.git


The following commit(s) were added to refs/heads/main by this push:
     new f255650  feat: Introduce `tvm_ffi.libinfo.load_lib_module` (#336)
f255650 is described below

commit f255650b8e5121452dd60805b206a0cb5bcb6525
Author: Junru Shao <[email protected]>
AuthorDate: Fri Dec 12 05:07:22 2025 -0800

    feat: Introduce `tvm_ffi.libinfo.load_lib_module` (#336)
    
    This PR makes downstream library loading process correct and convenient,
    by bringing in a new API `tvm_ffi.libinfo.load_lib_module`.
    
    To demonstrate the effect, the file
    `examples/packaging/python/my_ffi_extension/base.py`, which degenerates
    to only 2 lines after this PR:
    
    ```python
    import tvm_ffi
    _LIB = tvm_ffi.libinfo.load_lib_module("my-ffi-extension", 
"my_ffi_extension")
    ```
    
    It's worth mentioning that the new API works smoothly for both editable
    and non-editable builds, which is more correct than the existing one.
---
 examples/packaging/CMakeLists.txt                  |  3 --
 examples/packaging/python/my_ffi_extension/base.py | 28 +----------------
 python/tvm_ffi/libinfo.py                          | 35 +++++++++++++++++++++-
 3 files changed, 35 insertions(+), 31 deletions(-)

diff --git a/examples/packaging/CMakeLists.txt 
b/examples/packaging/CMakeLists.txt
index 0463a88..3648da6 100644
--- a/examples/packaging/CMakeLists.txt
+++ b/examples/packaging/CMakeLists.txt
@@ -60,9 +60,6 @@ add_library(my_ffi_extension SHARED src/extension.cc)
 target_link_libraries(my_ffi_extension tvm_ffi_header)
 target_link_libraries(my_ffi_extension tvm_ffi_shared)
 
-# show as my_ffi_extension.so
-set_target_properties(my_ffi_extension PROPERTIES PREFIX "")
-
 if (TVM_FFI_EXT_SHIP_DEBUG_SYMBOLS)
   # ship debugging symbols for backtrace on macos
   tvm_ffi_add_prefix_map(my_ffi_extension ${CMAKE_CURRENT_SOURCE_DIR})
diff --git a/examples/packaging/python/my_ffi_extension/base.py 
b/examples/packaging/python/my_ffi_extension/base.py
index 4165023..5f1005e 100644
--- a/examples/packaging/python/my_ffi_extension/base.py
+++ b/examples/packaging/python/my_ffi_extension/base.py
@@ -16,32 +16,6 @@
 # Base logic to load library for extension package
 """Utilities to locate and load the example extension shared library."""
 
-import sys
-from pathlib import Path
-
 import tvm_ffi
 
-
-def _load_lib() -> tvm_ffi.Module:
-    # first look at the directory of the current file
-    file_dir = Path(__file__).resolve().parent
-
-    path_candidates = [
-        file_dir,
-        file_dir / ".." / ".." / "build",
-    ]
-
-    if sys.platform.startswith("win32"):
-        lib_dll_name = "my_ffi_extension.dll"
-    elif sys.platform.startswith("darwin"):
-        lib_dll_name = "my_ffi_extension.dylib"
-    else:
-        lib_dll_name = "my_ffi_extension.so"
-    for candidate in path_candidates:
-        for path in Path(candidate).glob(lib_dll_name):
-            return tvm_ffi.load_module(str(path))
-
-    raise RuntimeError(f"Cannot find {lib_dll_name} in {path_candidates}")
-
-
-_LIB = _load_lib()
+_LIB = tvm_ffi.libinfo.load_lib_module("my-ffi-extension", "my_ffi_extension")
diff --git a/python/tvm_ffi/libinfo.py b/python/tvm_ffi/libinfo.py
index 32295ce..d1c1bcf 100644
--- a/python/tvm_ffi/libinfo.py
+++ b/python/tvm_ffi/libinfo.py
@@ -27,7 +27,10 @@ import importlib.metadata as im
 import os
 import sys
 from pathlib import Path
-from typing import Callable
+from typing import TYPE_CHECKING, Callable
+
+if TYPE_CHECKING:
+    from .module import Module
 
 
 def find_libtvm_ffi() -> str:
@@ -169,6 +172,36 @@ def load_lib_ctypes(package: str, target_name: str, mode: 
str) -> ctypes.CDLL:
     return ctypes.CDLL(str(lib_path), getattr(ctypes, mode))
 
 
+def load_lib_module(package: str, target_name: str, keep_module_alive: bool = 
True) -> Module:
+    """Load the tvm_ffi shared library by searching likely paths.
+
+    Parameters
+    ----------
+    package
+        The package name where the library is expected to be found. For 
example,
+        ``"apache-tvm-ffi"`` is the package name of `tvm-ffi`.
+
+    target_name
+        Name of the CMake target, e.g., ``"tvm_ffi"``. It is used to derive 
the platform-specific
+        shared library name, e.g., ``"libtvm_ffi.so"`` on Linux, 
``"tvm_ffi.dll"`` on Windows.
+
+    keep_module_alive
+        Whether to keep the loaded module alive to prevent it from being 
unloaded.
+
+    Returns
+    -------
+    The loaded shared library.
+
+    """
+    from .module import load_module  # noqa: PLC0415
+
+    lib_path: Path = _find_library_by_basename(package, target_name)
+    # The dll search path need to be added explicitly in windows
+    if sys.platform.startswith("win32"):
+        os.add_dll_directory(str(lib_path.parent))
+    return load_module(lib_path, keep_module_alive=keep_module_alive)
+
+
 def _find_library_by_basename(package: str, target_name: str) -> Path:  # 
noqa: PLR0912
     """Find a shared library by target_name name across known directories.
 

Reply via email to