Skip to content

Commit affbd85

Browse files
hjmjohnsonclaude
andcommitted
ENH: Skip tarball download when conda-installed ITK is available
Update the Linux, macOS, and Windows download-cache-and-build scripts to detect a pre-installed ITK from a conda/pixi environment before attempting to download ITKPythonBuilds tarballs. When ITKConfig.cmake is found under CONDA_PREFIX or PIXI_ENVIRONMENT_DIR, the entire download/extract phase is skipped and the build proceeds directly using the conda-provided ITK. This is backward-compatible: when no conda ITK is detected, the scripts behave exactly as before (tarball download path). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 1ad57ac commit affbd85

3 files changed

Lines changed: 158 additions & 82 deletions

scripts/dockcross-manylinux-download-cache-and-build-module-wheels.sh

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -87,27 +87,52 @@ ITKPYTHONPACKAGE_ORG=${ITKPYTHONPACKAGE_ORG:-InsightSoftwareConsortium}
8787
ITKPYTHONPACKAGE_TAG=${ITKPYTHONPACKAGE_TAG:-main}
8888

8989
# -----------------------------------------------------------------------
90-
# Download and extract cache
90+
# Check for conda/pixi-provided ITK (libitk-wrapping package).
91+
# When available, skip the tarball download entirely.
9192

92-
echo "Fetching https://raw.githubusercontent.com/${ITKPYTHONPACKAGE_ORG}/ITKPythonPackage/${ITKPYTHONPACKAGE_TAG}/scripts/dockcross-manylinux-download-cache.sh"
93-
curl -L "https://raw.githubusercontent.com/${ITKPYTHONPACKAGE_ORG}/ITKPythonPackage/${ITKPYTHONPACKAGE_TAG}/scripts/dockcross-manylinux-download-cache.sh" -O
94-
chmod u+x dockcross-manylinux-download-cache.sh
95-
_download_cmd="ITK_GIT_TAG=${ITK_GIT_TAG} \
96-
ITK_PACKAGE_VERSION=${ITK_PACKAGE_VERSION} \
97-
ITKPYTHONPACKAGE_ORG=${ITKPYTHONPACKAGE_ORG} \
98-
ITKPYTHONPACKAGE_TAG=${ITKPYTHONPACKAGE_TAG} \
99-
MANYLINUX_VERSION=${MANYLINUX_VERSION} \
100-
TARGET_ARCH=${TARGET_ARCH} \
101-
bash -x \
102-
${download_script_dir}/dockcross-manylinux-download-cache.sh $1"
103-
echo "Running: ${_download_cmd}"
104-
eval "${_download_cmd}"
93+
_conda_itk_dir=""
94+
for _prefix_var in CONDA_PREFIX PIXI_ENVIRONMENT_DIR; do
95+
_prefix="${!_prefix_var:-}"
96+
if [ -n "${_prefix}" ]; then
97+
for _candidate in "${_prefix}"/lib/cmake/ITK-*; do
98+
if [ -f "${_candidate}/ITKConfig.cmake" ]; then
99+
_conda_itk_dir="${_candidate}"
100+
echo "Detected conda-installed ITK at ${_conda_itk_dir} (via \$${_prefix_var})"
101+
break 2
102+
fi
103+
done
104+
fi
105+
done
106+
107+
if [ -n "${_conda_itk_dir}" ]; then
108+
echo "Using conda-installed ITK; skipping tarball download."
109+
# Point to this repo's own scripts (already present on disk)
110+
untarred_ipp_dir=${download_script_dir}
111+
ITK_SOURCE_DIR=""
112+
else
113+
# -----------------------------------------------------------------------
114+
# Download and extract cache (legacy tarball path)
115+
116+
echo "Fetching https://raw.githubusercontent.com/${ITKPYTHONPACKAGE_ORG}/ITKPythonPackage/${ITKPYTHONPACKAGE_TAG}/scripts/dockcross-manylinux-download-cache.sh"
117+
curl -L "https://raw.githubusercontent.com/${ITKPYTHONPACKAGE_ORG}/ITKPythonPackage/${ITKPYTHONPACKAGE_TAG}/scripts/dockcross-manylinux-download-cache.sh" -O
118+
chmod u+x dockcross-manylinux-download-cache.sh
119+
_download_cmd="ITK_GIT_TAG=${ITK_GIT_TAG} \
120+
ITK_PACKAGE_VERSION=${ITK_PACKAGE_VERSION} \
121+
ITKPYTHONPACKAGE_ORG=${ITKPYTHONPACKAGE_ORG} \
122+
ITKPYTHONPACKAGE_TAG=${ITKPYTHONPACKAGE_TAG} \
123+
MANYLINUX_VERSION=${MANYLINUX_VERSION} \
124+
TARGET_ARCH=${TARGET_ARCH} \
125+
bash -x \
126+
${download_script_dir}/dockcross-manylinux-download-cache.sh $1"
127+
echo "Running: ${_download_cmd}"
128+
eval "${_download_cmd}"
105129

106-
#NOTE: in this scenario, untarred_ipp_dir is extracted from tarball
107-
# during ${download_script_dir}/dockcross-manylinux-download-cache.sh
108-
untarred_ipp_dir=${download_script_dir}/ITKPythonPackage
130+
#NOTE: in this scenario, untarred_ipp_dir is extracted from tarball
131+
# during ${download_script_dir}/dockcross-manylinux-download-cache.sh
132+
untarred_ipp_dir=${download_script_dir}/ITKPythonPackage
109133

110-
ITK_SOURCE_DIR=${download_script_dir}/ITKPythonPackage-build/ITK
134+
ITK_SOURCE_DIR=${download_script_dir}/ITKPythonPackage-build/ITK
135+
fi
111136

112137
# -----------------------------------------------------------------------
113138
# Build module wheels

scripts/macpython-download-cache-and-build-module-wheels.sh

Lines changed: 85 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -76,73 +76,95 @@ if [ ! -d "${DASHBOARD_BUILD_DIRECTORY}" ]; then
7676
fi
7777
cd "${DASHBOARD_BUILD_DIRECTORY}" || exit
7878

79-
# NOTE: download phase will install pixi in the DASHBOARD_BUILD_DIRECTORY (which is separate from the pixi
80-
# environment used by ITKPythonPackage).
81-
export PIXI_HOME=${DASHBOARD_BUILD_DIRECTORY}/.pixi
82-
if [ ! -f "${PIXI_HOME}/.pixi/bin/pixi" ]; then
83-
# Install pixi
84-
curl -fsSL https://pixi.sh/install.sh | sh
85-
# These are the tools needed for cross platform downloads of the ITK build caches stored in https://github.com/InsightSoftwareConsortium/ITKPythonBuilds
86-
pixi global install zstd
87-
pixi global install aria2
88-
pixi global install gnu-tar
89-
pixi global install git
90-
pixi global install rsync
91-
fi
92-
export PATH="${PIXI_HOME}/bin:$PATH"
93-
94-
tarball_arch="-$(arch)"
95-
TARBALL_NAME="ITKPythonBuilds-macosx${tarball_arch}.tar"
96-
97-
if [[ ! -f ${TARBALL_NAME}.zst ]]; then
98-
echo "Local ITK cache tarball file not found..."
99-
# Fetch ITKPythonBuilds archive containing ITK build artifacts
100-
echo "Fetching https://github.com/InsightSoftwareConsortium/ITKPythonBuilds/releases/download/${ITK_PACKAGE_VERSION}/ITKPythonBuilds-macosx${tarball_arch}.tar.zst"
101-
if ! curl -L "https://github.com/InsightSoftwareConsortium/ITKPythonBuilds/releases/download/${ITK_PACKAGE_VERSION}/ITKPythonBuilds-macosx${tarball_arch}.tar.zst" -O; then
102-
echo "FAILED Download:"
103-
echo "curl -L https://github.com/InsightSoftwareConsortium/ITKPythonBuilds/releases/download/${ITK_PACKAGE_VERSION}/${TARBALL_NAME}.zst -O"
104-
exit 1
105-
fi
106-
fi
79+
# -----------------------------------------------------------------------
80+
# Check for conda/pixi-provided ITK (libitk-wrapping package).
81+
# When available, skip the tarball download entirely.
10782

108-
if [[ ! -f ./${TARBALL_NAME}.zst ]]; then
109-
echo "ERROR: can not find required binary './${TARBALL_NAME}.zst'"
110-
exit 255
111-
fi
83+
_conda_itk_dir=""
84+
for _prefix_var in CONDA_PREFIX PIXI_ENVIRONMENT_DIR; do
85+
_prefix="${!_prefix_var:-}"
86+
if [ -n "${_prefix}" ]; then
87+
for _candidate in "${_prefix}"/lib/cmake/ITK-*; do
88+
if [ -f "${_candidate}/ITKConfig.cmake" ]; then
89+
_conda_itk_dir="${_candidate}"
90+
echo "Detected conda-installed ITK at ${_conda_itk_dir} (via \$${_prefix_var})"
91+
break 2
92+
fi
93+
done
94+
fi
95+
done
11296

113-
local_compress_tarball_name=${DASHBOARD_BUILD_DIRECTORY}/ITKPythonBuilds-macosx${tarball_arch}.tar.zst
114-
if [[ ! -f ${local_compress_tarball_name} ]]; then
115-
aria2c -c --file-allocation=none -d "$(dirname "${local_compress_tarball_name}")" -o "$(basename "${local_compress_tarball_name}")" -s 10 -x 10 "https://github.com/InsightSoftwareConsortium/ITKPythonBuilds/releases/download/${ITK_PACKAGE_VERSION}/ITKPythonBuilds-macosx${tarball_arch}.tar.zst"
116-
fi
117-
local_tarball_name=${DASHBOARD_BUILD_DIRECTORY}/ITKPythonBuilds-macosx${tarball_arch}.tar
118-
unzstd --long=31 "${local_compress_tarball_name}" -o "${local_tarball_name}"
119-
# Find GNU tar (gtar from pixi or brew) for reliable extraction
120-
if command -v gtar >/dev/null 2>&1; then
121-
TAR_CMD=gtar
122-
TAR_FLAGS=(--warning=no-unknown-keyword --checkpoint=10000 --checkpoint-action=dot)
123-
elif tar --version 2>/dev/null | grep -q "GNU tar"; then
124-
TAR_CMD=tar
125-
TAR_FLAGS=(--warning=no-unknown-keyword --checkpoint=10000 --checkpoint-action=dot)
97+
if [ -n "${_conda_itk_dir}" ]; then
98+
echo "Using conda-installed ITK; skipping tarball download."
12699
else
127-
TAR_CMD=tar
128-
TAR_FLAGS=()
129-
fi
130-
"${TAR_CMD}" xf "${local_tarball_name}" "${TAR_FLAGS[@]}"
131-
rm "${local_tarball_name}"
132-
133-
# Optional: Update build scripts
134-
if [[ -n ${ITKPYTHONPACKAGE_TAG} ]]; then
135-
echo "Updating build scripts to ${ITKPYTHONPACKAGE_ORG}/ITKPythonPackage@${ITKPYTHONPACKAGE_TAG}"
136-
local_clone_ipp=${DASHBOARD_BUILD_DIRECTORY}/ITKPythonPackage_${ITKPYTHONPACKAGE_TAG}
137-
if [ ! -d "${local_clone_ipp}/.git" ]; then
138-
git clone "https://github.com/${ITKPYTHONPACKAGE_ORG}/ITKPythonPackage.git" "${local_clone_ipp}"
100+
# NOTE: download phase will install pixi in the DASHBOARD_BUILD_DIRECTORY (which is separate from the pixi
101+
# environment used by ITKPythonPackage).
102+
export PIXI_HOME=${DASHBOARD_BUILD_DIRECTORY}/.pixi
103+
if [ ! -f "${PIXI_HOME}/.pixi/bin/pixi" ]; then
104+
# Install pixi
105+
curl -fsSL https://pixi.sh/install.sh | sh
106+
# These are the tools needed for cross platform downloads of the ITK build caches stored in https://github.com/InsightSoftwareConsortium/ITKPythonBuilds
107+
pixi global install zstd
108+
pixi global install aria2
109+
pixi global install gnu-tar
110+
pixi global install git
111+
pixi global install rsync
112+
fi
113+
export PATH="${PIXI_HOME}/bin:$PATH"
114+
115+
tarball_arch="-$(arch)"
116+
TARBALL_NAME="ITKPythonBuilds-macosx${tarball_arch}.tar"
117+
118+
if [[ ! -f ${TARBALL_NAME}.zst ]]; then
119+
echo "Local ITK cache tarball file not found..."
120+
# Fetch ITKPythonBuilds archive containing ITK build artifacts
121+
echo "Fetching https://github.com/InsightSoftwareConsortium/ITKPythonBuilds/releases/download/${ITK_PACKAGE_VERSION}/ITKPythonBuilds-macosx${tarball_arch}.tar.zst"
122+
if ! curl -L "https://github.com/InsightSoftwareConsortium/ITKPythonBuilds/releases/download/${ITK_PACKAGE_VERSION}/ITKPythonBuilds-macosx${tarball_arch}.tar.zst" -O; then
123+
echo "FAILED Download:"
124+
echo "curl -L https://github.com/InsightSoftwareConsortium/ITKPythonBuilds/releases/download/${ITK_PACKAGE_VERSION}/${TARBALL_NAME}.zst -O"
125+
exit 1
126+
fi
127+
fi
128+
129+
if [[ ! -f ./${TARBALL_NAME}.zst ]]; then
130+
echo "ERROR: can not find required binary './${TARBALL_NAME}.zst'"
131+
exit 255
132+
fi
133+
134+
local_compress_tarball_name=${DASHBOARD_BUILD_DIRECTORY}/ITKPythonBuilds-macosx${tarball_arch}.tar.zst
135+
if [[ ! -f ${local_compress_tarball_name} ]]; then
136+
aria2c -c --file-allocation=none -d "$(dirname "${local_compress_tarball_name}")" -o "$(basename "${local_compress_tarball_name}")" -s 10 -x 10 "https://github.com/InsightSoftwareConsortium/ITKPythonBuilds/releases/download/${ITK_PACKAGE_VERSION}/ITKPythonBuilds-macosx${tarball_arch}.tar.zst"
137+
fi
138+
local_tarball_name=${DASHBOARD_BUILD_DIRECTORY}/ITKPythonBuilds-macosx${tarball_arch}.tar
139+
unzstd --long=31 "${local_compress_tarball_name}" -o "${local_tarball_name}"
140+
# Find GNU tar (gtar from pixi or brew) for reliable extraction
141+
if command -v gtar >/dev/null 2>&1; then
142+
TAR_CMD=gtar
143+
TAR_FLAGS=(--warning=no-unknown-keyword --checkpoint=10000 --checkpoint-action=dot)
144+
elif tar --version 2>/dev/null | grep -q "GNU tar"; then
145+
TAR_CMD=tar
146+
TAR_FLAGS=(--warning=no-unknown-keyword --checkpoint=10000 --checkpoint-action=dot)
147+
else
148+
TAR_CMD=tar
149+
TAR_FLAGS=()
150+
fi
151+
"${TAR_CMD}" xf "${local_tarball_name}" "${TAR_FLAGS[@]}"
152+
rm "${local_tarball_name}"
153+
154+
# Optional: Update build scripts
155+
if [[ -n ${ITKPYTHONPACKAGE_TAG} ]]; then
156+
echo "Updating build scripts to ${ITKPYTHONPACKAGE_ORG}/ITKPythonPackage@${ITKPYTHONPACKAGE_TAG}"
157+
local_clone_ipp=${DASHBOARD_BUILD_DIRECTORY}/ITKPythonPackage_${ITKPYTHONPACKAGE_TAG}
158+
if [ ! -d "${local_clone_ipp}/.git" ]; then
159+
git clone "https://github.com/${ITKPYTHONPACKAGE_ORG}/ITKPythonPackage.git" "${local_clone_ipp}"
160+
fi
161+
pushd "${local_clone_ipp}" || exit
162+
git checkout "${ITKPYTHONPACKAGE_TAG}"
163+
git reset "origin/${ITKPYTHONPACKAGE_TAG}" --hard
164+
git status
165+
popd || exit
166+
rsync -av "${local_clone_ipp}/" "${DASHBOARD_BUILD_DIRECTORY}/ITKPythonPackage/"
139167
fi
140-
pushd "${local_clone_ipp}" || exit
141-
git checkout "${ITKPYTHONPACKAGE_TAG}"
142-
git reset "origin/${ITKPYTHONPACKAGE_TAG}" --hard
143-
git status
144-
popd || exit
145-
rsync -av "${local_clone_ipp}/" "${DASHBOARD_BUILD_DIRECTORY}/ITKPythonPackage/"
146168
fi
147169

148170
echo "Building module wheels"

scripts/windows-download-cache-and-build-module-wheels.ps1

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,31 @@ echo "ITK_PACKAGE_VERSION: $ITK_PACKAGE_VERSION"
8787
echo "ITK_GIT_TAG : $ITK_GIT_TAG"
8888
echo "Platform env : $platformEnv"
8989

90+
# ---------------------------------------------------------------------------
91+
# Check for conda/pixi-provided ITK (libitk-wrapping package).
92+
# When available, skip the archive download entirely.
93+
# ---------------------------------------------------------------------------
94+
$condaItkDir = $null
95+
foreach ($prefixVar in @("CONDA_PREFIX", "PIXI_ENVIRONMENT_DIR")) {
96+
$prefix = [System.Environment]::GetEnvironmentVariable($prefixVar)
97+
if ($prefix -and (Test-Path "$prefix\lib\cmake")) {
98+
foreach ($candidate in (Get-ChildItem "$prefix\lib\cmake" -Directory -Filter "ITK-*" -ErrorAction SilentlyContinue)) {
99+
if (Test-Path "$($candidate.FullName)\ITKConfig.cmake") {
100+
$condaItkDir = $candidate.FullName
101+
echo "Detected conda-installed ITK at $condaItkDir (via `$$prefixVar)"
102+
break
103+
}
104+
}
105+
if ($condaItkDir) { break }
106+
}
107+
}
108+
109+
if ($condaItkDir) {
110+
echo "Using conda-installed ITK; skipping archive download."
111+
# Use local ITKPythonPackage scripts
112+
$ippDir = $PSScriptRoot | Split-Path
113+
} else {
114+
90115
# Install pixi and required global tools
91116
# NOTE: Python and Doxygen are provided by the pixi environment; no need to
92117
# install them separately here.
@@ -195,9 +220,13 @@ if ($ITKPYTHONPACKAGE_TAG) {
195220
Remove-Item -Recurse -Force $ippTmpDir
196221
}
197222

223+
} # end else (tarball download path)
224+
198225
# Build the module wheel
199226
# Assemble paths used by build_wheels.py
200-
$ippDir = "$DASHBOARD_BUILD_DIRECTORY\IPP"
227+
if (-not $ippDir) {
228+
$ippDir = "$DASHBOARD_BUILD_DIRECTORY\IPP"
229+
}
201230
$buildScript = "$ippDir\scripts\build_wheels.py"
202231
# build_wheels.py expects the cached ITK build at <build-dir-root>\build\ITK-windows-py3XX-...
203232
# Since the zip extracts directly into BDR (i.e. BDR\build\ITK-windows-py311-...), BDR is the root.

0 commit comments

Comments
 (0)