| 1 | #!/usr/bin/env bash |
| 2 | # Shared Dockerfile selection for the normal AMD CI build chain. |
| 3 | # CI_ROCM_DOCKERFILE_BASE and CI_ROCM_DOCKERFILE accept repository-relative paths. |
| 4 | # For Rock, set CI_ROCM_DOCKERFILE_BASE=docker/Dockerfile.rock_base and |
| 5 | # CI_ROCM_DOCKERFILE=docker/Dockerfile.rock. |
| 6 | # Custom recipes must preserve the CI targets and artifact layout. Additional |
| 7 | # COPY inputs also need the corresponding *_CONTENT_FILES overrides. |
| 8 | |
| 9 | rocm_base_dockerfile() { |
| 10 | local default="docker/Dockerfile.rocm_base" |
| 11 | printf '%s\n' "${CI_ROCM_DOCKERFILE_BASE:-${ROCM_BASE_DOCKERFILE:-${default}}}" |
| 12 | } |
| 13 | |
| 14 | rocm_ci_dockerfile() { |
| 15 | local default="docker/Dockerfile.rocm" |
| 16 | printf '%s\n' "${CI_ROCM_DOCKERFILE:-${CI_BASE_DOCKERFILE:-${default}}}" |
| 17 | } |
| 18 | |
| 19 | using_custom_rocm_dockerfiles() { |
| 20 | [[ "$(rocm_base_dockerfile)" != "docker/Dockerfile.rocm_base" \ |
| 21 | || "$(rocm_ci_dockerfile)" != "docker/Dockerfile.rocm" ]] |
| 22 | } |
| 23 | |
| 24 | rocm_dockerfile_stages() { |
| 25 | awk ' |
| 26 | toupper($1) == "FROM" { |
| 27 | for (idx = 2; idx < NF; idx++) { |
| 28 | if (tolower($idx) == "as") print tolower($(idx + 1)) |
| 29 | } |
| 30 | } |
| 31 | ' "$1" |
| 32 | } |
| 33 | |
| 34 | validate_rocm_dockerfile() { |
| 35 | local dockerfile="$1" |
| 36 | local stage="" |
| 37 | local stages="" |
| 38 | shift |
| 39 | |
| 40 | case "${dockerfile}" in |
| 41 | /*|../*|*/../*|*/..|*[[:space:]]*) |
| 42 | echo "ROCm Dockerfile must be a repository-relative path without '..' or whitespace: ${dockerfile}" >&2 |
| 43 | return 2 |
| 44 | ;; |
| 45 | esac |
| 46 | if [[ ! -f "${dockerfile}" ]]; then |
| 47 | echo "ROCm Dockerfile not found: ${dockerfile}" >&2 |
| 48 | return 2 |
| 49 | fi |
| 50 | if (($#)) && ! awk ' |
| 51 | toupper($1) == "FROM" { |
| 52 | named = 0 |
| 53 | for (idx = 2; idx < NF; idx++) { |
| 54 | if (tolower($idx) == "as") named = 1 |
| 55 | } |
| 56 | if (!named) exit 1 |
| 57 | } |
| 58 | ' "${dockerfile}"; then |
| 59 | echo "ROCm Dockerfile must name every build stage: ${dockerfile}" >&2 |
| 60 | return 2 |
| 61 | fi |
| 62 | stages=$(rocm_dockerfile_stages "${dockerfile}") |
| 63 | for stage in "$@"; do |
| 64 | if ! grep -Fxq -- "${stage}" <<< "${stages}"; then |
| 65 | echo "ROCm Dockerfile ${dockerfile} is missing required stage: ${stage}" >&2 |
| 66 | return 2 |
| 67 | fi |
| 68 | done |
| 69 | } |
| 70 | |
| 71 | configure_rocm_build() { |
| 72 | ROCM_BASE_DOCKERFILE=$(rocm_base_dockerfile) |
| 73 | CI_BASE_DOCKERFILE=$(rocm_ci_dockerfile) |
| 74 | export ROCM_BASE_DOCKERFILE CI_BASE_DOCKERFILE |
| 75 | using_custom_rocm_dockerfiles || return 0 |
| 76 | |
| 77 | # Custom stacks may supply dependencies without separate build stages. |
| 78 | export ROCM_DEP_CACHE_EXPORT_MODE=never |
| 79 | |
| 80 | # Preserve the standard runtime tags, which are unique to each build, |
| 81 | # while preventing experimental builds from promoting stable images. |
| 82 | export ROCM_BASE_PUSH_STABLE_TAG=0 |
| 83 | export CI_BASE_PUSH_STABLE_TAG=0 |
| 84 | echo "Custom ROCm Dockerfiles: ${ROCM_BASE_DOCKERFILE} and ${CI_BASE_DOCKERFILE}" |
| 85 | } |