From 009127f2f3af6ddf37dff48e9884b84faf801de1 Mon Sep 17 00:00:00 2001 From: Yaoyao Ding Date: Sun, 7 Sep 2025 22:29:18 -0400 Subject: [PATCH 1/2] fix --- ffi/python/tvm_ffi/cpp/load_inline.py | 48 ++++++++++++++++++--------- ffi/tests/python/test_load_inline.py | 4 --- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/ffi/python/tvm_ffi/cpp/load_inline.py b/ffi/python/tvm_ffi/cpp/load_inline.py index 61b3a74fce2c..7ae74fff77de 100644 --- a/ffi/python/tvm_ffi/cpp/load_inline.py +++ b/ffi/python/tvm_ffi/cpp/load_inline.py @@ -26,7 +26,7 @@ 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,13 @@ 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 +165,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 +181,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 +200,29 @@ 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 +236,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 +409,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 c35ebd30e225..6510cca540bf 100644 --- a/ffi/tests/python/test_load_inline.py +++ b/ffi/tests/python/test_load_inline.py @@ -28,7 +28,6 @@ from tvm_ffi.module import Module -@pytest.mark.xfail(not sys.platform.startswith("linux"), reason="need to support non-linux") def test_load_inline_cpp(): mod: Module = tvm_ffi.cpp.load_inline( name="hello", @@ -55,7 +54,6 @@ def test_load_inline_cpp(): numpy.testing.assert_equal(x + 1, y) -@pytest.mark.xfail(not sys.platform.startswith("linux"), reason="need to support non-linux") def test_load_inline_cpp_with_docstrings(): mod: Module = tvm_ffi.cpp.load_inline( name="hello", @@ -82,7 +80,6 @@ def test_load_inline_cpp_with_docstrings(): numpy.testing.assert_equal(x + 1, y) -@pytest.mark.xfail(not sys.platform.startswith("linux"), reason="need to support non-linux") def test_load_inline_cpp_multiple_sources(): mod: Module = tvm_ffi.cpp.load_inline( name="hello", @@ -125,7 +122,6 @@ def test_load_inline_cpp_multiple_sources(): numpy.testing.assert_equal(x + 1, y) -@pytest.mark.xfail(not sys.platform.startswith("linux"), reason="need to support non-linux") def test_load_inline_cpp_build_dir(): mod: Module = tvm_ffi.cpp.load_inline( name="hello", From 2ee6099391ebbc650f3a10000a7e75ecb4d5c609 Mon Sep 17 00:00:00 2001 From: Yaoyao Ding Date: Sun, 7 Sep 2025 23:13:41 -0400 Subject: [PATCH 2/2] fix bug --- ffi/python/tvm_ffi/cpp/load_inline.py | 26 ++++++++++++++++++++++---- ffi/tests/python/test_load_inline.py | 16 ++++++++++++++++ 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/ffi/python/tvm_ffi/cpp/load_inline.py b/ffi/python/tvm_ffi/cpp/load_inline.py index 7ae74fff77de..754a9d74652f 100644 --- a/ffi/python/tvm_ffi/cpp/load_inline.py +++ b/ffi/python/tvm_ffi/cpp/load_inline.py @@ -141,12 +141,28 @@ def _generate_ninja_build( default_include_paths = [find_include_path(), find_dlpack_include_path()] if IS_WINDOWS: - default_cflags = ["/std:c++17", '/MD', '/wd4819', '/wd4251', '/wd4244', '/wd4267', '/wd4275', '/wd4018', '/wd4190', '/wd4624', '/wd4067', '/wd4068', '/EHsc'] + 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"] # 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 + 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"] @@ -208,7 +224,9 @@ def _generate_ninja_build( # build targets ninja.append( - "build main.o: compile {}".format(os.path.abspath(os.path.join(build_dir, "main.cpp")).replace(":", "$:")) + "build main.o: compile {}".format( + os.path.abspath(os.path.join(build_dir, "main.cpp")).replace(":", "$:") + ) ) if with_cuda: ninja.append( @@ -236,7 +254,7 @@ 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' + encoding = "oem" if IS_WINDOWS else "utf-8" if status.stdout: msg.append("stdout:\n{}".format(status.stdout.decode(encoding))) if status.stderr: diff --git a/ffi/tests/python/test_load_inline.py b/ffi/tests/python/test_load_inline.py index 6510cca540bf..dbaf4394081c 100644 --- a/ffi/tests/python/test_load_inline.py +++ b/ffi/tests/python/test_load_inline.py @@ -28,6 +28,10 @@ from tvm_ffi.module import Module +@pytest.mark.xfail( + 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", @@ -54,6 +58,10 @@ def test_load_inline_cpp(): numpy.testing.assert_equal(x + 1, y) +@pytest.mark.xfail( + 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", @@ -80,6 +88,10 @@ def test_load_inline_cpp_with_docstrings(): numpy.testing.assert_equal(x + 1, y) +@pytest.mark.xfail( + 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", @@ -122,6 +134,10 @@ def test_load_inline_cpp_multiple_sources(): numpy.testing.assert_equal(x + 1, y) +@pytest.mark.xfail( + 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",