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 303f4703 [FIX][Rust] Fail loudly when tvm-ffi-config is missing (#825)
303f4703 is described below
commit 303f4703fcc088be03a18fc2bd4eeea582afbe7a
Author: Gabriel Wu <[email protected]>
AuthorDate: Mon Sep 28 22:23:26 2026 +0800
[FIX][Rust] Fail loudly when tvm-ffi-config is missing (#825)
## Why
`tvm-ffi-sys/build.rs` decides whether it is building documentation with
`env::var("RUSTDOC").is_ok()`. Cargo sets `RUSTDOC` for every build
script ([Cargo: environment variables set for build
scripts](https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts)),
so the check is always true. It was meant for the Rust docs build in
`docs/conf.py` (#160).
As a result, a normal `cargo build` without a working `tvm-ffi-config`
doesn't fail. It prints "tvm-ffi-config not available, skipping for
documentation build" and emits no `rustc-link-*` directives. The first
sign of trouble is a link error in a dependent crate:
```
rust-lld: error: undefined symbol: TVMFFIEnvGetStream
```
Cargo also caches the empty build-script output. The build script
declares no `rerun-if-*`, so it reruns only when the package's own files
change, and the build keeps failing after tvm-ffi is installed until
`cargo clean -p tvm-ffi-sys`.
## What
- **Documentation builds:** detected by `DOCS_RS`, which docs.rs sets.
`docs/conf.py` now sets it too for its `cargo doc`, so docs still build
without tvm-ffi installed. In that case the build script emits a
`cargo:warning` naming the reason and doesn't link.
- **Every other build:** fails in the build script, with the reason and
the fix, when `tvm-ffi-config` cannot be run, exits non-zero (its stderr
is included), or prints no library directory:
```
could not run `tvm-ffi-config`: No such file or directory (os error 2).
tvm-ffi-sys links libtvm_ffi from the directory that `tvm-ffi-config
--libdir` prints: install tvm-ffi (e.g. `pip install apache-tvm-ffi`)
and put tvm-ffi-config on PATH. To build documentation only, set
DOCS_RS=1.
```
- **Rerunning:** the build script declares its inputs with
`cargo:rerun-if-env-changed` (`DOCS_RS`, `PATH`, and the library-path
variable it reads) plus `rerun-if-changed=build.rs`, so output from one
environment isn't reused in another.
---
docs/conf.py | 3 ++-
rust/tvm-ffi-sys/build.rs | 64 ++++++++++++++++++++++++++++-------------------
2 files changed, 40 insertions(+), 27 deletions(-)
diff --git a/docs/conf.py b/docs/conf.py
index 07befa12..5e2de3d3 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -210,7 +210,8 @@ def _build_rust_docs() -> None:
["cargo", "doc", "--no-deps", "--workspace", "--target-dir",
"target"],
check=True,
cwd=_RUST_DIR,
- env={**os.environ, "RUSTDOCFLAGS": "--cfg docsrs"},
+ # DOCS_RS lets tvm-ffi-sys build without tvm-ffi installed, as on
docs.rs.
+ env={**os.environ, "RUSTDOCFLAGS": "--cfg docsrs", "DOCS_RS": "1"},
)
print(f"Rust documentation built successfully at {target_doc}")
diff --git a/rust/tvm-ffi-sys/build.rs b/rust/tvm-ffi-sys/build.rs
index fe787589..d7c9dca2 100644
--- a/rust/tvm-ffi-sys/build.rs
+++ b/rust/tvm-ffi-sys/build.rs
@@ -34,6 +34,7 @@ fn update_ld_library_path(lib_dir: &str) {
return;
}
// Get the current value of the environment variable at build time (if any)
+ println!("cargo:rerun-if-env-changed={}", os_env_var);
let current_val = env::var(os_env_var).unwrap_or_else(|_| String::new());
// Use platform-specific separator
let separator = if os_env_var == "PATH" { ";" } else { ":" };
@@ -47,37 +48,48 @@ fn update_ld_library_path(lib_dir: &str) {
}
fn main() {
- // When building documentation, we may not need actual linking
- // Check if this is a rustdoc build
- let is_rustdoc = env::var("RUSTDOC").is_ok() ||
env::var("CARGO_CFG_DOC").is_ok();
+ // docs.rs builds the documentation without tvm-ffi installed, and so does
+ // docs/conf.py, which sets DOCS_RS as docs.rs does. Cargo sets RUSTDOC for
+ // every build script, so it cannot tell a documentation build apart.
+ let docs_only = env::var_os("DOCS_RS").is_some();
+ println!("cargo:rerun-if-env-changed=DOCS_RS");
+ // The library directory comes from the tvm-ffi-config found on PATH.
+ println!("cargo:rerun-if-env-changed=PATH");
+ println!("cargo:rerun-if-changed=build.rs");
- // Run `mylib-config --libdir` to get the library path
- let config_result =
Command::new("tvm-ffi-config").arg("--libdir").output();
-
- let lib_dir = match config_result {
- Ok(output) if output.status.success() =>
String::from_utf8(output.stdout)
- .unwrap_or_default()
- .trim()
- .to_string(),
- _ if is_rustdoc => {
- // For rustdoc builds, we can proceed without the library
- eprintln!("Warning: tvm-ffi-config not available, skipping for
documentation build");
- return;
- }
- _ => {
- panic!("Failed to run tvm-ffi-config. Make sure tvm-ffi is
installed.");
+ // Run `tvm-ffi-config --libdir` to get the library path
+ let found = match Command::new("tvm-ffi-config").arg("--libdir").output() {
+ Ok(output) if output.status.success() => {
+ let lib_dir = String::from_utf8(output.stdout)
+ .unwrap_or_default()
+ .trim()
+ .to_string();
+ if lib_dir.is_empty() {
+ Err("`tvm-ffi-config --libdir` printed no library
directory".to_string())
+ } else {
+ Ok(lib_dir)
+ }
}
+ Ok(output) => Err(format!(
+ "`tvm-ffi-config --libdir` failed ({}): {}",
+ output.status,
+ String::from_utf8_lossy(&output.stderr).trim()
+ )),
+ Err(err) => Err(format!("could not run `tvm-ffi-config`: {err}")),
};
-
- if lib_dir.is_empty() {
- if is_rustdoc {
- eprintln!(
- "Warning: Empty lib_dir from tvm-ffi-config, skipping for
documentation build"
- );
+ let lib_dir = match found {
+ Ok(lib_dir) => lib_dir,
+ Err(reason) if docs_only => {
+ println!("cargo:warning={reason}; not linking libtvm_ffi for a
documentation build");
return;
}
- panic!("tvm-ffi-config returned empty library path");
- }
+ Err(reason) => panic!(
+ "{reason}. tvm-ffi-sys links libtvm_ffi from the directory that \
+ `tvm-ffi-config --libdir` prints: install tvm-ffi (e.g. `pip
install \
+ apache-tvm-ffi`) and put tvm-ffi-config on PATH. To build
documentation \
+ only, set DOCS_RS=1."
+ ),
+ };
// add the library directory to the linker search path
println!("cargo:rustc-link-search=native={}", lib_dir);