| 1 | #!/bin/bash |
| 2 | # This script tests if the python only compilation works correctly |
| 3 | # for users who do not have any compilers installed on their system |
| 4 | |
| 5 | set -e |
| 6 | |
| 7 | merge_base_commit="" |
| 8 | rocm_wheel="" |
| 9 | is_rocm=0 |
| 10 | _vllm_target_lower="$(printf '%s' "${VLLM_TARGET_DEVICE:-}" | tr '[:upper:]' '[:lower:]')" |
| 11 | if [[ "${_vllm_target_lower}" == "rocm" || -n "${ROCM_PATH:-}" || -d /opt/rocm ]] \ |
| 12 | || command -v rocminfo >/dev/null 2>&1; then |
| 13 | is_rocm=1 |
| 14 | fi |
| 15 | unset -v _vllm_target_lower |
| 16 | |
| 17 | if [[ "${is_rocm}" == "1" ]]; then |
| 18 | # Native CI passes the verified wheel artifact explicitly. Legacy ROCm |
| 19 | # images carry the same-build wheel in /opt/vllm-wheels. |
| 20 | if [[ -n "${VLLM_PRECOMPILED_WHEEL_LOCATION:-}" ]]; then |
| 21 | rocm_wheel="${VLLM_PRECOMPILED_WHEEL_LOCATION}" |
| 22 | if [[ ! -f "${rocm_wheel}" || "$(basename "${rocm_wheel}")" != vllm-*.whl ]]; then |
| 23 | echo "ERROR: invalid ROCm wheel location: ${rocm_wheel}" >&2 |
| 24 | exit 1 |
| 25 | fi |
| 26 | rocm_wheel="$(realpath -- "${rocm_wheel}")" |
| 27 | elif [[ -d /opt/vllm-wheels ]]; then |
| 28 | shopt -s nullglob |
| 29 | rocm_wheels=(/opt/vllm-wheels/vllm-*.whl) |
| 30 | shopt -u nullglob |
| 31 | if [[ "${#rocm_wheels[@]}" -ne 1 ]]; then |
| 32 | echo "ERROR: expected exactly one vLLM wheel in /opt/vllm-wheels, found ${#rocm_wheels[@]}." >&2 |
| 33 | exit 1 |
| 34 | fi |
| 35 | rocm_wheel="${rocm_wheels[0]}" |
| 36 | fi |
| 37 | fi |
| 38 | |
| 39 | if [[ -n "${rocm_wheel}" ]]; then |
| 40 | echo "INFO: using same-build ROCm wheel: ${rocm_wheel}" |
| 41 | else |
| 42 | # Some CI images do not include .git under /vllm-workspace. Their wrapper |
| 43 | # passes CI_STANDALONE_MERGE_BASE from the agent checkout. |
| 44 | if [[ -n "${CI_STANDALONE_MERGE_BASE:-}" ]]; then |
| 45 | merge_base_commit="${CI_STANDALONE_MERGE_BASE}" |
| 46 | elif merge_base_commit="$(git -C /vllm-workspace merge-base HEAD origin/main 2>/dev/null)"; then |
| 47 | : |
| 48 | elif merge_base_commit="$(git merge-base HEAD origin/main 2>/dev/null)"; then |
| 49 | : |
| 50 | else |
| 51 | echo "ERROR: need a git checkout or CI_STANDALONE_MERGE_BASE to resolve wheels.vllm.ai commit." >&2 |
| 52 | exit 1 |
| 53 | fi |
| 54 | |
| 55 | echo "INFO: current merge base commit with main: $merge_base_commit" |
| 56 | if git show --oneline -s "$merge_base_commit" 2>/dev/null; then |
| 57 | : |
| 58 | else |
| 59 | echo "INFO: git show unavailable in this environment; using SHA above for precompiled metadata." |
| 60 | fi |
| 61 | |
| 62 | # Test whether the metadata.json URL is valid, retry each 5 minutes up to 5 times. |
| 63 | # This avoids manual retries while a new main-branch wheel is still publishing. |
| 64 | if [[ "${is_rocm}" == "1" ]]; then |
| 65 | _rocm_env_variant="$(python3 - <<'PY' |
| 66 | import ctypes |
| 67 | import os |
| 68 | from pathlib import Path |
| 69 | |
| 70 | |
| 71 | def get_rocm_version() -> str | None: |
| 72 | rocm_home = os.environ.get("ROCM_HOME") or os.environ.get("ROCM_PATH") or "/opt/rocm" |
| 73 | try: |
| 74 | librocm_core = Path(rocm_home) / "lib" / "librocm-core.so" |
| 75 | if not librocm_core.is_file(): |
| 76 | return None |
| 77 | librocm = ctypes.CDLL(str(librocm_core)) |
| 78 | get_rocm_core_version = librocm.getROCmVersion |
| 79 | major = ctypes.c_uint32() |
| 80 | minor = ctypes.c_uint32() |
| 81 | patch = ctypes.c_uint32() |
| 82 | if get_rocm_core_version( |
| 83 | ctypes.byref(major), ctypes.byref(minor), ctypes.byref(patch) |
| 84 | ) == 0: |
| 85 | return f"{major.value}.{minor.value}.{patch.value}" |
| 86 | except Exception: |
| 87 | return None |
| 88 | return None |
| 89 | |
| 90 | |
| 91 | version = get_rocm_version() |
| 92 | if version: |
| 93 | print(f"rocm{version.replace('.', '')}", end="") |
| 94 | PY |
| 95 | )" |
| 96 | _available_variants="$(curl -sf "https://wheels.vllm.ai/rocm/${merge_base_commit}/" \ |
| 97 | | grep -oP 'rocm\d+' | sort -u | tr '\n' ' ' || true)" |
| 98 | if [[ -n "${VLLM_PRECOMPILED_WHEEL_VARIANT:-}" ]]; then |
| 99 | _rocm_variant="${VLLM_PRECOMPILED_WHEEL_VARIANT}" |
| 100 | if [[ -n "${_rocm_env_variant}" && "${_rocm_variant}" != "${_rocm_env_variant}" ]]; then |
| 101 | echo "ERROR: VLLM_PRECOMPILED_WHEEL_VARIANT=${_rocm_variant} does not match detected environment ROCm variant ${_rocm_env_variant}" >&2 |
| 102 | exit 1 |
| 103 | fi |
| 104 | else |
| 105 | _rocm_variant="${_rocm_env_variant}" |
| 106 | fi |
| 107 | if [[ -z "${_rocm_variant}" ]]; then |
| 108 | echo "ERROR: Could not detect ROCm variant from the environment for commit ${merge_base_commit}" >&2 |
| 109 | exit 1 |
| 110 | fi |
| 111 | if [[ -z "${_available_variants}" ]] \ |
| 112 | || [[ " ${_available_variants} " != *" ${_rocm_variant} "* ]]; then |
| 113 | echo "ERROR: Environment ROCm variant '${_rocm_variant}' is not published for commit ${merge_base_commit} (available:${_available_variants:-none})" >&2 |
| 114 | exit 1 |
| 115 | fi |
| 116 | meta_json_url="https://wheels.vllm.ai/rocm/${merge_base_commit}/${_rocm_variant}/vllm/metadata.json" |
| 117 | unset -v _rocm_env_variant _available_variants _rocm_variant |
| 118 | else |
| 119 | meta_json_url="https://wheels.vllm.ai/${merge_base_commit}/vllm/metadata.json" |
| 120 | fi |
| 121 | echo "INFO: will use metadata.json from ${meta_json_url}" |
| 122 | |
| 123 | for i in {1..5}; do |
| 124 | echo "Checking metadata.json URL (attempt $i)..." |
| 125 | if curl --fail "$meta_json_url" > metadata.json; then |
| 126 | echo "INFO: metadata.json URL is valid." |
| 127 | # check whether it is valid json by python (printed to stdout) |
| 128 | if python3 -m json.tool metadata.json; then |
| 129 | echo "INFO: metadata.json is valid JSON. Proceeding with the check." |
| 130 | # check whether there is an object in the json matching: |
| 131 | # "package_name": "vllm", and "platform_tag" matches the current architecture |
| 132 | # see `determine_wheel_url` in setup.py for more details |
| 133 | if python3 -c "import platform as p,json as j,sys as s; d = j.load(open('metadata.json')); \ |
| 134 | s.exit(int(not any(o.get('package_name') == 'vllm' and p.machine() in o.get('platform_tag') \ |
| 135 | for o in d)))" 2>/dev/null; then |
| 136 | echo "INFO: metadata.json contains a pre-compiled wheel for the current architecture." |
| 137 | break |
| 138 | else |
| 139 | echo "WARN: metadata.json does not have a pre-compiled wheel for the current architecture." |
| 140 | fi |
| 141 | else |
| 142 | echo "CRITICAL: metadata.json exists but is not valid JSON, please do report in #sig-ci channel!" |
| 143 | echo "INFO: metadata.json content:" |
| 144 | cat metadata.json |
| 145 | exit 1 |
| 146 | fi |
| 147 | fi |
| 148 | # failure handling & retry logic |
| 149 | if [ "$i" -eq 5 ]; then |
| 150 | echo "ERROR: metadata is still not available after 5 attempts." |
| 151 | echo "ERROR: Please check whether the precompiled wheel for commit $merge_base_commit is available." |
| 152 | echo " NOTE: If $merge_base_commit is a new commit on main, maybe try again after its release pipeline finishes." |
| 153 | echo " NOTE: If it fails, please report in #sig-ci channel." |
| 154 | exit 1 |
| 155 | else |
| 156 | echo "WARNING: metadata is not available. Retrying after 5 minutes..." |
| 157 | sleep 300 |
| 158 | fi |
| 159 | done |
| 160 | fi |
| 161 | |
| 162 | set -x |
| 163 | |
| 164 | cd /vllm-workspace/ |
| 165 | |
| 166 | # uninstall vllm |
| 167 | pip3 uninstall -y vllm |
| 168 | # restore the original files |
| 169 | if [[ -d src/vllm ]]; then |
| 170 | mv src/vllm ./vllm |
| 171 | elif [[ ! -d vllm ]]; then |
| 172 | echo "ERROR: expected vllm package at /vllm-workspace/src/vllm or /vllm-workspace/vllm" >&2 |
| 173 | exit 1 |
| 174 | fi |
| 175 | |
| 176 | # remove all compilers |
| 177 | apt remove --purge build-essential -y |
| 178 | apt autoremove -y |
| 179 | |
| 180 | rm -f /tmp/changed.file |
| 181 | echo 'import os; os.system("touch /tmp/changed.file")' >> vllm/__init__.py |
| 182 | |
| 183 | # ROCm CI uses setuptools develop for editable installs (see Dockerfile.rocm and run-amd-test.sh). |
| 184 | if [[ -n "${rocm_wheel}" ]]; then |
| 185 | VLLM_PRECOMPILED_WHEEL_LOCATION="${rocm_wheel}" VLLM_USE_PRECOMPILED=1 python3 setup.py develop --no-deps |
| 186 | elif [[ "${is_rocm}" == "1" ]]; then |
| 187 | VLLM_PRECOMPILED_WHEEL_COMMIT=$merge_base_commit VLLM_USE_PRECOMPILED=1 python3 setup.py develop --no-deps |
| 188 | else |
| 189 | VLLM_PRECOMPILED_WHEEL_COMMIT=$merge_base_commit VLLM_USE_PRECOMPILED=1 pip3 install -vvv -e . |
| 190 | fi |
| 191 | # Run the script |
| 192 | python3 -c 'import vllm' |
| 193 | |
| 194 | # Check if the clangd log file was created |
| 195 | if [ ! -f /tmp/changed.file ]; then |
| 196 | echo "ERROR: changed.file was not created, python only compilation failed" |
| 197 | exit 1 |
| 198 | fi |