[CI] Discover Rust coverage artifacts from build metadata

Co-authored-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
Bugen Zhao
2026-07-23 06:44:16 +00:00
co-authored by OpenAI Codex
parent 84aeec9f22
commit e1a763558c
3 changed files with 49 additions and 58 deletions
+28 -57
View File
@@ -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 <<EOF
$rust_cov_collect_objects
EOF
llvm-profdata merge \
-sparse \
"$@" \
"$RUST_COVERAGE_DIR"/*.profraw \
-o "$RUST_COVERAGE_DIR/merged.profdata" || return 1
llvm-cov export \
"$rust_cov_collect_vllm_rs" \
--object="$rust_cov_collect_parser" \
"$rust_cov_collect_primary" \
"$@" \
--format=lcov \
--instr-profile="$RUST_COVERAGE_DIR/merged.profdata" \
--ignore-filename-regex='/\.cargo/(registry|git)/|/rustc/|/target/' \
@@ -107,19 +87,10 @@ rust_coverage_upload() {
|| return 1
curl -fsSL \
"https://github.com/codecov/codecov-cli/releases/download/${RUST_CODECOV_VERSION}/codecovcli_linux" \
-o "$rust_cov_upload_codecov_dir/codecov" || {
rm -rf "$rust_cov_upload_codecov_dir"
return 1
}
-o "$rust_cov_upload_codecov_dir/codecov" || return 1
echo "$RUST_CODECOV_SHA256 $rust_cov_upload_codecov_dir/codecov" \
| sha256sum -c - || {
rm -rf "$rust_cov_upload_codecov_dir"
return 1
}
chmod +x "$rust_cov_upload_codecov_dir/codecov" || {
rm -rf "$rust_cov_upload_codecov_dir"
return 1
}
| sha256sum -c - || return 1
chmod +x "$rust_cov_upload_codecov_dir/codecov" || return 1
rust_cov_upload_slug="vllm-project/vllm"
if [ -n "${BUILDKITE_PULL_REQUEST:-}" ] \
+1
View File
@@ -54,6 +54,7 @@ if [[ "${VLLM_RUST_COVERAGE:-0}" == "1" ]]; then
# Build scripts and proc macros can run during compilation. Their profiles
# are unrelated to runtime coverage and would otherwise pollute the tree.
export LLVM_PROFILE_FILE=/dev/null
export VLLM_RUST_COVERAGE_OBJECTS="$COVERAGE_TOOLS_DIR/objects"
fi
python3 "$REPO_ROOT/tools/build_rust.py" "$PROFILE_ARG"
+20 -1
View File
@@ -36,6 +36,22 @@ def rust_extensions(*, optional: bool = False) -> 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: