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}"