diff --git a/Cargo.lock b/Cargo.lock index 9d953b563..d9fe83fef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,6 +11,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "anyhow" +version = "1.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" + [[package]] name = "bindgen" version = "0.71.1" @@ -177,6 +183,7 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" name = "nixl-sys" version = "0.8.0" dependencies = [ + "anyhow", "bindgen", "cc", "libc", diff --git a/src/bindings/rust/Cargo.toml b/src/bindings/rust/Cargo.toml index 595403594..1e9ec298d 100644 --- a/src/bindings/rust/Cargo.toml +++ b/src/bindings/rust/Cargo.toml @@ -40,6 +40,7 @@ bindgen = "0.71" cc = { version = "1.2.23", features = ["parallel"] } pkg-config = "0.3" os_info = "3.11" +anyhow = "1" [dev-dependencies] tempfile = "3.20.0" diff --git a/src/bindings/rust/build.rs b/src/bindings/rust/build.rs index f8223427f..c5ff6f69f 100644 --- a/src/bindings/rust/build.rs +++ b/src/bindings/rust/build.rs @@ -13,9 +13,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +use os_info; use std::env; use std::path::PathBuf; -use os_info; fn get_lib_path(nixl_root_path: &str, arch: &str) -> String { let os_info = os_info::get(); @@ -77,14 +77,30 @@ fn get_nixl_libs() -> Option> { pkg_config::probe_library("etcd-cpp-api"), pkg_config::probe_library("ucx"), ) { - (Ok(nixl), Ok(nixl_build), Ok(nixl_common), Ok(stream), Ok(serdes), Ok(ucx_utils), Ok(etcd), Ok(ucx)) => { - Some(vec![nixl, nixl_build, nixl_common, stream, serdes, ucx_utils, etcd, ucx]) - } + ( + Ok(nixl), + Ok(nixl_build), + Ok(nixl_common), + Ok(stream), + Ok(serdes), + Ok(ucx_utils), + Ok(etcd), + Ok(ucx), + ) => Some(vec![ + nixl, + nixl_build, + nixl_common, + stream, + serdes, + ucx_utils, + etcd, + ucx, + ]), _ => None, } } -fn build_nixl(cc_builder: &mut cc::Build) { +fn build_nixl(cc_builder: &mut cc::Build) -> anyhow::Result<()> { let nixl_root_path = env::var("NIXL_PREFIX").unwrap_or_else(|_| "/opt/nvidia/nvda_nixl".to_string()); @@ -94,7 +110,7 @@ fn build_nixl(cc_builder: &mut cc::Build) { let nixl_include_path = format!("{}/include", nixl_root_path); let nixl_include_paths = [ &nixl_include_path, - "../../api/cpp", + //"../../api/cpp", "../../infra", "../../core", "/usr/include", @@ -111,7 +127,10 @@ fn build_nixl(cc_builder: &mut cc::Build) { println!("cargo:rustc-link-search=native={}", nixl_root_path); println!("cargo:rustc-link-search=native={}/lib", nixl_root_path); println!("cargo:rustc-link-search=native={}/lib64", nixl_root_path); - println!("cargo:rustc-link-search=native={}/lib/x86_64-linux-gnu", nixl_root_path); + println!( + "cargo:rustc-link-search=native={}/lib/x86_64-linux-gnu", + nixl_root_path + ); // Try to use pkg-config if available if let Some(libs) = get_nixl_libs() { @@ -125,10 +144,7 @@ fn build_nixl(cc_builder: &mut cc::Build) { println!("cargo:warning=pkg-config not available, using manual library paths"); } - cc_builder - .file("wrapper.cpp") - .includes(nixl_include_paths); - + cc_builder.file("wrapper.cpp").includes(nixl_include_paths); println!("cargo:rustc-link-search={}", nixl_lib_path); @@ -139,10 +155,10 @@ fn build_nixl(cc_builder: &mut cc::Build) { } // Compile the wrapper C++ code - cc_builder.compile("nixl_wrapper"); + cc_builder.try_compile("nixl_wrapper")?; // Get the output path for bindings - let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + let out_path = PathBuf::from(env::var("OUT_DIR")?); // Generate bindings with minimal configuration let mut builder = bindgen::Builder::default() @@ -183,9 +199,10 @@ fn build_nixl(cc_builder: &mut cc::Build) { builder .parse_callbacks(Box::new(bindgen::CargoCallbacks::new())) .generate() - .expect("Unable to generate bindings") - .write_to_file(out_path.join("bindings.rs")) - .expect("Couldn't write bindings!"); + .map_err(|_| anyhow::anyhow!("Unable to generate bindings"))? + .write_to_file(out_path.join("bindings.rs"))?; + + Ok(()) } fn build_stubs(cc_builder: &mut cc::Build) { @@ -218,18 +235,38 @@ fn build_stubs(cc_builder: &mut cc::Build) { .expect("Couldn't write bindings!"); } -fn run_build(use_stub_api: bool) { - let mut cc_builder = cc::Build::new(); - cc_builder +fn create_builder() -> cc::Build { + let mut builder = cc::Build::new(); + builder .cpp(true) .compiler("g++") .flag("-std=c++17") .flag("-fPIC") .flag("-Wno-unused-parameter") .flag("-Wno-unused-variable"); + builder +} + +fn run_build(use_stub_api: bool) { + let mut cc_builder = create_builder(); if !use_stub_api { - build_nixl(&mut cc_builder); + let no_fallback = env::var("NIXL_NO_STUBS_FALLBACK") + .map(|v| v == "1") + .unwrap_or(false); + + if let Err(e) = build_nixl(&mut cc_builder) { + if !no_fallback { + println!( + "cargo:warning=NIXL build failed: {}, falling back to stub API", + e + ); + let mut stub_builder = create_builder(); + build_stubs(&mut stub_builder); + } else { + panic!("Failed to build NIXL: {}", e); + } + } } else { build_stubs(&mut cc_builder); } diff --git a/src/bindings/rust/src/lib.rs b/src/bindings/rust/src/lib.rs index adce69543..aae04a3d3 100644 --- a/src/bindings/rust/src/lib.rs +++ b/src/bindings/rust/src/lib.rs @@ -67,7 +67,7 @@ use bindings::{ nixl_capi_query_resp_list_get_params, nixl_capi_prep_xfer_dlist, nixl_capi_release_xfer_dlist_handle, nixl_capi_make_xfer_req, nixl_capi_get_local_partial_md, nixl_capi_send_local_partial_md, nixl_capi_query_xfer_backend, nixl_capi_opt_args_set_ip_addr, - nixl_capi_opt_args_set_port, nixl_capi_get_xfer_telemetry + nixl_capi_opt_args_set_port, nixl_capi_get_xfer_telemetry, nixl_capi_is_stub }; // Re-export status codes @@ -559,3 +559,7 @@ impl NixlRegistration for SystemStorage { Ok(()) } } + +pub fn is_stub() -> bool { + unsafe { nixl_capi_is_stub() } +} \ No newline at end of file diff --git a/src/bindings/rust/stubs.cpp b/src/bindings/rust/stubs.cpp index ab20b3a3e..62b789469 100644 --- a/src/bindings/rust/stubs.cpp +++ b/src/bindings/rust/stubs.cpp @@ -94,6 +94,20 @@ nixl_capi_load_remote_md(nixl_capi_agent_t agent, const void* data, size_t len, return nixl_capi_stub_abort(); } +nixl_capi_status_t +nixl_capi_send_local_md(nixl_capi_agent_t agent, nixl_capi_opt_args_t opt_args) +{ + return nixl_capi_stub_abort(); +} + +nixl_capi_status_t +nixl_capi_send_local_partial_md(nixl_capi_agent_t agent, + nixl_capi_reg_dlist_t descs, + nixl_capi_opt_args_t opt_args) +{ + return nixl_capi_stub_abort(); +} + nixl_capi_status_t nixl_capi_prep_xfer_dlist(nixl_capi_agent_t agent, const char *agent_name, @@ -129,6 +143,30 @@ nixl_capi_invalidate_remote_md(nixl_capi_agent_t agent, const char* remote_agent return nixl_capi_stub_abort(); } +nixl_capi_status_t +nixl_capi_invalidate_local_md(nixl_capi_agent_t agent, nixl_capi_opt_args_t opt_args) +{ + return nixl_capi_stub_abort(); +} + +nixl_capi_status_t +nixl_capi_check_remote_md(nixl_capi_agent_t agent, const char* remote_name, nixl_capi_xfer_dlist_t descs) +{ + return nixl_capi_stub_abort(); +} + +nixl_capi_status_t +nixl_capi_fetch_remote_md(nixl_capi_agent_t agent, const char* remote_name, nixl_capi_opt_args_t opt_args) +{ + return nixl_capi_stub_abort(); +} + +nixl_capi_status_t +nixl_capi_agent_make_connection(nixl_capi_agent_t agent, const char* remote_agent, nixl_capi_opt_args_t opt_args) +{ + return nixl_capi_stub_abort(); +} + nixl_capi_status_t nixl_capi_get_available_plugins(nixl_capi_agent_t agent, nixl_capi_string_list_t* plugins) { @@ -340,6 +378,42 @@ nixl_capi_xfer_dlist_resize(nixl_capi_xfer_dlist_t dlist, size_t new_size) return nixl_capi_stub_abort(); } +nixl_capi_status_t +nixl_capi_xfer_dlist_get_type(nixl_capi_xfer_dlist_t dlist, nixl_capi_mem_type_t* mem_type) +{ + return nixl_capi_stub_abort(); +} + +nixl_capi_status_t +nixl_capi_xfer_dlist_desc_count(nixl_capi_xfer_dlist_t dlist, size_t* count) +{ + return nixl_capi_stub_abort(); +} + +nixl_capi_status_t +nixl_capi_xfer_dlist_is_empty(nixl_capi_xfer_dlist_t dlist, bool* is_empty) +{ + return nixl_capi_stub_abort(); +} + +nixl_capi_status_t +nixl_capi_xfer_dlist_trim(nixl_capi_xfer_dlist_t dlist) +{ + return nixl_capi_stub_abort(); +} + +nixl_capi_status_t +nixl_capi_xfer_dlist_rem_desc(nixl_capi_xfer_dlist_t dlist, int index) +{ + return nixl_capi_stub_abort(); +} + +nixl_capi_status_t +nixl_capi_xfer_dlist_print(nixl_capi_xfer_dlist_t dlist) +{ + return nixl_capi_stub_abort(); +} + // Registration descriptor list functions nixl_capi_status_t nixl_capi_create_reg_dlist(nixl_capi_mem_type_t mem_type, nixl_capi_reg_dlist_t *dlist) { @@ -374,6 +448,42 @@ nixl_capi_reg_dlist_resize(nixl_capi_reg_dlist_t dlist, size_t new_size) return nixl_capi_stub_abort(); } +nixl_capi_status_t +nixl_capi_reg_dlist_get_type(nixl_capi_reg_dlist_t dlist, nixl_capi_mem_type_t* mem_type) +{ + return nixl_capi_stub_abort(); +} + +nixl_capi_status_t +nixl_capi_reg_dlist_desc_count(nixl_capi_reg_dlist_t dlist, size_t* count) +{ + return nixl_capi_stub_abort(); +} + +nixl_capi_status_t +nixl_capi_reg_dlist_is_empty(nixl_capi_reg_dlist_t dlist, bool* is_empty) +{ + return nixl_capi_stub_abort(); +} + +nixl_capi_status_t +nixl_capi_reg_dlist_trim(nixl_capi_reg_dlist_t dlist) +{ + return nixl_capi_stub_abort(); +} + +nixl_capi_status_t +nixl_capi_reg_dlist_rem_desc(nixl_capi_reg_dlist_t dlist, int index) +{ + return nixl_capi_stub_abort(); +} + +nixl_capi_status_t +nixl_capi_reg_dlist_print(nixl_capi_reg_dlist_t dlist) +{ + return nixl_capi_stub_abort(); +} + // Memory registration functions nixl_capi_status_t nixl_capi_register_mem(nixl_capi_agent_t agent, nixl_capi_reg_dlist_t dlist, nixl_capi_opt_args_t opt_args) @@ -416,6 +526,17 @@ nixl_capi_query_xfer_backend(nixl_capi_agent_t agent, return nixl_capi_stub_abort(); } +nixl_capi_status_t +nixl_capi_estimate_xfer_cost(nixl_capi_agent_t agent, + nixl_capi_xfer_req_t req_hndl, + nixl_capi_opt_args_t opt_args, + int64_t *duration_us, + int64_t *err_margin_us, + nixl_capi_cost_t *method) +{ + return nixl_capi_stub_abort(); +} + nixl_capi_status_t nixl_capi_destroy_xfer_req(nixl_capi_xfer_req_t req) { @@ -434,6 +555,13 @@ nixl_capi_get_notifs(nixl_capi_agent_t agent, nixl_capi_notif_map_t notif_map, n return nixl_capi_stub_abort(); } +nixl_capi_status_t +nixl_capi_gen_notif(nixl_capi_agent_t agent, const char* remote_agent, + const void* data, size_t len, nixl_capi_opt_args_t opt_args) +{ + return nixl_capi_stub_abort(); +} + nixl_capi_status_t nixl_capi_create_notif_map(nixl_capi_notif_map_t* notif_map) { @@ -514,4 +642,17 @@ nixl_capi_query_mem(nixl_capi_agent_t agent, return nixl_capi_stub_abort(); } +nixl_capi_status_t +nixl_capi_get_xfer_telemetry(nixl_capi_agent_t agent, + nixl_capi_xfer_req_t req_hndl, + nixl_capi_xfer_telemetry_t telemetry) +{ + return nixl_capi_stub_abort(); +} + +bool nixl_capi_is_stub() +{ + return true; +} + } // extern "C" diff --git a/src/bindings/rust/wrapper.cpp b/src/bindings/rust/wrapper.cpp index fa880b7b6..a440e9395 100644 --- a/src/bindings/rust/wrapper.cpp +++ b/src/bindings/rust/wrapper.cpp @@ -1903,4 +1903,7 @@ nixl_capi_get_xfer_telemetry(nixl_capi_agent_t agent, return NIXL_CAPI_ERROR_BACKEND; } } +bool nixl_capi_is_stub() { + return false; +} } // extern "C" diff --git a/src/bindings/rust/wrapper.h b/src/bindings/rust/wrapper.h index c6c848d24..0fb08870d 100644 --- a/src/bindings/rust/wrapper.h +++ b/src/bindings/rust/wrapper.h @@ -354,6 +354,7 @@ nixl_capi_get_xfer_telemetry(nixl_capi_agent_t agent, nixl_capi_xfer_req_t req_hndl, nixl_capi_xfer_telemetry_t telemetry); +bool nixl_capi_is_stub(); #ifdef __cplusplus }