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.git


The following commit(s) were added to refs/heads/main by this push:
     new 6a38d926e2 [FFI][Bugfix] Fix bug of `ffi.cpp.load_inline` on Windows 
(#18281)
6a38d926e2 is described below

commit 6a38d926e2b8e4670f8c6f52e691ae5bbd02151f
Author: Yaoyao Ding <[email protected]>
AuthorDate: Mon Sep 8 06:53:30 2025 -0400

    [FFI][Bugfix] Fix bug of `ffi.cpp.load_inline` on Windows (#18281)
    
    This PR enables the load_inline on windows platform:
---
 ffi/python/tvm_ffi/cpp/load_inline.py | 66 ++++++++++++++++++++++++++---------
 ffi/tests/python/test_load_inline.py  | 20 ++++++++---
 2 files changed, 66 insertions(+), 20 deletions(-)

diff --git a/ffi/python/tvm_ffi/cpp/load_inline.py 
b/ffi/python/tvm_ffi/cpp/load_inline.py
index 61b3a74fce..754a9d7465 100644
--- a/ffi/python/tvm_ffi/cpp/load_inline.py
+++ b/ffi/python/tvm_ffi/cpp/load_inline.py
@@ -26,7 +26,7 @@ import functools
 
 from tvm_ffi.module import Module, load_module
 from tvm_ffi.utils import FileLock
-from tvm_ffi.libinfo import find_include_path, find_dlpack_include_path
+from tvm_ffi.libinfo import find_include_path, find_dlpack_include_path, 
find_libtvm_ffi
 
 IS_WINDOWS = sys.platform == "win32"
 
@@ -141,9 +141,29 @@ def _generate_ninja_build(
     default_include_paths = [find_include_path(), find_dlpack_include_path()]
 
     if IS_WINDOWS:
-        default_cflags = ["/std:c++17"]
+        default_cflags = [
+            "/std:c++17",
+            "/MD",
+            "/wd4819",
+            "/wd4251",
+            "/wd4244",
+            "/wd4267",
+            "/wd4275",
+            "/wd4018",
+            "/wd4190",
+            "/wd4624",
+            "/wd4067",
+            "/wd4068",
+            "/EHsc",
+        ]
         default_cuda_cflags = ["-Xcompiler", "/std:c++17", "/O2"]
-        default_ldflags = ["/DLL"]
+        # Find the TVM FFI library for linking
+        tvm_ffi_lib = find_libtvm_ffi()
+        tvm_ffi_lib_path = os.path.dirname(tvm_ffi_lib)
+        tvm_ffi_lib_name = os.path.splitext(os.path.basename(tvm_ffi_lib))[
+            0
+        ]  # Remove .dll extension
+        default_ldflags = ["/DLL", f"/LIBPATH:{tvm_ffi_lib_path}", 
f"{tvm_ffi_lib_name}.lib"]
     else:
         default_cflags = ["-std=c++17", "-fPIC", "-O2"]
         default_cuda_cflags = ["-Xcompiler", "-fPIC", "-std=c++17", "-O2"]
@@ -161,8 +181,8 @@ def _generate_ninja_build(
 
     # append include paths
     for path in include_paths:
-        cflags.append("-I{}".format(path))
-        cuda_cflags.append("-I{}".format(path))
+        cflags.append("-I{}".format(path.replace(":", "$:")))
+        cuda_cflags.append("-I{}".format(path.replace(":", "$:")))
 
     # flags
     ninja = []
@@ -177,9 +197,13 @@ def _generate_ninja_build(
     # rules
     ninja.append("")
     ninja.append("rule compile")
-    ninja.append("  depfile = $out.d")
-    ninja.append("  deps = gcc")
-    ninja.append("  command = $cxx -MMD -MF $out.d $cflags -c $in -o $out")
+    if IS_WINDOWS:
+        ninja.append("  command = $cxx /showIncludes $cflags -c $in /Fo$out")
+        ninja.append("  deps = msvc")
+    else:
+        ninja.append("  depfile = $out.d")
+        ninja.append("  deps = gcc")
+        ninja.append("  command = $cxx -MMD -MF $out.d $cflags -c $in -o $out")
     ninja.append("")
 
     if with_cuda:
@@ -192,24 +216,31 @@ def _generate_ninja_build(
         ninja.append("")
 
     ninja.append("rule link")
-    ninja.append("  command = $cxx $in $ldflags -o $out")
+    if IS_WINDOWS:
+        ninja.append("  command = $cxx $in /link $ldflags /out:$out")
+    else:
+        ninja.append("  command = $cxx $in $ldflags -o $out")
     ninja.append("")
 
     # build targets
     ninja.append(
-        "build main.o: compile 
{}".format(os.path.abspath(os.path.join(build_dir, "main.cpp")))
+        "build main.o: compile {}".format(
+            os.path.abspath(os.path.join(build_dir, "main.cpp")).replace(":", 
"$:")
+        )
     )
     if with_cuda:
         ninja.append(
             "build cuda.o: compile_cuda {}".format(
-                os.path.abspath(os.path.join(build_dir, "cuda.cu"))
+                os.path.abspath(os.path.join(build_dir, 
"cuda.cu")).replace(":", "$:")
             )
         )
-    ninja.append("build {}.so: link main.o{}".format(name, " cuda.o" if 
with_cuda else ""))
+    # Use appropriate extension based on platform
+    ext = ".dll" if IS_WINDOWS else ".so"
+    ninja.append("build {}{}: link main.o{}".format(name, ext, " cuda.o" if 
with_cuda else ""))
     ninja.append("")
 
     # default target
-    ninja.append("default {}.so".format(name))
+    ninja.append("default {}{}".format(name, ext))
     ninja.append("")
     return "\n".join(ninja)
 
@@ -223,10 +254,11 @@ def _build_ninja(build_dir: str) -> None:
     status = subprocess.run(args=command, cwd=build_dir, capture_output=True)
     if status.returncode != 0:
         msg = ["ninja exited with status {}".format(status.returncode)]
+        encoding = "oem" if IS_WINDOWS else "utf-8"
         if status.stdout:
-            msg.append("stdout:\n{}".format(status.stdout.decode("utf-8")))
+            msg.append("stdout:\n{}".format(status.stdout.decode(encoding)))
         if status.stderr:
-            msg.append("stderr:\n{}".format(status.stderr.decode("utf-8")))
+            msg.append("stderr:\n{}".format(status.stderr.decode(encoding)))
 
         raise RuntimeError("\n".join(msg))
 
@@ -395,4 +427,6 @@ def load_inline(
         # build the module
         _build_ninja(build_dir)
 
-        return load_module(os.path.join(build_dir, "{}.so".format(name)))
+        # Use appropriate extension based on platform
+        ext = ".dll" if IS_WINDOWS else ".so"
+        return load_module(os.path.abspath(os.path.join(build_dir, 
"{}{}".format(name, ext))))
diff --git a/ffi/tests/python/test_load_inline.py 
b/ffi/tests/python/test_load_inline.py
index c35ebd30e2..dbaf439408 100644
--- a/ffi/tests/python/test_load_inline.py
+++ b/ffi/tests/python/test_load_inline.py
@@ -28,7 +28,10 @@ import tvm_ffi.cpp
 from tvm_ffi.module import Module
 
 
[email protected](not sys.platform.startswith("linux"), reason="need to 
support non-linux")
[email protected](
+    not sys.platform.startswith("linux") and not 
sys.platform.startswith("win32"),
+    reason="need to support other platforms",
+)
 def test_load_inline_cpp():
     mod: Module = tvm_ffi.cpp.load_inline(
         name="hello",
@@ -55,7 +58,10 @@ def test_load_inline_cpp():
     numpy.testing.assert_equal(x + 1, y)
 
 
[email protected](not sys.platform.startswith("linux"), reason="need to 
support non-linux")
[email protected](
+    not sys.platform.startswith("linux") and not 
sys.platform.startswith("win32"),
+    reason="need to support other platforms",
+)
 def test_load_inline_cpp_with_docstrings():
     mod: Module = tvm_ffi.cpp.load_inline(
         name="hello",
@@ -82,7 +88,10 @@ def test_load_inline_cpp_with_docstrings():
     numpy.testing.assert_equal(x + 1, y)
 
 
[email protected](not sys.platform.startswith("linux"), reason="need to 
support non-linux")
[email protected](
+    not sys.platform.startswith("linux") and not 
sys.platform.startswith("win32"),
+    reason="need to support other platforms",
+)
 def test_load_inline_cpp_multiple_sources():
     mod: Module = tvm_ffi.cpp.load_inline(
         name="hello",
@@ -125,7 +134,10 @@ def test_load_inline_cpp_multiple_sources():
     numpy.testing.assert_equal(x + 1, y)
 
 
[email protected](not sys.platform.startswith("linux"), reason="need to 
support non-linux")
[email protected](
+    not sys.platform.startswith("linux") and not 
sys.platform.startswith("win32"),
+    reason="need to support other platforms",
+)
 def test_load_inline_cpp_build_dir():
     mod: Module = tvm_ffi.cpp.load_inline(
         name="hello",

Reply via email to