Files
MOVZX 777e910dd0 Initial commit
Signed-off-by: MOVZX <movzx@yahoo.com>
2026-10-15 01:01:52 +07:00

71 lines
2.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# Generates the CUDA driver link stub: $1 = a CUDA C header, $2 = the .so to write.
#
# vllm links its C++ kernels against CUDA::cuda_driver, the CUDA driver library
# (libcuda.so.1). The driver package provides it; the CUDA toolkit wheel does
# not, and neither does a build container without a GPU. NVIDIA ships the
# link-time stub for it in the runfile installer, not in the pip wheel, so this
# script builds an equivalent one from the header: one exported symbol per
# driver entry point, no bodies, 87 KB.
#
# Link time only. The soname is libcuda.so.1, so the dynamic linker opens the
# real driver from the host at run time and can never pick the stub.
#
# Writes nothing when the file already has every entry point, so a re-run does
# not invalidate the compiled-ops hash recorded by build.sh.
set -euo pipefail
H="${1:?usage: $0 <cuda.h> <out.so>}"
OUT="${2:?usage: $0 <cuda.h> <out.so>}"
[ -r "$H" ] || { echo "no readable CUDA header at $H"; exit 1; }
decls(){
# Calls written as "CUresult CUDAAPI cuFoo(...)", split over lines.
awk '/CUresult[ \t]+CUDAAPI/{cap=1;buf=""} cap{buf=buf" "$0; if(buf~/;/){
if(match(buf,/CUresult[ \t]+CUDAAPI[ \t]+[A-Za-z_][A-Za-z0-9_]*/)){
s=substr(buf,RSTART,RLENGTH); sub(/.*CUDAAPI[ \t]+/,"",s); print s} cap=0}}' "$H"
# Versioned names hidden behind a macro: code writes cuFoo, the preprocessor
# rewrites it to cuFoo_v2, so the object file asks the linker for cuFoo_v2.
sed -nE 's/^#define[ \t]+(cu[A-Za-z0-9_]+)[ \t]+(cu[A-Za-z0-9_]+_v[0-9]+)([ \t]|$).*/\2/p' "$H"
}
want="$(decls | sort -u)"
n="$(printf '%s\n' "$want" | sed '/^$/d' | wc -l)"
[ "$n" -gt 100 ] || { echo "only $n driver entry points found in $H"; exit 1; }
if [ -e "$OUT" ]; then
have="$(nm -D --defined-only "$OUT" 2>/dev/null | awk '$2=="T"{print $3}' | sort -u)"
miss="$(LC_ALL=C comm -23 <(printf '%s\n' "$want") <(printf '%s\n' "$have") | sed '/^$/d')"
if [ -z "$miss" ]; then
echo "driver stub is current: $(basename "$OUT"), $n entry points"
exit 0
fi
echo "driver stub is missing $(printf '%s\n' "$miss" | wc -l) entry points, regenerating"
fi
mkdir -p "$(dirname "$OUT")"
src="$(mktemp --suffix=.c)"
cleanup(){ rm -f "$src"; }
trap cleanup EXIT
: > "$src"
printf '%s\n' "$want" | while read -r f; do
[ -n "$f" ] && printf 'unsigned int %s(void){ return 0; }\n' "$f" >> "$src"
done
cc -shared -fPIC -O0 -o "$OUT" "$src" -Wl,-soname,libcuda.so.1
have="$(nm -D --defined-only "$OUT" | awk '$2=="T"{print $3}' | sort -u)"
miss="$(LC_ALL=C comm -23 <(printf '%s\n' "$want") <(printf '%s\n' "$have") | sed '/^$/d')"
[ -z "$miss" ] || { echo "the stub is still missing:"; printf '%s\n' "$miss"; exit 1; }
echo "driver stub generated: $OUT ($(printf '%s\n' "$want" | wc -l) entry points, soname libcuda.so.1)"