Skip to content

Commit 2c10895

Browse files
hjmjohnsonclaude
andcommitted
ENH: Detect conda-installed ITK and skip C++ build steps
When a pre-built ITK is available in the conda/pixi environment (via the libitk-wrapping package), automatically skip the superbuild and C++ compilation steps and point the wheel builder at the installed ITK CMake config directory. Detection checks CONDA_PREFIX and PIXI_ENVIRONMENT_DIR for an ITK CMake config (lib/cmake/ITK-*/ITKConfig.cmake). When found, steps 01_superbuild_support_components and 02_build_wrapped_itk_cplusplus are replaced with no-op stubs, reducing remote module build times from ~1-2 hours to ~15 minutes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent a38952c commit 2c10895

1 file changed

Lines changed: 59 additions & 0 deletions

File tree

scripts/build_python_instance_base.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,35 @@ def update_venv_itk_build_configurations(self) -> None:
205205
"Python3_ROOT_DIR:PATH", f"{self.venv_info_dict['python_root_dir']}"
206206
)
207207

208+
def _detect_conda_itk(self) -> Path | None:
209+
"""Detect a pre-installed ITK from a conda/pixi environment.
210+
211+
Checks ``CONDA_PREFIX`` (or ``PIXI_ENVIRONMENT_DIR``) for an
212+
installed ITK CMake config directory. When found, the superbuild
213+
and C++ build steps can be skipped entirely.
214+
215+
Returns
216+
-------
217+
Path or None
218+
Path to the ITK CMake config directory, or *None* if not found.
219+
"""
220+
for env_var in ("CONDA_PREFIX", "PIXI_ENVIRONMENT_DIR"):
221+
prefix = os.environ.get(env_var, "")
222+
if not prefix:
223+
continue
224+
# Search for lib/cmake/ITK-* (version may vary)
225+
cmake_dir = Path(prefix) / "lib" / "cmake"
226+
if cmake_dir.is_dir():
227+
for candidate in sorted(cmake_dir.glob("ITK-*")):
228+
itk_config = candidate / "ITKConfig.cmake"
229+
if itk_config.is_file():
230+
print(
231+
f"Detected conda-installed ITK at {candidate} "
232+
f"(via ${env_var})"
233+
)
234+
return candidate
235+
return None
236+
208237
def run(self) -> None:
209238
"""Run the full build flow for this Python instance."""
210239
# Use BuildManager to persist and resume build steps
@@ -213,6 +242,21 @@ def run(self) -> None:
213242
if self.itk_module_deps:
214243
self._build_module_dependencies()
215244

245+
# Check for conda/pixi-provided ITK (libitk-wrapping package)
246+
conda_itk_dir = self._detect_conda_itk()
247+
if conda_itk_dir is not None:
248+
# Point the build at the pre-installed ITK — skip compilation
249+
self.cmake_itk_source_build_configurations.set(
250+
"ITK_DIR:PATH", str(conda_itk_dir)
251+
)
252+
# Set ITK_BINARY_DIR so wheel build and cleanup paths still resolve
253+
self.cmake_itk_source_build_configurations.set(
254+
"ITK_BINARY_DIR:PATH", str(conda_itk_dir)
255+
)
256+
print(
257+
"Using conda-installed ITK; skipping superbuild and C++ build steps."
258+
)
259+
216260
python_package_build_steps: OrderedDict[str, Callable] = OrderedDict(
217261
{
218262
"01_superbuild_support_components": self.build_superbuild_support_components,
@@ -223,6 +267,21 @@ def run(self) -> None:
223267
}
224268
)
225269

270+
if conda_itk_dir is not None:
271+
# Skip both superbuild and C++ build when using conda ITK
272+
python_package_build_steps = OrderedDict(
273+
(
274+
(f"{k}_skipped", (lambda: None))
275+
if k
276+
in (
277+
"01_superbuild_support_components",
278+
"02_build_wrapped_itk_cplusplus",
279+
)
280+
else (k, v)
281+
)
282+
for k, v in python_package_build_steps.items()
283+
)
284+
226285
if self.skip_itk_build:
227286
# Skip these steps if we are in the CI environment
228287
python_package_build_steps = OrderedDict(

0 commit comments

Comments
 (0)