diff --git a/.buildkite/scripts/rust-coverage.sh b/.buildkite/scripts/rust-coverage.sh index 574ee9652fd..d2d8b39027c 100644 --- a/.buildkite/scripts/rust-coverage.sh +++ b/.buildkite/scripts/rust-coverage.sh @@ -19,26 +19,25 @@ rust_coverage_start() { RUST_COVERAGE_DIR="/tmp/vllm-rust-coverage/${BUILDKITE_JOB_ID:-local}" export RUST_COVERAGE_FLAG RUST_COVERAGE_DIR mkdir -p "$RUST_COVERAGE_DIR" - LLVM_PROFILE_FILE="$RUST_COVERAGE_DIR/vllm-rust-%4m.profraw" + LLVM_PROFILE_FILE="$RUST_COVERAGE_DIR/rust-%4m.profraw" export LLVM_PROFILE_FILE trap rust_coverage_finalize 0 } rust_coverage_objects() { - python3 - <<'PY' + rust_cov_objects_manifest="$(dirname "$(command -v llvm-cov)")/../objects" + python3 - "$rust_cov_objects_manifest" <<'PY' from pathlib import Path import sys -for entry in sys.path: - package_dir = Path(entry or ".").resolve() / "vllm" - binary = package_dir / "vllm-rs" - parsers = sorted(package_dir.glob("_rust_tool_parser*.so")) - if binary.is_file() and len(parsers) == 1: - print(binary) - print(parsers[0]) - break -else: - raise RuntimeError("installed vLLM Rust coverage objects were not found") +for relative in Path(sys.argv[1]).read_text().splitlines(): + for entry in sys.path: + path = Path(entry or ".").resolve() / relative + if path.is_file(): + print(path) + break + else: + raise RuntimeError(f"installed Rust coverage object was not found: {relative}") PY } @@ -46,45 +45,26 @@ rust_coverage_collect() { rust_cov_collect_flag=${1:?coverage flag is required} rust_cov_collect_lcov="$RUST_COVERAGE_DIR/$rust_cov_collect_flag.lcov" - command -v llvm-profdata >/dev/null || return 1 - command -v llvm-cov >/dev/null || return 1 - - set -- - for rust_cov_collect_profile in "$RUST_COVERAGE_DIR"/*.profraw; do - if [ -s "$rust_cov_collect_profile" ]; then - set -- "$@" "$rust_cov_collect_profile" - fi - done - if [ "$#" -eq 0 ]; then - echo "Rust coverage profile is empty" >&2 - return 1 - fi - rust_cov_collect_objects=$(rust_coverage_objects) || return 1 - rust_cov_collect_object_count=$( - printf '%s\n' "$rust_cov_collect_objects" \ - | awk 'NF { count++ } END { print count + 0 }' - ) - rust_cov_collect_vllm_rs=$( - printf '%s\n' "$rust_cov_collect_objects" | sed -n '1p' - ) - rust_cov_collect_parser=$( - printf '%s\n' "$rust_cov_collect_objects" | sed -n '2p' - ) - if [ "$rust_cov_collect_object_count" -ne 2 ] \ - || [ ! -f "$rust_cov_collect_vllm_rs" ] \ - || [ ! -f "$rust_cov_collect_parser" ]; then - echo "Rust coverage objects were not found" >&2 - return 1 - fi + rust_cov_collect_primary= + set -- + while IFS= read -r rust_cov_collect_object; do + if [ -z "$rust_cov_collect_primary" ]; then + rust_cov_collect_primary=$rust_cov_collect_object + else + set -- "$@" "--object=$rust_cov_collect_object" + fi + done < list[RustExtension]: ] +def write_coverage_objects(extensions: list[RustExtension], output: Path) -> None: + artifacts = [] + for extension in extensions: + for target in sorted(set(extension.target.values())): + target_path = ROOT_DIR.joinpath(*target.split(".")) + if extension.binding == Binding.Exec: + matches = [target_path] + else: + matches = sorted(target_path.parent.glob(f"{target_path.name}*.so")) + if len(matches) != 1 or not matches[0].is_file(): + raise RuntimeError(f"unable to locate Rust artifact for {target}") + artifacts.append(matches[0].relative_to(ROOT_DIR).as_posix()) + + output.write_text("\n".join(artifacts) + "\n") + + def rust_py_extension_module_names() -> list[str]: module_names = [] for extension in rust_extensions(): @@ -52,12 +68,15 @@ def rust_py_extension_module_names() -> list[str]: def build_binary(build_rust_args: list[str]) -> None: os.chdir(ROOT_DIR) (ROOT_DIR / "vllm").mkdir(exist_ok=True) + extensions = rust_extensions(optional=False) setup( name="vllm-rust-frontend-build", packages=[], - rust_extensions=rust_extensions(optional=False), + rust_extensions=extensions, script_args=["build_rust", "--quiet", "--inplace", *build_rust_args], ) + if output := os.getenv("VLLM_RUST_COVERAGE_OBJECTS"): + write_coverage_objects(extensions, Path(output)) def main() -> None: