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

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


The following commit(s) were added to refs/heads/main by this push:
     new b5e383171 [FEAT][RUST] support rust in windows and add rust ci (#45)
b5e383171 is described below

commit b5e3831717f03f060683e4832e2a70413b39d8b4
Author: Linzhang Li <[email protected]>
AuthorDate: Mon Oct 26 14:17:33 2026 -0400

    [FEAT][RUST] support rust in windows and add rust ci (#45)
    
    ## Summary
    
    
    This PR builds `libtvm_tirx_rust` on Windows, and runs the tests of
    `rust/` in CI, which ran none
    of them so far; that is how the failures #44 fixed reached main.
    
    - **Windows**: `TVM_TIRX_USE_RUST` no longer refuses Windows. The
    `tvm-tirx-config` and
    `tvm-ffi-config` that CMake gives cargo are now generated C programs
    instead of `sh` scripts.
    - **CI**:
    - GitHub macOS and Windows run `cargo test` and
    `tests/python/ir/test_op_rust.py` with the Rust
        of the runners.
    - Jenkins CPU and ARM build with `-DTVM_TIRX_USE_RUST=ON` and run `cargo
    test` after the C++
    tests, with the crate's `rust-version` (1.84), which rustup installs.
    - Jenkins CPU checks that the bindings generated by tvm-ffi-stubgen are
    up to date.
---
 .github/workflows/main.yml                         | 10 ++++
 cmake/modules/Rust.cmake                           | 55 +++++++++++++++-------
 rust/tests/runtime/main.rs                         |  6 ++-
 tests/scripts/task_build_arm.sh                    |  6 +++
 tests/scripts/task_build_cpu.sh                    |  9 ++++
 .../{task_build_cpu.sh => task_install_rust.sh}    | 17 ++++---
 6 files changed, 79 insertions(+), 24 deletions(-)

diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 60f1bc964..0c6891393 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -75,6 +75,11 @@ jobs:
         run: >-
           uv run --no-sync python -m pytest -v 
tests/python/codegen/llvm/test_minimal.py
           tests/python/runtime/test_validate_wheel_library.py 
tests/python/script
+          tests/python/ir/test_op_rust.py
+      - name: Rust tests
+        timeout-minutes: 20
+        shell: bash
+        run: cargo test --manifest-path rust/Cargo.toml
       - name: Minimal Metal Compile-Only
         shell: bash
         run: |
@@ -125,3 +130,8 @@ jobs:
         run: >-
           uv run --no-sync python -m pytest -v 
tests/python/codegen/llvm/test_minimal.py
           tests/python/runtime/test_validate_wheel_library.py 
tests/python/script
+          tests/python/ir/test_op_rust.py
+      - name: Rust tests
+        timeout-minutes: 20
+        shell: cmd /C call {0}
+        run: cargo test --manifest-path rust/Cargo.toml
diff --git a/cmake/modules/Rust.cmake b/cmake/modules/Rust.cmake
index 66e260220..b1a5424a9 100644
--- a/cmake/modules/Rust.cmake
+++ b/cmake/modules/Rust.cmake
@@ -20,11 +20,11 @@
 # operators it defines (python/tvm_tirx/backend/rust), as loading the compiler 
registers the C++
 # ones.
 #
-# TVM_TIRX_USE_RUST is ON, OFF or AUTO. AUTO builds the library when it can: 
not on Windows, with
-# the crate's sources (a source distribution has none), with a cargo at least 
as new as the
-# crate's rust-version, and with the crate's dependencies, which `cargo fetch` 
gets from crates.io
-# or finds in cargo's cache. rustup's cargo ($CARGO_HOME/bin or ~/.cargo/bin) 
is preferred over one
-# on PATH, which may be an older system cargo; set TVM_TIRX_CARGO to choose 
another.
+# TVM_TIRX_USE_RUST is ON, OFF or AUTO. AUTO builds the library when it can: 
with the crate's
+# sources (a source distribution has none), with a cargo at least as new as 
the crate's
+# rust-version, and with the crate's dependencies, which `cargo fetch` gets 
from crates.io or finds
+# in cargo's cache. rustup's cargo ($CARGO_HOME/bin or ~/.cargo/bin) is 
preferred over one on PATH,
+# which may be an older system cargo; set TVM_TIRX_CARGO to choose another.
 #
 # A build without the library removes the one an earlier build left, which 
`import tvm_tirx` would
 # load otherwise.
@@ -35,9 +35,7 @@ if("${TVM_TIRX_USE_RUST}" MATCHES ${IS_FALSE_PATTERN})
 endif()
 set(_rust_manifest "${CMAKE_CURRENT_SOURCE_DIR}/rust/Cargo.toml")
 set(_rust_problem "")
-if(WIN32)
-  set(_rust_problem "it is not supported on Windows yet")
-elseif(NOT EXISTS "${_rust_manifest}")
+if(NOT EXISTS "${_rust_manifest}")
   set(_rust_problem "${_rust_manifest} does not exist")
 else()
   file(STRINGS "${_rust_manifest}" _rust_version REGEX "^rust-version *=")
@@ -77,17 +75,40 @@ endif()
 message(STATUS "Build libtvm_tirx_rust with ${TVM_TIRX_CARGO} 
${_cargo_version}")
 set(_rust_dir "${CMAKE_CURRENT_BINARY_DIR}/rust")
 # The build scripts of tvm-tirx and tvm-ffi-sys link the libraries in the 
directories that
-# `tvm-tirx-config --libdir` and `tvm-ffi-config --libdir` print: answer with 
this build's.
+# `tvm-tirx-config --libdir` and `tvm-ffi-config --libdir` print: answer with 
this build's, from
+# programs in rust/bin, since on Windows cargo runs only `.exe` files. A 
library's directory can
+# depend on the configuration (tvm-ffi's does), so each program gets it as a 
definition, and their
+# one source is the same for every configuration.
+file(GENERATE OUTPUT "${_rust_dir}/config_tool.c" CONTENT "\
+/* tvm-tirx-config and tvm-ffi-config for the cargo build of rust/, generated 
by CMake. */
+#include <stdio.h>
+#include <string.h>
+
+int main(int argc, char** argv) {
+  if (argc != 2 || strcmp(argv[1], \"--libdir\") != 0) {
+    fputs(TOOL \": only --libdir is supported here\\n\", stderr);
+    return 1;
+  }
+  puts(LIBDIR);
+  return 0;
+}
+")
+set(_rust_tools)
 foreach(_tool_target tvm-tirx-config:tvm_tirx_compiler 
tvm-ffi-config:tvm_ffi_shared)
   string(REPLACE ":" ";" _tool_target "${_tool_target}")
   list(GET _tool_target 0 _tool)
   list(GET _tool_target 1 _target)
-  file(GENERATE OUTPUT "${_rust_dir}/bin/${_tool}"
-    CONTENT "#!/bin/sh\n# ${_tool} for the cargo build of rust/, generated by 
CMake.\n\
-[ \"$1\" = --libdir ] || { echo \"${_tool}: only --libdir is supported here\" 
>&2; exit 1; }\n\
-echo \"$<TARGET_FILE_DIR:${_target}>\"\n"
-    FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ 
GROUP_EXECUTE
-      WORLD_READ WORLD_EXECUTE)
+  add_executable(rust_${_tool} "${_rust_dir}/config_tool.c")
+  target_compile_definitions(rust_${_tool} PRIVATE "TOOL=\"${_tool}\""
+    "LIBDIR=\"$<TARGET_FILE_DIR:${_target}>\"")
+  set_target_properties(rust_${_tool} PROPERTIES OUTPUT_NAME ${_tool}
+    RUNTIME_OUTPUT_DIRECTORY "${_rust_dir}/bin")
+  foreach(_config IN LISTS CMAKE_CONFIGURATION_TYPES CMAKE_BUILD_TYPE)
+    string(TOUPPER "${_config}" _config)
+    set_target_properties(rust_${_tool} PROPERTIES
+      RUNTIME_OUTPUT_DIRECTORY_${_config} "${_rust_dir}/bin")
+  endforeach()
+  list(APPEND _rust_tools rust_${_tool})
 endforeach()
 if(CMAKE_BUILD_TYPE STREQUAL "Debug")
   set(_rust_profile debug)
@@ -100,12 +121,12 @@ set(_rust_built 
"${_rust_dir}/target/${_rust_profile}/${CMAKE_SHARED_LIBRARY_PRE
 set(_rust_lib 
"$<TARGET_FILE_DIR:tvm_tirx_compiler>/${CMAKE_SHARED_LIBRARY_PREFIX}tvm_tirx_rust${CMAKE_SHARED_LIBRARY_SUFFIX}")
 # Cargo decides what to rebuild, so the target always runs it.
 add_custom_target(tvm_tirx_rust ALL
-  COMMAND "${CMAKE_COMMAND}" -E env "PATH=${_rust_dir}/bin:$ENV{PATH}"
+  COMMAND "${CMAKE_COMMAND}" -E env --modify 
"PATH=path_list_prepend:${_rust_dir}/bin"
     "CARGO_TARGET_DIR=${_rust_dir}/target"
     "${TVM_TIRX_CARGO}" build --lib ${_rust_profile_args}
     --manifest-path "${_rust_manifest}"
   COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${_rust_built}" 
"${_rust_lib}"
   COMMENT "Building libtvm_tirx_rust with cargo"
   USES_TERMINAL VERBATIM)
-add_dependencies(tvm_tirx_rust tvm_tirx_compiler tvm_ffi_shared)
+add_dependencies(tvm_tirx_rust tvm_tirx_compiler tvm_ffi_shared ${_rust_tools})
 install(FILES "${_rust_lib}" DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT 
tvm_tirx)
diff --git a/rust/tests/runtime/main.rs b/rust/tests/runtime/main.rs
index 6de1ab1de..a31b4d48a 100644
--- a/rust/tests/runtime/main.rs
+++ b/rust/tests/runtime/main.rs
@@ -54,7 +54,11 @@ fn memory_scopes() {
 #[test]
 fn queries() {
     assert!(runtime::enabled("cpu").unwrap());
-    assert!(runtime::num_threads().unwrap() >= 1);
+    // The thread pool is thread-local. On Windows it joins its workers when 
the test's thread
+    // exits, under the loader lock that the workers need to exit, so the test 
would never end.
+    if cfg!(not(windows)) {
+        assert!(runtime::num_threads().unwrap() >= 1);
+    }
 }
 
 #[test]
diff --git a/tests/scripts/task_build_arm.sh b/tests/scripts/task_build_arm.sh
index 15a8c00a6..6602a07e0 100755
--- a/tests/scripts/task_build_arm.sh
+++ b/tests/scripts/task_build_arm.sh
@@ -18,10 +18,16 @@
 
 set -euxo pipefail
 
+source ./tests/scripts/task_install_rust.sh
+
 export CMAKE_ARGS="
     -DTVM_TIRX_BUILD_TESTS=ON
+    -DTVM_TIRX_USE_RUST=ON
     -DCMAKE_CXX_FLAGS=-Werror
 "
 uv build --wheel --no-build-isolation --offline --out-dir dist .
 
 ./build/tirx_cpptest
+
+# build/rust/bin holds the tvm-tirx-config and tvm-ffi-config of this build, 
which print build/lib.
+PATH="$PWD/build/rust/bin:$PATH" cargo test --manifest-path rust/Cargo.toml
diff --git a/tests/scripts/task_build_cpu.sh b/tests/scripts/task_build_cpu.sh
index 7d6b7a805..f7ac2df70 100755
--- a/tests/scripts/task_build_cpu.sh
+++ b/tests/scripts/task_build_cpu.sh
@@ -18,10 +18,19 @@
 
 set -euxo pipefail
 
+source ./tests/scripts/task_install_rust.sh
+
 export CMAKE_ARGS="
     -DTVM_TIRX_BUILD_TESTS=ON
+    -DTVM_TIRX_USE_RUST=ON
     -DCMAKE_CXX_FLAGS='-Wno-error=range-loop-construct -Wno-error=comment'
 "
 uv build --wheel --no-build-isolation --offline --out-dir dist .
 
 ./build/tirx_cpptest
+
+# build/rust/bin holds the tvm-tirx-config and tvm-ffi-config of this build, 
which print build/lib.
+PATH="$PWD/build/rust/bin:$PATH" cargo test --manifest-path rust/Cargo.toml
+
+# The bindings that tvm-ffi-stubgen generates in rust/ must match the types of 
this build.
+uv run --no-sync python -m tvm_ffi.stub.cli rust/src --target rust --dlls 
build/lib/libtvm_tirx_compiler.so --check
diff --git a/tests/scripts/task_build_cpu.sh 
b/tests/scripts/task_install_rust.sh
similarity index 52%
copy from tests/scripts/task_build_cpu.sh
copy to tests/scripts/task_install_rust.sh
index 7d6b7a805..80ee6f42f 100755
--- a/tests/scripts/task_build_cpu.sh
+++ b/tests/scripts/task_install_rust.sh
@@ -18,10 +18,15 @@
 
 set -euxo pipefail
 
-export CMAKE_ARGS="
-    -DTVM_TIRX_BUILD_TESTS=ON
-    -DCMAKE_CXX_FLAGS='-Wno-error=range-loop-construct -Wno-error=comment'
-"
-uv build --wheel --no-build-isolation --offline --out-dir dist .
+# Install the toolchain of the crate's rust-version, which the CI images do 
not have, for the build
+# and the tests of rust/. Source it from the repository root.
+export RUSTUP_HOME="$PWD/.local/rustup" CARGO_HOME="$PWD/.local/cargo"
+curl --proto '=https' --tlsv1.2 --retry 3 -sSf https://sh.rustup.rs | sh -s -- 
-y -q \
+    --no-modify-path --profile minimal \
+    --default-toolchain "$(sed -n 's/^rust-version = "\(.*\)"$/\1/p' 
rust/Cargo.toml)"
+export PATH="$CARGO_HOME/bin:$PATH"
 
-./build/tirx_cpptest
+# rustc links with the cc first on PATH, which in the CI images is a wrapper 
of sccache: link with
+# the compiler that CC names, as the C++ build does.
+rust_host=$(rustc -vV | sed -n 's/^host: //p')
+export "CARGO_TARGET_$(echo "$rust_host" | tr 'a-z-' 'A-Z_')_LINKER=${CC:-cc}"

Reply via email to