Skip to content

Commit 1db3a7a

Browse files
authored
Cache the Arm FVP and toolchain downloads in the CI images (#24585)
Every CI job that runs examples/arm/setup.sh still downloads the default FVPs and the Arm GNU toolchain from developer.arm.com, about 394 MB, and the NXP MCUXpresso test fetches the same toolchain with wget. Arm has asked us to stop hitting their CDN this often, and the pinned versions change a few times a year, so the CI images can carry them. download_with_retry now looks in ARM_SETUP_DOWNLOAD_CACHE first. A file there named after the URL is copied instead of downloaded, but only when it matches the pinned MD5, so a stale cache costs a download, never a wrong archive. Each miss is logged as a GitHub warning, so a cache that stops matching shows up on the run. The NXP script copies its toolchain from the same place. The arm-sdk and zephyr-sdk images fill /opt/arm-download-cache at build time with the Corstone-300 and Corstone-320 FVPs and the arm-none-eabi toolchain, sourcing the same fvp_utils.sh and toolchain_utils.sh as setup.sh, which build.sh copies into the build context as it already does for requirements-lintrunner.txt. The fill is best effort, so an outage of Arm's CDN cannot break the image build for jobs that never download from it. The image tag only hashes .ci/docker, so docker-builds.yml also triggers on those two files and a pin bump on main rebuilds the images under the same tag. Until a job gets the rebuilt image it downloads and warns: during the rebuild, on runner nodes that still hold the old image, on PRs based before the bump, and after a ciflow/docker build of a pin-bump PR, which overwrites main's images until the next main or weekly rebuild. Images are rebuilt about once a day, mostly for the PyTorch pin PR, so image builds still make roughly ten downloads a day, against about 10,000 from jobs before. Authored with Claude Code. cc @digantdesai @freddan80 @per @zingo @oscarandersson8218 @mansnils @Sebastian-Larsson @robell
1 parent e2a2269 commit 1db3a7a

6 files changed

Lines changed: 70 additions & 1 deletion

File tree

‎.ci/docker/build.sh‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@ fi
116116
# Copy requirements-lintrunner.txt from root to here
117117
cp ../../requirements-lintrunner.txt ./
118118

119+
# Copy the Arm setup scripts that pin the FVP and toolchain downloads
120+
mkdir -p arm-setup
121+
cp ../../backends/arm/scripts/{utils,fvp_utils,toolchain_utils}.sh arm-setup/
122+
119123
# OSDC runners have no docker daemon, so the build runs on the in-cluster
120124
# BuildKit pool via a remote buildx builder. That builder has nowhere to load
121125
# an image into, so the result has to go straight to the registry.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#!/bin/bash
2+
# Copyright (c) Meta Platforms, Inc. and affiliates.
3+
# All rights reserved.
4+
#
5+
# This source code is licensed under the BSD-style license found in the
6+
# LICENSE file in the root directory of this source tree.
7+
8+
# Cache the developer.arm.com downloads of examples/arm/setup.sh, so CI jobs
9+
# copy them from ARM_SETUP_DOWNLOAD_CACHE instead of fetching them each run.
10+
# Jobs download whatever is missing, so a failed download only costs the cache.
11+
12+
set -exu
13+
14+
ARCH="$(uname -m)"
15+
OS="$(uname -s)"
16+
ARM_SETUP_CURL_PROGRESS_ARGS=(--no-progress-meter)
17+
# Fill the cache rather than read from it
18+
cache_dir="${ARM_SETUP_DOWNLOAD_CACHE}"
19+
unset ARM_SETUP_DOWNLOAD_CACHE
20+
source ./arm-setup/fvp_utils.sh
21+
source ./arm-setup/toolchain_utils.sh
22+
23+
cache_download() {
24+
local url=$1
25+
local md5=$2
26+
local output="${cache_dir}/$(basename "${url}")"
27+
download_with_retry "cache" "${url}" "${output}" "${md5}" || rm -f "${output}"
28+
}
29+
30+
mkdir -p "${cache_dir}"
31+
cache_download "${corstone300_url}" "${corstone300_md5_checksum}"
32+
cache_download "${corstone320_url}" "${corstone320_md5_checksum}"
33+
gcc_select_toolchain
34+
cache_download "${toolchain_url}" "${toolchain_md5_checksum}"

‎.ci/docker/ubuntu/Dockerfile‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,16 @@ COPY ./common/utils.sh utils.sh
103103
RUN if [ -n "${ZEPHYR_SDK}" ]; then bash ./install_zephyr.sh; fi
104104
RUN rm install_zephyr.sh zephyr_sdk_release_proxy.py utils.sh
105105

106+
# Cache the developer.arm.com downloads of examples/arm/setup.sh, which the
107+
# Arm and Zephyr jobs run.
108+
ENV ARM_SETUP_DOWNLOAD_CACHE=/opt/arm-download-cache
109+
COPY ./common/install_arm_downloads.sh install_arm_downloads.sh
110+
COPY ./arm-setup arm-setup
111+
RUN if [ -n "${ARM_SDK}${ZEPHYR_SDK}" ]; then \
112+
bash ./install_arm_downloads.sh || echo "Arm download cache not populated"; \
113+
fi
114+
RUN rm -r install_arm_downloads.sh arm-setup
115+
106116
ARG QNN_SDK
107117

108118
ARG MEDIATEK_SDK

‎.github/workflows/docker-builds.yml‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ on:
1616
- .ci/docker/**
1717
- .github/workflows/docker-builds.yml
1818
- requirements-lintrunner.txt
19+
- backends/arm/scripts/fvp_utils.sh
20+
- backends/arm/scripts/toolchain_utils.sh
1921
schedule:
2022
- cron: 1 3 * * 3
2123

‎backends/arm/scripts/utils.sh‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ function download_with_retry() {
7676
# both are caught here. --fail rejects HTTP errors,
7777
# --retry-all-errors handles transport errors, and verify_md5 catches
7878
# truncation / wrong-content via the published archive checksum.
79+
# If the absolute path ARM_SETUP_DOWNLOAD_CACHE holds a file named after
80+
# the URL with the expected MD5, it is copied instead; the CI images cache
81+
# them there.
7982

8083
# Arg 1: log context (passed to log_step)
8184
# Arg 2: URL to download
@@ -89,6 +92,16 @@ function download_with_retry() {
8992
local output="${3}"
9093
local expected_md5="${4}"
9194

95+
if [[ -n "${ARM_SETUP_DOWNLOAD_CACHE:-}" ]]; then
96+
local cached="${ARM_SETUP_DOWNLOAD_CACHE}/$(basename "${url}")"
97+
if [[ -f "${cached}" ]] && verify_md5 "${expected_md5}" "${cached}" \
98+
&& cp "${cached}" "${output}"; then
99+
log_step "${context}" "Using cached ${cached}"
100+
return 0
101+
fi
102+
echo "::warning::[Arm Setup/${context}] No usable ${cached}; downloading"
103+
fi
104+
92105
local max_attempts=5
93106
for attempt in $(seq 1 ${max_attempts}); do
94107
rm -f "${output}"

‎examples/nxp/mcuxpresso/imxrt700/executorch_cifarnet/test_build_from_scratch.sh‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,13 @@ echo Downloading ARM GCC toolchain
1212
if [ ! -d arm-toolchain ]; then
1313
mkdir -p arm-toolchain
1414
pushd arm-toolchain
15-
wget $ARM_TOOLCHAIN_URL
15+
# The Arm CI images cache this archive (see backends/arm/scripts/utils.sh)
16+
cached_toolchain="${ARM_SETUP_DOWNLOAD_CACHE:-}/$(basename $ARM_TOOLCHAIN_URL)"
17+
if [ -n "${ARM_SETUP_DOWNLOAD_CACHE:-}" ] && [ -f "$cached_toolchain" ]; then
18+
cp "$cached_toolchain" .
19+
else
20+
wget $ARM_TOOLCHAIN_URL
21+
fi
1622
tar -xvf *.tar.xz
1723
rm *.tar.xz
1824
popd

0 commit comments

Comments
 (0)