diff --git a/.github/workflows/platforms.yml b/.github/workflows/platforms.yml index f68afdc..fd41c85 100644 --- a/.github/workflows/platforms.yml +++ b/.github/workflows/platforms.yml @@ -175,9 +175,16 @@ jobs: cmake -S vllm-cpp-sys/vllm.cpp -B target/vulkan-native \ -G Ninja -DCMAKE_BUILD_TYPE=Release \ -DVLLM_CPP_BUILD_TESTS=ON -DVLLM_CPP_BUILD_EXAMPLES=OFF \ - -DVLLM_CPP_SERVER=OFF -DVLLM_CPP_CUDA=OFF \ - -DVLLM_CPP_METAL=OFF -DVLLM_CPP_MLX=OFF \ - -DVLLM_CPP_VULKAN=ON -DVLLM_CPP_TRITON=OFF + -DVLLM_CPP_SERVER=OFF -DVLLM_CPP_HIP=OFF \ + -DVLLM_CPP_TENSTORRENT=OFF -DVLLM_CPP_LITERAL_STATIC=OFF \ + -DVLLM_CPP_BENCH_PROFILE_CONTROL=OFF -DVLLM_CPP_NCCL=OFF \ + -DVLLM_CPP_MARLIN=ON -DVLLM_CPP_FLASH_ATTN=ON \ + -DVLLM_CPP_CUDA=OFF -DVLLM_CPP_METAL=OFF \ + -DVLLM_CPP_MLX=OFF -DVLLM_CPP_VULKAN=ON \ + -DVLLM_CPP_TRITON=OFF -DVLLM_CPP_TRITON_REGEN=OFF \ + -DVLLM_CPP_TRITON_VENDORED_ARCH= \ + -DVLLM_CPP_TRITON_TARGET= -DVLLM_CPP_CUTLASS_FETCH=OFF \ + -DVLLM_CPP_SANITIZE=OFF cmake --build target/vulkan-native --target test_vulkan_backend test_backend_cross_device ctest --test-dir target/vulkan-native --output-on-failure \ --tests-regex '^(test_vulkan_backend|test_backend_cross_device)$' diff --git a/Justfile b/Justfile index fa4c63a..cf4c849 100644 --- a/Justfile +++ b/Justfile @@ -97,10 +97,17 @@ sys: bindings-check header-check build-support-test backend-config backend-integ # Test all Linux CPU link modes and the exact shared-library exports. link-modes: + just --justfile '{{ root }}/Justfile' _link-modes \ + '{{ root }}/vllm-cpp-sys' \ + "${CARGO_TARGET_DIR:-{{ root }}/target/link-modes}" + +[private] +_link-modes crate_root target_base: #!/usr/bin/env bash set -euo pipefail - repo_root={{ quote(root) }} - target_base=${CARGO_TARGET_DIR:-"$repo_root/target/link-modes"} + crate_root={{ quote(crate_root) }} + target_base={{ quote(target_base) }} + crate_root=$(cd "$crate_root" && pwd -P) mkdir -p "$target_base" target_base=$(cd "$target_base" && pwd -P) recipe_base="$target_base/vllm-cpp-sys-link-modes" @@ -114,7 +121,7 @@ link-modes: esac } trap cleanup EXIT - cd "$repo_root" + cd "$crate_root" export CARGO_TERM_COLOR=never find_one() { @@ -218,7 +225,7 @@ link-modes: prefix="$work/system-prefix" mkdir -p "$prefix/include" "$prefix/lib" "$prefix/lib64" "$prefix/blake3-lib" - cp vllm-cpp-sys/vllm.cpp/include/vllm.h "$prefix/include/" + cp vllm.cpp/include/vllm.h "$prefix/include/" bundled_static_lib=$(find_installed_library \ "$bundled_static_target/release/build" libvllm.a) @@ -395,8 +402,8 @@ package-test: echo 'could not read the native project version from vllm.cpp/CMakeLists.txt' >&2 exit 1 } - [[ $native_version == "$version" ]] || { - echo "native and crate versions differ: native=$native_version crates=$version" >&2 + [[ $native_version == 0.0.2 ]] || { + echo "expected pinned native version 0.0.2, found $native_version" >&2 exit 1 } jq -e --arg version "$version" ' @@ -445,13 +452,14 @@ package-test: diff -u "$sys_list" <(archive_inventory "$sys_package" "vllm-cpp-sys-$version") diff -u "$safe_list" <(archive_inventory "$safe_package" "vllm-cpp-$safe_version") + native_exclude_pattern='^vllm\.cpp/cmake/(CudaArchFeaturesTest|CudaSourceGencodeTest|DumpTritonAOTContract|InSourceGuardTest|TritonAOTDefaultTest|TritonAOTMultiArchTest|VerifyExports)\.cmake$|^vllm\.cpp/include/vt/rocm/(rocm_gelu_mul_sep|rocm_gemma4_expert_geglu|rocm_matmul_batch|rocm_rmsnorm_plus_add)\.h$|^vllm\.cpp/src/vllm/entrypoints/openai/(api_server|server_main)\.cpp$|^vllm\.cpp/src/vllm/platforms/tenstorrent\.cpp$|^vllm\.cpp/src/vt/cuda/marlin/.*/generate_kernels\.py$|^vllm\.cpp/src/vt/rocm/[^/]+\.hip$|^vllm\.cpp/src/vt/tenstorrent/|^vllm\.cpp/src/vt/vulkan/shaders/' native_inventory() { local base=$1 local member shift for member in "$@"; do find "$base/$member" -type f -print - done | sed "s#^$base/##" | LC_ALL=C sort + done | sed "s#^$base/##" | grep -Ev "$native_exclude_pattern" | LC_ALL=C sort } native_members=( vllm.cpp/CMakeLists.txt @@ -461,9 +469,11 @@ package-test: vllm.cpp/include vllm.cpp/src vllm.cpp/scripts/triton-aot-compile.py + vllm.cpp/tests/vt/test_rocm_backend.cpp vllm.cpp/triton_kernels vllm.cpp/third_party/README.md vllm.cpp/third_party/blake3 + vllm.cpp/third_party/doctest/doctest.h vllm.cpp/third_party/minja vllm.cpp/third_party/nlohmann vllm.cpp/third_party/vulkan @@ -481,6 +491,7 @@ package-test: README.md \ THIRD_PARTY.md \ build.rs \ + licenses/DOCTEST-MIT.txt \ licenses/FLASH-ATTENTION-BSD-3-CLAUSE.txt \ licenses/FLASH-LINEAR-ATTENTION-MIT.txt \ src/bindings.rs \ @@ -500,7 +511,7 @@ package-test: <(native_inventory "$repo_root/vllm-cpp-sys" "${native_members[@]}") \ <(native_inventory "$sys_root" "${native_members[@]}") diff -u \ - <(printf '%s\n' CMakeLists.txt LICENSE NOTICE cmake include scripts src third_party triton_kernels | LC_ALL=C sort) \ + <(printf '%s\n' CMakeLists.txt LICENSE NOTICE cmake include scripts src tests third_party triton_kernels | LC_ALL=C sort) \ <(find "$sys_root/vllm.cpp" -mindepth 1 -maxdepth 1 -printf '%f\n' | LC_ALL=C sort) safe_expected="$temp/vllm-cpp.expected" @@ -535,6 +546,7 @@ package-test: required_sys_members=( README.md THIRD_PARTY.md + licenses/DOCTEST-MIT.txt licenses/FLASH-ATTENTION-BSD-3-CLAUSE.txt licenses/FLASH-LINEAR-ATTENTION-MIT.txt vllm.cpp/include/vllm.h @@ -546,13 +558,24 @@ package-test: vllm.cpp/src/vt/cuda/cuda_matmul_fp8_cutlass.cu vllm.cpp/src/vt/cuda/flash_attn/src/flash.h vllm.cpp/src/vt/cuda/marlin/core/scalar_type.hpp + vllm.cpp/src/vt/cuda/triton_aot_vendored/sm_80/MANIFEST + vllm.cpp/src/vt/cuda/triton_aot_vendored/sm_86/MANIFEST + vllm.cpp/src/vt/cuda/triton_aot_vendored/sm_89/MANIFEST + vllm.cpp/src/vt/cuda/triton_aot_vendored/sm_90a/MANIFEST + vllm.cpp/src/vt/cuda/triton_aot_vendored/sm_100a/MANIFEST vllm.cpp/src/vt/cuda/triton_aot_vendored/sm_121a/MANIFEST + vllm.cpp/src/vt/metal/metal_mlx_provider.mm + vllm.cpp/src/vt/vulkan/vulkan_spirv.h + vllm.cpp/src/vllm/platforms/rocm.cpp + vllm.cpp/include/vt/rocm/rocm_arch.h + vllm.cpp/include/vt/rocm/rocm_runtime.h + vllm.cpp/tests/vt/test_rocm_backend.cpp vllm.cpp/scripts/triton-aot-compile.py vllm.cpp/triton_kernels/chunk_delta_h.py - vllm.cpp/src/vt/vulkan/vulkan_spirv.h vllm.cpp/third_party/README.md vllm.cpp/third_party/blake3/LICENSE_A2 vllm.cpp/third_party/blake3/LICENSE_CC0 + vllm.cpp/third_party/doctest/doctest.h vllm.cpp/third_party/minja/LICENSE vllm.cpp/third_party/nlohmann/json.hpp vllm.cpp/third_party/vulkan/vulkan_core.h @@ -580,10 +603,22 @@ package-test: vllm.cpp/benchmarks vllm.cpp/docs vllm.cpp/examples - vllm.cpp/tests vllm.cpp/tools - vllm.cpp/third_party/doctest vllm.cpp/third_party/httplib + vllm.cpp/cmake/CudaArchFeaturesTest.cmake + vllm.cpp/cmake/CudaSourceGencodeTest.cmake + vllm.cpp/cmake/DumpTritonAOTContract.cmake + vllm.cpp/cmake/InSourceGuardTest.cmake + vllm.cpp/cmake/TritonAOTDefaultTest.cmake + vllm.cpp/cmake/TritonAOTMultiArchTest.cmake + vllm.cpp/cmake/VerifyExports.cmake + vllm.cpp/src/vllm/entrypoints/openai/api_server.cpp + vllm.cpp/src/vllm/entrypoints/openai/server_main.cpp + vllm.cpp/src/vllm/platforms/tenstorrent.cpp + vllm.cpp/src/vt/cuda/marlin/libtorch_stable/moe/marlin_moe_wna16/generate_kernels.py + vllm.cpp/src/vt/rocm + vllm.cpp/src/vt/tenstorrent + vllm.cpp/src/vt/vulkan/shaders ) for member in "${denied_sys_members[@]}"; do [[ ! -e $sys_root/$member ]] || { @@ -591,6 +626,14 @@ package-test: exit 1 } done + diff -u \ + <(printf '%s\n' vllm.cpp/tests/vt/test_rocm_backend.cpp) \ + <(find "$sys_root/vllm.cpp/tests" -type f -printf '%P\n' \ + | sed 's#^#vllm.cpp/tests/#' | LC_ALL=C sort) + diff -u \ + <(printf '%s\n' vllm.cpp/third_party/doctest/doctest.h) \ + <(find "$sys_root/vllm.cpp/third_party/doctest" -type f -printf '%P\n' \ + | sed 's#^#vllm.cpp/third_party/doctest/#' | LC_ALL=C sort) forbidden_pattern='(^|/)(target|stuff|\.git|\.github|__pycache__|\.cache|cache|fixtures?|downloads?|_deps|sdk)(/|$)|(^|/)(cutlass)(/|$)|(^|/)(model\.safetensors|tokenizer\.json|tokenizer_config\.json)$|\.(o|obj|a|so|dylib|dll|pyc|safetensors|gguf|pt|pth)$' for listing in "$sys_list" "$safe_list"; do @@ -633,6 +676,7 @@ package-test: LICENSE-MIT \ NOTICE \ THIRD_PARTY.md \ + licenses/DOCTEST-MIT.txt \ licenses/FLASH-ATTENTION-BSD-3-CLAUSE.txt \ licenses/FLASH-LINEAR-ATTENTION-MIT.txt \ vllm.cpp/LICENSE \ @@ -671,13 +715,16 @@ package-test: sys_package_size=$(stat -c '%s' "$sys_package") sys_unpacked_size=$(du -sb "$sys_root" | cut -f1) + sys_regular_file_bytes=$(find "$sys_root" -type f -printf '%s\n' \ + | awk '{ total += $1 } END { print total + 0 }') + sys_package_sha256=$(sha256sum "$sys_package" | awk '{ print $1 }') sys_entry_count=$(wc -l < "$sys_list") safe_package_size=$(stat -c '%s' "$safe_package") safe_unpacked_size=$(du -sb "$safe_root" | cut -f1) safe_entry_count=$(wc -l < "$safe_list") ((sys_package_size <= 6 * 1024 * 1024)) - ((sys_unpacked_size <= 36 * 1024 * 1024)) - ((sys_entry_count <= 1300)) + ((sys_unpacked_size <= 40 * 1024 * 1024)) + ((sys_entry_count <= 1400)) ((safe_package_size <= 128 * 1024)) ((safe_unpacked_size <= 256 * 1024)) ((safe_entry_count <= 40)) @@ -693,11 +740,8 @@ package-test: and .[0].features.default == ["bundled"] ' <(cargo metadata --manifest-path "$sys_root/Cargo.toml" \ --locked --offline --no-deps --format-version 1) >/dev/null - ( - cd "$sys_root" - CARGO_NET_OFFLINE=true CARGO_TARGET_DIR="$temp_target" \ - cargo test --locked --release --tests --offline - ) + just --justfile "$repo_root/Justfile" _link-modes \ + "$sys_root" "$temp/extracted-link-modes" sys_consumer="$temp/sys-consumer" mkdir -p "$sys_consumer/src" @@ -819,8 +863,9 @@ package-test: cargo run --locked --release --offline ) - printf 'sys package: %d entries, %d bytes unpacked, %d bytes compressed\n' \ - "$sys_entry_count" "$sys_unpacked_size" "$sys_package_size" + printf 'sys package: %d entries, %d regular-file bytes, %d du bytes, %d compressed bytes, sha256 %s\n' \ + "$sys_entry_count" "$sys_regular_file_bytes" "$sys_unpacked_size" \ + "$sys_package_size" "$sys_package_sha256" printf 'safe package: %d entries, %d bytes unpacked, %d bytes compressed\n' \ "$safe_entry_count" "$safe_unpacked_size" "$safe_package_size" diff --git a/vllm-cpp-sys/Cargo.toml b/vllm-cpp-sys/Cargo.toml index 5a35713..8f416c3 100644 --- a/vllm-cpp-sys/Cargo.toml +++ b/vllm-cpp-sys/Cargo.toml @@ -26,11 +26,31 @@ include = [ "/licenses/**", "/vllm.cpp/CMakeLists.txt", "/vllm.cpp/cmake/**", + "!/vllm.cpp/cmake/CudaArchFeaturesTest.cmake", + "!/vllm.cpp/cmake/CudaSourceGencodeTest.cmake", + "!/vllm.cpp/cmake/DumpTritonAOTContract.cmake", + "!/vllm.cpp/cmake/InSourceGuardTest.cmake", + "!/vllm.cpp/cmake/TritonAOTDefaultTest.cmake", + "!/vllm.cpp/cmake/TritonAOTMultiArchTest.cmake", + "!/vllm.cpp/cmake/VerifyExports.cmake", "/vllm.cpp/include/**", + "!/vllm.cpp/include/vt/rocm/rocm_gelu_mul_sep.h", + "!/vllm.cpp/include/vt/rocm/rocm_gemma4_expert_geglu.h", + "!/vllm.cpp/include/vt/rocm/rocm_matmul_batch.h", + "!/vllm.cpp/include/vt/rocm/rocm_rmsnorm_plus_add.h", "/vllm.cpp/src/**", + "!/vllm.cpp/src/vllm/entrypoints/openai/api_server.cpp", + "!/vllm.cpp/src/vllm/entrypoints/openai/server_main.cpp", + "!/vllm.cpp/src/vllm/platforms/tenstorrent.cpp", + "!/vllm.cpp/src/vt/cuda/marlin/**/generate_kernels.py", + "!/vllm.cpp/src/vt/rocm/*.hip", + "!/vllm.cpp/src/vt/tenstorrent/**", + "!/vllm.cpp/src/vt/vulkan/shaders/**", + "/vllm.cpp/tests/vt/test_rocm_backend.cpp", "/vllm.cpp/triton_kernels/**", "/vllm.cpp/scripts/triton-aot-compile.py", "/vllm.cpp/third_party/blake3/**", + "/vllm.cpp/third_party/doctest/doctest.h", "/vllm.cpp/third_party/minja/**", "/vllm.cpp/third_party/nlohmann/**", "/vllm.cpp/third_party/vulkan/**", diff --git a/vllm-cpp-sys/README.md b/vllm-cpp-sys/README.md index 2693b60..06d132a 100644 --- a/vllm-cpp-sys/README.md +++ b/vllm-cpp-sys/README.md @@ -4,7 +4,7 @@ Raw Rust bindings and native linking for the stable C API of [vllm.cpp](https:// This crate exposes checked-in generated unsafe declarations for the 35 exported C symbols in ABI version 17. Callers are responsible for pointer validity, lifetimes, callback threading, status/error handling, and matching every native allocation with its documented free function. Applications should prefer the current safe [`vllm-cpp`](https://docs.rs/vllm-cpp) crate unless they require direct ABI access. Ordinary consumers do not need Just, bindgen, or libclang. -The package contains Rust declarations and conformance tests, native build/link integration, the pinned native source inputs required by the supported feature set, and their licenses/notices. It excludes upstream tests, fixtures, models, examples, benchmarks, agent records, fetched SDKs, external CUTLASS trees, and build output. See the repository [changelog](https://github.com/querymt/vllm-cpp-rs/blob/main/CHANGELOG.md) and [release process](https://github.com/querymt/vllm-cpp-rs/blob/main/RELEASING.md) for the coordinated crate boundary. +The package contains Rust declarations and conformance tests, native build/link integration, the pinned native source inputs required by the supported feature set, and their licenses/notices. It excludes upstream test trees except for one unconditional ROCm syntax-check translation unit, plus fixtures, models, examples, benchmarks, agent records, fetched SDKs, external CUTLASS trees, and build output. See the repository [changelog](https://github.com/querymt/vllm-cpp-rs/blob/main/CHANGELOG.md) and [release process](https://github.com/querymt/vllm-cpp-rs/blob/main/RELEASING.md) for the coordinated crate boundary. ## Link Modes @@ -28,12 +28,14 @@ Feature selection is build configuration, not runtime or hardware evidence. Acce |---|---|---| | `cuda` | Linux x86_64/aarch64; requires exact `VLLM_CPP_CUDA_ARCHITECTURES` | Static mode links CMake's exact `CUDA_CUDART` and `CUDA_cublasLt_LIBRARY` results; dynamic mode relies on `libvllm.so` dependencies | | `cuda-cutlass` | Implies CUDA; requires canonical `VLLM_CPP_CUTLASS_DIR` with CUTLASS >=4.5.0; fetch is OFF; `103a`/`110` rejected | Header-only external input | -| `triton-aot` | Implies CUDA; checked-in single-architecture artifacts only; regeneration is OFF | Static mode also links CMake's exact `CUDA_cuda_driver_LIBRARY`; dynamic mode relies on `libvllm.so` | +| `triton-aot` | Implies CUDA; embeds all six checked-in AOT trees; regeneration is OFF | Static mode also links CMake's exact `CUDA_cuda_driver_LIBRARY`; dynamic mode relies on `libvllm.so` | | `vulkan` | Linux x86_64/aarch64; packaged Khronos headers and checked-in SPIR-V | No Vulkan SDK link; runtime loader uses `dlopen` | | `metal` | Exact `aarch64-apple-darwin`; native MSL backend | Static mode links `c++`, then `Metal` and `Foundation` frameworks | | `mlx` | Implies Metal; requires canonical external `MLX_ROOT` with `include/mlx/array.h`, `lib/libmlx.dylib`, and `lib/mlx.metallib` | Static mode adds `$MLX_ROOT/lib` before `dylib=mlx`; no rpath or packaged MLX payload | -CUDA architectures are exactly `80`, `86`, `87`, `89`, `90a`, `100a`, `103a`, `110`, `120a`, `121a`, or `120a;121a`. Triton accepts only `80`, `86`, `89`, `90a`, `100a`, or `121a`. Plain CUDA passes a nonexistent CUTLASS root to CMake so ambient source cannot silently change the build. Use separate `CARGO_TARGET_DIR` values for each backend/link combination. +CUDA architectures are exactly `80`, `86`, `87`, `89`, `90a`, `100a`, `103a`, `110`, `120a`, `121a`, or `120a;121a`. `triton-aot` accepts every one of those values, including the fat `120a;121a` build, and embeds the complete `sm_80`, `sm_86`, `sm_89`, `sm_90a`, `sm_100a`, and `sm_121a` vendored set. Runtime dispatch selects only an exact-SM cubin; architectures without an exact tree use the portable CUDA path rather than a neighboring cubin. Plain CUDA passes a nonexistent CUTLASS root to CMake so ambient source cannot silently change the build. Use separate `CARGO_TARGET_DIR` values for each backend/link combination. + +Cargo builds explicitly disable HIP/ROCm, Tenstorrent, NCCL, native tests/examples, and the HTTP server. CUTLASS fetching and Triton regeneration remain OFF, so supported bundled builds never download native inputs. Marlin and FlashAttention remain explicitly enabled when their CUDA architecture and external CUTLASS prerequisites are satisfied. Metal and MLX remain bundled-only and do not imply `bundled`; `--no-default-features` callers must explicitly select `bundled,metal` or `bundled,mlx`. Setting `MLX_ROOT` without `mlx` is rejected. MLX is never downloaded, copied, or packaged, and applications are responsible for making `libmlx.dylib` and its metallib deployment visible at runtime. diff --git a/vllm-cpp-sys/THIRD_PARTY.md b/vllm-cpp-sys/THIRD_PARTY.md index 574ad7b..d1404b5 100644 --- a/vllm-cpp-sys/THIRD_PARTY.md +++ b/vllm-cpp-sys/THIRD_PARTY.md @@ -12,7 +12,8 @@ | Marlin / GPTQ-Marlin slice | `vllm.cpp/src/vt/cuda/marlin/**` | vLLM commit `e24d1b24`, with retained file notices and vllm.cpp adapter changes | Apache-2.0 in `vllm.cpp/LICENSE` and retained source notices | | Flash Linear Attention Triton kernels | `vllm.cpp/triton_kernels/**`, generated AOT files under `vllm.cpp/src/vt/cuda/triton_aot_vendored/**` | FLA source ported through vLLM 0.24.0; exact source and artifact hashes are pinned in each AOT `MANIFEST` | `licenses/FLASH-LINEAR-ATTENTION-MIT.txt` | | nlohmann/json | `vllm.cpp/third_party/nlohmann/**` | nlohmann/json 3.12.0 | MIT notice retained in `json.hpp` | +| doctest | `vllm.cpp/third_party/doctest/doctest.h` | doctest 2.5.2, required by the packaged ROCm syntax-check source | `licenses/DOCTEST-MIT.txt` | -The package excludes upstream tests, fixtures, benchmarks, models, external SDKs, and build output. It contains only native source/build inputs and required licenses/notices. +The package excludes upstream tests, fixtures, benchmarks, models, external SDKs, and build output. It contains only native source/build inputs and required licenses/notices, including the one ROCm test translation unit compiled unconditionally as a syntax check. vllm.cpp is an independent community project and is not affiliated with or endorsed by the vLLM project, the PyTorch Foundation, or the Linux Foundation. diff --git a/vllm-cpp-sys/build.rs b/vllm-cpp-sys/build.rs index fa2cf13..d9b6838 100644 --- a/vllm-cpp-sys/build.rs +++ b/vllm-cpp-sys/build.rs @@ -45,9 +45,11 @@ fn main() { "vllm.cpp/cmake", "vllm.cpp/include/vllm.h", "vllm.cpp/src", + "vllm.cpp/tests/vt/test_rocm_backend.cpp", "vllm.cpp/triton_kernels", "vllm.cpp/scripts/triton-aot-compile.py", "vllm.cpp/third_party/blake3", + "vllm.cpp/third_party/doctest/doctest.h", "vllm.cpp/third_party/minja", "vllm.cpp/third_party/nlohmann", "vllm.cpp/third_party/vulkan", diff --git a/vllm-cpp-sys/licenses/DOCTEST-MIT.txt b/vllm-cpp-sys/licenses/DOCTEST-MIT.txt new file mode 100644 index 0000000..9472d7c --- /dev/null +++ b/vllm-cpp-sys/licenses/DOCTEST-MIT.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016-2023 Viktor Kirilov + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vllm-cpp-sys/src/build_config.rs b/vllm-cpp-sys/src/build_config.rs index 0ee338f..f07b3a7 100644 --- a/vllm-cpp-sys/src/build_config.rs +++ b/vllm-cpp-sys/src/build_config.rs @@ -17,8 +17,6 @@ const CUDA_ARCHITECTURES: &[&str] = &[ "121a", "120a;121a", ]; -const TRITON_ARCHITECTURES: &[&str] = &["80", "86", "89", "90a", "100a", "121a"]; - #[derive(Clone, Debug, Default, Eq, PartialEq)] pub struct Features { pub bundled: bool, @@ -172,12 +170,21 @@ pub fn plan(inputs: &Inputs, probe: &impl PathProbe) -> Result Result, ConfigError> { CUDA_ARCHITECTURES.join(", ") ))); } - if inputs.features.triton_aot && !TRITON_ARCHITECTURES.contains(&architectures) { - return Err(ConfigError::new(format!( - "`triton-aot` requires one vendored single architecture: {}; got {architectures:?}", - TRITON_ARCHITECTURES.join(", ") - ))); - } Ok(Some(architectures.to_owned())) } diff --git a/vllm-cpp-sys/tests/build_config.rs b/vllm-cpp-sys/tests/build_config.rs index 25b7478..17d22c7 100644 --- a/vllm-cpp-sys/tests/build_config.rs +++ b/vllm-cpp-sys/tests/build_config.rs @@ -132,23 +132,50 @@ fn error(inputs: &Inputs, probe: &MockProbe) -> String { plan(inputs, probe).unwrap_err().to_string() } +fn deterministic_defines( + cuda: &str, + metal: &str, + vulkan: &str, + mlx: &str, + triton: &str, + sanitizer: &str, +) -> Vec<(&'static str, String)> { + [ + ("VLLM_CPP_BUILD_TESTS", "OFF"), + ("VLLM_CPP_BUILD_EXAMPLES", "OFF"), + ("VLLM_CPP_SERVER", "OFF"), + ("VLLM_CPP_HIP", "OFF"), + ("VLLM_CPP_TENSTORRENT", "OFF"), + ("VLLM_CPP_LITERAL_STATIC", "OFF"), + ("VLLM_CPP_BENCH_PROFILE_CONTROL", "OFF"), + ("VLLM_CPP_NCCL", "OFF"), + ("VLLM_CPP_MARLIN", "ON"), + ("VLLM_CPP_FLASH_ATTN", "ON"), + ("VLLM_CPP_CUDA", cuda), + ("VLLM_CPP_METAL", metal), + ("VLLM_CPP_VULKAN", vulkan), + ("VLLM_CPP_MLX", mlx), + ("VLLM_CPP_TRITON", triton), + ("VLLM_CPP_TRITON_REGEN", "OFF"), + ("VLLM_CPP_TRITON_VENDORED_ARCH", ""), + ("VLLM_CPP_TRITON_TARGET", ""), + ("VLLM_CPP_CUTLASS_FETCH", "OFF"), + ("VLLM_CPP_SANITIZE", sanitizer), + ] + .into_iter() + .map(|(name, value)| (name, value.to_owned())) + .collect() +} + #[test] fn cpu_and_vulkan_plans_are_deterministic() { let cpu = plan(&linux(), &MockProbe::default()).unwrap(); let arm_cpu = plan(&linux_arm64(), &MockProbe::default()).unwrap(); assert_eq!(arm_cpu, cpu); - assert!(cpu - .cmake_defines - .contains(&("VLLM_CPP_CUDA", "OFF".to_owned()))); - assert!(cpu - .cmake_defines - .contains(&("VLLM_CPP_VULKAN", "OFF".to_owned()))); - assert!(cpu - .cmake_defines - .contains(&("VLLM_CPP_METAL", "OFF".to_owned()))); - assert!(cpu - .cmake_defines - .contains(&("VLLM_CPP_MLX", "OFF".to_owned()))); + assert_eq!( + cpu.cmake_defines, + deterministic_defines("OFF", "OFF", "OFF", "OFF", "OFF", "OFF") + ); assert!(!cpu .cmake_defines .iter() @@ -167,31 +194,28 @@ fn cpu_and_vulkan_plans_are_deterministic() { let first = plan(&vulkan, &MockProbe::default()).unwrap(); let second = plan(&vulkan, &MockProbe::default()).unwrap(); assert_eq!(first, second); - assert!(first - .cmake_defines - .contains(&("VLLM_CPP_VULKAN", "ON".to_owned()))); + assert_eq!( + first.cmake_defines, + deterministic_defines("OFF", "OFF", "ON", "OFF", "OFF", "OFF") + ); } #[test] fn apple_cpu_metal_and_mlx_plans_are_deterministic() { let cpu = plan(&apple(), &MockProbe::default()).unwrap(); + assert_eq!( + cpu.cmake_defines, + deterministic_defines("OFF", "OFF", "OFF", "OFF", "OFF", "OFF") + ); assert_eq!(cpu.link_requirements, vec![LinkRequirement::Library("c++")]); - assert!(cpu - .cmake_defines - .contains(&("VLLM_CPP_METAL", "OFF".to_owned()))); - assert!(cpu - .cmake_defines - .contains(&("VLLM_CPP_MLX", "OFF".to_owned()))); let mut metal = apple(); metal.features.metal = true; let metal_plan = plan(&metal, &MockProbe::default()).unwrap(); - assert!(metal_plan - .cmake_defines - .contains(&("VLLM_CPP_METAL", "ON".to_owned()))); - assert!(metal_plan - .cmake_defines - .contains(&("VLLM_CPP_MLX", "OFF".to_owned()))); + assert_eq!( + metal_plan.cmake_defines, + deterministic_defines("OFF", "ON", "OFF", "OFF", "OFF", "OFF") + ); assert_eq!( metal_plan.link_requirements, vec![ @@ -205,12 +229,9 @@ fn apple_cpu_metal_and_mlx_plans_are_deterministic() { mlx.features.mlx = true; mlx.environment.mlx_root = Some(PathBuf::from("mlx")); let mlx_plan = plan(&mlx, &MockProbe::mlx()).unwrap(); - assert!(mlx_plan - .cmake_defines - .contains(&("VLLM_CPP_MLX", "ON".to_owned()))); - assert!(mlx_plan - .cmake_defines - .contains(&("MLX_ROOT", "/mlx".to_owned()))); + let mut expected_mlx = deterministic_defines("OFF", "ON", "OFF", "ON", "OFF", "OFF"); + expected_mlx.push(("MLX_ROOT", "/mlx".to_owned())); + assert_eq!(mlx_plan.cmake_defines, expected_mlx); assert_eq!( mlx_plan.link_requirements, vec![ @@ -225,9 +246,7 @@ fn apple_cpu_metal_and_mlx_plans_are_deterministic() { mlx.features.dynamic_link = true; let dynamic_mlx = plan(&mlx, &MockProbe::mlx()).unwrap(); assert!(dynamic_mlx.link_requirements.is_empty()); - assert!(dynamic_mlx - .cmake_defines - .contains(&("MLX_ROOT", "/mlx".to_owned()))); + assert_eq!(dynamic_mlx.cmake_defines, expected_mlx); } #[test] @@ -483,32 +502,41 @@ fn cuda_cache_keys_match_find_cudatoolkit() { } #[test] -fn triton_accepts_only_vendored_single_architectures() { - for architecture in ["80", "86", "89", "90a", "100a", "121a"] { +fn triton_accepts_every_valid_cuda_architecture() { + for architecture in [ + "80", + "86", + "87", + "89", + "90a", + "100a", + "103a", + "110", + "120a", + "121a", + "120a;121a", + ] { let mut inputs = linux(); inputs.features.cuda = true; inputs.features.triton_aot = true; inputs.environment.cuda_architectures = Some(architecture.to_owned()); let plan = plan(&inputs, &MockProbe::default()).unwrap(); - assert!(plan - .cmake_defines - .contains(&("VLLM_CPP_TRITON", "ON".to_owned()))); - assert!(plan - .cmake_defines - .contains(&("VLLM_CPP_TRITON_REGEN", "OFF".to_owned()))); - } - - for invalid in ["87", "103a", "110", "120a", "120a;121a"] { - let mut inputs = linux(); - inputs.features.cuda = true; - inputs.features.triton_aot = true; - inputs.environment.cuda_architectures = Some(invalid.to_owned()); - assert!(error(&inputs, &MockProbe::default()).contains("vendored single")); + let mut expected = deterministic_defines("ON", "OFF", "OFF", "OFF", "ON", "OFF"); + expected.push(("VLLM_CPP_CUDA_ARCHITECTURES", architecture.to_owned())); + assert_eq!(plan.cmake_defines, expected); } } #[test] fn rejects_cuda_sanitizers_and_unsupported_vulkan_targets() { + let mut sanitized = linux(); + sanitized.environment.sanitizer = Some("address,undefined".to_owned()); + let sanitized_plan = plan(&sanitized, &MockProbe::default()).unwrap(); + assert_eq!( + sanitized_plan.cmake_defines, + deterministic_defines("OFF", "OFF", "OFF", "OFF", "OFF", "address,undefined") + ); + let mut inputs = linux(); inputs.features.cuda = true; inputs.environment.cuda_architectures = Some("80".to_owned()); diff --git a/vllm-cpp-sys/tests/symbols.rs b/vllm-cpp-sys/tests/symbols.rs index 2a4ac5d..96e958e 100644 --- a/vllm-cpp-sys/tests/symbols.rs +++ b/vllm-cpp-sys/tests/symbols.rs @@ -1,5 +1,7 @@ use std::collections::BTreeSet; -use std::ffi::{c_char, c_void, CStr, CString}; +#[cfg(feature = "bundled")] +use std::ffi::CString; +use std::ffi::{c_char, c_void, CStr}; use vllm_cpp_sys as ffi; @@ -101,8 +103,9 @@ fn reports_target_identity_and_handles_invalid_model_path() { assert!(!error.to_bytes().is_empty()); } +#[cfg(feature = "bundled")] #[test] -fn server_entry_point_is_present_and_nonblocking_for_help_or_server_off() { +fn bundled_server_entry_point_reports_the_server_off_stub() { let mut arguments = [ CString::new("vllm-server").unwrap(), CString::new("--help").unwrap(), @@ -112,14 +115,12 @@ fn server_entry_point_is_present_and_nonblocking_for_help_or_server_off() { .map(|argument| argument.as_ptr().cast_mut()) .collect::>(); let status = unsafe { ffi::vllm_server_main(argv.len() as i32, argv.as_mut_ptr()) }; - assert!(matches!(status, 0 | 1)); - if status == 1 { - let error = unsafe { CStr::from_ptr(ffi::vllm_last_error()) }; - assert!(error - .to_bytes() - .windows(13) - .any(|part| part == b"without VLLM_")); - } + assert_eq!(status, 1); + let error = unsafe { CStr::from_ptr(ffi::vllm_last_error()) }; + assert_eq!( + error.to_bytes(), + b"vllm_server_main: this library was built without VLLM_CPP_SERVER; rebuild with -DVLLM_CPP_SERVER=ON to serve HTTP" + ); } #[test]